diff --git a/.gitignore b/.gitignore index 471e038534..ea395911b6 100644 --- a/.gitignore +++ b/.gitignore @@ -17,4 +17,11 @@ v2/pkg/protocols/common/helpers/deserialization/testdata/ValueObject.class v2/pkg/protocols/common/helpers/deserialization/testdata/ValueObject2.ser *.exe v2/.gitignore +v2/pkg/js/devtools/bindgen/cmd/bindgen +v2/pkg/js/devtools/jsdocgen/jsdocgen +bindgen +jsdocgen +nuclei +v2/scrapefuncs *.DS_Store +v2/pkg/protocols/headless/engine/.cache diff --git a/docs/mint.json b/docs/mint.json index 5095a8e1ba..22990e2bc9 100644 --- a/docs/mint.json +++ b/docs/mint.json @@ -71,6 +71,7 @@ "template-guide/network", "template-guide/dns", "template-guide/file", + "template-guide/javascript", { "group": "Operators", "pages": [ diff --git a/docs/template-guide/javascript.mdx b/docs/template-guide/javascript.mdx new file mode 100644 index 0000000000..b5765460d0 --- /dev/null +++ b/docs/template-guide/javascript.mdx @@ -0,0 +1,185 @@ +--- +title: "Javascript" +--- + +## Introduction + +Nuclei and its community thrives on its ability to write exploits/checks in fast and simple way in YAML format and we aim to make **nuclei templates** as standard for writing security checks and that comes with understanding its limitations and addressing them as well as expanding its capabilities. It is already possible to write most complex HTTP, DNS, SSL protocol exploits / checks with increasing support and a powerful and easy to use DSL in nuclei engine but we understand this may not be enough for addressing / writing vulnerabilities across all protocols as well as other non-remote domains of security like local privilege escalation checks, kernel etc. + +To address this and expand to other domains of security, Nuclei v3 ships with a embedded runtime for javascript that is tailored for **Nuclei** with the help of **[Goja](https://github.com/dop251/goja)**. + + +## Features + +- **Provider/Driver specific exploit** + +Some vulnerabilities are specific to software/driver, example a redis buffer overflow exploit or a exploit of specific VPN software or anything that's not a IETF standard protocol. since they are not standard protocols and it doesn't make much sense to add them as a protocol in nuclei. +Such exploits cannot be written using 'network' protocol or Very complex to write, such exploits can be written by exposing required library in nuclei (if not already present) and writing actual exploit in javascript protocol minus the boilerplate and scaling issues and other goodies of nuclei + +- **Non Network Checks** + +Security is not limited to network and nuclei also doesn't intend to limit itself to network only. There are lot of security checks that are not network related like + +1. local privilege escalation checks +2. kernel exploits +3. account misconfigurations +4. system misconfigurations etc + +- **Complex network protocol exploits** + +Some network exploits are very complex to write due to nature of protocol or exploit itself example [CVE-2020-0796](https://nvd.nist.gov/vuln/detail/cve-2020-0796) where you have to manually construct a packet. such exploits are usually written in python but now can be written in javascript protocol itself + +- **Multi Step Exploits** + +Ldap / kerberos exploits usually involves multi step process of authentication and then exploitation etc and not easy to write in YAML based DSL + +- **Scalable and maintainable exploits** + +One off exploits written in code are not scalable and maintainable due to nature of language , boilerplate code and lot of other factors. The goal here is to only write **bare minimum** code required to run exploit and let nuclei engine handle the rest + +- **Leveraging turing complete language** + +While YAML based DSL is powerful and easy to use it is not turing complete and has its own limitations. Javascript is turing complete thus users who are already familiar with javascript can write network and other exploits without learning new DSL or hacking around existing DSL. + +## Goja + +Goja is ECMAScript/Javascript engine/runtime written in pure go and has full support for ECMAScript 5.1. It is fast, can be used in goroutines and has very small memory footprint which makes it good fit for embedding in nuclei and provides additional layer of security and flexibility due to nature of javascript language and its implementation. + +This does not break any nuclei design principle nor does it change how nuclei works and is dependency free. It complements nuclei engine by adding existing turing complete language (i.e javascript) instead of re-inventing the wheel by creating new DSL (domain specific language) + +## Requirements + +- A bare minimum knowledge of javascript (loops, functions , arrays is enough) is required to write javascript protocol template +- Nuclei v3.0.0 or above + + +## API Reference + +API reference of all exposed modules and functions can be found [here](https://projectdiscovery.github.io/js-proto-docs/). + +## Javascript Protocol + +Javascript protocol is new protocol added in nuclei v3 to allow writing exploits / checks in javascript language but internally are executed in go. And this javscript is tailored towards nuclei ecosystem this means + +- It is not intended to fit / imported with any existing javascript libraries or frameworks outside of nuclei ecosystem. +- Nuclei Engine provides a set of functions, libraries that are tailor made for writing exploits / checks and only adds required/necessary functionality to compliment existing YAML based DSL. +- It is not intended to be used as general purpose javascript runtime and does not replace matchers or extractors or any existing functionality of nuclei. +- Javascript Protocol is intended to bridge gap between network protocol to add any new xyz protocol while adding lot of other functionalities. +- Nuclei v3.0.0 ships with **15+ libraries (ssh,ftp,rdp,kerberos,redis)** tailored for writing exploits/checks in javascript and will be continiously expanded in future. + +Here is a simple example of javascript protocol template + +```yaml +id: ssh-server-fingerprint + +info: + name: Fingerprint SSH Server Software + author: Ice3man543,tarunKoyalwar + severity: info + + +javascript: + - code: | + var m = require("nuclei/ssh"); + var c = m.SSHClient(); + var response = c.ConnectSSHInfoMode(Host, Port); + to_json(response); + args: + Host: "{{Host}}" + Port: "22" + + extractors: + - type: json + json: + - '.ServerID.Raw' +``` + +In above nuclei template we are fingerprinting SSH Server Software by connecting in Non-Auth mode and extracting server banner. Lets break down the template. + +### Code + +Code contains actual javascript code that is executed by nuclei engine at runtime In above template we are + +- importing `nuclei/ssh` module/library +- creating a new instance of `SSHClient` object +- connecting to SSH server in `Info` mode +- converting response to json + +### Args + +Args can be simply understood as variables in javascript that are passed at runtime and support DSL usage + + +### **Output** + +Value of Last expression is returned as output of javascript protocol template and can be used in matchers / extractors. If server returns an error instead then `error` variable is exposed in matcher/extractor with error message. + +### Example + +**SSH Password Bruteforce Template** + +```yaml +id: ssh-brute + +info: + name: SSH Credential Stuffing + author: tarunKoyalwar + severity: critical + + +javascript: + - pre-condition: | + var m = require("nuclei/ssh"); + var c = m.SSHClient(); + var response = c.ConnectSSHInfoMode(Host, Port); + // only bruteforce if ssh server allows password based authentication + response["UserAuth"].includes("password") + + code: | + var m = require("nuclei/ssh"); + var c = m.SSHClient(); + c.Connect(Host,Port,Username,Password); + + args: + Host: "{{Host}}" + Port: "22" + Username: "{{usernames}}" + Password: "{{passwords}}" + + threads: 10 + attack: clusterbomb + payloads: + usernames: helpers/wordlists/wp-users.txt + passwords: helpers/wordlists/wp-passwords.txt + + stop-at-first-match: true + matchers: + - type: dsl + dsl: + - "response == true" + - "success == true" + condition: and +``` + +In above nuclei template we are bruteforcing ssh server with list of usernames and passwords. We can tell that this might not have been possible to achieve with network template Let's break down the template. + +### Pre-Condition + +`pre-condition` is a optional javascript code that is executed before running "code" and acts as pre-condition to exploit. In above template before attempting to bruteforce we are checking if +- address is actually a ssh server +- ssh server is configured to allow password based authentication + +**Furthur explaination** + +- If pre-condition returns `true` only then code is executed otherwise it is skipped +- In code section we import `nuclei/ssh` module and create a new instance of `SSHClient` object +- and then we attempt to connect to ssh server with username and password +- this template uses [payloads](https://docs.nuclei.sh/template-guide/http/http-payloads) to launch a clusterbomb attack with 10 threads and exits on first match + +Looking at this template now we can tell that javascript template is very powerful to write multi step and protocol/vendor specific exploits which is primary goal of javascript protocol. + +A collection of javascript protocol templates can be found [here](https://github.com/projectdiscovery/nuclei-templates/pull/8206). + +## Contributing + +If you want to add a new module or function to nuclei javascript runtime please open a PR with your changes, refer [Contributing](https://github.com/projectdiscovery/nuclei/blob/7085b47c19dbe3a70b3d4eb23177995bda5c285a/v2/pkg/js/CONTRIBUTE.md) for more details. diff --git a/integration_tests/protocols/code/py-env-var.yaml b/integration_tests/protocols/code/py-env-var.yaml index b05ccf0923..38510e7c13 100644 --- a/integration_tests/protocols/code/py-env-var.yaml +++ b/integration_tests/protocols/code/py-env-var.yaml @@ -20,4 +20,4 @@ code: - type: word words: - "hello from input baz" -# digest: 4a0a00473045022100e17c7a809fd64419baf401b5331edab3a68a4c182f7777614beb1862eb6ea8b7022011b95fc0e22d7f82e08e01b56ce87afdbe03027c238ba290a058d695226173ae \ No newline at end of file +# digest: 4a0a004730450221009b73a0d173beca99aff61fcfe366d929760411f0b9facfe5502a0f2e677342fa02201327b024e52a89891bb90ecdd2f7521370fe40ac89b3f93e9e5f5072f0192de7 \ No newline at end of file diff --git a/integration_tests/protocols/code/py-file.yaml b/integration_tests/protocols/code/py-file.yaml index ee76c50c32..ae8bcdd346 100644 --- a/integration_tests/protocols/code/py-file.yaml +++ b/integration_tests/protocols/code/py-file.yaml @@ -18,4 +18,4 @@ code: - type: word words: - "hello from input" -# digest: 490a004630440220241d7faae14ab5760dbe7acf621a3923d0650148bc14a52a9be06ba76e8e0abf02201885fcc432d354d3c99ea97b964838719451bc97f148229f187f61eee7525eb6 \ No newline at end of file +# digest: 490a00463044022037b485132a0ff1f52bde1ce71908fd692d93d9cda15d5b70275c7fc89a0aa257022043f36ca1c7062d4d74dde377e5a0065c1507bfcad2a8389772eebfa99fd16af2 \ No newline at end of file diff --git a/integration_tests/protocols/code/py-interactsh.yaml b/integration_tests/protocols/code/py-interactsh.yaml index 664c2d7e8f..978050906a 100644 --- a/integration_tests/protocols/code/py-interactsh.yaml +++ b/integration_tests/protocols/code/py-interactsh.yaml @@ -26,4 +26,4 @@ code: part: interactsh_protocol words: - "http" -# digest: 490a004630440220427cb7100f0b7d95224f490a6f4f626186782cb26c69f2551d6aefcdbc7c17d20220206161ad3a98afe8fcef9dd06d9a6dd5f34c5f7e3cd3ab7f81328f033dcd2b48 \ No newline at end of file +# digest: 4a0a004730450221008d0e317bd37ab7dfdbaf3d26ed2072521f0ea00a61d45d0e6d592886faeac1840220410070cd29ffa05113b387c5afcd13fd65dab2b67f21583a1aeddb352ab5aa88 \ No newline at end of file diff --git a/integration_tests/protocols/code/py-snippet.yaml b/integration_tests/protocols/code/py-snippet.yaml index 6b77ca5227..5f05ab481e 100644 --- a/integration_tests/protocols/code/py-snippet.yaml +++ b/integration_tests/protocols/code/py-snippet.yaml @@ -20,4 +20,4 @@ code: - type: word words: - "hello from input" -# digest: 4a0a00473045022056092462597e85139626656d37df123094cb3861bdf583450c38814bac8df9cb022100e83a8c552f8f8a098f6b7ec8a32c6b448b995e000884beadb50cb0f2720117de \ No newline at end of file +# digest: 4b0a00483046022100b7fef4d710fa7e3b8916dc990a381551deb42c558d92a043358325f3994078f5022100db47c9f752185ad42af1a5268788567f88fcd8e41053674fdb637f01f02bbbaa \ No newline at end of file diff --git a/integration_tests/protocols/javascript/net-multi-step.yaml b/integration_tests/protocols/javascript/net-multi-step.yaml new file mode 100644 index 0000000000..0d638fa553 --- /dev/null +++ b/integration_tests/protocols/javascript/net-multi-step.yaml @@ -0,0 +1,32 @@ +id: network-multi-step +info: + name: network multi-step + author: tarunKoyalwar + severity: high + description: | + Network multi-step template for testing + + +javascript: + - code: | + var m = require("nuclei/net"); + var conn = m.Open("tcp",address); + conn.SetTimeout(timeout); // optional timeout + conn.Send("FIRST") + conn.RecvString(4) // READ 4 bytes i.e PING + conn.Send("SECOND") + conn.RecvString(4) // READ 4 bytes i.e PONG + conn.RecvString(6) // READ 6 bytes i.e NUCLEI + + args: + address: "{{Host}}:{{Port}}" + Host: "{{Host}}" + Port: 5431 + timeout: 3 # in sec + + matchers: + - type: dsl + dsl: + - success == true + - response == "NUCLEI" + condition: and diff --git a/integration_tests/protocols/javascript/redis-pass-brute.yaml b/integration_tests/protocols/javascript/redis-pass-brute.yaml new file mode 100644 index 0000000000..d4d092305d --- /dev/null +++ b/integration_tests/protocols/javascript/redis-pass-brute.yaml @@ -0,0 +1,43 @@ +id: redis-pass-brute +info: + name: redis password bruteforce + author: tarunKoyalwar + severity: high + description: | + This template bruteforces passwords for protected redis instances. + If redis is not protected with password. it is also matched + metadata: + shodan-query: product:"redis" + + +javascript: + - pre-condition: | + isPortOpen(Host,Port) + + code: | + var m = require("nuclei/redis"); + m.GetServerInfoAuth(Host,Port,Password); + + args: + Host: "{{Host}}" + Port: "6379" + Password: "{{passwords}}" + + payloads: + passwords: + - "" + - root + - password + - admin + - iamadmin + stop-at-first-match: true + + matchers-condition: and + matchers: + - type: word + words: + - "redis_version" + - type: word + negative: true + words: + - "redis_mode:sentinel" diff --git a/integration_tests/protocols/javascript/ssh-server-fingerprint.yaml b/integration_tests/protocols/javascript/ssh-server-fingerprint.yaml new file mode 100644 index 0000000000..20d472779d --- /dev/null +++ b/integration_tests/protocols/javascript/ssh-server-fingerprint.yaml @@ -0,0 +1,26 @@ +id: ssh-server-fingerprint + +info: + name: Fingerprint SSH Server Software + author: Ice3man543,tarunKoyalwar + severity: info + metadata: + shodan-query: port:22 + + +javascript: + - code: | + var m = require("nuclei/ssh"); + var c = m.SSHClient(); + var response = c.ConnectSSHInfoMode(Host, Port); + to_json(response); + args: + Host: "{{Host}}" + Port: "22" + + extractors: + - type: json + name: server + json: + - '.ServerID.Raw' + part: response diff --git a/v2/Makefile b/v2/Makefile index e08efb52f8..966bdefef8 100644 --- a/v2/Makefile +++ b/v2/Makefile @@ -30,3 +30,8 @@ functional: cd cmd/functional-test; bash run.sh tidy: $(GOMOD) tidy +devtools: + $(GOBUILD) $(GOFLAGS) -ldflags '$(LDFLAGS)' -o "bindgen" pkg/js/devtools/bindgen/cmd/bindgen/main.go + $(GOBUILD) $(GOFLAGS) -ldflags '$(LDFLAGS)' -o "jsdocgen" pkg/js/devtools/jsdocgen/main.go + $(GOBUILD) $(GOFLAGS) -ldflags '$(LDFLAGS)' -o "scrapefuncs" pkg/js/devtools/scrapefuncs/main.go + diff --git a/v2/cmd/integration-test/integration-test.go b/v2/cmd/integration-test/integration-test.go index f18560c773..d9d0c681ac 100644 --- a/v2/cmd/integration-test/integration-test.go +++ b/v2/cmd/integration-test/integration-test.go @@ -50,6 +50,7 @@ var ( "generic": genericTestcases, "dsl": dslTestcases, "flow": flowTestcases, + "javascript": jsTestcases, } // For debug purposes diff --git a/v2/cmd/integration-test/javascript.go b/v2/cmd/integration-test/javascript.go new file mode 100644 index 0000000000..d0caafc665 --- /dev/null +++ b/v2/cmd/integration-test/javascript.go @@ -0,0 +1,155 @@ +package main + +import ( + "log" + "time" + + "github.com/ory/dockertest/v3" + "github.com/projectdiscovery/nuclei/v2/pkg/testutils" + osutils "github.com/projectdiscovery/utils/os" + "go.uber.org/multierr" +) + +var jsTestcases = []TestCaseInfo{ + {Path: "protocols/javascript/redis-pass-brute.yaml", TestCase: &javascriptRedisPassBrute{}, DisableOn: func() bool { return osutils.IsWindows() || osutils.IsOSX() }}, + {Path: "protocols/javascript/ssh-server-fingerprint.yaml", TestCase: &javascriptSSHServerFingerprint{}, DisableOn: func() bool { return osutils.IsWindows() || osutils.IsOSX() }}, + {Path: "protocols/javascript/net-multi-step.yaml", TestCase: &networkMultiStep{}}, +} + +var ( + redisResource *dockertest.Resource + sshResource *dockertest.Resource + pool *dockertest.Pool + defaultRetry = 3 +) + +type javascriptRedisPassBrute struct{} + +func (j *javascriptRedisPassBrute) Execute(filePath string) error { + if redisResource == nil || pool == nil { + // skip test as redis is not running + return nil + } + tempPort := redisResource.GetPort("6379/tcp") + finalURL := "localhost:" + tempPort + defer purge(redisResource) + errs := []error{} + for i := 0; i < defaultRetry; i++ { + results := []string{} + var err error + _ = pool.Retry(func() error { + //let ssh server start + time.Sleep(3 * time.Second) + results, err = testutils.RunNucleiTemplateAndGetResults(filePath, finalURL, debug) + return nil + }) + if err != nil { + return err + } + if err := expectResultsCount(results, 1); err == nil { + return nil + } else { + errs = append(errs, err) + } + } + return multierr.Combine(errs...) +} + +type javascriptSSHServerFingerprint struct{} + +func (j *javascriptSSHServerFingerprint) Execute(filePath string) error { + if sshResource == nil || pool == nil { + // skip test as redis is not running + return nil + } + tempPort := sshResource.GetPort("2222/tcp") + finalURL := "localhost:" + tempPort + defer purge(sshResource) + errs := []error{} + for i := 0; i < defaultRetry; i++ { + results := []string{} + var err error + _ = pool.Retry(func() error { + //let ssh server start + time.Sleep(3 * time.Second) + results, err = testutils.RunNucleiTemplateAndGetResults(filePath, finalURL, debug) + return nil + }) + if err != nil { + return err + } + if err := expectResultsCount(results, 1); err == nil { + return nil + } else { + errs = append(errs, err) + } + } + return multierr.Combine(errs...) +} + +// purge any given resource if it is not nil +func purge(resource *dockertest.Resource) { + if resource != nil && pool != nil { + containerName := resource.Container.Name + _ = pool.Client.StopContainer(resource.Container.ID, 0) + err := pool.Purge(resource) + if err != nil { + log.Printf("Could not purge resource: %s", err) + } + _ = pool.RemoveContainerByName(containerName) + } +} + +func init() { + // uses a sensible default on windows (tcp/http) and linux/osx (socket) + pool, err := dockertest.NewPool("") + if err != nil { + log.Printf("something went wrong with dockertest: %s", err) + return + } + + // uses pool to try to connect to Docker + err = pool.Client.Ping() + if err != nil { + log.Printf("Could not connect to Docker: %s", err) + } + + // setup a temporary redis instance + redisResource, err = pool.RunWithOptions(&dockertest.RunOptions{ + Repository: "redis", + Tag: "latest", + Cmd: []string{"redis-server", "--requirepass", "iamadmin"}, + Platform: "linux/amd64", + }) + if err != nil { + log.Printf("Could not start resource: %s", err) + return + } + // by default expire after 30 sec + if err := redisResource.Expire(30); err != nil { + log.Printf("Could not expire resource: %s", err) + } + + // setup a temporary ssh server + sshResource, err = pool.RunWithOptions(&dockertest.RunOptions{ + Repository: "lscr.io/linuxserver/openssh-server", + Tag: "latest", + Env: []string{ + "PUID=1000", + "PGID=1000", + "TZ=Etc/UTC", + "PASSWORD_ACCESS=true", + "USER_NAME=admin", + "USER_PASSWORD=admin", + }, + Platform: "linux/amd64", + }) + if err != nil { + log.Printf("Could not start resource: %s", err) + return + } + // by default expire after 30 sec + if err := sshResource.Expire(30); err != nil { + log.Printf("Could not expire resource: %s", err) + } +} diff --git a/v2/go.mod b/v2/go.mod index 8ac07b9b8d..73e35beb67 100644 --- a/v2/go.mod +++ b/v2/go.mod @@ -17,7 +17,7 @@ require ( github.com/json-iterator/go v1.1.12 github.com/julienschmidt/httprouter v1.3.0 github.com/logrusorgru/aurora v2.0.3+incompatible - github.com/miekg/dns v1.1.55 + github.com/miekg/dns v1.1.56 github.com/olekukonko/tablewriter v0.0.5 github.com/pkg/errors v0.9.1 github.com/projectdiscovery/clistats v0.0.19 @@ -39,9 +39,9 @@ require ( github.com/weppos/publicsuffix-go v0.30.2-0.20230730094716-a20f9abcc222 github.com/xanzy/go-gitlab v0.84.0 go.uber.org/multierr v1.11.0 - golang.org/x/net v0.14.0 + golang.org/x/net v0.15.0 golang.org/x/oauth2 v0.11.0 - golang.org/x/text v0.12.0 + golang.org/x/text v0.13.0 gopkg.in/yaml.v2 v2.4.0 moul.io/http2curl v1.0.0 ) @@ -60,21 +60,32 @@ require ( github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.11.72 github.com/aws/aws-sdk-go-v2/service/s3 v1.37.0 github.com/charmbracelet/glamour v0.6.0 + github.com/denisenkom/go-mssqldb v0.12.3 + github.com/ditashi/jsbeautifier-go v0.0.0-20141206144643-2520a8026a9c github.com/docker/go-units v0.5.0 - github.com/dop251/goja v0.0.0-20230812105242-81d76064690d + github.com/dop251/goja v0.0.0-20230828202809-3dbe69dd2b8e github.com/fatih/structs v1.1.0 github.com/go-git/go-git/v5 v5.7.0 + github.com/go-ldap/ldap/v3 v3.4.5 + github.com/go-pg/pg v8.0.7+incompatible + github.com/go-sql-driver/mysql v1.6.0 github.com/h2non/filetype v1.1.3 + github.com/hirochachacha/go-smb2 v1.1.0 github.com/klauspost/compress v1.16.7 github.com/labstack/echo/v4 v4.10.2 + github.com/lib/pq v1.10.1 github.com/mholt/archiver v3.1.1+incompatible - github.com/projectdiscovery/dsl v0.0.21 + github.com/ory/dockertest/v3 v3.10.0 + github.com/praetorian-inc/fingerprintx v1.1.9 + github.com/projectdiscovery/dsl v0.0.22-0.20230911020052-7ab80c9abba8 github.com/projectdiscovery/fasttemplate v0.0.2 github.com/projectdiscovery/goflags v0.1.20 github.com/projectdiscovery/gologger v1.1.11 + github.com/projectdiscovery/gostruct v0.0.1 github.com/projectdiscovery/gozero v0.0.0-20230510004414-f1d11fdaf5c6 github.com/projectdiscovery/httpx v1.3.4 github.com/projectdiscovery/mapcidr v1.1.2 + github.com/projectdiscovery/n3iwf v0.0.0-20230523120440-b8cd232ff1f5 github.com/projectdiscovery/ratelimit v0.0.9 github.com/projectdiscovery/rdap v0.9.1-0.20221108103045-9865884d1917 github.com/projectdiscovery/sarif v0.0.1 @@ -82,7 +93,11 @@ require ( github.com/projectdiscovery/uncover v1.0.6-0.20230601103158-bfd7e02a5bb1 github.com/projectdiscovery/utils v0.0.54 github.com/projectdiscovery/wappalyzergo v0.0.107 + github.com/redis/go-redis/v9 v9.1.0 + github.com/ropnop/gokrb5/v8 v8.0.0-20201111231119-729746023c02 + github.com/sashabaranov/go-openai v1.15.3 github.com/stretchr/testify v1.8.4 + github.com/zmap/zgrab2 v0.1.8-0.20230806160807-97ba87c0e706 gopkg.in/src-d/go-git.v4 v4.13.1 gopkg.in/yaml.v3 v3.0.1 ) @@ -91,7 +106,10 @@ require ( aead.dev/minisign v0.2.0 // indirect github.com/Azure/azure-sdk-for-go/sdk/azcore v1.7.0 // indirect github.com/Azure/azure-sdk-for-go/sdk/internal v1.3.0 // indirect + github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 // indirect + github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358 // indirect github.com/AzureAD/microsoft-authentication-library-for-go v1.0.0 // indirect + github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5 // indirect github.com/VividCortex/ewma v1.2.0 // indirect github.com/andybalholm/brotli v1.0.5 // indirect github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.4.10 // indirect @@ -102,42 +120,71 @@ require ( github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect github.com/bits-and-blooms/bitset v1.8.0 // indirect github.com/bits-and-blooms/bloom/v3 v3.5.0 // indirect + github.com/bytedance/sonic v1.8.0 // indirect + github.com/cenkalti/backoff/v4 v4.2.1 // indirect + github.com/cespare/xxhash/v2 v2.2.0 // indirect github.com/cheggaaa/pb/v3 v3.1.4 // indirect + github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 // indirect github.com/cloudflare/cfssl v1.6.4 // indirect github.com/cloudflare/circl v1.3.3 // indirect + github.com/containerd/continuity v0.4.2 // indirect + github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect github.com/dlclark/regexp2 v1.10.0 // indirect + github.com/docker/cli v24.0.5+incompatible // indirect + github.com/docker/docker v24.0.5+incompatible // indirect + github.com/docker/go-connections v0.4.0 // indirect github.com/fatih/color v1.15.0 // indirect + github.com/free5gc/util v1.0.5-0.20230511064842-2e120956883b // indirect github.com/gabriel-vasile/mimetype v1.4.2 // indirect github.com/gaukas/godicttls v0.0.4 // indirect + github.com/geoffgarside/ber v1.1.0 // indirect + github.com/gin-contrib/sse v0.1.0 // indirect + github.com/gin-gonic/gin v1.9.0 // indirect + github.com/go-asn1-ber/asn1-ber v1.5.4 // indirect github.com/go-sourcemap/sourcemap v2.1.3+incompatible // indirect + github.com/goccy/go-json v0.10.0 // indirect + github.com/gogo/protobuf v1.3.2 // indirect + github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe // indirect + github.com/golang-sql/sqlexp v0.1.0 // indirect github.com/google/certificate-transparency-go v1.1.4 // indirect github.com/google/go-github/v30 v30.1.0 // indirect github.com/google/pprof v0.0.0-20230821062121-407c9e7a662f // indirect + github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect + github.com/hashicorp/go-uuid v1.0.2 // indirect github.com/hashicorp/go-version v1.6.0 // indirect github.com/hashicorp/golang-lru/v2 v2.0.6 // indirect github.com/hbakhtiyor/strsim v0.0.0-20190107154042-4d2bbb273edf // indirect + github.com/jcmturner/aescts/v2 v2.0.0 // indirect + github.com/jcmturner/dnsutils/v2 v2.0.0 // indirect + github.com/jcmturner/gofork v1.0.0 // indirect + github.com/jcmturner/rpc/v2 v2.0.2 // indirect + github.com/jinzhu/inflection v1.0.0 // indirect github.com/jmespath/go-jmespath v0.4.0 // indirect - github.com/kataras/jwt v0.1.8 // indirect + github.com/kataras/jwt v0.1.10 // indirect github.com/kylelemons/godebug v1.1.0 // indirect github.com/lucasb-eyer/go-colorful v1.2.0 // indirect github.com/mackerelio/go-osstat v0.2.4 // indirect github.com/minio/selfupdate v0.6.0 // indirect github.com/mitchellh/go-homedir v1.1.0 // indirect + github.com/mitchellh/mapstructure v1.5.0 // indirect + github.com/moby/term v0.5.0 // indirect github.com/muesli/reflow v0.3.0 // indirect github.com/muesli/termenv v0.15.1 // indirect + github.com/opencontainers/go-digest v1.0.0 // indirect + github.com/opencontainers/image-spec v1.0.2 // indirect + github.com/opencontainers/runc v1.1.9 // indirect + github.com/pelletier/go-toml/v2 v2.0.6 // indirect github.com/pjbgf/sha1cd v0.3.0 // indirect github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 // indirect github.com/projectdiscovery/asnmap v1.0.4 // indirect github.com/projectdiscovery/cdncheck v1.0.9 // indirect github.com/projectdiscovery/freeport v0.0.5 // indirect - github.com/projectdiscovery/gostruct v0.0.1 // indirect github.com/quic-go/quic-go v0.38.1 // indirect github.com/refraction-networking/utls v1.5.2 // indirect - github.com/sashabaranov/go-openai v1.14.2 // indirect github.com/shoenig/go-m1cpu v0.1.6 // indirect + github.com/sirupsen/logrus v1.9.3 // indirect github.com/skeema/knownhosts v1.1.1 // indirect github.com/smartystreets/assertions v1.0.0 // indirect - github.com/smartystreets/goconvey v1.6.4 // indirect github.com/tidwall/btree v1.6.0 // indirect github.com/tidwall/buntdb v1.3.0 // indirect github.com/tidwall/gjson v1.16.0 // indirect @@ -146,12 +193,20 @@ require ( github.com/tidwall/pretty v1.2.1 // indirect github.com/tidwall/rtred v0.1.2 // indirect github.com/tidwall/tinyqueue v0.1.1 // indirect + github.com/tim-ywliu/nested-logrus-formatter v1.3.2 // indirect + github.com/twitchyliquid64/golang-asm v0.15.1 // indirect + github.com/ugorji/go/codec v1.2.9 // indirect + github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb // indirect + github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect + github.com/xeipuuv/gojsonschema v1.2.0 // indirect github.com/ysmood/fetchup v0.2.3 // indirect github.com/ysmood/got v0.34.1 // indirect github.com/yuin/goldmark v1.5.4 // indirect github.com/yuin/goldmark-emoji v1.0.1 // indirect github.com/zeebo/blake3 v0.2.3 // indirect + golang.org/x/arch v0.0.0-20210923205945-b76863e36670 // indirect gopkg.in/djherbis/times.v1 v1.3.0 // indirect + mellium.im/sasl v0.3.1 // indirect ) require ( @@ -217,16 +272,16 @@ require ( github.com/ysmood/leakless v0.8.0 // indirect github.com/yusufpapurcu/wmi v1.2.3 // indirect github.com/zmap/rc2 v0.0.0-20190804163417-abaa70531248 // indirect - github.com/zmap/zcrypto v0.0.0-20230814193918-dbe676986518 // indirect + github.com/zmap/zcrypto v0.0.0-20230829152017-3b5d61809233 // indirect go.etcd.io/bbolt v1.3.7 // indirect go.uber.org/zap v1.25.0 // indirect goftp.io/server/v2 v2.0.1 // indirect - golang.org/x/crypto v0.12.0 - golang.org/x/exp v0.0.0-20230817173708-d852ddb80c63 + golang.org/x/crypto v0.13.0 + golang.org/x/exp v0.0.0-20230905200255-921286631fa9 golang.org/x/mod v0.12.0 // indirect - golang.org/x/sys v0.11.0 // indirect + golang.org/x/sys v0.12.0 // indirect golang.org/x/time v0.3.0 // indirect - golang.org/x/tools v0.12.1-0.20230815132531-74c255bcf846 // indirect + golang.org/x/tools v0.13.0 // indirect google.golang.org/appengine v1.6.7 // indirect google.golang.org/protobuf v1.31.0 // indirect gopkg.in/alecthomas/kingpin.v2 v2.2.6 // indirect @@ -234,7 +289,7 @@ require ( ) require ( - github.com/Microsoft/go-winio v0.5.2 // indirect + github.com/Microsoft/go-winio v0.6.1 // indirect github.com/ProtonMail/go-crypto v0.0.0-20230518184743-7afd39499903 // indirect github.com/acomagu/bufpipe v1.0.4 // indirect github.com/alecthomas/chroma v0.10.0 @@ -247,11 +302,12 @@ require ( github.com/aws/aws-sdk-go-v2/service/ssooidc v1.14.13 // indirect github.com/aws/aws-sdk-go-v2/service/sts v1.19.3 // indirect github.com/aws/smithy-go v1.13.5 // indirect + github.com/dop251/goja_nodejs v0.0.0-20230821135201-94e508132562 github.com/emirpasic/gods v1.18.1 // indirect github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect github.com/go-git/go-billy/v5 v5.4.1 // indirect github.com/golang-jwt/jwt v3.2.2+incompatible // indirect - github.com/imdario/mergo v0.3.15 // indirect + github.com/imdario/mergo v0.3.16 // indirect github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect github.com/kevinburke/ssh_config v1.2.0 // indirect github.com/labstack/gommon v0.4.0 // indirect diff --git a/v2/go.sum b/v2/go.sum index ce1fe11e53..4db66f16b2 100644 --- a/v2/go.sum +++ b/v2/go.sum @@ -1,43 +1,92 @@ aead.dev/minisign v0.2.0 h1:kAWrq/hBRu4AARY6AlciO83xhNnW9UaC8YipS2uhLPk= aead.dev/minisign v0.2.0/go.mod h1:zdq6LdSd9TbuSxchxwhpA9zEb9YXcVGoE8JakuiGaIQ= +cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= +cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= +cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= +cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= +cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= +cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To= +cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4= +cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M= +cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc= +cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk= +cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs= +cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc= +cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY= +cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= +cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= +cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= +cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg= +cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc= +cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= cloud.google.com/go/compute/metadata v0.2.0/go.mod h1:zFmK7XCadkQkj6TtorcaGlCW1hT1fIilQDwofLpJ20k= +cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= +cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= +cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= +cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= +cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= +cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU= +cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= +cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos= +cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= +cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= +cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= +dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= git.mills.io/prologic/smtpd v0.0.0-20210710122116-a525b76c287a h1:3i+FJ7IpSZHL+VAjtpQeZCRhrpP0odl5XfoLBY4fxJ8= git.mills.io/prologic/smtpd v0.0.0-20210710122116-a525b76c287a/go.mod h1:C7hXLmFmPYPjIDGfQl1clsmQ5TMEQfmzWTrJk475bUs= +github.com/Azure/azure-sdk-for-go/sdk/azcore v0.19.0/go.mod h1:h6H6c8enJmmocHUbLiiGY6sx7f9i+X3m1CHdd5c6Rdw= github.com/Azure/azure-sdk-for-go/sdk/azcore v1.7.0 h1:8q4SaHjFsClSvuVne0ID/5Ka8u3fcIHyqkLjcFpNRHQ= github.com/Azure/azure-sdk-for-go/sdk/azcore v1.7.0/go.mod h1:bjGvMhVMb+EEm3VRNQawDMUyMMjo+S5ewNjflkep/0Q= +github.com/Azure/azure-sdk-for-go/sdk/azidentity v0.11.0/go.mod h1:HcM1YX14R7CJcghJGOYCgdezslRSVzqwLf/q+4Y2r/0= github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.3.0 h1:vcYCAze6p19qBW7MhZybIsqD8sMV8js0NyQM8JDnVtg= github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.3.0/go.mod h1:OQeznEEkTZ9OrhHJoDD8ZDq51FHgXjqtP9z6bEwBq9U= +github.com/Azure/azure-sdk-for-go/sdk/internal v0.7.0/go.mod h1:yqy467j36fJxcRV2TzfVZ1pCb5vxm4BtZPUdYWe/Xo8= github.com/Azure/azure-sdk-for-go/sdk/internal v1.3.0 h1:sXr+ck84g/ZlZUOZiNELInmMgOsuGwdjjVkEIde0OtY= github.com/Azure/azure-sdk-for-go/sdk/internal v1.3.0/go.mod h1:okt5dMMTOFjX/aovMlrjvvXoPMBVSPzk9185BT0+eZM= github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/storage/armstorage v1.2.0 h1:Ma67P/GGprNwsslzEH6+Kb8nybI8jpDTm4Wmzu2ReK8= github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.1.0 h1:nVocQV40OQne5613EeLayJiRAJuKlBGy+m22qWG+WRg= github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.1.0/go.mod h1:7QJP7dr2wznCMeqIrhMgWGf7XpAQnVrJqDm9nvV3Cu4= +github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 h1:L/gRVlceqvL25UVaW/CKtUDjefjrs0SPonmDGUVOYP0= +github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= +github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358 h1:mFRzDkZVAjdal+s7s0MwaRv9igoPqLRdzOLzw/8Xvq8= +github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358/go.mod h1:chxPXzSsl7ZWRAuOIE23GDNzjWuZquvFlgA8xmpunjU= github.com/AzureAD/microsoft-authentication-library-for-go v1.0.0 h1:OBhqkivkhkMqLPymWEppkm7vgPQY2XsHoEkaMQ0AdZY= github.com/AzureAD/microsoft-authentication-library-for-go v1.0.0/go.mod h1:kgDmCTgBzIEPFElEF+FK0SdjAor06dRq2Go927dnQ6o= +github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/DataDog/gostackparse v0.6.0 h1:egCGQviIabPwsyoWpGvIBGrEnNWez35aEO7OJ1vBI4o= github.com/DataDog/gostackparse v0.6.0/go.mod h1:lTfqcJKqS9KnXQGnyQMCugq3u1FP6UZMfWR0aitKFMM= github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible h1:1G1pk05UrOh0NlF1oeaaix1x8XzrfjIDK47TY0Zehcw= github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0= github.com/Masterminds/semver/v3 v3.2.1 h1:RN9w6+7QoMeJVGyfmbcgs28Br8cvmnucEXnY0rYXWg0= github.com/Masterminds/semver/v3 v3.2.1/go.mod h1:qvl/7zhW3nngYb5+80sSMF+FG2BjYrf8m9wsX0PNOMQ= -github.com/Microsoft/go-winio v0.5.2 h1:a9IhgEQBCUEk6QCdml9CiJGhAws+YwffDHEMp1VMrpA= github.com/Microsoft/go-winio v0.5.2/go.mod h1:WpS1mjBmmwHBEWmogvA2mj8546UReBk4v8QkMxJ6pZY= +github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow= +github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM= github.com/Mzack9999/gcache v0.0.0-20230410081825-519e28eab057 h1:KFac3SiGbId8ub47e7kd2PLZeACxc1LkiiNoDOFRClE= github.com/Mzack9999/gcache v0.0.0-20230410081825-519e28eab057/go.mod h1:iLB2pivrPICvLOuROKmlqURtFIEsoJZaMidQfCG1+D4= github.com/Mzack9999/go-http-digest-auth-client v0.6.1-0.20220414142836-eb8883508809 h1:ZbFL+BDfBqegi+/Ssh7im5+aQfBRx6it+kHnC7jaDU8= github.com/Mzack9999/go-http-digest-auth-client v0.6.1-0.20220414142836-eb8883508809/go.mod h1:upgc3Zs45jBDnBT4tVRgRcgm26ABpaP7MoTSdgysca4= github.com/Mzack9999/ldapserver v1.0.2-0.20211229000134-b44a0d6ad0dd h1:RTWs+wEY9efxTKK5aFic5C5KybqQelGcX+JdM69KoTo= github.com/Mzack9999/ldapserver v1.0.2-0.20211229000134-b44a0d6ad0dd/go.mod h1:AqtPw7WNT0O69k+AbPKWVGYeW94TqgMW/g+Ppc8AZr4= +github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5 h1:TngWCqHvy9oXAN6lEVMRuU21PR1EtLVZJmdB18Gu3Rw= +github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5/go.mod h1:lmUJ/7eu/Q8D7ML55dXQrVaamCz2vxCfdQBasLZfHKk= github.com/ProtonMail/go-crypto v0.0.0-20230217124315-7d5c6f04bbb8/go.mod h1:I0gYDMZ6Z5GRU7l58bNFSkPTFN6Yl12dsUlAZ8xy98g= github.com/ProtonMail/go-crypto v0.0.0-20230518184743-7afd39499903 h1:ZK3C5DtzV2nVAQTx5S5jQvMeDqWtD1By5mOoyY/xJek= github.com/ProtonMail/go-crypto v0.0.0-20230518184743-7afd39499903/go.mod h1:8TI4H3IbrackdNgv+92dI+rhpCaLqM0IfpgCgenFvRE= github.com/PuerkitoBio/goquery v1.8.1 h1:uQxhNlArOIdbrH1tr0UXwdVFgDcZDrZVdcpygAcwmWM= github.com/PuerkitoBio/goquery v1.8.1/go.mod h1:Q8ICL1kNUJ2sXGoAhPGUdYDJvgQgHzJsnnd3H7Ho5jQ= github.com/RumbleDiscovery/rumble-tools v0.0.0-20201105153123-f2adbb3244d2/go.mod h1:jD2+mU+E2SZUuAOHZvZj4xP4frlOo+N/YrXDvASFhkE= +github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo= +github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI= github.com/VividCortex/ewma v1.2.0 h1:f58SaIzcDXrSy3kWaHNvuJgJ3Nmz59Zji6XoJR/q1ow= github.com/VividCortex/ewma v1.2.0/go.mod h1:nz4BbCtbLyFDeC9SUHbtcT5644juEuWfUAUnGx7j5l4= +github.com/VividCortex/gohistogram v1.0.0/go.mod h1:Pf5mBqqDxYaXu3hDrrU+w6nw50o/4+TcAqDqk/vUH7g= github.com/acomagu/bufpipe v1.0.4 h1:e3H4WUzM3npvo5uv95QuJM3cQspFNtFBzvJ2oNjKIDQ= github.com/acomagu/bufpipe v1.0.4/go.mod h1:mxdxdup/WdsKVreO5GpW4+M/1CE2sMG4jeGJ2sYmHc4= +github.com/afex/hystrix-go v0.0.0-20180502004556-fa1af6a1f4f5/go.mod h1:SkGFH1ia65gfNATL8TAiHDNxPzPdmEL5uirI2Uyuz6c= github.com/akrylysov/pogreb v0.10.1 h1:FqlR8VR7uCbJdfUob916tPM+idpKgeESDXOA1K0DK4w= github.com/akrylysov/pogreb v0.10.1/go.mod h1:pNs6QmpQ1UlTJKDezuRWmaqkgUE2TuU0YTWyqJZ7+lI= github.com/alcortesm/tgz v0.0.0-20161220082320-9c5fe88206d7 h1:uSoVVbwJiQipAclBbw+8quDsfcvFjOpI5iCf4p/cqCs= @@ -46,11 +95,17 @@ github.com/alecthomas/chroma v0.10.0 h1:7XDcGkCQopCNKjZHfYrNLraA+M7e0fMiJ/Mfikbf github.com/alecthomas/chroma v0.10.0/go.mod h1:jtJATyUxlIORhUOFNA9NZDWGAQ8wpxQQqNSB4rjA/1s= github.com/alecthomas/jsonschema v0.0.0-20211022214203-8b29eab41725 h1:NjwIgLQlD46o79bheVG4SCdRnnOz4XtgUN1WABX5DLA= github.com/alecthomas/jsonschema v0.0.0-20211022214203-8b29eab41725/go.mod h1:/n6+1/DWPltRLWL/VKyUxg6tzsl5kHUCcraimt4vr60= +github.com/alecthomas/kingpin/v2 v2.3.1/go.mod h1:oYL5vtsvEHZGHxU7DMp32Dvx+qL+ptGn6lWaot2vCNE= +github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751 h1:JYp7IbQjafoB+tBA3gMyHYHrpOtNuDiK/uB5uXxq5wM= github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= +github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= +github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137 h1:s6gZFSlWYmbqAuRjVTiNNhvNRfY2Wxp9nhfyel4rklc= github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137/go.mod h1:OMCwj8VM1Kc9e19TLln2VL61YJF0x1XFtfdL4JdbSyE= +github.com/alexbrainman/sspi v0.0.0-20210105120005-909beea2cc74 h1:Kk6a4nehpJ3UuJRqlA3JxYxBZEqCeOmATOvrbT4p9RA= +github.com/alexbrainman/sspi v0.0.0-20210105120005-909beea2cc74/go.mod h1:cEWa1LVoE5KvSD9ONXsZrj0z6KqySlCCNKHlLzbqAt4= github.com/andybalholm/brotli v1.0.5 h1:8uQZIdzKmjc/iuPu7O2ioW48L81FgatrcpfFmiq/cCs= github.com/andybalholm/brotli v1.0.5/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig= github.com/andybalholm/cascadia v1.3.1 h1:nhxRkql1kdYCc8Snf7D5/D3spOX+dBgjA6u8x004T2c= @@ -65,10 +120,19 @@ github.com/antchfx/xmlquery v1.3.15 h1:aJConNMi1sMha5G8YJoAIF5P+H+qG1L73bSItWHo8 github.com/antchfx/xmlquery v1.3.15/go.mod h1:zMDv5tIGjOxY/JCNNinnle7V/EwthZ5IT8eeCGJKRWA= github.com/antchfx/xpath v1.2.3 h1:CCZWOzv5bAqjVv0offZ2LVgVYFbeldKQVuLNbViZdes= github.com/antchfx/xpath v1.2.3/go.mod h1:i54GszH55fYfBmoZXapTHN8T8tkcHfRgLyVwwqzXNcs= +github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= +github.com/apache/thrift v0.13.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= +github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= +github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= +github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio= github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= +github.com/aryann/difflib v0.0.0-20170710044230-e206f873d14a/go.mod h1:DAHtR1m6lCRdSC2Tm3DSWRPvIPr6xNKyeHdqDQSQT+A= github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 h1:DklsrG3dyBCFEj5IhUbnKptjxatkF07cF2ak3yi77so= github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw= +github.com/aws/aws-lambda-go v1.13.3/go.mod h1:4UKl9IzQMoD+QF79YdCuzCwp8VbmG4VAQwij/eHl5CU= +github.com/aws/aws-sdk-go v1.27.0/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= +github.com/aws/aws-sdk-go-v2 v0.18.0/go.mod h1:JWVYvqSMppoMJC0x5wdwiImzgXTI9FuZwxzkQq9wy+g= github.com/aws/aws-sdk-go-v2 v1.19.0 h1:klAT+y3pGFBU/qVf1uzwttpBbiuozJYWzNLHioyDJ+k= github.com/aws/aws-sdk-go-v2 v1.19.0/go.mod h1:uzbQtefpm44goOPmdKyAlXSNcwlRgF3ePWVW6EtJvvw= github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.4.10 h1:dK82zF6kkPeCo8J1e+tGx4JdvDIQzj7ygIoLg8WMuGs= @@ -113,73 +177,150 @@ github.com/aymanbagabas/go-osc52/v2 v2.0.1/go.mod h1:uYgXzlJ7ZpABp8OJ+exZzJJhRNQ github.com/aymerick/douceur v0.2.0 h1:Mv+mAeH1Q+n9Fr+oyamOlAkUNPWPlA8PPGR0QAaYuPk= github.com/aymerick/douceur v0.2.0/go.mod h1:wlT5vV2O3h55X9m7iVYN0TBM0NH/MmbLnd30/FjWUq4= github.com/benbjohnson/clock v1.3.0 h1:ip6w0uFQkncKQ979AypyG0ER7mqUSBdKLOgAle/AT8A= +github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= +github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= +github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= +github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= github.com/bits-and-blooms/bitset v1.8.0 h1:FD+XqgOZDUxxZ8hzoBFuV9+cGWY9CslN6d5MS5JVb4c= github.com/bits-and-blooms/bitset v1.8.0/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8= github.com/bits-and-blooms/bloom/v3 v3.5.0 h1:AKDvi1V3xJCmSR6QhcBfHbCN4Vf8FfxeWkMNQfmAGhY= github.com/bits-and-blooms/bloom/v3 v3.5.0/go.mod h1:Y8vrn7nk1tPIlmLtW2ZPV+W7StdVMor6bC1xgpjMZFs= github.com/bluele/gcache v0.0.2 h1:WcbfdXICg7G/DGBh1PFfcirkWOQV+v077yF1pSy3DGw= github.com/bluele/gcache v0.0.2/go.mod h1:m15KV+ECjptwSPxKhOhQoAFQVtUFjTVkc3H8o0t/fp0= +github.com/bsm/ginkgo/v2 v2.9.5 h1:rtVBYPs3+TC5iLUVOis1B9tjLTup7Cj5IfzosKtvTJ0= +github.com/bsm/gomega v1.26.0 h1:LhQm+AFcgV2M0WyKroMASzAzCAJVpAxQXv4SaI9a69Y= github.com/bwesterb/go-ristretto v1.2.0/go.mod h1:fUIoIZaG73pV5biE2Blr2xEzDoMj7NFEuV9ekS419A0= +github.com/bytedance/sonic v1.5.0/go.mod h1:ED5hyg4y6t3/9Ku1R6dU/4KyJ48DZ4jPhfY1O2AihPM= +github.com/bytedance/sonic v1.8.0 h1:ea0Xadu+sHlu7x5O3gKhRpQ1IKiMrSiHttPF0ybECuA= +github.com/bytedance/sonic v1.8.0/go.mod h1:i736AoUSYt75HyZLoJW9ERYxcy6eaN6h4BZXU064P/U= github.com/caddyserver/certmagic v0.19.2 h1:HZd1AKLx4592MalEGQS39DKs2ZOAJCEM/xYPMQ2/ui0= github.com/caddyserver/certmagic v0.19.2/go.mod h1:fsL01NomQ6N+kE2j37ZCnig2MFosG+MIO4ztnmG/zz8= +github.com/casbin/casbin/v2 v2.1.2/go.mod h1:YcPU1XXisHhLzuxH9coDNf2FbKpjGlbCg3n9yuLkIJQ= +github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM= +github.com/cenkalti/backoff/v4 v4.2.1 h1:y4OZtCnogmCPw98Zjyt5a6+QwPLGkiQsYW5oUqylYbM= +github.com/cenkalti/backoff/v4 v4.2.1/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= +github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= +github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/charmbracelet/glamour v0.6.0 h1:wi8fse3Y7nfcabbbDuwolqTqMQPMnVPeZhDM273bISc= github.com/charmbracelet/glamour v0.6.0/go.mod h1:taqWV4swIMMbWALc0m7AfE9JkPSU8om2538k9ITBxOc= github.com/cheggaaa/pb/v3 v3.1.4 h1:DN8j4TVVdKu3WxVwcRKu0sG00IIU6FewoABZzXbRQeo= github.com/cheggaaa/pb/v3 v3.1.4/go.mod h1:6wVjILNBaXMs8c21qRiaUM8BR82erfgau1DQ4iUXmSA= +github.com/chenzhuoyu/base64x v0.0.0-20211019084208-fb5309c8db06/go.mod h1:DH46F32mSOjUmXrMHnKwZdA8wcEefY7UVqBKYGjpdQY= +github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 h1:qSGYFH7+jGhDF8vLC+iwCD4WpbV1EBDSzWkJODFLams= +github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311/go.mod h1:b583jCggY9gE99b6G5LEC39OIiVsWj+R97kbl5odCEk= +github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= github.com/chzyer/logex v1.2.0/go.mod h1:9+9sk7u7pGNWYMkh0hdiL++6OeibzJccyQU4p4MedaY= +github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= github.com/chzyer/readline v1.5.0/go.mod h1:x22KAscuvRqlLoK9CsoYsmxoXZMMFVyOl86cAH8qUic= +github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= github.com/chzyer/test v0.0.0-20210722231415-061457976a23/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= +github.com/clbanning/x2j v0.0.0-20191024224557-825249438eec/go.mod h1:jMjuTZXRI4dUb/I5gc9Hdhagfvm9+RyrPryS/auMzxE= +github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cloudflare/cfssl v1.6.4 h1:NMOvfrEjFfC63K3SGXgAnFdsgkmiq4kATme5BfcqrO8= github.com/cloudflare/cfssl v1.6.4/go.mod h1:8b3CQMxfWPAeom3zBnGJ6sd+G1NkL5TXqmDXacb+1J0= github.com/cloudflare/circl v1.1.0/go.mod h1:prBCrKB9DV4poKZY1l9zBXg2QJY7mvgRvtMxxK7fi4I= github.com/cloudflare/circl v1.3.3 h1:fE/Qz0QdIGqeWfnwq0RE0R7MI51s0M2E4Ga9kq5AEMs= github.com/cloudflare/circl v1.3.3/go.mod h1:5XYMA4rFBvNIrhs50XuiBJ15vF2pZn4nnUKZrLbUZFA= +github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/cnf/structhash v0.0.0-20201127153200-e1b16c1ebc08 h1:ox2F0PSMlrAAiAdknSRMDrAr8mfxPCfSZolH+/qQnyQ= github.com/cnf/structhash v0.0.0-20201127153200-e1b16c1ebc08/go.mod h1:pCxVEbcm3AMg7ejXyorUXi6HQCzOIBf7zEDVPtw0/U4= +github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8= +github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI= +github.com/containerd/continuity v0.4.2 h1:v3y/4Yz5jwnvqPKJJ+7Wf93fyWoCB3F5EclWG023MDM= +github.com/containerd/continuity v0.4.2/go.mod h1:F6PTNCKepoxEaXLQp3wDAjygEnImnZ/7o4JzpodfroQ= +github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= +github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= +github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= github.com/corpix/uarand v0.2.0 h1:U98xXwud/AVuCpkpgfPF7J5TQgr7R5tqT8VZP5KWbzE= github.com/corpix/uarand v0.2.0/go.mod h1:/3Z1QIqWkDIhf6XWn/08/uMHoQ8JUoTIKc2iPchBOmM= +github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= +github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/denisenkom/go-mssqldb v0.12.3 h1:pBSGx9Tq67pBOTLmxNuirNTeB8Vjmf886Kx+8Y+8shw= +github.com/denisenkom/go-mssqldb v0.12.3/go.mod h1:k0mtMFOnU+AihqFxPMiF05rtiDrorD1Vrm1KEz5hxDo= +github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= +github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78= +github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc= github.com/dimchansky/utfbom v1.1.1 h1:vV6w1AhK4VMnhBno/TPVCoK9U/LP0PkLCS9tbxHdi/U= github.com/dimchansky/utfbom v1.1.1/go.mod h1:SxdoEBH5qIqFocHMyGOXVAybYJdr71b1Q/j0mACtrfE= +github.com/ditashi/jsbeautifier-go v0.0.0-20141206144643-2520a8026a9c h1:+Zo5Ca9GH0RoeVZQKzFJcTLoAixx5s5Gq3pTIS+n354= +github.com/ditashi/jsbeautifier-go v0.0.0-20141206144643-2520a8026a9c/go.mod h1:HJGU9ULdREjOcVGZVPB5s6zYmHi1RxzT71l2wQyLmnE= github.com/dlclark/regexp2 v1.4.0/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc= github.com/dlclark/regexp2 v1.4.1-0.20201116162257-a2a8dda75c91/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc= github.com/dlclark/regexp2 v1.7.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8= github.com/dlclark/regexp2 v1.10.0 h1:+/GIL799phkJqYW+3YbOd8LCcbHzT0Pbo8zl70MHsq0= github.com/dlclark/regexp2 v1.10.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8= github.com/dnaeon/go-vcr v1.2.0 h1:zHCHvJYTMh1N7xnV7zf1m1GPBF9Ad0Jk/whtQ1663qI= +github.com/dnaeon/go-vcr v1.2.0/go.mod h1:R4UdLID7HZT3taECzJs4YgbbH6PIGXB6W/sc5OLb6RQ= +github.com/docker/cli v24.0.5+incompatible h1:WeBimjvS0eKdH4Ygx+ihVq1Q++xg36M/rMi4aXAvodc= +github.com/docker/cli v24.0.5+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= +github.com/docker/docker v24.0.5+incompatible h1:WmgcE4fxyI6EEXxBRxsHnZXrO1pQ3smi0k/jho4HLeY= +github.com/docker/docker v24.0.5+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ= +github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec= github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= github.com/dop251/goja v0.0.0-20211022113120-dc8c55024d06/go.mod h1:R9ET47fwRVRPZnOGvHxxhuZcbrMCuiqOz3Rlrh4KSnk= -github.com/dop251/goja v0.0.0-20230812105242-81d76064690d h1:9aaGwVf4q+kknu+mROAXUApJ1DoOwhE8dGj/XLBYzWg= -github.com/dop251/goja v0.0.0-20230812105242-81d76064690d/go.mod h1:QMWlm50DNe14hD7t24KEqZuUdC9sOTy8W6XbCU1mlw4= +github.com/dop251/goja v0.0.0-20230531210528-d7324b2d74f7/go.mod h1:QMWlm50DNe14hD7t24KEqZuUdC9sOTy8W6XbCU1mlw4= +github.com/dop251/goja v0.0.0-20230828202809-3dbe69dd2b8e h1:UvQD6hTSfeM6hhTQ24Dlw2RppP05W7SWbWb6kubJAog= +github.com/dop251/goja v0.0.0-20230828202809-3dbe69dd2b8e/go.mod h1:QMWlm50DNe14hD7t24KEqZuUdC9sOTy8W6XbCU1mlw4= github.com/dop251/goja_nodejs v0.0.0-20210225215109-d91c329300e7/go.mod h1:hn7BA7c8pLvoGndExHudxTDKZ84Pyvv+90pbBjbTz0Y= github.com/dop251/goja_nodejs v0.0.0-20211022123610-8dd9abb0616d/go.mod h1:DngW8aVqWbuLRMHItjPUyqdj+HWPvnQe8V8y1nDpIbM= +github.com/dop251/goja_nodejs v0.0.0-20230821135201-94e508132562 h1:ObbB2tzHWWAxzsG5futqeq2Ual2zYlo/+eMkSc5sn8w= +github.com/dop251/goja_nodejs v0.0.0-20230821135201-94e508132562/go.mod h1:X2TOTJ+Uamd454RFp7ig2tmP3hQg0Z2Qk8gbVQmU0mk= github.com/dsnet/compress v0.0.1 h1:PlZu0n3Tuv04TzpfPbrnI0HW/YwodEXDS+oPKahKF0Q= github.com/dsnet/compress v0.0.1/go.mod h1:Aw8dCMJ7RioblQeTqt88akK31OvO8Dhf5JflhBbQEHo= github.com/dsnet/golib v0.0.0-20171103203638-1ea166775780/go.mod h1:Lj+Z9rebOhdfkVLjJ8T6VcRQv3SXugXy999NBtR9aFY= +github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= +github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs= +github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU= +github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I= +github.com/edsrzf/mmap-go v1.0.0/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M= github.com/elazarl/goproxy v0.0.0-20221015165544-a0805db90819 h1:RIB4cRk+lBqKK3Oy0r2gRX4ui7tuhiZq2SuTtTCi0/0= github.com/emirpasic/gods v1.12.0/go.mod h1:YfzfFFoVP/catgzJb4IKIqXjX78Ha8FMSDh3ymbK86o= github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc= github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ= +github.com/envoyproxy/go-control-plane v0.6.9/go.mod h1:SBwIajubJHhxtWwsL9s8ss4safvEdbitLhGGK48rN6g= +github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= +github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= +github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= github.com/fatih/color v1.15.0 h1:kOqh6YHBtK8aywxGerMG2Eq3H6Qgoqeo13Bk2Mv/nBs= github.com/fatih/color v1.15.0/go.mod h1:0h5ZqXfHYED7Bhv2ZJamyIOUej9KtShiJESRwBDUSsw= github.com/fatih/structs v1.1.0 h1:Q7juDM0QtcnhCpeyLGQKyg4TOIghuNXrkL32pHAUMxo= github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M= github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc= +github.com/franela/goblin v0.0.0-20200105215937-c9ffbefa60db/go.mod h1:7dvUGVsVBjqR7JHJk0brhHOZYGmfBYOrK0ZhYMEtBr4= +github.com/franela/goreq v0.0.0-20171204163338-bcd34c9993f8/go.mod h1:ZhphrRTfi2rbfLwlschooIH4+wKKDR4Pdxhh+TRoA20= github.com/frankban/quicktest v1.14.4 h1:g2rn0vABPOOXmZUj+vbmUp0lPoXEMuhTpIluN0XL9UY= +github.com/free5gc/util v1.0.5-0.20230511064842-2e120956883b h1:XMw3j+4AEXLeL/uyiZ7/qYE1X7Ul05RTwWBhzxCLi+0= +github.com/free5gc/util v1.0.5-0.20230511064842-2e120956883b/go.mod h1:l2Jrml4vojDomW5jdDJhIS60KdbrE9uPYhyAq/7OnF4= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.5.4 h1:jRbGcIw6P2Meqdwuo0H1p6JVLbL5DHKAKlYndzMwVZI= github.com/gabriel-vasile/mimetype v1.4.2 h1:w5qFW6JKBz9Y393Y4q372O9A7cUSequkh1Q7OhCmWKU= github.com/gabriel-vasile/mimetype v1.4.2/go.mod h1:zApsH/mKG4w07erKIaJPFiX0Tsq9BFQgN3qGY5GnNgA= github.com/gaukas/godicttls v0.0.4 h1:NlRaXb3J6hAnTmWdsEKb9bcSBD6BvcIjdGdeb0zfXbk= github.com/gaukas/godicttls v0.0.4/go.mod h1:l6EenT4TLWgTdwslVb4sEMOCf7Bv0JAK67deKr9/NCI= +github.com/geoffgarside/ber v1.1.0 h1:qTmFG4jJbwiSzSXoNJeHcOprVzZ8Ulde2Rrrifu5U9w= +github.com/geoffgarside/ber v1.1.0/go.mod h1:jVPKeCbj6MvQZhwLYsGwaGI52oUorHoHKNecGT85ZCc= +github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= +github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE= +github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI= +github.com/gin-gonic/gin v1.9.0 h1:OjyFBKICoexlu99ctXNR2gg+c5pKrKMuyjgARg9qeY8= +github.com/gin-gonic/gin v1.9.0/go.mod h1:W1Me9+hsUSyj3CePGrd1/QrKJMSJ1Tu/0hFEH89961k= github.com/gliderlabs/ssh v0.2.2/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0= github.com/gliderlabs/ssh v0.3.5 h1:OcaySEmAQJgyYcArR+gGGTHCyE7nvhEMTlYY+Dp8CpY= +github.com/go-asn1-ber/asn1-ber v1.5.4 h1:vXT6d/FNDiELJnLb6hGNa309LMsrCoYFvpwHDF0+Y1A= +github.com/go-asn1-ber/asn1-ber v1.5.4/go.mod h1:hEBeB/ic+5LoWskz+yKT7vGhhPYkProFKoKdwZRWMe0= github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 h1:+zs/tPmkDkHx3U66DAb0lQFJrpS6731Oaa12ikc+DiI= github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376/go.mod h1:an3vInlBmSxCcxctByoQdvwPiA7DTK7jaaFDBTtu0ic= github.com/go-git/go-billy/v5 v5.4.1 h1:Uwp5tDRkPr+l/TnbHOQzp+tmJfLceOlbVucgpTz8ix4= @@ -187,9 +328,26 @@ github.com/go-git/go-billy/v5 v5.4.1/go.mod h1:vjbugF6Fz7JIflbVpl1hJsGjSHNltrSw4 github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20230305113008-0c11038e723f h1:Pz0DHeFij3XFhoBRGUDPzSJ+w2UcK5/0JvF8DRI58r8= github.com/go-git/go-git/v5 v5.7.0 h1:t9AudWVLmqzlo+4bqdf7GY+46SUuRsx59SboFxkq2aE= github.com/go-git/go-git/v5 v5.7.0/go.mod h1:coJHKEOk5kUClpsNlXrUvPrDxY3w3gjHvhcZd8Fodw8= +github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= +github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= +github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= +github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= +github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= +github.com/go-kit/kit v0.10.0/go.mod h1:xUsJbQ/Fp4kEt7AFgCuvyX4a71u8h9jB8tj/ORgOZ7o= +github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= +github.com/go-kit/log v0.2.0/go.mod h1:NwTd00d/i8cPZ3xOwwiv2PO5MOcx78fFErGNcVmBjv0= +github.com/go-kit/log v0.2.1/go.mod h1:NwTd00d/i8cPZ3xOwwiv2PO5MOcx78fFErGNcVmBjv0= +github.com/go-ldap/ldap/v3 v3.4.5 h1:ekEKmaDrpvR2yf5Nc/DClsGG9lAmdDixe44mLzlW5r8= +github.com/go-ldap/ldap/v3 v3.4.5/go.mod h1:bMGIq3AGbytbaMwf8wdv5Phdxz0FWHTIYMSzyrYgnQs= +github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= +github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= +github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= +github.com/go-logfmt/logfmt v0.5.1/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs= github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ= github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY= github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= +github.com/go-pg/pg v8.0.7+incompatible h1:ty/sXL1OZLo+47KK9N8llRcmbA9tZasqbQ/OO4ld53g= +github.com/go-pg/pg v8.0.7+incompatible/go.mod h1:a2oXow+aFOrvwcKs3eIA0lNFmMilrxK2sOkB5NWe0vA= github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s= github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA= github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY= @@ -201,6 +359,10 @@ github.com/go-rod/rod v0.114.0 h1:P+zLOqsj+vKf4C86SfjP6ymyPl9VXoYKm+ceCeQms6Y= github.com/go-rod/rod v0.114.0/go.mod h1:aiedSEFg5DwG/fnNbUOTPMTTWX3MRj6vIs/a684Mthw= github.com/go-sourcemap/sourcemap v2.1.3+incompatible h1:W1iEw64niKVGogNgBN3ePyLFfuisuzeidWPMPWmECqU= github.com/go-sourcemap/sourcemap v2.1.3+incompatible/go.mod h1:F8jJfvm2KbVjc5NqelyYJmf/v5J0dwNLS2mL4sNA1Jg= +github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= +github.com/go-sql-driver/mysql v1.6.0 h1:BCTh4TKNUYmOmMUcQ3IipzF5prigylS7XXjEkfCHuOE= +github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= +github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI= github.com/goburrow/cache v0.1.4 h1:As4KzO3hgmzPlnaMniZU9+VmoNYseUhuELbxy9mRBfw= github.com/goburrow/cache v0.1.4/go.mod h1:cDFesZDnIlrHoNlMYqqMpCRawuXulgx+y7mXU8HZ+/c= @@ -210,17 +372,52 @@ github.com/gobwas/pool v0.2.1 h1:xfeeEhW7pwmX8nuLVlqbzVc7udMDrwetjEv+TZIz1og= github.com/gobwas/pool v0.2.1/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw= github.com/gobwas/ws v1.2.1 h1:F2aeBZrm2NDsc7vbovKrWSogd4wvfAxg0FQ89/iqOTk= github.com/gobwas/ws v1.2.1/go.mod h1:hRKAFb8wOxFROYNsT1bqfWnhX+b5MFeJM9r2ZSwg/KY= +github.com/goccy/go-json v0.10.0 h1:mXKd9Qw4NuzShiRlOXKews24ufknHO7gx30lsDyokKA= +github.com/goccy/go-json v0.10.0/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= github.com/gofrs/uuid v3.3.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= +github.com/gogo/googleapis v1.1.0/go.mod h1:gf4bu3Q80BeJ6H1S1vYPm8/ELATdvryBaNFGgqEef3s= +github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= +github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= +github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= +github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= +github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/golang-jwt/jwt v3.2.2+incompatible h1:IfV12K8xAKAnZqdXVzCZ+TOjboZ2keLg81eXfW3O+oY= github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I= github.com/golang-jwt/jwt/v4 v4.4.2/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= github.com/golang-jwt/jwt/v4 v4.5.0 h1:7cYmW1XlMY7h7ii7UhUyChSgS5wUJEnm9uZVTGqOWzg= github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= +github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe h1:lXe2qZdvpiX5WZkZR4hgp4KJVfY3nMkvmwbVkpv1rVY= +github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0= +github.com/golang-sql/sqlexp v0.1.0 h1:ZCD6MBpcuOVfGVqsEmY5/4FtYiKz6tSyUv9LPEDei6A= +github.com/golang-sql/sqlexp v0.1.0/go.mod h1:J4ad9Vo8ZCWQ2GMrC4UCQy1JpCbwU9m3EOqtpKwwwHI= +github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= +github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= +github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= +github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= +github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= +github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= +github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= +github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= +github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= +github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= @@ -228,10 +425,19 @@ github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiu github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= +github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/certificate-transparency-go v1.1.4 h1:hCyXHDbtqlr/lMXU0D4WgbalXL0Zk4dSWWMbPV8VrqY= github.com/google/certificate-transparency-go v1.1.4/go.mod h1:D6lvbfwckhNrbM9WVl1EVeMOyzC19mpIjMOI4nxBHtQ= +github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= @@ -246,37 +452,89 @@ github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8= github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= +github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= +github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= +github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= +github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20230207041349-798e818bf904/go.mod h1:uglQLonpP8qtYCYyzA+8c/9qtqgA3qsXGYqCPKARAFg= github.com/google/pprof v0.0.0-20230821062121-407c9e7a662f h1:pDhu5sgp8yJlEF/g6osliIIpF9K4F5jvkULXa4daRDQ= github.com/google/pprof v0.0.0-20230821062121-407c9e7a662f/go.mod h1:czg5+yv1E0ZGTi6S6vVK1mke0fV+FaUhNGcd6VRS9Ik= +github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= +github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4= +github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ= +github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.3.1 h1:KjJaJ9iWZ3jOFZIf1Lqf4laDRCasjl0BCmnEGxkdLb4= github.com/google/uuid v1.3.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= +github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= +github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg= github.com/gorilla/css v1.0.0 h1:BQqNyPTi50JCFMTw/b67hByjMVXZRwGha6wxVGkeihY= github.com/gorilla/css v1.0.0/go.mod h1:Dn721qIggHpt4+EFCcTLTU/vk5ySda2ReITrtgBl60c= +github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= +github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= +github.com/gorilla/securecookie v1.1.1/go.mod h1:ra0sb63/xPlUeL+yeDciTfxMRAA+MP+HVt/4epWDjd4= +github.com/gorilla/sessions v1.2.0/go.mod h1:dk2InVEVJ0sfLlnXv9EAgkf6ecYs/i80K/zI+bUmuGM= +github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= +github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= +github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= +github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= github.com/h2non/filetype v1.1.3 h1:FKkx9QbD7HR/zjK1Ia5XiBsq9zdLi5Kf3zGyFTAFkGg= github.com/h2non/filetype v1.1.3/go.mod h1:319b3zT68BvV+WRj7cwy856M2ehB3HqNOt6sy1HndBY= +github.com/hashicorp/consul/api v1.3.0/go.mod h1:MmDNSzIMUjNpY/mQ398R4bk2FnqQLoPndWW5VkKPlCE= +github.com/hashicorp/consul/sdk v0.3.0/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= +github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= +github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ= github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48= github.com/hashicorp/go-hclog v0.9.2 h1:CG6TE5H9/JXsFWJCfoIVpKFIkFe6ysEuHirp4DxCsHI= github.com/hashicorp/go-hclog v0.9.2/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrjA0H7acj2lQ= +github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= +github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= +github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= github.com/hashicorp/go-retryablehttp v0.7.2 h1:AcYqCvkpalPnPF2pn0KamgwamS42TqUDDYFRKq/RAd0= github.com/hashicorp/go-retryablehttp v0.7.2/go.mod h1:Jy/gPYAdjqffZ/yFGCFV2doI5wjtH1ewM9u8iYVjtX8= +github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU= +github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU= +github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4= +github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= +github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= +github.com/hashicorp/go-uuid v1.0.2 h1:cfejS+Tpcp13yd5nYHWDI6qVCny6wyX2Mt5SGur2IGE= +github.com/hashicorp/go-uuid v1.0.2/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= +github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= github.com/hashicorp/go-version v1.6.0 h1:feTTfFNnjP967rlCxM/I9g701jU+RN74YKx2mOkIeek= github.com/hashicorp/go-version v1.6.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= +github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90= +github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru/v2 v2.0.6 h1:3xi/Cafd1NaoEnS/yDssIiuVeDVywU0QdFGl3aQaQHM= github.com/hashicorp/golang-lru/v2 v2.0.6/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM= +github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64= +github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ= +github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I= +github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc= github.com/hbakhtiyor/strsim v0.0.0-20190107154042-4d2bbb273edf h1:umfGUaWdFP2s6457fz1+xXYIWDxdGc7HdkLS9aJ1skk= github.com/hbakhtiyor/strsim v0.0.0-20190107154042-4d2bbb273edf/go.mod h1:V99KdStnMHZsvVOwIvhfcUzYgYkRZeQWUtumtL+SKxA= github.com/hdm/jarm-go v0.0.7 h1:Eq0geenHrBSYuKrdVhrBdMMzOmA+CAMLzN2WrF3eL6A= github.com/hdm/jarm-go v0.0.7/go.mod h1:kinGoS0+Sdn1Rr54OtanET5E5n7AlD6T6CrJAKDjJSQ= +github.com/hirochachacha/go-smb2 v1.1.0 h1:b6hs9qKIql9eVXAiN0M2wSFY5xnhbHAQoCwRKbaRTZI= +github.com/hirochachacha/go-smb2 v1.1.0/go.mod h1:8F1A4d5EZzrGu5R7PU163UcMRDJQl4FtcxjBfsY8TZE= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= +github.com/hudl/fargo v1.3.0/go.mod h1:y3CKSmjA+wD2gak7sUSXTAoopbhU08POFhmITJgmKTg= github.com/iancoleman/orderedmap v0.0.0-20190318233801-ac98e3ecb4b0 h1:i462o439ZjprVSFSZLZxcsoAe592sZB1rci2Z8j4wdk= github.com/iancoleman/orderedmap v0.0.0-20190318233801-ac98e3ecb4b0/go.mod h1:N0Wam8K1arqPXNWjMo21EXnBPOPp36vB07FNRdD2geA= +github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/ianlancetaylor/demangle v0.0.0-20220319035150-800ac71e25c2/go.mod h1:aYm2/VgdVmcIU8iMfdMvDMsRAQjcfZSKFby6HOFvi/w= -github.com/imdario/mergo v0.3.15 h1:M8XP7IuFNsqUx6VPK2P9OSmsYsI/YFaGil0uD21V3dM= -github.com/imdario/mergo v0.3.15/go.mod h1:WBLT9ZmE3lPoWsEzCh9LPo3TiwVN+ZKEjmz+hD27ysY= +github.com/imdario/mergo v0.3.16 h1:wwQJbIsHYGMUyLSPrEq1CT16AhnhNJQ51+4fdHUnCl4= +github.com/imdario/mergo v0.3.16/go.mod h1:WBLT9ZmE3lPoWsEzCh9LPo3TiwVN+ZKEjmz+hD27ysY= +github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= +github.com/influxdata/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo= github.com/itchyny/gojq v0.12.13 h1:IxyYlHYIlspQHHTE0f3cJF0NKDMfajxViuhBLnHd/QU= github.com/itchyny/gojq v0.12.13/go.mod h1:JzwzAqenfhrPUuwbmEz3nu3JQmFLlQTQMUcOdnu/Sf4= github.com/itchyny/timefmt-go v0.1.5 h1:G0INE2la8S6ru/ZI5JecgyzbbJNs5lG1RcBqa7Jm6GE= @@ -285,31 +543,60 @@ github.com/jarcoal/httpmock v1.0.4 h1:jp+dy/+nonJE4g4xbVtl9QdrUNbn6/3hDT5R4nDIZn github.com/jarcoal/httpmock v1.0.4/go.mod h1:ATjnClrvW/3tijVmpL/va5Z3aAyGvqU3gCT8nX0Txik= github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A= github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo= +github.com/jcmturner/aescts/v2 v2.0.0 h1:9YKLH6ey7H4eDBXW8khjYslgyqG2xZikXP0EQFKrle8= +github.com/jcmturner/aescts/v2 v2.0.0/go.mod h1:AiaICIRyfYg35RUkr8yESTqvSy7csK90qZ5xfvvsoNs= +github.com/jcmturner/dnsutils/v2 v2.0.0 h1:lltnkeZGL0wILNvrNiVCR6Ro5PGU/SeBvVO/8c/iPbo= +github.com/jcmturner/dnsutils/v2 v2.0.0/go.mod h1:b0TnjGOvI/n42bZa+hmXL+kFJZsFT7G4t3HTlQ184QM= +github.com/jcmturner/gofork v1.0.0 h1:J7uCkflzTEhUZ64xqKnkDxq3kzc96ajM1Gli5ktUem8= +github.com/jcmturner/gofork v1.0.0/go.mod h1:MK8+TM0La+2rjBD4jE12Kj1pCCxK7d2LK/UM3ncEo0o= +github.com/jcmturner/goidentity/v6 v6.0.1 h1:VKnZd2oEIMorCTsFBnJWbExfNN7yZr3EhJAxwOkZg6o= +github.com/jcmturner/goidentity/v6 v6.0.1/go.mod h1:X1YW3bgtvwAXju7V3LCIMpY0Gbxyjn/mY9zx4tFonSg= +github.com/jcmturner/rpc/v2 v2.0.2 h1:gMB4IwRXYsWw4Bc6o/az2HJgFUA1ffSh90i26ZJ6Xl0= +github.com/jcmturner/rpc/v2 v2.0.2/go.mod h1:VUJYCIDm3PVOEHw8sgt091/20OJjskO/YJki3ELg/Hc= github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= +github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E= +github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc= github.com/jlaffaye/ftp v0.0.0-20190624084859-c1312a7102bf/go.mod h1:lli8NYPQOFy3O++YmYbqVgOcQ1JPCwdOy+5zSjKJ9qY= +github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg= github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo= github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8= github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U= +github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= +github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= +github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= +github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/json-iterator/go v1.1.8/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= +github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= +github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo= github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= +github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= github.com/julienschmidt/httprouter v1.3.0 h1:U0609e9tgbseu3rBINet9P48AI/D3oJs4dN7jwJOQ1U= github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= -github.com/kataras/jwt v0.1.8 h1:u71baOsYD22HWeSOg32tCHbczPjdCk7V4MMeJqTtmGk= -github.com/kataras/jwt v0.1.8/go.mod h1:Q5j2IkcIHnfwy+oNY3TVWuEBJNw0ADgCcXK9CaZwV4o= +github.com/kataras/jwt v0.1.10 h1:GBXOF9RVInDPhCFBiDumRG9Tt27l7ugLeLo8HL5SeKQ= +github.com/kataras/jwt v0.1.10/go.mod h1:xkimAtDhU/aGlQqjwvgtg+VyuPwMiyZHaY8LJRh0mYo= github.com/kevinburke/ssh_config v0.0.0-20190725054713-01f96b0aa0cd/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM= github.com/kevinburke/ssh_config v1.2.0 h1:x584FjTGwHzMwvHx18PXxbBVzfnxogHaAReU4gf13a4= github.com/kevinburke/ssh_config v1.2.0/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM= +github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= +github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= +github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/klauspost/compress v1.4.1/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= github.com/klauspost/compress v1.16.7 h1:2mk3MPGNzKyxErAw8YaohYh69+pa4sIQSC0fPGCFR9I= github.com/klauspost/compress v1.16.7/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= github.com/klauspost/cpuid v1.2.0/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= +github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= github.com/klauspost/cpuid/v2 v2.0.12/go.mod h1:g2LTdtYhdyuGPqyWyv7qRAmj1WBqxuObKfj5c0PQa7c= github.com/klauspost/cpuid/v2 v2.2.5 h1:0E5MSMDEoAulmXNFquVs//DdoomxaoTY1kUhbc/qbZg= github.com/klauspost/cpuid/v2 v2.2.5/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= @@ -327,8 +614,12 @@ github.com/labstack/gommon v0.4.0 h1:y7cvthEAEbU0yHOf4axH8ZG2NH8knB9iNSoTO8dyIk8 github.com/labstack/gommon v0.4.0/go.mod h1:uW6kP17uPlLJsD3ijUYn3/M5bAxtlZhMI6m3MFxTMTM= github.com/leodido/go-urn v1.2.4 h1:XlAE/cm/ms7TE/VMVoduSpNBoyc2dOxHs5MZSwAN63Q= github.com/leodido/go-urn v1.2.4/go.mod h1:7ZrI8mTSeBSHl/UaRyKQW1qZeMgak41ANeCNaVckg+4= +github.com/lib/pq v1.10.1 h1:6VXZrLU0jHBYyAqrSPa+MgPfnSvTPuMgK+k0o5kVFWo= +github.com/lib/pq v1.10.1/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/libdns/libdns v0.2.1 h1:Wu59T7wSHRgtA0cfxC+n1c/e+O3upJGWytknkmFEDis= github.com/libdns/libdns v0.2.1/go.mod h1:yQCXzk1lEZmmCPa857bnk4TsOiqYasqpyOEeSObbb40= +github.com/lightstep/lightstep-tracer-common/golang/gogo v0.0.0-20190605223551-bc2310a04743/go.mod h1:qklhhLq1aX+mtWk9cPHPzaBjWImj5ULL6C7HFJtXQMM= +github.com/lightstep/lightstep-tracer-go v0.18.1/go.mod h1:jlF1pusYV4pidLvZ+XD0UBX0ZE6WURAspgAczcDHrL4= github.com/logrusorgru/aurora v2.0.3+incompatible h1:tOpm7WcpBTn4fjmVfgpQq0EfczGlG91VSDkswnjF5A8= github.com/logrusorgru/aurora v2.0.3+incompatible/go.mod h1:7rIyQOR62GCctdiQpZ/zOJlFyk6y+94wXzv6RNZgaR4= github.com/lor00x/goldap v0.0.0-20180618054307-a546dffdd1a3 h1:wIONC+HMNRqmWBjuMxhatuSzHaljStc4gjDeKycxy0A= @@ -337,21 +628,28 @@ github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69 github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0= github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 h1:6E+4a0GO5zZEnZ81pIr0yLvtUWk2if982qA3F3QD6H4= github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I= +github.com/lyft/protoc-gen-validate v0.0.13/go.mod h1:XbGvPuh87YZc5TdIa2/I4pLk0QoUACkjt2znoq26NVQ= github.com/mackerelio/go-osstat v0.2.4 h1:qxGbdPkFo65PXOb/F/nhDKpF2nGmGaCFDLXoZjJTtUs= github.com/mackerelio/go-osstat v0.2.4/go.mod h1:Zy+qzGdZs3A9cuIqmgbJvwbmLQH9dJvtio5ZjJTbdlQ= github.com/matryer/is v1.2.0 h1:92UTHpy8CDwaJ08GqLDzhhuixiBUUD1p3AU6PHddz4A= github.com/matryer/is v1.2.0/go.mod h1:2fLPjFQM9rhQ15aVEtbuwhJinnOqrmgXPNdZsdwlWXA= +github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= github.com/mattn/go-colorable v0.1.11/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= +github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= +github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA= github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= github.com/mattn/go-runewidth v0.0.12/go.mod h1:RAqKPSqVFrSLVXbA8x7dzmKdmGzieGRCM46jaSJTDAk= github.com/mattn/go-runewidth v0.0.14 h1:+xnbZSEeDbOIg5/mE6JF0w6n9duR1l3/WmbinWVwUuU= github.com/mattn/go-runewidth v0.0.14/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= +github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= +github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= github.com/mholt/acmez v1.2.0 h1:1hhLxSgY5FvH5HCnGUuwbKY2VQVo8IU7rxXKSnZ7F30= github.com/mholt/acmez v1.2.0/go.mod h1:VT9YwH1xgNX1kmYY89gY8xPJC84BFAisjo8Egigt4kE= github.com/mholt/archiver v3.1.1+incompatible h1:1dCVxuqs0dJseYEhi5pl7MYPH9zDa1wBi7mF09cbNkU= @@ -359,20 +657,35 @@ github.com/mholt/archiver v3.1.1+incompatible/go.mod h1:Dh2dOXnSdiLxRiPoVfIr/fI1 github.com/microcosm-cc/bluemonday v1.0.21/go.mod h1:ytNkv4RrDrLJ2pqlsSI46O6IVXmZOBBD4SaJyDwwTkM= github.com/microcosm-cc/bluemonday v1.0.25 h1:4NEwSfiJ+Wva0VxN5B8OwMicaJvD8r9tlJWm9rtloEg= github.com/microcosm-cc/bluemonday v1.0.25/go.mod h1:ZIOjCQp1OrzBBPIJmfX4qDYFuhU02nx4bn030ixfHLE= +github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= github.com/miekg/dns v1.1.35/go.mod h1:KNUDUusw/aVsxyTYZM1oqvCicbwhgbNgztCETuNZ7xM= -github.com/miekg/dns v1.1.55 h1:GoQ4hpsj0nFLYe+bWiCToyrBEJXkQfOOIvFGFy0lEgo= -github.com/miekg/dns v1.1.55/go.mod h1:uInx36IzPl7FYnDcMeVWxj9byh7DutNykX4G9Sj60FY= +github.com/miekg/dns v1.1.56 h1:5imZaSeoRNvpM9SzWNhEcP9QliKiz20/dA2QabIGVnE= +github.com/miekg/dns v1.1.56/go.mod h1:cRm6Oo2C8TY9ZS/TqsSrseAcncm74lfK5G+ikN2SWWY= github.com/minio/minio-go/v6 v6.0.46/go.mod h1:qD0lajrGW49lKZLtXKtCB4X/qkMf0a5tBvN2PaZg7Gg= github.com/minio/selfupdate v0.6.0 h1:i76PgT0K5xO9+hjzKcacQtO7+MjJ4JKA8Ak8XQ9DDwU= github.com/minio/selfupdate v0.6.0/go.mod h1:bO02GTIPCMQFTEvE5h4DjYB58bCoZ35XLeBf0buTDdM= github.com/minio/sha256-simd v0.1.1/go.mod h1:B5e1o+1/KgNmWrSQK08Y6Z1Vb5pwIktudl0J58iy0KM= +github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= +github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= +github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= +github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg= +github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY= +github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= +github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= +github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= +github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/moby/term v0.5.0 h1:xt8Q1nalod/v7BqbG21f8mQPqH+xAaC9C3N3wfWbVP0= +github.com/moby/term v0.5.0/go.mod h1:8FzsFHVUBGZdbDsJw/ot+X+d5HLUbvklYLJ9uGfcI3Y= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= +github.com/modocache/gover v0.0.0-20171022184752-b58185e213c5/go.mod h1:caMODM3PzxT8aQXRPkAt8xlV/e7d7w8GM5g0fa5F0D8= github.com/mreiferson/go-httpclient v0.0.0-20160630210159-31f0106b4474/go.mod h1:OQA4XLvDbMgS8P0CevmM4m9Q3Jq4phKUzcocxuGJ5m8= github.com/mreiferson/go-httpclient v0.0.0-20201222173833-5e475fde3a4d/go.mod h1:OQA4XLvDbMgS8P0CevmM4m9Q3Jq4phKUzcocxuGJ5m8= github.com/muesli/reflow v0.3.0 h1:IFsN6K9NfGtjeggFP+68I4chLZV2yIKsXJFNZ+eWh6s= @@ -380,10 +693,22 @@ github.com/muesli/reflow v0.3.0/go.mod h1:pbwTDkVPibjO2kyvBQRBxTWEEGDGq0FlB1BIKt github.com/muesli/termenv v0.13.0/go.mod h1:sP1+uffeLaEYpyOTb8pLCUctGcGLnoFjSn4YJK5e2bc= github.com/muesli/termenv v0.15.1 h1:UzuTb/+hhlBugQz28rpzey4ZuKcZ03MeKsoG7IJZIxs= github.com/muesli/termenv v0.15.1/go.mod h1:HeAQPTzpfs016yGtA4g00CsdYnVLJvxsS4ANqrZs2sQ= +github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= +github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= +github.com/nats-io/jwt v0.3.0/go.mod h1:fRYCDE99xlTsqUzISS1Bi75UBJ6ljOJQOAAu5VglpSg= +github.com/nats-io/jwt v0.3.2/go.mod h1:/euKqTS1ZD+zzjYrY7pseZrTtWQSjujC7xjPc8wL6eU= +github.com/nats-io/nats-server/v2 v2.1.2/go.mod h1:Afk+wRZqkMQs/p45uXdrVLuab3gwv3Z8C4HTBu8GD/k= +github.com/nats-io/nats.go v1.9.1/go.mod h1:ZjDU1L/7fJ09jvUSRVBR2e7+RnLiiIQyqyzEE/Zbp4w= +github.com/nats-io/nkeys v0.1.0/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w= +github.com/nats-io/nkeys v0.1.3/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w= +github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= github.com/nwaples/rardecode v1.1.3 h1:cWCaZwfM5H7nAD6PyEdcVnczzV8i/JtotnyW/dD9lEc= github.com/nwaples/rardecode v1.1.3/go.mod h1:5DzqNKiOdpKKBH87u8VlvAnPZMXcGRhxWkRpHbbfGS0= github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= +github.com/oklog/oklog v0.3.2/go.mod h1:FCV+B7mhrz4o+ueLpx+KqkyXRGMWOYEvfiXtdGtbWGs= +github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA= +github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= @@ -393,20 +718,50 @@ github.com/onsi/ginkgo/v2 v2.9.5 h1:+6Hr4uxzP4XIUyAkg61dWBw8lb/gc4/X5luuxN/EC+Q= github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.27.6 h1:ENqfyGeS5AX/rlXDd/ETokDz93u0YufY1Pgxuy/PvWE= github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk= +github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= +github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= +github.com/opencontainers/image-spec v1.0.2 h1:9yCKha/T5XdGtO0q9Q9a6T5NUCsTn/DrBg0D7ufOcFM= +github.com/opencontainers/image-spec v1.0.2/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0= +github.com/opencontainers/runc v1.1.9 h1:XR0VIHTGce5eWPkaPesqTBrhW2yAcaraWfsEalNwQLM= +github.com/opencontainers/runc v1.1.9/go.mod h1:CbUumNnWCuTGFukNXahoo/RFBZvDAgRh/smNYNOhA50= +github.com/opentracing-contrib/go-observer v0.0.0-20170622124052-a52f23424492/go.mod h1:Ngi6UdF0k5OKD5t5wlmGhe/EDKPoUM3BXZSSfIuJbis= +github.com/opentracing/basictracer-go v1.0.0/go.mod h1:QfBfYuafItcjQuMwinw9GhYKwFXS9KnPs5lxoYwgW74= +github.com/opentracing/opentracing-go v1.0.2/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= +github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= +github.com/openzipkin-contrib/zipkin-go-opentracing v0.4.5/go.mod h1:/wsWhb9smxSfWAKL3wpBW7V8scJMt8N8gnaMCS9E/cA= +github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJc5AZX7/PBEpw= +github.com/openzipkin/zipkin-go v0.2.1/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4= +github.com/openzipkin/zipkin-go v0.2.2/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4= +github.com/ory/dockertest/v3 v3.10.0 h1:4K3z2VMe8Woe++invjaTB7VRyQXQy5UY+loujO4aNE4= +github.com/ory/dockertest/v3 v3.10.0/go.mod h1:nr57ZbRWMqfsdGdFNLHz5jjNdDb7VVFnzAeW1n5N1Lg= +github.com/pact-foundation/pact-go v1.0.4/go.mod h1:uExwJY4kCzNPcHRj+hCR/HBbOOIwwtUjcrb0b5/5kLM= +github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= +github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k= github.com/pelletier/go-buffruneio v0.2.0/go.mod h1:JkE26KsDizTr40EUHkXVtNPvgGtbSNq5BcowyYOWdKo= +github.com/pelletier/go-toml/v2 v2.0.6 h1:nrzqCb7j9cDFj2coyLNLaZuJTLjWjlaz6nvTvIwycIU= +github.com/pelletier/go-toml/v2 v2.0.6/go.mod h1:eumQOmlWiOPt5WriQQqoM5y18pDHwha2N+QD+EUNTek= +github.com/performancecopilot/speed v3.0.0+incompatible/go.mod h1:/CLtqpZ5gBg1M9iaPbIdPPGyKcA8hKdoy6hAWba7Yac= +github.com/pierrec/lz4 v1.0.2-0.20190131084431-473cd7ce01a1/go.mod h1:3/3N9NVKO0jef7pBehbT1qWhCMrIgbYNnFAZCqQ5LRc= +github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= github.com/pierrec/lz4 v2.6.1+incompatible h1:9UY3+iC23yxF0UfGaYrGplQ+79Rg+h/q9FV9ix19jjM= github.com/pierrec/lz4 v2.6.1+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= github.com/pjbgf/sha1cd v0.3.0 h1:4D5XXmUUBUl/xQ6IjCkEAbqXskkq/4O7LmGn0AqMDs4= github.com/pjbgf/sha1cd v0.3.0/go.mod h1:nZ1rrWOcGJ5uZgEEVL1VUM9iRQiZvWdbZjkKyFzPPsI= +github.com/pkg/browser v0.0.0-20180916011732-0a3d74bf9ce4/go.mod h1:4OwLy04Bl9Ef3GJJCoec+30X3LQs/0/m4HFRt/2LUSA= github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 h1:KoWmjvw+nsYOo29YJK9vDA65RGE3NrOnUtO7a+RF9HU= github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8/go.mod h1:HKlIX3XHQyzLZPlr7++PzdhaXEj94dEiJgZDTsxEqUI= +github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/profile v1.2.1/go.mod h1:hJw3o1OdXxsrSjjVksARp5W95eeEaEfptyVZyv6JUPA= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c h1:ncq/mPwQF4JjgDlrVEn3C11VoGHZN7m8qihwgMEtzYw= github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE= +github.com/praetorian-inc/fingerprintx v1.1.9 h1:zWbG/Fdan0s/dvXkeaHb/CdFTz/yEEzrAF4iCzok3r8= +github.com/praetorian-inc/fingerprintx v1.1.9/go.mod h1:k6EJIHe/Da4DH5e4JuoZHe+qSGq/KPUmXGaK+xW74OI= github.com/projectdiscovery/asnmap v1.0.4 h1:dmXrls7Y0Sdeb6cLlKGwdYX8h1K9q2iYOGXioD4U2AY= github.com/projectdiscovery/asnmap v1.0.4/go.mod h1:iTLDyYsblEwYHcLiKZCRx8Et+xV7NlvgGLusANpgegc= github.com/projectdiscovery/blackrock v0.0.1 h1:lHQqhaaEFjgf5WkuItbpeCZv2DUIE45k0VbGJyft6LQ= @@ -415,8 +770,8 @@ github.com/projectdiscovery/cdncheck v1.0.9 h1:BS15gzj9gb5AVSKqTDzPamfSgStu7nJQO github.com/projectdiscovery/cdncheck v1.0.9/go.mod h1:18SSl1w7rMj53CGeRIZTbDoa286a6xZIxGbaiEo4Fxs= github.com/projectdiscovery/clistats v0.0.19 h1:SA/qRHbmS9VEbVEPzX/ka01hZDYATL9ZjAnDatybhLw= github.com/projectdiscovery/clistats v0.0.19/go.mod h1:NQDAW/O7cK9xBIgk46kJjwGRkjSg5JkB8E4DvuxXr+c= -github.com/projectdiscovery/dsl v0.0.21 h1:usf8J/JmhYQNm0r3qehnLM9qb5ZCPw47d6VyhrJxuxo= -github.com/projectdiscovery/dsl v0.0.21/go.mod h1:0X21hFJdxUtn9sy6JyBNo0yeC6yi+NMGGyeMqdL7e6Y= +github.com/projectdiscovery/dsl v0.0.22-0.20230911020052-7ab80c9abba8 h1:llDw01bhwrcR9HTijzaCSbXp6Vs/urGRihx75NNJknE= +github.com/projectdiscovery/dsl v0.0.22-0.20230911020052-7ab80c9abba8/go.mod h1:k39cUvYjFWRJUa7ayOBRJ5EzAawJKo7XGibPub3DZEA= github.com/projectdiscovery/fastdialer v0.0.37 h1:GEn0VYD/Q+KWiUlQDPP5stvIauN8+gE/eooPzrwidic= github.com/projectdiscovery/fastdialer v0.0.37/go.mod h1:e4Rg9mQ5mNCDFV37njgGCognM0PdLq5f8CcljBqTkRw= github.com/projectdiscovery/fasttemplate v0.0.2 h1:h2cISk5xDhlJEinlBQS6RRx0vOlOirB2y3Yu4PJzpiA= @@ -439,6 +794,8 @@ github.com/projectdiscovery/interactsh v1.1.6 h1:Jm09jXtV/3zPWIkf1+KpbPR6TnjXI/4 github.com/projectdiscovery/interactsh v1.1.6/go.mod h1:mJm+f7qfxgtiCJ+FclViaw5oqNMCkuMu8l+MjxHDmY0= github.com/projectdiscovery/mapcidr v1.1.2 h1:Mmq/nPqvVc7fjvH/kJVK0IBOny/LrJIxZ4tQsLPCrsA= github.com/projectdiscovery/mapcidr v1.1.2/go.mod h1:Aoq0x/wJl6KDbtQ8OcPkjIDCqx2iEyx5ty1nzso8wXM= +github.com/projectdiscovery/n3iwf v0.0.0-20230523120440-b8cd232ff1f5 h1:L/e8z8yw1pfT6bg35NiN7yd1XKtJap5Nk6lMwQ0RNi8= +github.com/projectdiscovery/n3iwf v0.0.0-20230523120440-b8cd232ff1f5/go.mod h1:pGW2ncnTxTxHtP9wzcIJAB+3/NMp6IiuQWd2NK7K+oc= github.com/projectdiscovery/networkpolicy v0.0.6 h1:yDvm0XCrS9HeemRrBS+J+22surzVczM94W5nHiOy/1o= github.com/projectdiscovery/networkpolicy v0.0.6/go.mod h1:8HJQ/33Pi7v3a3MRWIQGXzpj+zHw2d60TysEL4qdoQk= github.com/projectdiscovery/ratelimit v0.0.9 h1:28t2xDHUnyss1irzqPG3Oxz5hkRjl+3Q2I/aes7nau8= @@ -464,8 +821,43 @@ github.com/projectdiscovery/wappalyzergo v0.0.107 h1:B8gzJpAh08f1o+OiDunHAfKtqXi github.com/projectdiscovery/wappalyzergo v0.0.107/go.mod h1:4Z3DKhi75zIPMuA+qSDDWxZvnhL4qTLmDx4dxNMu7MA= github.com/projectdiscovery/yamldoc-go v1.0.4 h1:eZoESapnMw6WAHiVgRwNqvbJEfNHEH148uthhFbG5jE= github.com/projectdiscovery/yamldoc-go v1.0.4/go.mod h1:8PIPRcUD55UbtQdcfFR1hpIGRWG0P7alClXNGt1TBik= +github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= +github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829/go.mod h1:p2iRAGwDERtqlqzRXnrOVns+ignqQo//hLXqYxZYVNs= +github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= +github.com/prometheus/client_golang v1.3.0/go.mod h1:hJaj2vgQTGQmVCsAACORcieXFeDPbaTKGT+JTgUa3og= +github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= +github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0= +github.com/prometheus/client_golang v1.12.1/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY= +github.com/prometheus/client_golang v1.14.0/go.mod h1:8vpkKitgIVNcqrRBWh1C4TIUQgYNtG/XQE4E/Zae36Y= +github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= +github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= +github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/client_model v0.1.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/client_model v0.3.0/go.mod h1:LDGWKZIo7rky3hgvBe+caln+Dr3dPggB5dvjtD7w9+w= +github.com/prometheus/common v0.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= +github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= +github.com/prometheus/common v0.7.0/go.mod h1:DjGbpBbp5NYNiECxcL/VnbXCCaQpKd3tt26CguLLsqA= +github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= +github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc= +github.com/prometheus/common v0.32.1/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls= +github.com/prometheus/common v0.37.0/go.mod h1:phzohg0JFMnBEFGxTDbfu3QyL5GI8gTQJFhYO5B3mfA= +github.com/prometheus/common v0.42.0/go.mod h1:xBwqVerjNdUDjgODMpudtOMwlOwf2SaTr1yjz4b7Zbc= +github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= +github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= +github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= +github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= +github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= +github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= +github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= +github.com/prometheus/procfs v0.8.0/go.mod h1:z7EfXMXOkbkqb9IINtpCn86r/to3BnA0uaxHdg830/4= +github.com/prometheus/procfs v0.9.0/go.mod h1:+pB4zwohETzFnmlpe6yd2lSc+0/46IYZRB/chUwxUZY= github.com/quic-go/quic-go v0.38.1 h1:M36YWA5dEhEeT+slOu/SwMEucbYd0YFidxG3KlGPZaE= github.com/quic-go/quic-go v0.38.1/go.mod h1:ijnZM7JsFIkp4cRyjxJNIzdSfCLmUMg9wdyhGmg+SN4= +github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= +github.com/redis/go-redis/v9 v9.1.0 h1:137FnGdk+EQdCbye1FW+qOEcY5S+SpY9T0NiuqvtfMY= +github.com/redis/go-redis/v9 v9.1.0/go.mod h1:urWj3He21Dj5k4TK1y59xH8Uj6ATueP8AH1cY3lZl4c= github.com/refraction-networking/utls v1.5.2 h1:l6diiLbEoRqdQ+/osPDO0z0lTc8O8VZV+p82N+Hi+ws= github.com/refraction-networking/utls v1.5.2/go.mod h1:SPuDbBmgLGp8s+HLNc83FuavwZCFoMmExj+ltUHiHUw= github.com/remeh/sizedwaitgroup v1.0.0 h1:VNGGFwNo/R5+MJBf6yrsr110p0m4/OX4S3DCy7Kyl5E= @@ -474,14 +866,22 @@ github.com/rivo/uniseg v0.1.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJ github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= github.com/rivo/uniseg v0.4.4 h1:8TfxU8dW6PdqD27gjM8MVNuicgxIjxpm4K7x4jp8sis= github.com/rivo/uniseg v0.4.4/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= +github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= +github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= +github.com/ropnop/gokrb5/v8 v8.0.0-20201111231119-729746023c02 h1:Nk74A6E84pynxLN74hIrQ7Q3cS0/0L5I7coOLNSFAMs= +github.com/ropnop/gokrb5/v8 v8.0.0-20201111231119-729746023c02/go.mod h1:OGEfzIZJs5m/VgAb1BvWR8fH17RTQWx84HTB1koGf9s= github.com/rs/xid v1.5.0 h1:mKX4bl4iPYJtEIxp6CYiUuLQ/8DYMoz0PUdtGgMFRVc= github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= +github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= github.com/saintfish/chardet v0.0.0-20230101081208-5e3ef4b5456d h1:hrujxIzL1woJ7AwssoOcM/tq5JjjG2yYOc8odClEiXA= github.com/saintfish/chardet v0.0.0-20230101081208-5e3ef4b5456d/go.mod h1:uugorj2VCxiV1x+LzaIdVa9b4S4qGAcH6cbhh4qVxOU= -github.com/sashabaranov/go-openai v1.14.2 h1:5DPTtR9JBjKPJS008/A409I5ntFhUPPGCmaAihcPRyo= -github.com/sashabaranov/go-openai v1.14.2/go.mod h1:lj5b/K+zjTSFxVLijLSTDZuP7adOgerWeFyZLUhAKRg= +github.com/samuel/go-zookeeper v0.0.0-20190923202752-2cc03de413da/go.mod h1:gi+0XIa01GRL2eRQVjQkKGqKF3SF9vZR/HnPullcV2E= +github.com/sashabaranov/go-openai v1.15.3 h1:rzoNK9n+Cak+PM6OQ9puxDmFllxfnVea9StlmhglXqA= +github.com/sashabaranov/go-openai v1.15.3/go.mod h1:lj5b/K+zjTSFxVLijLSTDZuP7adOgerWeFyZLUhAKRg= +github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= github.com/segmentio/ksuid v1.0.4 h1:sBo2BdShXjmcugAMwjugoGUdUV0pcxY5mW4xKRn3v4c= github.com/segmentio/ksuid v1.0.4/go.mod h1:/XUiZBD3kVx5SmUOl55voK5yeAbBNNIed+2O73XgrPE= github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= @@ -493,10 +893,15 @@ github.com/shoenig/go-m1cpu v0.1.6 h1:nxdKQNcEB6vzgA2E2bvzKIYRuNj7XNJ4S/aRSwKzFt github.com/shoenig/go-m1cpu v0.1.6/go.mod h1:1JJMcUBvfNwpq05QDQVAnx3gUHr9IYF7GNg9SUEw2VQ= github.com/shoenig/test v0.6.4 h1:kVTaSd7WLz5WZ2IaoM0RSzRsUD+m8wRR+5qvntpn4LU= github.com/shoenig/test v0.6.4/go.mod h1:byHiCGXqrVaflBLAMq/srcZIHynQPQgeyvkvXnjqq0k= +github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= +github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.3.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= +github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= +github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= +github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/skeema/knownhosts v1.1.1 h1:MTk78x9FPgDFVFkDLTrsnnfCJl7g1C/nnKvePgrIngE= github.com/skeema/knownhosts v1.1.1/go.mod h1:g4fPeYpque7P0xefxtGzV81ihjC8sX2IqpAoNkjxbMo= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= @@ -505,12 +910,19 @@ github.com/smartystreets/assertions v1.0.0/go.mod h1:kHHU4qYBaI3q23Pp3VPrmWhuIUr github.com/smartystreets/goconvey v0.0.0-20190330032615-68dc04aab96a/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= github.com/smartystreets/goconvey v1.6.4 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIKYqbNC9s= github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= +github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= +github.com/sony/gobreaker v0.4.1/go.mod h1:ZKptC7FHNvhBz7dN2LGjPVBz2sZJmc0/PkyDJOjmxWY= github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI= github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/spf13/cast v1.5.1 h1:R+kOtfhWQE6TVQzY+4D7wJLBgkdVasCEFxSUBYBYIlA= github.com/spf13/cast v1.5.1/go.mod h1:b9PdjNptOpzXr7Rq1q9gJML/2cdGQAo69NKzQ10KN48= +github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= +github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/src-d/gcfg v1.4.0 h1:xXbNR5AlLSA315x2UO+fTSSAXCDf+Ar38/6oyGbDKQ4= github.com/src-d/gcfg v1.4.0/go.mod h1:p/UMsR43ujA89BJY9duynAwIpvqEujIH/jFlfL7jWoI= +github.com/streadway/amqp v0.0.0-20190404075320-75d898a42a94/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= +github.com/streadway/amqp v0.0.0-20190827072141-edfb9018d271/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= +github.com/streadway/handy v0.0.0-20190108123426-d5acb3125c2a/go.mod h1:qNTQ5P5JnDBl6z3cMAg/SywNDC5ABu5ApDIw6lUbRmI= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= @@ -523,6 +935,7 @@ github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81P github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= @@ -548,34 +961,55 @@ github.com/tidwall/rtred v0.1.2 h1:exmoQtOLvDoO8ud++6LwVsAMTu0KPzLTUrMln8u1yu8= github.com/tidwall/rtred v0.1.2/go.mod h1:hd69WNXQ5RP9vHd7dqekAz+RIdtfBogmglkZSRxCHFQ= github.com/tidwall/tinyqueue v0.1.1 h1:SpNEvEggbpyN5DIReaJ2/1ndroY8iyEGxPYxoSaymYE= github.com/tidwall/tinyqueue v0.1.1/go.mod h1:O/QNHwrnjqr6IHItYrzoHAKYhBkLI67Q096fQP5zMYw= +github.com/tim-ywliu/nested-logrus-formatter v1.3.2 h1:jugNJ2/CNCI79SxOJCOhwUHeN3O7/7/bj+ZRGOFlCSw= +github.com/tim-ywliu/nested-logrus-formatter v1.3.2/go.mod h1:oGPmcxZB65j9Wo7mCnQKSrKEJtVDqyjD666SGmyStXI= github.com/tklauser/go-sysconf v0.3.11 h1:89WgdJhk5SNwJfu+GKyYveZ4IaJ7xAkecBo+KdJV0CM= github.com/tklauser/go-sysconf v0.3.11/go.mod h1:GqXfhXY3kiPa0nAXPDIQIWzJbMCB7AmcWpGR8lSZfqI= github.com/tklauser/numcpus v0.6.0 h1:kebhY2Qt+3U6RNK7UqpYNA+tJ23IBEGKkB7JQBfDYms= github.com/tklauser/numcpus v0.6.0/go.mod h1:FEZLMke0lhOUG6w2JadTzp0a+Nl8PF/GFkQ5UVIcaL4= +github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/trivago/tgo v1.0.7 h1:uaWH/XIy9aWYWpjm2CU3RpcqZXmX2ysQ9/Go+d9gyrM= github.com/trivago/tgo v1.0.7/go.mod h1:w4dpD+3tzNIIiIfkWWa85w5/B77tlvdZckQ+6PkFnhc= +github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI= +github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08= github.com/twmb/murmur3 v1.1.6 h1:mqrRot1BRxm+Yct+vavLMou2/iJt0tNVTTC0QoIjaZg= github.com/twmb/murmur3 v1.1.6/go.mod h1:Qq/R7NUyOfr65zD+6Q5IHKsJLwP7exErjN6lyyq3OSQ= +github.com/ugorji/go/codec v1.2.9 h1:rmenucSohSTiyL09Y+l2OCk+FrMxGMzho2+tjr5ticU= +github.com/ugorji/go/codec v1.2.9/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg= github.com/ulikunitz/xz v0.5.6/go.mod h1:2bypXElzHzzJZwzH67Y6wb67pO62Rzfn7BSiF4ABRW8= github.com/ulikunitz/xz v0.5.11 h1:kpFauv27b6ynzBNT/Xy+1k+fK4WswhN/6PN5WhFAGw8= github.com/ulikunitz/xz v0.5.11/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14= github.com/ulule/deepcopier v0.0.0-20200430083143-45decc6639b6 h1:TtyC78WMafNW8QFfv3TeP3yWNDG+uxNkk9vOrnDu6JA= github.com/ulule/deepcopier v0.0.0-20200430083143-45decc6639b6/go.mod h1:h8272+G2omSmi30fBXiZDMkmHuOgonplfKIKjQWzlfs= +github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= +github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= github.com/valyala/fasttemplate v1.2.1/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ= github.com/valyala/fasttemplate v1.2.2 h1:lxLXG0uE3Qnshl9QyaK6XJxMXlQZELvChBOCmQD0Loo= github.com/valyala/fasttemplate v1.2.2/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ= +github.com/weppos/publicsuffix-go v0.12.0/go.mod h1:z3LCPQ38eedDQSwmsSRW4Y7t2L8Ln16JPQ02lHAdn5k= github.com/weppos/publicsuffix-go v0.13.0/go.mod h1:z3LCPQ38eedDQSwmsSRW4Y7t2L8Ln16JPQ02lHAdn5k= +github.com/weppos/publicsuffix-go v0.30.0/go.mod h1:kBi8zwYnR0zrbm8RcuN1o9Fzgpnnn+btVN8uWPMyXAY= github.com/weppos/publicsuffix-go v0.30.2-0.20230730094716-a20f9abcc222 h1:h2JizvZl9aIj6za9S5AyrkU+OzIS4CetQthH/ejO+lg= github.com/weppos/publicsuffix-go v0.30.2-0.20230730094716-a20f9abcc222/go.mod h1:s41lQh6dIsDWIC1OWh7ChWJXLH0zkJ9KHZVqA7vHyuQ= +github.com/weppos/publicsuffix-go/publicsuffix/generator v0.0.0-20220927085643-dc0d00c92642/go.mod h1:GHfoeIdZLdZmLjMlzBftbTDntahTttUMWjxZwQJhULE= github.com/xanzy/go-gitlab v0.84.0 h1:PdpCaskQSgcVDsx21c6ikf8Rfyo7SNtFAJwP9PrbCFE= github.com/xanzy/go-gitlab v0.84.0/go.mod h1:5ryv+MnpZStBH8I/77HuQBsMbBGANtVpLWC15qOjWAw= github.com/xanzy/ssh-agent v0.2.1/go.mod h1:mLlQY/MoOhWBj+gOGMQkOeiEvkx+8pJSI+0Bx9h2kr4= github.com/xanzy/ssh-agent v0.3.3 h1:+/15pJfg/RsTxqYcX6fHqOXZwwMP+2VyYWJeWM2qQFM= github.com/xanzy/ssh-agent v0.3.3/go.mod h1:6dzNDKs0J9rVPHPhaGCukekBHKqfl+L3KghI1Bc68Uw= +github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= +github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb h1:zGWFAtiMcyryUHoUjUJX0/lt1H2+i2Ka2n+D3DImSNo= +github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= +github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 h1:EzJWgHovont7NscjpAxXsDA8S8BMYve8Y5+7cuRE7R0= +github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= +github.com/xeipuuv/gojsonschema v1.2.0 h1:LhYJRs+L4fBtjZUfuSZIKGeVu0QRy8e5Xi7D17UxZ74= +github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y= +github.com/xhit/go-str2duration v1.2.0/go.mod h1:3cPSlfZlUHVlneIVfePFWcJZsuwf+P1v2SRTV4cUmp4= github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8 h1:nIPpBwaJSVYIxUFsDv3M8ofmx9yWTog9BfvIu0q41lo= github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8/go.mod h1:HUYIGzjTL3rfEspMxjDjgmT5uz5wzYJKVo23qUhYTos= +github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= github.com/yl2chen/cidranger v1.0.2 h1:lbOWZVCG1tCRX4u24kuM1Tb4nHqWkDxwLdoS+SevawU= github.com/yl2chen/cidranger v1.0.2/go.mod h1:9U1yz7WPYDwf0vpNWFaeRh0bjwz5RVgRy/9UEQfHl0g= github.com/ysmood/fetchup v0.2.3 h1:ulX+SonA0Vma5zUFXtv52Kzip/xe7aj4vqT5AJwQ+ZQ= @@ -592,6 +1026,9 @@ github.com/ysmood/gson v0.7.3 h1:QFkWbTH8MxyUTKPkVWAENJhxqdBa4lYTQWqZCiLG6kE= github.com/ysmood/gson v0.7.3/go.mod h1:3Kzs5zDl21g5F/BlLTNcuAGAYLKt2lV5G8D1zF3RNmg= github.com/ysmood/leakless v0.8.0 h1:BzLrVoiwxikpgEQR0Lk8NyBN5Cit2b1z+u0mgL4ZJak= github.com/ysmood/leakless v0.8.0/go.mod h1:R8iAXPRaG97QJwqxs74RdwzcRHT1SWCGTNqY8q0JvMQ= +github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= github.com/yuin/goldmark v1.5.2/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= @@ -614,26 +1051,54 @@ github.com/zmap/zcertificate v0.0.0-20180516150559-0e3d58b1bac4/go.mod h1:5iU54t github.com/zmap/zcertificate v0.0.1/go.mod h1:q0dlN54Jm4NVSSuzisusQY0hqDWvu92C+TWveAxiVWk= github.com/zmap/zcrypto v0.0.0-20201128221613-3719af1573cf/go.mod h1:aPM7r+JOkfL+9qSB4KbYjtoEzJqUK50EXkkJabeNJDQ= github.com/zmap/zcrypto v0.0.0-20201211161100-e54a5822fb7e/go.mod h1:aPM7r+JOkfL+9qSB4KbYjtoEzJqUK50EXkkJabeNJDQ= -github.com/zmap/zcrypto v0.0.0-20230814193918-dbe676986518 h1:O8GHQBxrphDuNhJQdKBHwP3JQUtZUyi3b+jjPYmF7oA= -github.com/zmap/zcrypto v0.0.0-20230814193918-dbe676986518/go.mod h1:Z2SNNuFhO+AAsezbGEHTWeW30hHv5niUYT3fwJ61Nl0= +github.com/zmap/zcrypto v0.0.0-20230310154051-c8b263fd8300/go.mod h1:mOd4yUMgn2fe2nV9KXsa9AyQBFZGzygVPovsZR+Rl5w= +github.com/zmap/zcrypto v0.0.0-20230829152017-3b5d61809233 h1:6J0/zRqCBtXnPOs9Iw2o9QoPfWmcq6KJJcpRPHoyPzM= +github.com/zmap/zcrypto v0.0.0-20230829152017-3b5d61809233/go.mod h1:Z2SNNuFhO+AAsezbGEHTWeW30hHv5niUYT3fwJ61Nl0= +github.com/zmap/zflags v1.4.0-beta.1.0.20200204220219-9d95409821b6/go.mod h1:HXDUD+uue8yeLHr0eXx1lvY6CvMiHbTKw5nGmA9OUoo= +github.com/zmap/zgrab2 v0.1.8-0.20230806160807-97ba87c0e706 h1:LaMyYFWQA7kh3ovPfAaFDTKlJu3JGng8khruOtsBVnE= +github.com/zmap/zgrab2 v0.1.8-0.20230806160807-97ba87c0e706/go.mod h1:re2kMcs84XHb8Xl6RInt0emoKCuphfmfjHYuteviLHQ= github.com/zmap/zlint/v3 v3.0.0/go.mod h1:paGwFySdHIBEMJ61YjoqT4h7Ge+fdYG4sUQhnTb1lJ8= +go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= go.etcd.io/bbolt v1.3.7 h1:j+zJOnnEjF/kyHlDDgGnVL/AIqIJPq8UoB2GSNfkUfQ= go.etcd.io/bbolt v1.3.7/go.mod h1:N9Mkw9X8x5fupy0IKsmuqVtoGDyxsaDlbk4Rd05IAQw= +go.etcd.io/etcd v0.0.0-20191023171146-3cf2f69b5738/go.mod h1:dnLIgRNXwCJa5e+c6mIZCrds/GIG4ncV9HhK5PX7jPg= +go.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= +go.opencensus.io v0.20.2/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= +go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= +go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= +go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= +go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= go.uber.org/goleak v1.2.0 h1:xqgm/S+aQvhWFTtR0XK3Jvg7z8kGV8P4X14IzwN3Eqk= +go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= +go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4= go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= +go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA= +go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= +go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= go.uber.org/zap v1.25.0 h1:4Hvk6GtkucQ790dqmj7l1eEnRdKm3k3ZUrUMS2d5+5c= go.uber.org/zap v1.25.0/go.mod h1:JIAUzQIH94IC4fOJQm7gMmBJP5k7wQfdcnYdPoEXJYk= goftp.io/server/v2 v2.0.1 h1:H+9UbCX2N206ePDSVNCjBftOKOgil6kQ5RAQNx5hJwE= goftp.io/server/v2 v2.0.1/go.mod h1:7+H/EIq7tXdfo1Muu5p+l3oQ6rYkDZ8lY7IM5d5kVdQ= +golang.org/x/arch v0.0.0-20210923205945-b76863e36670 h1:18EFjUmQOcUvxNYSkA6jO9VAiXCnxFY6NyDX0bHDmkU= +golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190219172222-a4c6cb3142f2/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190513172903-22d7a77e9e5f/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20200117160349-530e935923ad/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200510223506-06a226fb4e37/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20200728195943-123391ffb6de/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20201124201722-c8d3bf9c5392/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= golang.org/x/crypto v0.0.0-20201208171446-5f87f3452ae9/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= @@ -642,29 +1107,91 @@ golang.org/x/crypto v0.0.0-20211209193657-4570a0811e8b/go.mod h1:IxCIyHEi3zRg3s0 golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU= golang.org/x/crypto v0.11.0/go.mod h1:xgJhtzW8F9jGdVFWZESrid1U1bjeNy4zgy5cRr/CIio= -golang.org/x/crypto v0.12.0 h1:tFM/ta59kqch6LlvYnPa0yx5a83cL2nHflFhYKvv9Yk= -golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98yw= -golang.org/x/exp v0.0.0-20230817173708-d852ddb80c63 h1:m64FZMko/V45gv0bNmrNYoDEq8U5YUhetc9cBWKS1TQ= -golang.org/x/exp v0.0.0-20230817173708-d852ddb80c63/go.mod h1:0v4NqG35kSWCMzLaMeX+IQrlSnVE/bqGSyC2cz/9Le8= +golang.org/x/crypto v0.13.0 h1:mvySKfSWJ+UKUii46M40LOvyWfN0s2U+46/jDd0e6Ck= +golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc= +golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= +golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek= +golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY= +golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= +golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= +golang.org/x/exp v0.0.0-20230905200255-921286631fa9 h1:GoHiUyI/Tp2nVkLI2mCxVkOjsbSXD66ic0XW0js0R9g= +golang.org/x/exp v0.0.0-20230905200255-921286631fa9/go.mod h1:S2oDrQGGwySpoQPVqRShND87VCbxmc6bL1Yd2oYrm6k= +golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= +golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= +golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= +golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= +golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= +golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= +golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= +golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= +golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= +golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.12.0 h1:rmsUpXtvNzj340zd98LZ4KntptpfRHwpFOHG188oHXc= golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190125091013-d26f9f9a57f3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= +golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200528225125-3c3fba18258b/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20210610132358-84b48f89b13b/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210916014120-12bc252f5db8/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= +golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.0.0-20221002022538-bcab6841153b/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk= golang.org/x/net v0.5.0/go.mod h1:DivGGAXEgPSlEBzxGzZI+ZLohi+xUj054jfeKui00ws= @@ -673,30 +1200,75 @@ golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= golang.org/x/net v0.12.0/go.mod h1:zEVYFnQC7m/vmpQFELhcD1EWkZlX69l4oqgmer6hfKA= -golang.org/x/net v0.14.0 h1:BONx9s002vGdD9umnlX1Po8vOZmrgH34qlHcD1MfK14= -golang.org/x/net v0.14.0/go.mod h1:PpSgVXXLK0OxS0F31C1/tv6XNguvCrnXIDrFMspZIUI= +golang.org/x/net v0.15.0 h1:ugBLEUaxABaB5AJqW9enI0ACdci2RUd4eP51NTBvuJ8= +golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= +golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= +golang.org/x/oauth2 v0.5.0/go.mod h1:9/XBHVqLaWO3/BRHs5jbpYCnOZVjj5V0ndyaAM7KB4I= golang.org/x/oauth2 v0.6.0/go.mod h1:ycmewcwgD4Rpr3eZJLSB4Kyyljb3qDh40vJ8STE5HKw= golang.org/x/oauth2 v0.11.0 h1:vPL4xzxBM4niKCW6g9whtaWVXTJf1U5e4aZxxFx/gbU= golang.org/x/oauth2 v0.11.0/go.mod h1:LdF7O/8bLR/qWK9DrpXmbHLTouvRHK0SgJl0GmDBchk= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20220601150217-0de741cfad7f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E= +golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190221075227-b4e8571b14e0/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190924154521-2837fb4f24fe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191220142924-d4481acd189f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201126233918-771906719818/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -704,12 +1276,16 @@ golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210228012217-479acdf4ea46/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210616045830-e2b7044e8c71/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211103235746-7861aae1554b/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220330033206-e17cdc41300f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -724,8 +1300,8 @@ golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.11.0 h1:eG7RXZHdqOJ1i+0lgLgCpSXAp6M3LYlAo6osgSi0xOM= -golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.12.0 h1:CM0HF96J0hcLAwsHPJZjfdNzs0gftsLfgKt57wWHJ0o= +golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= @@ -735,8 +1311,10 @@ golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U= golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= golang.org/x/term v0.10.0/go.mod h1:lpqdcUyK/oCiQxvxVrppt5ggO2KCZ5QblwqPnfZ6d5o= -golang.org/x/term v0.11.0 h1:F9tnn/DA/Im8nCwm+fX+1/eBwi4qFjRT++MhtVC4ZX0= +golang.org/x/term v0.12.0 h1:/ZfYdc3zq+q02Rv9vGqTeSItdzZTSNDmfTi0mBAuidU= +golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= @@ -748,29 +1326,160 @@ golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.11.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= -golang.org/x/text v0.12.0 h1:k+n5B8goJNdU7hSvEtMUz3d1Q6D/XW4COJSJR6fN0mc= -golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= +golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k= +golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= +golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4= golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= +golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190729092621-ff9f1409240a/go.mod h1:jcCCGcm9btYwXyDqrUWc6MKQKKGJCWEQ3AfLSRIbEuI= +golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191216052735-49a3e744a425/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200103221440-774c71fcf114/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= +golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= +golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= +golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= -golang.org/x/tools v0.12.1-0.20230815132531-74c255bcf846 h1:Vve/L0v7CXXuxUmaMGIEK/dEeq7uiqb5qBgQrZzIE7E= -golang.org/x/tools v0.12.1-0.20230815132531-74c255bcf846/go.mod h1:Sc0INKfu04TlqNoRA1hgpFZbhYXHPr4V5DzpSBTPqQM= +golang.org/x/tools v0.13.0 h1:Iey4qkscZuv0VvIt8E0neZjtPVQFSc870HQ448QgEmQ= +golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/api v0.3.1/go.mod h1:6wY9I6uQWHQ8EM57III9mq/AjF+i8G65rmVagqKMtkk= +google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= +google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= +google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= +google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= +google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= +google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= +google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM= +google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= +google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= +google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c= google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190530194941-fb225487d101/go.mod h1:z3L6/3dTEVtUr6QSP8miRzeRqwQOioJ9I66odjN4I7s= +google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= +google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA= +google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U= +google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= +google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= +google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= +google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= +google.golang.org/grpc v1.20.0/go.mod h1:chYK+tFQF0nDUGJgXMSgLCQk3phJEuONr2DCgLDdAQM= +google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= +google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= +google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= +google.golang.org/grpc v1.22.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.23.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= +google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= +google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= +google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= +google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= +google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= +google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= +google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= +google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= +google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8= google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= gopkg.in/alecthomas/kingpin.v2 v2.2.6 h1:jMFz6MfLP0/4fUyZle81rXUoxOBFi19VUFKVDOQfozc= @@ -780,13 +1489,17 @@ gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8 gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= +gopkg.in/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw= gopkg.in/corvus-ch/zbase32.v1 v1.0.0 h1:K4u1NprbDNvKPczKfHLbwdOWHTZ0zfv2ow71H1nRnFU= gopkg.in/corvus-ch/zbase32.v1 v1.0.0/go.mod h1:T3oKkPOm4AV/bNXCNFUxRmlE9RUyBz/DSo0nK9U+c0Y= gopkg.in/djherbis/times.v1 v1.3.0 h1:uxMS4iMtH6Pwsxog094W0FYldiNnfY/xba00vq6C2+o= gopkg.in/djherbis/times.v1 v1.3.0/go.mod h1:AQlg6unIsrsCEdQYhTzERy542dz6SFdQFZFv6mUY0P8= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= +gopkg.in/gcfg.v1 v1.2.3/go.mod h1:yesOnuUOFQAhST5vPY4nbZsb/huCgGGXlipJsBn0b3o= gopkg.in/ini.v1 v1.42.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/mgo.v2 v2.0.0-20190816093944-a6b53ec6cb22/go.mod h1:yeKp02qBN3iKW1OzL3MGk2IdtZzaj7SFntXj72NppTA= +gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= gopkg.in/src-d/go-billy.v4 v4.3.2 h1:0SQA1pRztfTFx2miS8sA97XvooFeNOmvUenF4o0EcVg= gopkg.in/src-d/go-billy.v4 v4.3.2/go.mod h1:nDjArDMp+XMs1aFAESLRjfGSgfvoYN0hDfzEk0GjC98= gopkg.in/src-d/go-git-fixtures.v3 v3.5.0 h1:ivZFOIltbce2Mo8IjzUHAFoq/IylO9WHhNOAJK+LsJg= @@ -797,15 +1510,35 @@ gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkep gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME= gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI= +gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gotest.tools/v3 v3.3.0 h1:MfDY1b1/0xN1CyMlQDac0ziEy9zJQd9CXBRRDHw2jJo= +honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= +honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= +honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= +mellium.im/sasl v0.3.1 h1:wE0LW6g7U83vhvxjC1IY8DnXM+EU095yeo8XClvCdfo= +mellium.im/sasl v0.3.1/go.mod h1:xm59PUYpZHhgQ9ZqoJ5QaCqzWMi8IeS49dhp6plPCzw= moul.io/http2curl v1.0.0 h1:6XwpyZOYsgZJrU8exnG87ncVkU1FVCcTRpwzOkTDUi8= moul.io/http2curl v1.0.0/go.mod h1:f6cULg+e4Md/oW1cYmwW4IWQOVl2lGbmCNGOHvzX2kE= +rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= +rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4= +rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= +rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= +sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o= +sourcegraph.com/sourcegraph/appdash v0.0.0-20190731080439-ebfcffb1b5c0/go.mod h1:hI742Nqp5OhwiqlzhgfbWU4mW4yO10fP+LoT9WOswdU= diff --git a/v2/pkg/js/CONTRIBUTE.md b/v2/pkg/js/CONTRIBUTE.md new file mode 100644 index 0000000000..3608b17383 --- /dev/null +++ b/v2/pkg/js/CONTRIBUTE.md @@ -0,0 +1,73 @@ +# JS Contribution Guide + +The JS layer provides a mechanism to add scriptability into the Nuclei Engine. The `pkg/js` directory contains the implementation of the JS runtime in Nuclei. This document provides a guide to adding new libraries, extending existing ones and other types of contributions. + +## First step + +The Very First before making any type of contribution to javascript runtime in nuclei is taking a look at [design.md](./DESIGN.md) to understand spread out design of nuclei javascript runtime. + + +## Documentation/Typo Contribution + +Most of Javascript API Reference documentation is auto-generated with help of code-generation and [jsdocgen](./devtools/jsdocgen/README.md) and hence any type of documentation contribution are always welcome and can be done by editing [javscript jsdoc](./generated/js/) files + + +## Improving Existing Libraries(aka node_modules) + +Improving existing libraries includes adding new functions, types, fixing bugs etc to any of the existing libraries in [libs](./libs/) directory. This is very easy to achieve and can be done by following steps below + +1. Do suggested changes in targeted package in [libs](./libs/) directory +2. Refer [devtools](./devtools/README.md) to autogenerate bindings and documentation +3. Check for errors / improve documentation in generated documentation in [generated/js/*](./generated/js/*) directory + +## Adding New Libraries(aka node_modules) + +Libraries/node_modules represent adding new protocol or something similar and should not include helper functions or types/objects .Adding new libraries requires few more steps than improving existing libraries and can be done by following steps below + +1. Refer any existing library in [libs](./libs/) directory to understand style and structure of node_modules +2. Create new package in [libs](./libs/) directory with suggested protocol / library +3. Refer [devtools](./devtools/README.md) to autogenerate bindings and documentation +4. Check for errors / improve documentation in generated documentation in [generated/js/*](./generated/js/*) directory +5. Import newly created library with '_' import in [compiler](./compiler/compiler.go) + + +## Adding Helper Objects/Types/Functions + +Helper objects/types/functions can simply be understood as javascript utils to simplify writing javscript and reduce code duplication in javascript templates. Helper functions/objects are divided into two categories + +### javascript based helpers + +javascript based helpers are written in javascript and are available in javascript runtime by default without needing to import any module. These are located in [global/js](./global/js/) directory and are exported using [exports.js](./global/exports.js) file. + + +### go based helpers + +go based helpers are written in go and can import any go library if required. Minimal/Simple helper functions can be directly added using `runtime.Set("function_name", function)` in [global/scripts.go](./global/scripts.go) file. For more complex helpers, a new package can be created in [libs](./libs/) directory and can be imported in [global/scripts.go](./global/scripts.go) file. Refer to existing implementations in [globals](./global/) directory for more details. + + +### Updating / Publishing Docs + +Javscript Protocol Documentation is auto-generated using [jsdoc] and is hosted at [js-proto-docs](https://projectdiscovery.github.io/js-proto-docs/). To update documentation, please follow steps mentioned at [projectdiscovery/js-proto-docs](https://github.com/projectdiscovery/js-proto-docs) + + +### Go Code Guidelines + +1. Always use 'protocolstate.Dialer' (i.e fastdialer) to dial connections instead of net.Dial this has many benefits along with proxy support , **network policy** usage (i.e local network access can be disabled from cli) +2. When usage of 'protocolstate.Dialer' is not possible due to some reason ex: imported library does not accept dialer etc then validate host using 'protocolstate.IsHostAllowed' before dialing connection. +```go + if !protocolstate.IsHostAllowed(host) { + // host is not valid according to network policy + return false, protocolstate.ErrHostDenied.Msgf(host) + } +``` +3. Keep exported package clean. Do not keep unncessary global exports which the consumer of the API doesn't need to know about. Keep only user-exposed API public. +4. Use timeouts and context cancellation when calling Network related stuff. Also make sure to close your connections or provide a mechanism to the user of the API to do so. +5. Always try to return single types from inside javascript with an error like `(IsRDP, error)` instead of returning multiple values `(name, version string, err error)`. The second one will get converted to an array is much harder for consumers to deal with. Instead, try to return `Structures` which will be accessible natively. + + +### Javascript Code Guidelines + +1. Catch exceptions using `try/catch` blocks and handle errors gracefully, showing useful information. By default, the implementation returns a Go error on a unhandled exception along with stack trace in debug mode. +2. Use `let`/`cost` instead of `var` to declare variables. +3. Keep the global scope clean. The VMs are not shared so do not rely on VM state. +4. Use functions to divide the code and keep the implementation clean. \ No newline at end of file diff --git a/v2/pkg/js/DESIGN.md b/v2/pkg/js/DESIGN.md new file mode 100644 index 0000000000..516ae0c218 --- /dev/null +++ b/v2/pkg/js/DESIGN.md @@ -0,0 +1,47 @@ +# javascript protocol design + +javascript protocol is implemented using `goja`(pure go javascript VM) and overall logic/design of its usage is split into multiple packages/directories + +## [api_reference](./api_reference/) + +api_reference contains a static site generated using `jsdoc` . It contains documentation for all the exposed functions and types in javascript protocol. + +## [compiler](./compiler/) + +compiler contains abstracted logic for compiling and executing javascript code. It also handles loading javascript aka node modules , adding builtin / global types and functions etc. + +## [devtools](./devtools/README.md) + +devtools contains development related tools to automate booring tasks like generating bindings, adding jsdoc comments, generating api reference etc. + +## [generated](./generated/README.md) + +generated contains two types of generated code + +### [- generated/go](./generated/go/) + +generated/go contains actual bindings for native go packages using `goja` this involves exposing libraries,functions and types written in go to javascript. + +### [- generated/js](./generated/js/) + +generated/js contains a visual representation of all exposed functions and types in javascript minus the actual implementation . it is meant to be used as a reference for developers and generating api reference. + +## [global](./global/) + +global (or builtin) contains all builtin types and functions that are by default available in javascript runtime without needing to import any module using 'require' keyword. Its split into 2 sections + +### [- global/js](./global/js/) + +global/js contains javascript code and it acts more like a javascript library and contains functions / types written in javascript itself and exported using [exports.js](./global/exports.js) + +### [- global/scripts.go](./global/scripts.go) + +global/scripts.go contains declaration and implementation of functions written in go and are made available in javascript runtime. It also contains loading javascript based global functions this is done by executing javascript code in every vm instance. + +## [gojs](./gojs/) + +gojs contain minimalistic types and interfaces used to register packages written in go as node_modules in javascript runtime. + +## [libs](./libs/) + +libs contains all go native packages that contain **actual** implementation of all the functions and types that are exposed to javascript runtime. \ No newline at end of file diff --git a/v2/pkg/js/THANKS.md b/v2/pkg/js/THANKS.md new file mode 100644 index 0000000000..55619040a0 --- /dev/null +++ b/v2/pkg/js/THANKS.md @@ -0,0 +1,9 @@ +# THANKS + +- https://github.com/dop251/goja - Pure Go Javascript VM used by nuclei JS layer. +- https://github.com/gogap/gojs-tool - Inspiration for code generation used in JS Libraries addition. +- https://github.com/ropnop/kerbrute - Kerberos Module of JS layer +- https://github.com/praetorian-inc/fingerprintx - A lot of Network Protocol fingerprinting functionality is used from `fingerprintx` package. +- https://github.com/zmap/zgrab2 - Used for SMB and SSH protocol handshake Metadata gathering. + +A lot of other Go based libraries are used in the javascript layer. Thanks goes to the creators and maintainers. \ No newline at end of file diff --git a/v2/pkg/js/compiler/compiler.go b/v2/pkg/js/compiler/compiler.go new file mode 100644 index 0000000000..360071e10d --- /dev/null +++ b/v2/pkg/js/compiler/compiler.go @@ -0,0 +1,203 @@ +// Package compiler provides a compiler for the goja runtime. +package compiler + +import ( + "runtime/debug" + + "github.com/dop251/goja" + "github.com/dop251/goja_nodejs/console" + "github.com/dop251/goja_nodejs/require" + jsoniter "github.com/json-iterator/go" + "github.com/pkg/errors" + + "github.com/projectdiscovery/gologger" + _ "github.com/projectdiscovery/nuclei/v2/pkg/js/generated/go/libbytes" + _ "github.com/projectdiscovery/nuclei/v2/pkg/js/generated/go/libikev2" + _ "github.com/projectdiscovery/nuclei/v2/pkg/js/generated/go/libkerberos" + _ "github.com/projectdiscovery/nuclei/v2/pkg/js/generated/go/libldap" + _ "github.com/projectdiscovery/nuclei/v2/pkg/js/generated/go/libmssql" + _ "github.com/projectdiscovery/nuclei/v2/pkg/js/generated/go/libmysql" + _ "github.com/projectdiscovery/nuclei/v2/pkg/js/generated/go/libnet" + _ "github.com/projectdiscovery/nuclei/v2/pkg/js/generated/go/liboracle" + _ "github.com/projectdiscovery/nuclei/v2/pkg/js/generated/go/libpop3" + _ "github.com/projectdiscovery/nuclei/v2/pkg/js/generated/go/libpostgres" + _ "github.com/projectdiscovery/nuclei/v2/pkg/js/generated/go/librdp" + _ "github.com/projectdiscovery/nuclei/v2/pkg/js/generated/go/libredis" + _ "github.com/projectdiscovery/nuclei/v2/pkg/js/generated/go/librsync" + _ "github.com/projectdiscovery/nuclei/v2/pkg/js/generated/go/libsmb" + _ "github.com/projectdiscovery/nuclei/v2/pkg/js/generated/go/libsmtp" + _ "github.com/projectdiscovery/nuclei/v2/pkg/js/generated/go/libssh" + _ "github.com/projectdiscovery/nuclei/v2/pkg/js/generated/go/libstructs" + _ "github.com/projectdiscovery/nuclei/v2/pkg/js/generated/go/libtelnet" + _ "github.com/projectdiscovery/nuclei/v2/pkg/js/generated/go/libvnc" + "github.com/projectdiscovery/nuclei/v2/pkg/js/global" + "github.com/projectdiscovery/nuclei/v2/pkg/js/libs/goconsole" + "github.com/projectdiscovery/nuclei/v2/pkg/protocols/common/generators" +) + +// Compiler provides a runtime to execute goja runtime +// based javascript scripts efficiently while also +// providing them access to custom modules defined in libs/. +type Compiler struct { + registry *require.Registry +} + +// New creates a new compiler for the goja runtime. +func New() *Compiler { + registry := new(require.Registry) // this can be shared by multiple runtimes + // autoregister console node module with default printer it uses gologger backend + require.RegisterNativeModule(console.ModuleName, console.RequireWithPrinter(goconsole.NewGoConsolePrinter())) + return &Compiler{registry: registry} +} + +// ExecuteOptions provides options for executing a script. +type ExecuteOptions struct { + // Pool specifies whether to use a pool of goja runtimes + // Can be used to speedup execution but requires + // the script to not make any global changes. + Pool bool + + // CaptureOutput specifies whether to capture the output + // of the script execution. + CaptureOutput bool + + // CaptureVariables specifies the variables to capture + // from the script execution. + CaptureVariables []string +} + +// ExecuteArgs is the arguments to pass to the script. +type ExecuteArgs struct { + Args map[string]interface{} //these are protocol variables + TemplateCtx map[string]interface{} // templateCtx contains template scoped variables +} + +// NewExecuteArgs returns a new execute arguments. +func NewExecuteArgs() *ExecuteArgs { + return &ExecuteArgs{ + Args: make(map[string]interface{}), + TemplateCtx: make(map[string]interface{}), + } +} + +// ExecuteResult is the result of executing a script. +type ExecuteResult map[string]interface{} + +func NewExecuteResult() ExecuteResult { + return make(map[string]interface{}) +} + +// GetSuccess returns whether the script was successful or not. +func (e ExecuteResult) GetSuccess() bool { + val, ok := e["success"].(bool) + if !ok { + return false + } + return val +} + +// Execute executes a script with the default options. +func (c *Compiler) Execute(code string, args *ExecuteArgs) (ExecuteResult, error) { + return c.ExecuteWithOptions(code, args, &ExecuteOptions{}) +} + +// VM returns a new goja runtime for the compiler. +func (c *Compiler) VM() *goja.Runtime { + runtime := c.newRuntime(false) + c.registerHelpersForVM(runtime) + return runtime +} + +// ExecuteWithOptions executes a script with the provided options. +func (c *Compiler) ExecuteWithOptions(code string, args *ExecuteArgs, opts *ExecuteOptions) (ExecuteResult, error) { + defer func() { + if err := recover(); err != nil { + gologger.Error().Msgf("Recovered panic %s %v: %v", code, args, err) + gologger.Verbose().Msgf("%s", debug.Stack()) + return + } + }() + if opts == nil { + opts = &ExecuteOptions{} + } + runtime := c.newRuntime(opts.Pool) + c.registerHelpersForVM(runtime) + + if args == nil { + args = NewExecuteArgs() + } + for k, v := range args.Args { + _ = runtime.Set(k, v) + } + if args.TemplateCtx == nil { + args.TemplateCtx = make(map[string]interface{}) + } + // merge all args into templatectx + args.TemplateCtx = generators.MergeMaps(args.TemplateCtx, args.Args) + _ = runtime.Set("template", args.TemplateCtx) + + results, err := runtime.RunString(code) + if err != nil { + return nil, err + } + captured := results.Export() + + if opts.CaptureOutput { + return convertOutputToResult(captured) + } + if len(opts.CaptureVariables) > 0 { + return c.captureVariables(runtime, opts.CaptureVariables) + } + // success is true by default . since js throws errors on failure + // hence output result is always success + return ExecuteResult{"response": captured, "success": results.ToBoolean()}, nil +} + +// captureVariables captures the variables from the runtime. +func (c *Compiler) captureVariables(runtime *goja.Runtime, variables []string) (ExecuteResult, error) { + results := make(ExecuteResult, len(variables)) + for _, variable := range variables { + value := runtime.Get(variable) + if value == nil { + continue + } + results[variable] = value.Export() + } + return results, nil +} + +func convertOutputToResult(output interface{}) (ExecuteResult, error) { + marshalled, err := jsoniter.Marshal(output) + if err != nil { + return nil, errors.Wrap(err, "could not marshal output") + } + + var outputMap map[string]interface{} + if err := jsoniter.Unmarshal(marshalled, &outputMap); err != nil { + var v interface{} + if unmarshalErr := jsoniter.Unmarshal(marshalled, &v); unmarshalErr != nil { + return nil, unmarshalErr + } + outputMap = map[string]interface{}{"output": v} + return outputMap, nil + } + return outputMap, nil +} + +// newRuntime creates a new goja runtime +// TODO: Add support for runtime reuse for helper functions +func (c *Compiler) newRuntime(reuse bool) *goja.Runtime { + return goja.New() +} + +// registerHelpersForVM registers all the helper functions for the goja runtime. +func (c *Compiler) registerHelpersForVM(runtime *goja.Runtime) { + _ = c.registry.Enable(runtime) + // by default import below modules every time + _ = runtime.Set("console", require.Require(runtime, console.ModuleName)) + + // Register embedded scripts + if err := global.RegisterNativeScripts(runtime); err != nil { + gologger.Error().Msgf("Could not register scripts: %s\n", err) + } +} diff --git a/v2/pkg/js/compiler/compiler_test.go b/v2/pkg/js/compiler/compiler_test.go new file mode 100644 index 0000000000..8a85a75e33 --- /dev/null +++ b/v2/pkg/js/compiler/compiler_test.go @@ -0,0 +1,79 @@ +package compiler + +import ( + "strings" + "testing" + + "github.com/projectdiscovery/gologger" + "github.com/projectdiscovery/gologger/levels" +) + +func TestNewCompilerConsoleDebug(t *testing.T) { + gotString := "" + gologger.DefaultLogger.SetMaxLevel(levels.LevelDebug) + gologger.DefaultLogger.SetWriter(&noopWriter{ + Callback: func(data []byte, level levels.Level) { + gotString = string(data) + }, + }) + + compiler := New() + _, err := compiler.Execute("console.log('hello world');", NewExecuteArgs()) + if err != nil { + t.Fatal(err) + } + if !strings.HasSuffix(gotString, "hello world") { + t.Fatalf("console.log not working, got=%v", gotString) + } +} + +func TestExecuteResultGetSuccess(t *testing.T) { + compiler := New() + result, err := compiler.Execute("1+1 == 2", NewExecuteArgs()) + if err != nil { + t.Fatal(err) + } + if result.GetSuccess() != true { + t.Fatalf("expected true, got=%v", result.GetSuccess()) + } +} + +func TestCompilerCaptureVariables(t *testing.T) { + compiler := New() + result, err := compiler.ExecuteWithOptions("var a = 1;", NewExecuteArgs(), &ExecuteOptions{CaptureVariables: []string{"a"}}) + if err != nil { + t.Fatal(err) + } + gotValue, ok := result["a"] + if !ok { + t.Fatalf("expected a to be present in the result") + } + if gotValue.(int64) != 1 { + t.Fatalf("expected a to be 1, got=%v", gotValue) + } +} + +func TestCompilerCaptureOutput(t *testing.T) { + compiler := New() + result, err := compiler.ExecuteWithOptions("let obj = {'a':'b'}; obj", NewExecuteArgs(), &ExecuteOptions{CaptureOutput: true}) + if err != nil { + t.Fatal(err) + } + gotValue, ok := result["a"] + if !ok { + t.Fatalf("expected a to be present in the result") + } + if gotValue.(string) != "b" { + t.Fatalf("expected a to be b, got=%v", gotValue) + } +} + +type noopWriter struct { + Callback func(data []byte, level levels.Level) +} + +func (n *noopWriter) Write(data []byte, level levels.Level) { + if n.Callback != nil { + n.Callback(data, level) + } +} diff --git a/v2/pkg/js/devtools/README.md b/v2/pkg/js/devtools/README.md new file mode 100644 index 0000000000..373e4b92ce --- /dev/null +++ b/v2/pkg/js/devtools/README.md @@ -0,0 +1,35 @@ +## devtools + +devtools contains tools and scripts to automate booring tasks related to javascript layer/ packages. + +### bindgen + +[bindgen](./bindgen/README.md) is a tool that automatically generated bindings for native go packages with 'goja' + +### jsdocgen + +[jsdocgen](./jsdocgen/README.md) is LLM (OpenAI) based dev tool it takes generated javascript files and annotes them with jsdoc comments using predefined prompt + +### scrapefuncs + +[scrapefuncs](./scrapefuncs/README.md) is a tool to scrapes all helper functions exposed in javascript with help of go/ast and generates a js file with jsdoc comments using LLM (OpenAI) + + +### Generating API Reference (aka static site using javascript files using jsdoc) + +```console +jsdoc -R [Homepage.md] -r -d api_reference -t [optional: jsdoc theme to use] generated/js +``` + +generated static site will be available at `api_reference/` directory and can be verified using simplehttpserver + +```console +simplehttpserver +``` + +and then open `http://localhost:8000/` in browser + + +### Notes + +we currently use [clean-jsdoc-theme](https://www.npmjs.com/package/clean-jsdoc-theme) demo at [sample-jsproto-docs/](https://projectdiscovery.github.io/js-proto-docs/) \ No newline at end of file diff --git a/v2/pkg/js/devtools/bindgen/INSTALL.md b/v2/pkg/js/devtools/bindgen/INSTALL.md new file mode 100644 index 0000000000..11cfb1e93e --- /dev/null +++ b/v2/pkg/js/devtools/bindgen/INSTALL.md @@ -0,0 +1,4 @@ +# INSTALL + +1. Requires `js-beautify` node plugin installed in `$PATH`. +2. Requires `gofmt` installed in `$PATH`. diff --git a/v2/pkg/js/devtools/bindgen/README.md b/v2/pkg/js/devtools/bindgen/README.md new file mode 100644 index 0000000000..f4028d05e0 --- /dev/null +++ b/v2/pkg/js/devtools/bindgen/README.md @@ -0,0 +1,14 @@ +## bindgen (aka bindings generator) + +bindgen is a tool that automatically generated bindings for native go packages with 'goja' + +Native Go packages are available [here](../../libs/) + +Generated Output is available [here](../../generated/) + +bindgen generates 3 different types of outputs + +- `go` => this directory contains corresponding goja bindings (actual bindings code) ex: [kerberos.go](../../generated/go/libkerberos/kerberos.go) +- `js` => this is more of a javascript **representation** of all exposed functions and types etc in javascript ex: [kerberos.js](../../generated/js/libkerberos/kerberos.js) and does not server any functional purpose other than reference +- `markdown` => autogenerated markdown documentation for each library / package ex: [kerberos.md](../../generated/markdown/libkerberos/kerberos.md) + diff --git a/v2/pkg/js/devtools/bindgen/cmd/bindgen/main.go b/v2/pkg/js/devtools/bindgen/cmd/bindgen/main.go new file mode 100644 index 0000000000..36c1f10474 --- /dev/null +++ b/v2/pkg/js/devtools/bindgen/cmd/bindgen/main.go @@ -0,0 +1,76 @@ +package main + +import ( + "flag" + "fmt" + "log" + "path" + "path/filepath" + + "github.com/pkg/errors" + generator "github.com/projectdiscovery/nuclei/v2/pkg/js/devtools/bindgen" + fileutil "github.com/projectdiscovery/utils/file" +) + +var ( + dir string + generatedDir string + targetModules string +) + +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.Parse() + log.SetFlags(0) + if !fileutil.FolderExists(dir) { + log.Fatalf("directory %s does not exist", dir) + } + if err := process(); err != nil { + log.Fatal(err) + } +} + +func process() error { + modules, err := generator.GetLibraryModules(dir) + if err != nil { + return errors.Wrap(err, "could not get library modules") + } + if len(modules) == 0 && fileutil.FolderExists(dir) { + // if no modules are found, then given directory is the module itself + targetModules = path.Base(dir) + modules = append(modules, targetModules) + dir = filepath.Dir(dir) + } + for _, module := range modules { + log.Printf("[module] Generating %s", module) + + data, err := generator.CreateTemplateData(filepath.Join(dir, module), "github.com/projectdiscovery/nuclei/v2/pkg/js/libs/") + if err != nil { + return fmt.Errorf("could not create template data: %v", err) + } + + prefixed := "lib" + module + 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) + } + // disabled for now since we have static website for docs + // err = data.WriteMarkdownLibraryDocumentation(path.Join(generatedDir, "markdown/"), module) + // if err != nil { + // return fmt.Errorf("could not write markdown template: %v", err) + // } + + // err = data.WriteMarkdownIndexTemplate(path.Join(generatedDir, "markdown/")) + // if err != nil { + // return fmt.Errorf("could not write markdown index template: %v", err) + // } + data.InitNativeScripts() + } + return nil +} diff --git a/v2/pkg/js/devtools/bindgen/generator.go b/v2/pkg/js/devtools/bindgen/generator.go new file mode 100644 index 0000000000..6f46b2ee67 --- /dev/null +++ b/v2/pkg/js/devtools/bindgen/generator.go @@ -0,0 +1,412 @@ +package generator + +import ( + "fmt" + "go/ast" + "go/importer" + "go/parser" + "go/token" + "go/types" + "log" + "os" + "strings" + + _ "embed" + + "github.com/pkg/errors" + "github.com/projectdiscovery/nuclei/v2/pkg/js/compiler" +) + +var ( + //go:embed templates/js_class.tmpl + jsClassFile string + //go:embed templates/go_class.tmpl + goClassFile string + //go:embed templates/markdown_class.tmpl + markdownClassFile string +) + +// TemplateData contains the parameters for the JS code generator +type TemplateData struct { + PackageName string + PackagePath string + PackageFuncs map[string]string + PackageInterfaces map[string]string + PackageFuncsExtraNoType map[string]PackageFunctionExtra + PackageFuncsExtra map[string]PackageFuncExtra + PackageVars map[string]string + PackageVarsValues map[string]string + PackageTypes map[string]string + PackageTypesExtra map[string]PackageTypeExtra + + typesPackage *types.Package + + // NativeScripts contains the list of native scripts + // that should be included in the package. + NativeScripts []string +} + +// PackageTypeExtra contains extra information about a type +type PackageTypeExtra struct { + Fields map[string]string +} + +// PackageFuncExtra contains extra information about a function +type PackageFuncExtra struct { + Items map[string]PackageFunctionExtra + Doc string +} + +// PackageFunctionExtra contains extra information about a function +type PackageFunctionExtra struct { + Args []string + Name string + Returns []string + Doc string +} + +// newTemplateData creates a new template data structure +func newTemplateData(packagePrefix, pkgName string) *TemplateData { + return &TemplateData{ + PackageName: pkgName, + PackagePath: packagePrefix + pkgName, + PackageFuncs: make(map[string]string), + PackageFuncsExtraNoType: make(map[string]PackageFunctionExtra), + PackageFuncsExtra: make(map[string]PackageFuncExtra), + PackageVars: make(map[string]string), + PackageVarsValues: make(map[string]string), + PackageTypes: make(map[string]string), + PackageInterfaces: make(map[string]string), + PackageTypesExtra: make(map[string]PackageTypeExtra), + } +} + +// GetLibraryModules takes a directory and returns subdirectories as modules +func GetLibraryModules(directory string) ([]string, error) { + dirs, err := os.ReadDir(directory) + if err != nil { + return nil, errors.Wrap(err, "could not read directory") + } + var modules []string + for _, dir := range dirs { + if dir.IsDir() { + modules = append(modules, dir.Name()) + } + } + return modules, nil +} + +// CreateTemplateData creates a TemplateData structure from a directory +// of go source code. +func CreateTemplateData(directory string, packagePrefix string) (*TemplateData, error) { + fmt.Println(directory) + fset := token.NewFileSet() + + pkgs, err := parser.ParseDir(fset, directory, nil, parser.ParseComments) + if err != nil { + return nil, errors.Wrap(err, "could not parse directory") + } + if len(pkgs) != 1 { + return nil, fmt.Errorf("expected 1 package, got %d", len(pkgs)) + } + + config := &types.Config{ + Importer: importer.ForCompiler(fset, "source", nil), + } + var packageName string + var files []*ast.File + for k, v := range pkgs { + packageName = k + for _, f := range v.Files { + files = append(files, f) + } + break + } + + pkg, err := config.Check(packageName, fset, files, nil) + if err != nil { + return nil, errors.Wrap(err, "could not check package") + } + + var pkgMain *ast.Package + for _, p := range pkgs { + pkgMain = p + break + } + + log.Printf("[create] [discover] Package: %s\n", pkgMain.Name) + data := newTemplateData(packagePrefix, pkgMain.Name) + data.typesPackage = pkg + data.gatherPackageData(pkgMain, data) + + for item, v := range data.PackageFuncsExtra { + if len(v.Items) == 0 { + delete(data.PackageFuncsExtra, item) + } + } + return data, nil +} + +// InitNativeScripts initializes the native scripts array +// with all the exported functions from the runtime +func (d *TemplateData) InitNativeScripts() { + compiler := compiler.New() + runtime := compiler.VM() + + exports := runtime.Get("exports") + if exports == nil { + return + } + exportsObj := exports.Export() + if exportsObj == nil { + return + } + for v := range exportsObj.(map[string]interface{}) { + d.NativeScripts = append(d.NativeScripts, v) + } +} + +// gatherPackageData gathers data about the package +func (d *TemplateData) gatherPackageData(pkg *ast.Package, data *TemplateData) { + ast.Inspect(pkg, func(node ast.Node) bool { + switch node := node.(type) { + case *ast.FuncDecl: + extra := d.collectFuncDecl(node) + if extra.Name == "" { + return true + } + data.PackageFuncsExtraNoType[node.Name.Name] = extra + data.PackageFuncs[node.Name.Name] = node.Name.Name + case *ast.TypeSpec: + if !node.Name.IsExported() { + return true + } + if node.Type == nil { + return true + } + structDecl, ok := node.Type.(*ast.StructType) + if !ok { + return true + } + + packageTypes := PackageTypeExtra{ + Fields: make(map[string]string), + } + for _, field := range structDecl.Fields.List { + fieldName := field.Names[0].Name + + var fieldTypeValue string + switch fieldType := field.Type.(type) { + case *ast.Ident: // Field type is a simple identifier + fieldTypeValue = fieldType.Name + case *ast.ArrayType: + switch fieldType.Elt.(type) { + case *ast.Ident: + fieldTypeValue = fmt.Sprintf("[]%s", fieldType.Elt.(*ast.Ident).Name) + case *ast.StarExpr: + fieldTypeValue = fmt.Sprintf("[]%s", d.handleStarExpr(fieldType.Elt.(*ast.StarExpr))) + } + case *ast.SelectorExpr: // Field type is a qualified identifier + fieldTypeValue = fmt.Sprintf("%s.%s", fieldType.X, fieldType.Sel) + } + packageTypes.Fields[fieldName] = fieldTypeValue + } + if len(packageTypes.Fields) == 0 { + return true + } + data.PackageTypesExtra[node.Name.Name] = packageTypes + case *ast.GenDecl: + identifyGenDecl(pkg, node, data) + } + return true + }) +} + +func identifyGenDecl(pkg *ast.Package, decl *ast.GenDecl, data *TemplateData) { + for _, spec := range decl.Specs { + switch spec := spec.(type) { + case *ast.ValueSpec: + if !spec.Names[0].IsExported() { + continue + } + if spec.Values == nil || len(spec.Values) == 0 { + continue + } + data.PackageVars[spec.Names[0].Name] = spec.Names[0].Name + data.PackageVarsValues[spec.Names[0].Name] = spec.Values[0].(*ast.BasicLit).Value + case *ast.TypeSpec: + if !spec.Name.IsExported() { + continue + } + if spec.Type == nil { + continue + } + + switch spec.Type.(type) { + case *ast.InterfaceType: + data.PackageInterfaces[spec.Name.Name] = convertCommentsToJavascript(decl.Doc.Text()) + + case *ast.StructType: + data.PackageFuncsExtra[spec.Name.Name] = PackageFuncExtra{ + Items: make(map[string]PackageFunctionExtra), + Doc: convertCommentsToJavascript(decl.Doc.Text()), + } + + // Traverse the AST. + collectStructFuncsFromAST(pkg, spec, data) + data.PackageTypes[spec.Name.Name] = spec.Name.Name + } + } + } +} + +func collectStructFuncsFromAST(pkg *ast.Package, spec *ast.TypeSpec, data *TemplateData) { + ast.Inspect(pkg, func(n ast.Node) bool { + if fn, isFunc := n.(*ast.FuncDecl); isFunc && fn.Name.IsExported() { + processFunc(fn, spec, data) + } + return true + }) +} + +func processFunc(fn *ast.FuncDecl, spec *ast.TypeSpec, data *TemplateData) { + if fn.Recv == nil || len(fn.Recv.List) == 0 { + return + } + + if t, ok := fn.Recv.List[0].Type.(*ast.StarExpr); ok { + if ident, ok := t.X.(*ast.Ident); ok && spec.Name.Name == ident.Name { + processFunctionDetails(fn, ident, data) + } + } +} + +func processFunctionDetails(fn *ast.FuncDecl, ident *ast.Ident, data *TemplateData) { + extra := PackageFunctionExtra{ + Name: fn.Name.Name, + Args: extractArgs(fn), + Doc: convertCommentsToJavascript(fn.Doc.Text()), + Returns: data.extractReturns(fn), + } + data.PackageFuncsExtra[ident.Name].Items[fn.Name.Name] = extra +} + +func extractArgs(fn *ast.FuncDecl) []string { + args := make([]string, 0) + for _, arg := range fn.Type.Params.List { + for _, name := range arg.Names { + args = append(args, name.Name) + } + } + return args +} + +func (d *TemplateData) extractReturns(fn *ast.FuncDecl) []string { + returns := make([]string, 0) + if fn.Type.Results == nil { + return returns + } + for _, ret := range fn.Type.Results.List { + returnType := d.extractReturnType(ret) + if returnType != "" { + returns = append(returns, returnType) + } + } + return returns +} + +func (d *TemplateData) extractReturnType(ret *ast.Field) string { + switch v := ret.Type.(type) { + case *ast.ArrayType: + if v, ok := v.Elt.(*ast.Ident); ok { + return fmt.Sprintf("[]%s", v.Name) + } + if v, ok := v.Elt.(*ast.StarExpr); ok { + return fmt.Sprintf("[]%s", d.handleStarExpr(v)) + } + case *ast.Ident: + return v.Name + case *ast.StarExpr: + return d.handleStarExpr(v) + } + return "" +} + +func (d *TemplateData) handleStarExpr(v *ast.StarExpr) string { + switch vk := v.X.(type) { + case *ast.Ident: + return vk.Name + case *ast.SelectorExpr: + if vk.X != nil { + d.collectTypeFromExternal(d.typesPackage, vk.X.(*ast.Ident).Name, vk.Sel.Name) + } + return vk.Sel.Name + } + return "" +} + +func (d *TemplateData) collectTypeFromExternal(pkg *types.Package, pkgName, name string) { + extra := PackageTypeExtra{ + Fields: make(map[string]string), + } + + for _, importValue := range pkg.Imports() { + if importValue.Name() != pkgName { + continue + } + obj := importValue.Scope().Lookup(name) + if obj == nil || !obj.Exported() { + continue + } + typeName, ok := obj.(*types.TypeName) + if !ok { + continue + } + underlying, ok := typeName.Type().Underlying().(*types.Struct) + if !ok { + continue + } + for i := 0; i < underlying.NumFields(); i++ { + field := underlying.Field(i) + fieldType := field.Type().String() + + if val, ok := field.Type().Underlying().(*types.Pointer); ok { + fieldType = field.Name() + d.collectTypeFromExternal(pkg, pkgName, val.Elem().(*types.Named).Obj().Name()) + } + if _, ok := field.Type().Underlying().(*types.Struct); ok { + fieldType = field.Name() + d.collectTypeFromExternal(pkg, pkgName, field.Name()) + } + extra.Fields[field.Name()] = fieldType + } + if len(extra.Fields) > 0 { + d.PackageTypesExtra[name] = extra + } + } +} + +func (d *TemplateData) collectFuncDecl(decl *ast.FuncDecl) (extra PackageFunctionExtra) { + if decl.Recv != nil { + return + } + if !decl.Name.IsExported() { + return + } + extra.Name = decl.Name.Name + extra.Doc = convertCommentsToJavascript(decl.Doc.Text()) + + for _, arg := range decl.Type.Params.List { + for _, name := range arg.Names { + extra.Args = append(extra.Args, name.Name) + } + } + extra.Returns = d.extractReturns(decl) + return extra +} + +// convertCommentsToJavascript converts comments to javascript comments. +func convertCommentsToJavascript(comments string) string { + suffix := strings.Trim(strings.TrimSuffix(strings.ReplaceAll(comments, "\n", "\n// "), "// "), "\n") + return fmt.Sprintf("// %s", suffix) +} diff --git a/v2/pkg/js/devtools/bindgen/output.go b/v2/pkg/js/devtools/bindgen/output.go new file mode 100644 index 0000000000..990d1fa43e --- /dev/null +++ b/v2/pkg/js/devtools/bindgen/output.go @@ -0,0 +1,160 @@ +package generator + +import ( + "bytes" + "fmt" + "os" + "os/exec" + "path" + "strings" + "text/template" + + "github.com/pkg/errors" +) + +// markdownIndexes is a map of markdown modules to their filename index +// +// It is used to generate the index.md file for the documentation +var markdownIndexes = make(map[string]string) + +// WriteGoTemplate writes the go template to the output file +func (d *TemplateData) WriteGoTemplate(outputDirectory string, pkgName string) error { + _ = os.MkdirAll(outputDirectory, os.ModePerm) + + var err error + tmpl := template.New("go_class") + tmpl = tmpl.Funcs(templateFuncs()) + tmpl, err = tmpl.Parse(goClassFile) + if err != nil { + return errors.Wrap(err, "could not parse go class template") + } + + filename := path.Join(outputDirectory, fmt.Sprintf("%s.go", pkgName)) + output, err := os.Create(filename) + if err != nil { + return errors.Wrap(err, "could not create go class template") + } + + if err := tmpl.Execute(output, d); err != nil { + output.Close() + return errors.Wrap(err, "could not execute go class template") + } + output.Close() + + cmd := exec.Command("gofmt", "-w", filename) + cmd.Stderr = os.Stderr + cmd.Stdout = os.Stdout + if err := cmd.Run(); err != nil { + return errors.Wrap(err, "could not format go class template") + } + return nil +} + +// WriteJSTemplate writes the js template to the output file +func (d *TemplateData) WriteJSTemplate(outputDirectory string, pkgName string) error { + _ = os.MkdirAll(outputDirectory, os.ModePerm) + + var err error + tmpl := template.New("js_class") + tmpl, err = tmpl.Parse(jsClassFile) + if err != nil { + return errors.Wrap(err, "could not parse js class template") + } + + filename := path.Join(outputDirectory, fmt.Sprintf("%s.js", pkgName)) + output, err := os.Create(filename) + if err != nil { + return errors.Wrap(err, "could not create js class template") + } + + if err := tmpl.Execute(output, d); err != nil { + output.Close() + return errors.Wrap(err, "could not execute js class template") + } + output.Close() + + cmd := exec.Command("js-beautify", "-r", filename) + cmd.Stderr = os.Stderr + cmd.Stdout = os.Stdout + if err := cmd.Run(); err != nil { + return err + } + return nil +} + +// WriteMarkdownIndexTemplate writes the markdown documentation to the output file +func (d *TemplateData) WriteMarkdownIndexTemplate(outputDirectory string) error { + _ = os.MkdirAll(outputDirectory, os.ModePerm) + + filename := path.Join(outputDirectory, "index.md") + output, err := os.Create(filename) + if err != nil { + return errors.Wrap(err, "could not create markdown index template") + } + defer output.Close() + + buffer := &bytes.Buffer{} + _, _ = buffer.WriteString("# Index\n\n") + for _, v := range markdownIndexes { + _, _ = buffer.WriteString(fmt.Sprintf("* %s\n", v)) + } + _, _ = buffer.WriteString("\n\n") + + _, _ = buffer.WriteString("# Scripts\n\n") + for _, v := range d.NativeScripts { + _, _ = buffer.WriteString(fmt.Sprintf("* `%s`\n", v)) + } + if _, err := output.Write(buffer.Bytes()); err != nil { + return errors.Wrap(err, "could not write markdown index template") + } + return nil +} + +// WriteMarkdownLibraryDocumentation writes the markdown documentation for a js library +// to the output file +func (d *TemplateData) WriteMarkdownLibraryDocumentation(outputDirectory string, pkgName string) error { + var err error + _ = os.MkdirAll(outputDirectory, os.ModePerm) + + tmpl := template.New("markdown_class") + tmpl = tmpl.Funcs(templateFuncs()) + tmpl, err = tmpl.Parse(markdownClassFile) + if err != nil { + return errors.Wrap(err, "could not parse markdown class template") + } + + filename := path.Join(outputDirectory, fmt.Sprintf("%s.md", pkgName)) + output, err := os.Create(filename) + if err != nil { + return errors.Wrap(err, "could not create markdown class template") + } + + markdownIndexes[pkgName] = fmt.Sprintf("[%s](%s.md)", pkgName, pkgName) + if err := tmpl.Execute(output, d); err != nil { + output.Close() + return err + } + output.Close() + + return nil +} + +// templateFuncs returns the template functions for the generator +func templateFuncs() map[string]interface{} { + return map[string]interface{}{ + "exist": func(v map[string]string, key string) bool { + _, exist := v[key] + return exist + }, + "toTitle": func(v string) string { + if len(v) == 0 { + return v + } + + return strings.ToUpper(string(v[0])) + v[1:] + }, + "uncomment": func(v string) string { + return strings.ReplaceAll(strings.ReplaceAll(v, "// ", " "), "\n", " ") + }, + } +} diff --git a/v2/pkg/js/devtools/bindgen/templates/go_class.tmpl b/v2/pkg/js/devtools/bindgen/templates/go_class.tmpl new file mode 100644 index 0000000000..3432430ab6 --- /dev/null +++ b/v2/pkg/js/devtools/bindgen/templates/go_class.tmpl @@ -0,0 +1,48 @@ +package {{.PackageName}} + +{{$pkgName:=(printf "lib_%s" .PackageName) -}} + +import ( + {{$pkgName}} "{{.PackagePath}}" + + "github.com/dop251/goja" + "github.com/projectdiscovery/nuclei/v2/pkg/js/gojs" +) + +var ( + module = gojs.NewGojaModule("nuclei/{{.PackageName}}") +) + +func init() { + module.Set( + gojs.Objects{ + {{- $pkgFuncs:=.PackageFuncs}} + // Functions + {{- range $objName, $objDefine := .PackageFuncs}} + "{{$objName}}": {{$pkgName}}.{{$objDefine}}, + {{- end}} + + // Var and consts + {{- range $objName, $objDefine := .PackageVars}} + "{{$objName}}": {{$pkgName}}.{{$objDefine}}, + {{- end}} + + // Types (value type) + {{- range $objName, $objDefine := .PackageTypes}} + "{{$objName}}": {{printf "func() %s.%s { return %s.%s{} }" $pkgName $objDefine $pkgName $objDefine}}, + {{- end}} + + // Types (pointer type) + {{range $objName, $objDefine := .PackageTypes}} + {{- $newObjName := printf "%s%s" "New" $objName -}} + {{- if not (exist $pkgFuncs $newObjName) -}} + "{{$newObjName}}": {{printf "func() *%s.%s { return &%s.%s{} }" $pkgName $objDefine $pkgName $objDefine}}, + {{end -}} + {{- end -}} + }, + ).Register() +} + +func Enable(runtime *goja.Runtime) { + module.Enable(runtime) +} \ No newline at end of file diff --git a/v2/pkg/js/devtools/bindgen/templates/js_class.tmpl b/v2/pkg/js/devtools/bindgen/templates/js_class.tmpl new file mode 100644 index 0000000000..064eba80d3 --- /dev/null +++ b/v2/pkg/js/devtools/bindgen/templates/js_class.tmpl @@ -0,0 +1,35 @@ +{{$packageName:=(printf "%s" .PackageName) -}} +/**@module {{$packageName}} */ +// {{$packageName}} implements bindings for {{.PackageName}} protocol in javascript +// to be used from nuclei scanner. + +{{- range $typeName, $methods := .PackageFuncsExtra }} + +{{ $methods.Doc }} +class {{$typeName}} { + + {{- range $methodName, $method := $methods.Items }} + {{$method.Doc}} + {{ $method.Name }}({{range $index, $arg := $method.Args}}{{if $index}}, {{end}}{{ $arg }}{{end}}) { + return {{range $idx, $arg := $method.Returns}}{{if $idx}}, {{end}}{{ $arg }}{{end}}; + }; + {{- end }} +}; + +{{- end }} + +{{- range $objName, $method := .PackageFuncsExtraNoType}} +function {{$objName}}({{range $index, $arg := $method.Args}}{{if $index}}, {{end}}{{ $arg }}{{end}}) { + + }; +{{- end}} + + +module.exports = { +{{- range $typeName, $methods := .PackageFuncsExtra }} + {{$typeName}}: {{$typeName}}, +{{- end }} +{{- range $objName, $method := .PackageFuncsExtraNoType}} + {{$objName}}: {{$objName}}, +{{- end}} +}; \ No newline at end of file diff --git a/v2/pkg/js/devtools/bindgen/templates/markdown_class.tmpl b/v2/pkg/js/devtools/bindgen/templates/markdown_class.tmpl new file mode 100644 index 0000000000..506532e8ef --- /dev/null +++ b/v2/pkg/js/devtools/bindgen/templates/markdown_class.tmpl @@ -0,0 +1,71 @@ +{{$packageName:=(printf "%s" .PackageName) -}} +## {{$packageName}} +--- + + +`{{$packageName}}` implements bindings for `{{.PackageName}}` protocol in javascript +to be used from nuclei scanner. + + +{{ if .PackageFuncsExtra }} +## Types + +{{- range $typeName, $methods := .PackageFuncsExtra }} + +### {{$typeName}} + +{{ uncomment $methods.Doc }} + +| Method | Description | Arguments | Returns | +|--------|-------------|-----------|---------| +{{- range $methodName, $method := $methods.Items }} +| `{{$methodName}}` | {{uncomment $method.Doc}} | {{range $index, $arg := $method.Args}}{{if $index}}, {{end}}`{{ $arg }}`{{end}} | {{range $idx, $arg := $method.Returns}}{{if $idx}}, {{end}}`{{ $arg }}`{{end}} | +{{- end }} + +{{- end }} +{{- end }} + +{{ if .PackageFuncsExtraNoType }} +## Exported Functions + +| Name | Description | Arguments | Returns | +|--------|-------------|-----------|---------| +{{- range $objName, $method := .PackageFuncsExtraNoType}} +{{$objName}} | {{uncomment $method.Doc}} | {{range $index, $arg := $method.Args}}{{if $index}}, {{end}}`{{ $arg }}`{{end}} | {{range $idx, $arg := $method.Returns}}{{if $idx}}, {{end}}`{{ $arg }}`{{end}} | +{{- end}} +{{- end}} + +{{ if .PackageTypesExtra }} +## Exported Types Fields + +{{- range $typeName, $methods := .PackageTypesExtra }} +### {{$typeName}} + +| Name | Type | +|--------|-------------| +{{- range $fieldName, $field := $methods.Fields }} +| {{$fieldName}} | `{{ $field }}` | +{{- end }} +{{- end }} +{{- end }} + +{{ if .PackageVarsValues }} + +## Exported Variables Values + +| Name | Value | +|--------|-------------| +{{- range $varName, $var := .PackageVarsValues }} +| {{$varName}} | `{{ $var }}` | +{{- end }} +{{- end}} + +{{ if .PackageInterfaces }} +## Exported Interfaces + +{{- range $typeName, $doc := .PackageInterfaces }} +### {{$typeName}} + +{{ uncomment $doc }} +{{- end }} +{{- end }} diff --git a/v2/pkg/js/devtools/jsdocgen/README.md b/v2/pkg/js/devtools/jsdocgen/README.md new file mode 100644 index 0000000000..10bf824173 --- /dev/null +++ b/v2/pkg/js/devtools/jsdocgen/README.md @@ -0,0 +1,116 @@ +## jsdocgen + +jsdocgen is LLM (OpenAI) based dev tool it takes generated javascript files and annotes them with jsdoc comments using predefined prompt + +### Usage + +```bash + ./jsdocgen -h +Usage of ./jsdocgen: + -dir string + directory to process + -key string + openai api key + -keyfile string + openai api key file +``` + +### Example + +```bash +./jsdocgen -dir modules/generated/js/libmysql -keyfile ~/.openai/key +``` + + +### Example Conversion + +when `bindgen` is executed it generates basic javascript (which currently is incorrect) and looks like this but the idea is to generate bare minimum that LLM has idea what we are trying to do + +```javascript +/**@module rdp */ +// rdp implements bindings for rdp protocol in javascript +// to be used from nuclei scanner. + +// RDPClient is a client for rdp servers +class RDPClient { + // CheckRDPAuth checks if the given host and port are running rdp server + // with authentication and returns their metadata. + CheckRDPAuth(host, port) { + return CheckRDPAuthResponse, error; + }; + // IsRDP checks if the given host and port are running rdp server. + // + // If connection is successful, it returns true. + // If connection is unsuccessful, it returns false and error. + // + // The Name of the OS is also returned if the connection is successful. + IsRDP(host, port) { + return IsRDPResponse, error; + }; +}; + + +module.exports = { + RDPClient: RDPClient, +}; +``` + +And when `jsdocgen` is executed it generates the following output + +```javascript +/** + * @module rdp + * This module implements bindings for rdp protocol in javascript to be used from nuclei scanner. + */ + +/** + * @class + * @classdesc RDPClient is a client for rdp servers + */ +class RDPClient { + /** + * @method + * @name CheckRDPAuth + * @description checks if the given host and port are running rdp server with authentication and returns their metadata. + * @param {string} host - The host of the rdp server + * @param {number} port - The port of the rdp server + * @returns {CheckRDPAuthResponse} - The response from the rdp server + * @throws {error} If there is an error in the request + * @example + * let client = new RDPClient(); + * client.CheckRDPAuth("localhost", 3389); + */ + CheckRDPAuth(host, port) { + // implemented in go + }; + + /** + * @method + * @name IsRDP + * @description checks if the given host and port are running rdp server. + * If connection is successful, it returns true. + * If connection is unsuccessful, it throws an error. + * The Name of the OS is also returned if the connection is successful. + * @param {string} host - The host of the rdp server + * @param {number} port - The port of the rdp server + * @returns {IsRDPResponse} - The response from the rdp server + * @throws {error} If there is an error in the request + * @example + * let client = new RDPClient(); + * client.IsRDP("localhost", 3389); + */ + IsRDP(host, port) { + // implemented in go + }; +}; + +module.exports = { + RDPClient: RDPClient, +}; +``` + +Now we can see the output is much more readable and make sense. + +## Note: + +jsdocgen is not perfect and it is not supposed to be, it is intended to **almost** automate boooring stuff but will always require some manual intervention to make it perfect. \ No newline at end of file diff --git a/v2/pkg/js/devtools/jsdocgen/jsdocgen b/v2/pkg/js/devtools/jsdocgen/jsdocgen new file mode 100755 index 0000000000..f032086022 Binary files /dev/null and b/v2/pkg/js/devtools/jsdocgen/jsdocgen differ diff --git a/v2/pkg/js/devtools/jsdocgen/main.go b/v2/pkg/js/devtools/jsdocgen/main.go new file mode 100644 index 0000000000..cc5083f0be --- /dev/null +++ b/v2/pkg/js/devtools/jsdocgen/main.go @@ -0,0 +1,108 @@ +package main + +import ( + "context" + "flag" + "log" + "os" + "path/filepath" + "strings" + + errorutil "github.com/projectdiscovery/utils/errors" + fileutil "github.com/projectdiscovery/utils/file" + openai "github.com/sashabaranov/go-openai" +) + +var ( + dir string + key string + keyfile string +) + +const sysPrompt = ` +Act as helpful coding assistant and using provided original javascript code and instructions create a new javascript file with valid jsdoc annotations/tags +--- instructions --- +new javascript file should contain JsDOC annotations like @module, @class, @method, @typedef, @throws, @return, @param, and @example, +incorporating all necessary information applicable. Your new file must strictly stick to classes, methods, or functions present in the original code - no new elements are permitted. +While writing @example, do not access properties (aka variables) of types that are not defined/known. Properly identify if a element is function or method and properly annotate it. +Always include return types of functions/methods (when applicable). Omit Implementations of functions/methods in new javascript and replace it with '// implemented in go' comment. +Also Skip using @exports anywhere in file.Take additional care not to include 'error' as return type of any function/method as errors are thrown not returned in javascript. +Donot add jsdoc annotations to 'module.exports' and copy it without any modification +` + +const userPrompt = ` +---original javascript--- +{{source}} +---new javascript--- +` + +// doclint is automatic javascript documentation linter for nuclei +// it uses LLM to autocomplete the generated js code to proper JSDOC notation +func main() { + flag.StringVar(&dir, "dir", "", "directory to process") + flag.StringVar(&key, "key", "", "openai api key") + flag.StringVar(&keyfile, "keyfile", "", "openai api key file") + flag.Parse() + log.SetFlags(0) + + if dir == "" { + log.Fatal("dir is not set") + } + finalKey := "" + if key != "" { + key = finalKey + } + if keyfile != "" && fileutil.FileExists(keyfile) { + data, err := os.ReadFile(keyfile) + if err != nil { + log.Fatal(err) + } + finalKey = string(data) + } + if key := os.Getenv("OPENAI_API_KEY"); key != "" { + finalKey = key + } + + if finalKey == "" { + log.Fatal("openai api key is not set") + } + llm := openai.NewClient(finalKey) + + _ = filepath.WalkDir(dir, func(path string, d os.DirEntry, err error) error { + if !d.IsDir() && filepath.Ext(path) == ".js" { + log.Printf("Processing %s", path) + if err := updateDocsWithLLM(llm, path); err != nil { + log.Printf("Error processing %s: %s", path, err) + } else { + log.Printf("Processed %s", path) + } + } + return nil + }) +} + +// updateDocsWithLLM updates the documentation of a javascript file +func updateDocsWithLLM(llm *openai.Client, path string) error { + // read the file + bin, err := os.ReadFile(path) + if err != nil { + return err + } + + resp, err := llm.CreateChatCompletion(context.TODO(), openai.ChatCompletionRequest{ + Model: "gpt-4", + Messages: []openai.ChatCompletionMessage{ + {Role: "system", Content: sysPrompt}, + {Role: "user", Content: strings.ReplaceAll(userPrompt, "{{source}}", string(bin))}, + }, + Temperature: 0.1, + }) + if err != nil { + return err + } + if len(resp.Choices) == 0 { + return errorutil.New("no choices returned") + } + data := resp.Choices[0].Message.Content + return os.WriteFile(path, []byte(data), 0644) +} diff --git a/v2/pkg/js/devtools/scrapefuncs/README.md b/v2/pkg/js/devtools/scrapefuncs/README.md new file mode 100644 index 0000000000..de7c29ce2c --- /dev/null +++ b/v2/pkg/js/devtools/scrapefuncs/README.md @@ -0,0 +1,130 @@ +## scrapefuncs + +scrapefuncs is go/ast based tool to scrapes all helper functions exposed in javascript with help of go/ast and generates a js file with jsdoc comments using LLM (OpenAI) + +### Usage + +```console +Usage of ./scrapefuncs: + -dir string + directory to process (default "pkg/js/global") + -key string + openai api key + -keyfile string + openai api key file + -out string + output js file with declarations of all global functions +``` + + +### Example + +```console +$ ./scrapefuncs -keyfile ~/.openai.key +[+] Scraped 7 functions + +Name: Rand +Signatures: "Rand(n int) []byte" +Description: Rand returns a random byte slice of length n + +Name: RandInt +Signatures: "RandInt() int" +Description: RandInt returns a random int + +Name: log +Signatures: "log(msg string)" +Signatures: "log(msg map[string]interface{})" +Description: log prints given input to stdout with [JS] prefix for debugging purposes + +Name: getNetworkPort +Signatures: "getNetworkPort(port string, defaultPort string) string" +Description: getNetworkPort registers defaultPort and returns defaultPort if it is a colliding port with other protocols + +Name: isPortOpen +Signatures: "isPortOpen(host string, port string, [timeout int]) bool" +Description: isPortOpen checks if given port is open on host. timeout is optional and defaults to 5 seconds + +Name: ToBytes +Signatures: "ToBytes(...interface{}) []byte" +Description: ToBytes converts given input to byte slice + +Name: ToString +Signatures: "ToString(...interface{}) string" +Description: ToString converts given input to string + + +[+] Generating jsdoc for all functions + +/** + * Rand returns a random byte slice of length n + * Rand(n int) []byte + * @function + * @param {number} n - The length of the byte slice. + */ +function Rand(n) { + // implemented in go +}; + +/** + * RandInt returns a random int + * RandInt() int + * @function + */ +function RandInt() { + // implemented in go +}; + +/** + * log prints given input to stdout with [JS] prefix for debugging purposes + * log(msg string) + * log(msg map[string]interface{}) + * @function + * @param {string|Object} msg - The message to print. + */ +function log(msg) { + // implemented in go +}; + +/** + * getNetworkPort registers defaultPort and returns defaultPort if it is a colliding port with other protocols + * getNetworkPort(port string, defaultPort string) string + * @function + * @param {string} port - The port to check. + * @param {string} defaultPort - The default port to return if the port is colliding. + */ +function getNetworkPort(port, defaultPort) { + // implemented in go +}; + +/** + * isPortOpen checks if given port is open on host. timeout is optional and defaults to 5 seconds + * isPortOpen(host string, port string, [timeout int]) bool + * @function + * @param {string} host - The host to check. + * @param {string} port - The port to check. + * @param {number} [timeout=5] - The timeout in seconds. + */ +function isPortOpen(host, port, timeout = 5) { + // implemented in go +}; + +/** + * ToBytes converts given input to byte slice + * ToBytes(...interface{}) []byte + * @function + * @param {...any} args - The input to convert. + */ +function ToBytes(...args) { + // implemented in go +}; + +/** + * ToString converts given input to string + * ToString(...interface{}) string + * @function + * @param {...any} args - The input to convert. + */ +function ToString(...args) { + // implemented in go +}; +``` \ No newline at end of file diff --git a/v2/pkg/js/devtools/scrapefuncs/main.go b/v2/pkg/js/devtools/scrapefuncs/main.go new file mode 100644 index 0000000000..04c62f91f1 --- /dev/null +++ b/v2/pkg/js/devtools/scrapefuncs/main.go @@ -0,0 +1,157 @@ +package main + +import ( + "bytes" + "context" + "flag" + "fmt" + "go/ast" + "go/parser" + "go/token" + "log" + "os" + "strings" + + filutil "github.com/projectdiscovery/utils/file" + "github.com/sashabaranov/go-openai" +) + +var sysprompt = ` +data present after ---raw data--- contains raw data extracted by a parser and contains information about function +--- example --- +Name: log +Signatures: "log(msg string)" +Signatures: "log(msg map[string]interface{})" +Description: log prints given input to stdout with [JS] prefix for debugging purposes +--- end example --- +Here Name is name of function , signature[s] is actual function declaration and description is description of function +using this data for every such function generate a abstract implementation of function in javascript along with jsdoc annotations +--- example expected output--- +/** + * log prints given input to stdout with [JS] prefix for debugging purposes + * log(msg string) + * log(msg map[string]interface{}) + * @function + * @param {string} msg - The message to print. + */ +function log(msg) { + // implemented in go +}; +--- instructions --- +ACT as helpful coding assistant and do the same for all functions present in data +` + +const userPrompt = ` +---raw data--- +{{source}} +---new javascript--- +` + +var ( + dir string + key string + keyfile string + out string +) + +func main() { + flag.StringVar(&dir, "dir", "pkg/js/global", "directory to process") + flag.StringVar(&key, "key", "", "openai api key") + flag.StringVar(&keyfile, "keyfile", "", "openai api key file") + flag.StringVar(&out, "out", "", "output js file with declarations of all global functions") + flag.Parse() + + finalKey := "" + if key != "" { + key = finalKey + } + if keyfile != "" && filutil.FileExists(keyfile) { + data, err := os.ReadFile(keyfile) + if err != nil { + log.Fatal(err) + } + finalKey = string(data) + } + if key := os.Getenv("OPENAI_API_KEY"); key != "" { + finalKey = key + } + + if finalKey == "" { + log.Fatal("openai api key is not set") + } + llm := openai.NewClient(finalKey) + var buff bytes.Buffer + + fset := token.NewFileSet() + pkgs, err := parser.ParseDir(fset, dir, nil, 0) + if err != nil { + fmt.Println(err) + return + } + + for _, pkg := range pkgs { + for _, file := range pkg.Files { + ast.Inspect(file, func(n ast.Node) bool { + switch x := n.(type) { + case *ast.CallExpr: + if sel, ok := x.Fun.(*ast.SelectorExpr); ok { + if sel.Sel.Name == "RegisterFuncWithSignature" { + for _, arg := range x.Args { + if kv, ok := arg.(*ast.CompositeLit); ok { + for _, elt := range kv.Elts { + if kv, ok := elt.(*ast.KeyValueExpr); ok { + key := kv.Key.(*ast.Ident).Name + switch key { + case "Name", "Description": + buff.WriteString(fmt.Sprintf("%s: %s\n", key, strings.Trim(kv.Value.(*ast.BasicLit).Value, `"`))) + case "Signatures": + if comp, ok := kv.Value.(*ast.CompositeLit); ok { + for _, signature := range comp.Elts { + buff.WriteString(fmt.Sprintf("%s: %s\n", key, signature.(*ast.BasicLit).Value)) + } + } + } + } + } + } + } + buff.WriteString("\n") + } + } + } + return true + }) + } + } + + fmt.Printf("[+] Scraped %d functions\n\n", strings.Count(buff.String(), "Name:")) + fmt.Println(buff.String()) + + fmt.Printf("[+] Generating jsdoc for all functions\n\n") + resp, err := llm.CreateChatCompletion(context.TODO(), openai.ChatCompletionRequest{ + Model: "gpt-4", + Messages: []openai.ChatCompletionMessage{ + {Role: "system", Content: sysprompt}, + {Role: "user", Content: strings.ReplaceAll(userPrompt, "{{source}}", buff.String())}, + }, + Temperature: 0.1, + }) + if err != nil { + fmt.Println(err) + return + } + if len(resp.Choices) == 0 { + fmt.Println("no choices returned") + return + } + data := resp.Choices[0].Message.Content + + fmt.Println(data) + + if out != "" { + if err := os.WriteFile(out, []byte(data), 0600); err != nil { + fmt.Println(err) + return + } + } +} diff --git a/v2/pkg/js/generated/README.md b/v2/pkg/js/generated/README.md new file mode 100644 index 0000000000..7a995ec78c --- /dev/null +++ b/v2/pkg/js/generated/README.md @@ -0,0 +1,5 @@ +## generated + +!! Warning !! This is generated code, do not edit manually !! + +To make any changes to this code, please refer to [bindgen](../devtools/bindgen/README.md) \ No newline at end of file diff --git a/v2/pkg/js/generated/go/libbytes/bytes.go b/v2/pkg/js/generated/go/libbytes/bytes.go new file mode 100644 index 0000000000..dbbe273c1b --- /dev/null +++ b/v2/pkg/js/generated/go/libbytes/bytes.go @@ -0,0 +1,32 @@ +package bytes + +import ( + lib_bytes "github.com/projectdiscovery/nuclei/v2/pkg/js/libs/bytes" + + "github.com/dop251/goja" + "github.com/projectdiscovery/nuclei/v2/pkg/js/gojs" +) + +var ( + module = gojs.NewGojaModule("nuclei/bytes") +) + +func init() { + module.Set( + gojs.Objects{ + // Functions + "NewBuffer": lib_bytes.NewBuffer, + + // Var and consts + + // Types (value type) + "Buffer": func() lib_bytes.Buffer { return lib_bytes.Buffer{} }, + + // Types (pointer type) + }, + ).Register() +} + +func Enable(runtime *goja.Runtime) { + module.Enable(runtime) +} diff --git a/v2/pkg/js/generated/go/libgoconsole/goconsole.go b/v2/pkg/js/generated/go/libgoconsole/goconsole.go new file mode 100644 index 0000000000..9885471f02 --- /dev/null +++ b/v2/pkg/js/generated/go/libgoconsole/goconsole.go @@ -0,0 +1,32 @@ +package goconsole + +import ( + lib_goconsole "github.com/projectdiscovery/nuclei/v2/pkg/js/libs/goconsole" + + "github.com/dop251/goja" + "github.com/projectdiscovery/nuclei/v2/pkg/js/gojs" +) + +var ( + module = gojs.NewGojaModule("nuclei/goconsole") +) + +func init() { + module.Set( + gojs.Objects{ + // Functions + "NewGoConsolePrinter": lib_goconsole.NewGoConsolePrinter, + + // Var and consts + + // Types (value type) + "GoConsolePrinter": func() lib_goconsole.GoConsolePrinter { return lib_goconsole.GoConsolePrinter{} }, + + // Types (pointer type) + }, + ).Register() +} + +func Enable(runtime *goja.Runtime) { + module.Enable(runtime) +} diff --git a/v2/pkg/js/generated/go/libikev2/ikev2.go b/v2/pkg/js/generated/go/libikev2/ikev2.go new file mode 100644 index 0000000000..c99c27d2ef --- /dev/null +++ b/v2/pkg/js/generated/go/libikev2/ikev2.go @@ -0,0 +1,44 @@ +package ikev2 + +import ( + lib_ikev2 "github.com/projectdiscovery/nuclei/v2/pkg/js/libs/ikev2" + + "github.com/dop251/goja" + "github.com/projectdiscovery/nuclei/v2/pkg/js/gojs" +) + +var ( + module = gojs.NewGojaModule("nuclei/ikev2") +) + +func init() { + module.Set( + gojs.Objects{ + // Functions + + // Var and consts + "IKE_EXCHANGE_AUTH": lib_ikev2.IKE_EXCHANGE_AUTH, + "IKE_EXCHANGE_CREATE_CHILD_SA": lib_ikev2.IKE_EXCHANGE_CREATE_CHILD_SA, + "IKE_EXCHANGE_INFORMATIONAL": lib_ikev2.IKE_EXCHANGE_INFORMATIONAL, + "IKE_EXCHANGE_SA_INIT": lib_ikev2.IKE_EXCHANGE_SA_INIT, + "IKE_FLAGS_InitiatorBitCheck": lib_ikev2.IKE_FLAGS_InitiatorBitCheck, + "IKE_NOTIFY_NO_PROPOSAL_CHOSEN": lib_ikev2.IKE_NOTIFY_NO_PROPOSAL_CHOSEN, + "IKE_NOTIFY_USE_TRANSPORT_MODE": lib_ikev2.IKE_NOTIFY_USE_TRANSPORT_MODE, + "IKE_VERSION_2": lib_ikev2.IKE_VERSION_2, + + // Types (value type) + "IKEMessage": func() lib_ikev2.IKEMessage { return lib_ikev2.IKEMessage{} }, + "IKENonce": func() lib_ikev2.IKENonce { return lib_ikev2.IKENonce{} }, + "IKENotification": func() lib_ikev2.IKENotification { return lib_ikev2.IKENotification{} }, + + // Types (pointer type) + "NewIKEMessage": func() *lib_ikev2.IKEMessage { return &lib_ikev2.IKEMessage{} }, + "NewIKENonce": func() *lib_ikev2.IKENonce { return &lib_ikev2.IKENonce{} }, + "NewIKENotification": func() *lib_ikev2.IKENotification { return &lib_ikev2.IKENotification{} }, + }, + ).Register() +} + +func Enable(runtime *goja.Runtime) { + module.Enable(runtime) +} diff --git a/v2/pkg/js/generated/go/libkerberos/kerberos.go b/v2/pkg/js/generated/go/libkerberos/kerberos.go new file mode 100644 index 0000000000..d38cf1ecd9 --- /dev/null +++ b/v2/pkg/js/generated/go/libkerberos/kerberos.go @@ -0,0 +1,34 @@ +package kerberos + +import ( + lib_kerberos "github.com/projectdiscovery/nuclei/v2/pkg/js/libs/kerberos" + + "github.com/dop251/goja" + "github.com/projectdiscovery/nuclei/v2/pkg/js/gojs" +) + +var ( + module = gojs.NewGojaModule("nuclei/kerberos") +) + +func init() { + module.Set( + gojs.Objects{ + // Functions + + // Var and consts + + // Types (value type) + "EnumerateUserResponse": func() lib_kerberos.EnumerateUserResponse { return lib_kerberos.EnumerateUserResponse{} }, + "KerberosClient": func() lib_kerberos.KerberosClient { return lib_kerberos.KerberosClient{} }, + + // Types (pointer type) + "NewEnumerateUserResponse": func() *lib_kerberos.EnumerateUserResponse { return &lib_kerberos.EnumerateUserResponse{} }, + "NewKerberosClient": func() *lib_kerberos.KerberosClient { return &lib_kerberos.KerberosClient{} }, + }, + ).Register() +} + +func Enable(runtime *goja.Runtime) { + module.Enable(runtime) +} diff --git a/v2/pkg/js/generated/go/libldap/ldap.go b/v2/pkg/js/generated/go/libldap/ldap.go new file mode 100644 index 0000000000..3ed1245f4a --- /dev/null +++ b/v2/pkg/js/generated/go/libldap/ldap.go @@ -0,0 +1,34 @@ +package ldap + +import ( + lib_ldap "github.com/projectdiscovery/nuclei/v2/pkg/js/libs/ldap" + + "github.com/dop251/goja" + "github.com/projectdiscovery/nuclei/v2/pkg/js/gojs" +) + +var ( + module = gojs.NewGojaModule("nuclei/ldap") +) + +func init() { + module.Set( + gojs.Objects{ + // Functions + + // Var and consts + + // Types (value type) + "LDAPMetadata": func() lib_ldap.LDAPMetadata { return lib_ldap.LDAPMetadata{} }, + "LdapClient": func() lib_ldap.LdapClient { return lib_ldap.LdapClient{} }, + + // Types (pointer type) + "NewLDAPMetadata": func() *lib_ldap.LDAPMetadata { return &lib_ldap.LDAPMetadata{} }, + "NewLdapClient": func() *lib_ldap.LdapClient { return &lib_ldap.LdapClient{} }, + }, + ).Register() +} + +func Enable(runtime *goja.Runtime) { + module.Enable(runtime) +} diff --git a/v2/pkg/js/generated/go/libmssql/mssql.go b/v2/pkg/js/generated/go/libmssql/mssql.go new file mode 100644 index 0000000000..884dc0eef7 --- /dev/null +++ b/v2/pkg/js/generated/go/libmssql/mssql.go @@ -0,0 +1,32 @@ +package mssql + +import ( + lib_mssql "github.com/projectdiscovery/nuclei/v2/pkg/js/libs/mssql" + + "github.com/dop251/goja" + "github.com/projectdiscovery/nuclei/v2/pkg/js/gojs" +) + +var ( + module = gojs.NewGojaModule("nuclei/mssql") +) + +func init() { + module.Set( + gojs.Objects{ + // Functions + + // Var and consts + + // Types (value type) + "MSSQLClient": func() lib_mssql.MSSQLClient { return lib_mssql.MSSQLClient{} }, + + // Types (pointer type) + "NewMSSQLClient": func() *lib_mssql.MSSQLClient { return &lib_mssql.MSSQLClient{} }, + }, + ).Register() +} + +func Enable(runtime *goja.Runtime) { + module.Enable(runtime) +} diff --git a/v2/pkg/js/generated/go/libmysql/mysql.go b/v2/pkg/js/generated/go/libmysql/mysql.go new file mode 100644 index 0000000000..6a57045663 --- /dev/null +++ b/v2/pkg/js/generated/go/libmysql/mysql.go @@ -0,0 +1,32 @@ +package mysql + +import ( + lib_mysql "github.com/projectdiscovery/nuclei/v2/pkg/js/libs/mysql" + + "github.com/dop251/goja" + "github.com/projectdiscovery/nuclei/v2/pkg/js/gojs" +) + +var ( + module = gojs.NewGojaModule("nuclei/mysql") +) + +func init() { + module.Set( + gojs.Objects{ + // Functions + + // Var and consts + + // Types (value type) + "MySQLClient": func() lib_mysql.MySQLClient { return lib_mysql.MySQLClient{} }, + + // Types (pointer type) + "NewMySQLClient": func() *lib_mysql.MySQLClient { return &lib_mysql.MySQLClient{} }, + }, + ).Register() +} + +func Enable(runtime *goja.Runtime) { + module.Enable(runtime) +} diff --git a/v2/pkg/js/generated/go/libnet/net.go b/v2/pkg/js/generated/go/libnet/net.go new file mode 100644 index 0000000000..22338ca257 --- /dev/null +++ b/v2/pkg/js/generated/go/libnet/net.go @@ -0,0 +1,34 @@ +package net + +import ( + lib_net "github.com/projectdiscovery/nuclei/v2/pkg/js/libs/net" + + "github.com/dop251/goja" + "github.com/projectdiscovery/nuclei/v2/pkg/js/gojs" +) + +var ( + module = gojs.NewGojaModule("nuclei/net") +) + +func init() { + module.Set( + gojs.Objects{ + // Functions + "Open": lib_net.Open, + "OpenTLS": lib_net.OpenTLS, + + // Var and consts + + // Types (value type) + "NetConn": func() lib_net.NetConn { return lib_net.NetConn{} }, + + // Types (pointer type) + "NewNetConn": func() *lib_net.NetConn { return &lib_net.NetConn{} }, + }, + ).Register() +} + +func Enable(runtime *goja.Runtime) { + module.Enable(runtime) +} diff --git a/v2/pkg/js/generated/go/liboracle/oracle.go b/v2/pkg/js/generated/go/liboracle/oracle.go new file mode 100644 index 0000000000..d72d8bbd76 --- /dev/null +++ b/v2/pkg/js/generated/go/liboracle/oracle.go @@ -0,0 +1,34 @@ +package oracle + +import ( + lib_oracle "github.com/projectdiscovery/nuclei/v2/pkg/js/libs/oracle" + + "github.com/dop251/goja" + "github.com/projectdiscovery/nuclei/v2/pkg/js/gojs" +) + +var ( + module = gojs.NewGojaModule("nuclei/oracle") +) + +func init() { + module.Set( + gojs.Objects{ + // Functions + + // Var and consts + + // Types (value type) + "IsOracleResponse": func() lib_oracle.IsOracleResponse { return lib_oracle.IsOracleResponse{} }, + "OracleClient": func() lib_oracle.OracleClient { return lib_oracle.OracleClient{} }, + + // Types (pointer type) + "NewIsOracleResponse": func() *lib_oracle.IsOracleResponse { return &lib_oracle.IsOracleResponse{} }, + "NewOracleClient": func() *lib_oracle.OracleClient { return &lib_oracle.OracleClient{} }, + }, + ).Register() +} + +func Enable(runtime *goja.Runtime) { + module.Enable(runtime) +} diff --git a/v2/pkg/js/generated/go/libpop3/pop3.go b/v2/pkg/js/generated/go/libpop3/pop3.go new file mode 100644 index 0000000000..273e0a20be --- /dev/null +++ b/v2/pkg/js/generated/go/libpop3/pop3.go @@ -0,0 +1,34 @@ +package pop3 + +import ( + lib_pop3 "github.com/projectdiscovery/nuclei/v2/pkg/js/libs/pop3" + + "github.com/dop251/goja" + "github.com/projectdiscovery/nuclei/v2/pkg/js/gojs" +) + +var ( + module = gojs.NewGojaModule("nuclei/pop3") +) + +func init() { + module.Set( + gojs.Objects{ + // Functions + + // Var and consts + + // Types (value type) + "IsPOP3Response": func() lib_pop3.IsPOP3Response { return lib_pop3.IsPOP3Response{} }, + "Pop3Client": func() lib_pop3.Pop3Client { return lib_pop3.Pop3Client{} }, + + // Types (pointer type) + "NewIsPOP3Response": func() *lib_pop3.IsPOP3Response { return &lib_pop3.IsPOP3Response{} }, + "NewPop3Client": func() *lib_pop3.Pop3Client { return &lib_pop3.Pop3Client{} }, + }, + ).Register() +} + +func Enable(runtime *goja.Runtime) { + module.Enable(runtime) +} diff --git a/v2/pkg/js/generated/go/libpostgres/postgres.go b/v2/pkg/js/generated/go/libpostgres/postgres.go new file mode 100644 index 0000000000..9dca20d948 --- /dev/null +++ b/v2/pkg/js/generated/go/libpostgres/postgres.go @@ -0,0 +1,32 @@ +package postgres + +import ( + lib_postgres "github.com/projectdiscovery/nuclei/v2/pkg/js/libs/postgres" + + "github.com/dop251/goja" + "github.com/projectdiscovery/nuclei/v2/pkg/js/gojs" +) + +var ( + module = gojs.NewGojaModule("nuclei/postgres") +) + +func init() { + module.Set( + gojs.Objects{ + // Functions + + // Var and consts + + // Types (value type) + "PGClient": func() lib_postgres.PGClient { return lib_postgres.PGClient{} }, + + // Types (pointer type) + "NewPGClient": func() *lib_postgres.PGClient { return &lib_postgres.PGClient{} }, + }, + ).Register() +} + +func Enable(runtime *goja.Runtime) { + module.Enable(runtime) +} diff --git a/v2/pkg/js/generated/go/librdp/rdp.go b/v2/pkg/js/generated/go/librdp/rdp.go new file mode 100644 index 0000000000..7212a08a77 --- /dev/null +++ b/v2/pkg/js/generated/go/librdp/rdp.go @@ -0,0 +1,36 @@ +package rdp + +import ( + lib_rdp "github.com/projectdiscovery/nuclei/v2/pkg/js/libs/rdp" + + "github.com/dop251/goja" + "github.com/projectdiscovery/nuclei/v2/pkg/js/gojs" +) + +var ( + module = gojs.NewGojaModule("nuclei/rdp") +) + +func init() { + module.Set( + gojs.Objects{ + // Functions + + // Var and consts + + // Types (value type) + "CheckRDPAuthResponse": func() lib_rdp.CheckRDPAuthResponse { return lib_rdp.CheckRDPAuthResponse{} }, + "IsRDPResponse": func() lib_rdp.IsRDPResponse { return lib_rdp.IsRDPResponse{} }, + "RDPClient": func() lib_rdp.RDPClient { return lib_rdp.RDPClient{} }, + + // Types (pointer type) + "NewCheckRDPAuthResponse": func() *lib_rdp.CheckRDPAuthResponse { return &lib_rdp.CheckRDPAuthResponse{} }, + "NewIsRDPResponse": func() *lib_rdp.IsRDPResponse { return &lib_rdp.IsRDPResponse{} }, + "NewRDPClient": func() *lib_rdp.RDPClient { return &lib_rdp.RDPClient{} }, + }, + ).Register() +} + +func Enable(runtime *goja.Runtime) { + module.Enable(runtime) +} diff --git a/v2/pkg/js/generated/go/libredis/redis.go b/v2/pkg/js/generated/go/libredis/redis.go new file mode 100644 index 0000000000..e52a1f0134 --- /dev/null +++ b/v2/pkg/js/generated/go/libredis/redis.go @@ -0,0 +1,35 @@ +package redis + +import ( + lib_redis "github.com/projectdiscovery/nuclei/v2/pkg/js/libs/redis" + + "github.com/dop251/goja" + "github.com/projectdiscovery/nuclei/v2/pkg/js/gojs" +) + +var ( + module = gojs.NewGojaModule("nuclei/redis") +) + +func init() { + module.Set( + gojs.Objects{ + // Functions + "Connect": lib_redis.Connect, + "GetServerInfo": lib_redis.GetServerInfo, + "GetServerInfoAuth": lib_redis.GetServerInfoAuth, + "IsAuthenticated": lib_redis.IsAuthenticated, + "RunLuaScript": lib_redis.RunLuaScript, + + // Var and consts + + // Types (value type) + + // Types (pointer type) + }, + ).Register() +} + +func Enable(runtime *goja.Runtime) { + module.Enable(runtime) +} diff --git a/v2/pkg/js/generated/go/librsync/rsync.go b/v2/pkg/js/generated/go/librsync/rsync.go new file mode 100644 index 0000000000..eca6a37c75 --- /dev/null +++ b/v2/pkg/js/generated/go/librsync/rsync.go @@ -0,0 +1,34 @@ +package rsync + +import ( + lib_rsync "github.com/projectdiscovery/nuclei/v2/pkg/js/libs/rsync" + + "github.com/dop251/goja" + "github.com/projectdiscovery/nuclei/v2/pkg/js/gojs" +) + +var ( + module = gojs.NewGojaModule("nuclei/rsync") +) + +func init() { + module.Set( + gojs.Objects{ + // Functions + + // Var and consts + + // Types (value type) + "IsRsyncResponse": func() lib_rsync.IsRsyncResponse { return lib_rsync.IsRsyncResponse{} }, + "RsyncClient": func() lib_rsync.RsyncClient { return lib_rsync.RsyncClient{} }, + + // Types (pointer type) + "NewIsRsyncResponse": func() *lib_rsync.IsRsyncResponse { return &lib_rsync.IsRsyncResponse{} }, + "NewRsyncClient": func() *lib_rsync.RsyncClient { return &lib_rsync.RsyncClient{} }, + }, + ).Register() +} + +func Enable(runtime *goja.Runtime) { + module.Enable(runtime) +} diff --git a/v2/pkg/js/generated/go/libsmb/smb.go b/v2/pkg/js/generated/go/libsmb/smb.go new file mode 100644 index 0000000000..dc92186c82 --- /dev/null +++ b/v2/pkg/js/generated/go/libsmb/smb.go @@ -0,0 +1,32 @@ +package smb + +import ( + lib_smb "github.com/projectdiscovery/nuclei/v2/pkg/js/libs/smb" + + "github.com/dop251/goja" + "github.com/projectdiscovery/nuclei/v2/pkg/js/gojs" +) + +var ( + module = gojs.NewGojaModule("nuclei/smb") +) + +func init() { + module.Set( + gojs.Objects{ + // Functions + + // Var and consts + + // Types (value type) + "SMBClient": func() lib_smb.SMBClient { return lib_smb.SMBClient{} }, + + // Types (pointer type) + "NewSMBClient": func() *lib_smb.SMBClient { return &lib_smb.SMBClient{} }, + }, + ).Register() +} + +func Enable(runtime *goja.Runtime) { + module.Enable(runtime) +} diff --git a/v2/pkg/js/generated/go/libsmtp/smtp.go b/v2/pkg/js/generated/go/libsmtp/smtp.go new file mode 100644 index 0000000000..aad05e4b95 --- /dev/null +++ b/v2/pkg/js/generated/go/libsmtp/smtp.go @@ -0,0 +1,34 @@ +package smtp + +import ( + lib_smtp "github.com/projectdiscovery/nuclei/v2/pkg/js/libs/smtp" + + "github.com/dop251/goja" + "github.com/projectdiscovery/nuclei/v2/pkg/js/gojs" +) + +var ( + module = gojs.NewGojaModule("nuclei/smtp") +) + +func init() { + module.Set( + gojs.Objects{ + // Functions + + // Var and consts + + // Types (value type) + "IsSMTPResponse": func() lib_smtp.IsSMTPResponse { return lib_smtp.IsSMTPResponse{} }, + "SMTPClient": func() lib_smtp.SMTPClient { return lib_smtp.SMTPClient{} }, + + // Types (pointer type) + "NewIsSMTPResponse": func() *lib_smtp.IsSMTPResponse { return &lib_smtp.IsSMTPResponse{} }, + "NewSMTPClient": func() *lib_smtp.SMTPClient { return &lib_smtp.SMTPClient{} }, + }, + ).Register() +} + +func Enable(runtime *goja.Runtime) { + module.Enable(runtime) +} diff --git a/v2/pkg/js/generated/go/libssh/ssh.go b/v2/pkg/js/generated/go/libssh/ssh.go new file mode 100644 index 0000000000..f70fc78f9a --- /dev/null +++ b/v2/pkg/js/generated/go/libssh/ssh.go @@ -0,0 +1,32 @@ +package ssh + +import ( + lib_ssh "github.com/projectdiscovery/nuclei/v2/pkg/js/libs/ssh" + + "github.com/dop251/goja" + "github.com/projectdiscovery/nuclei/v2/pkg/js/gojs" +) + +var ( + module = gojs.NewGojaModule("nuclei/ssh") +) + +func init() { + module.Set( + gojs.Objects{ + // Functions + + // Var and consts + + // Types (value type) + "SSHClient": func() lib_ssh.SSHClient { return lib_ssh.SSHClient{} }, + + // Types (pointer type) + "NewSSHClient": func() *lib_ssh.SSHClient { return &lib_ssh.SSHClient{} }, + }, + ).Register() +} + +func Enable(runtime *goja.Runtime) { + module.Enable(runtime) +} diff --git a/v2/pkg/js/generated/go/libstructs/structs.go b/v2/pkg/js/generated/go/libstructs/structs.go new file mode 100644 index 0000000000..eddbb3cde6 --- /dev/null +++ b/v2/pkg/js/generated/go/libstructs/structs.go @@ -0,0 +1,33 @@ +package structs + +import ( + lib_structs "github.com/projectdiscovery/nuclei/v2/pkg/js/libs/structs" + + "github.com/dop251/goja" + "github.com/projectdiscovery/nuclei/v2/pkg/js/gojs" +) + +var ( + module = gojs.NewGojaModule("nuclei/structs") +) + +func init() { + module.Set( + gojs.Objects{ + // Functions + "Pack": lib_structs.Pack, + "StructsCalcSize": lib_structs.StructsCalcSize, + "Unpack": lib_structs.Unpack, + + // Var and consts + + // Types (value type) + + // Types (pointer type) + }, + ).Register() +} + +func Enable(runtime *goja.Runtime) { + module.Enable(runtime) +} diff --git a/v2/pkg/js/generated/go/libtelnet/telnet.go b/v2/pkg/js/generated/go/libtelnet/telnet.go new file mode 100644 index 0000000000..9d75977a39 --- /dev/null +++ b/v2/pkg/js/generated/go/libtelnet/telnet.go @@ -0,0 +1,34 @@ +package telnet + +import ( + lib_telnet "github.com/projectdiscovery/nuclei/v2/pkg/js/libs/telnet" + + "github.com/dop251/goja" + "github.com/projectdiscovery/nuclei/v2/pkg/js/gojs" +) + +var ( + module = gojs.NewGojaModule("nuclei/telnet") +) + +func init() { + module.Set( + gojs.Objects{ + // Functions + + // Var and consts + + // Types (value type) + "IsTelnetResponse": func() lib_telnet.IsTelnetResponse { return lib_telnet.IsTelnetResponse{} }, + "TelnetClient": func() lib_telnet.TelnetClient { return lib_telnet.TelnetClient{} }, + + // Types (pointer type) + "NewIsTelnetResponse": func() *lib_telnet.IsTelnetResponse { return &lib_telnet.IsTelnetResponse{} }, + "NewTelnetClient": func() *lib_telnet.TelnetClient { return &lib_telnet.TelnetClient{} }, + }, + ).Register() +} + +func Enable(runtime *goja.Runtime) { + module.Enable(runtime) +} diff --git a/v2/pkg/js/generated/go/libvnc/vnc.go b/v2/pkg/js/generated/go/libvnc/vnc.go new file mode 100644 index 0000000000..a5e2bc852e --- /dev/null +++ b/v2/pkg/js/generated/go/libvnc/vnc.go @@ -0,0 +1,34 @@ +package vnc + +import ( + lib_vnc "github.com/projectdiscovery/nuclei/v2/pkg/js/libs/vnc" + + "github.com/dop251/goja" + "github.com/projectdiscovery/nuclei/v2/pkg/js/gojs" +) + +var ( + module = gojs.NewGojaModule("nuclei/vnc") +) + +func init() { + module.Set( + gojs.Objects{ + // Functions + + // Var and consts + + // Types (value type) + "IsVNCResponse": func() lib_vnc.IsVNCResponse { return lib_vnc.IsVNCResponse{} }, + "VNCClient": func() lib_vnc.VNCClient { return lib_vnc.VNCClient{} }, + + // Types (pointer type) + "NewIsVNCResponse": func() *lib_vnc.IsVNCResponse { return &lib_vnc.IsVNCResponse{} }, + "NewVNCClient": func() *lib_vnc.VNCClient { return &lib_vnc.VNCClient{} }, + }, + ).Register() +} + +func Enable(runtime *goja.Runtime) { + module.Enable(runtime) +} diff --git a/v2/pkg/js/generated/js/global.js b/v2/pkg/js/generated/js/global.js new file mode 100644 index 0000000000..03ec8d21e2 --- /dev/null +++ b/v2/pkg/js/generated/js/global.js @@ -0,0 +1,88 @@ +/** + * Rand returns a random byte slice of length n + * Rand(n int) []byte + * @function + * @param {number} n - The length of the byte slice. + * @example + * let myint = Rand(10); // returns a random byte slice of length 10 + */ +function Rand(n) { + // implemented in go +}; + +/** + * RandInt returns a random int + * RandInt() int + * @function + * @example + * let myint = RandInt(); // returns a random int + */ +function RandInt() { + // implemented in go +}; + +/** + * log prints given input to stdout with [JS] prefix for debugging purposes + * log(msg string) + * log(msg map[string]interface{}) + * @function + * @param {string|Object} msg - The message to print. + * @example + * log("Hello World!"); + * log({"Hello": "World!"}); + */ +function log(msg) { + // implemented in go +}; + +/** + * getNetworkPort registers defaultPort and returns defaultPort if it is a colliding port with other protocols + * getNetworkPort(port string, defaultPort string) string + * @function + * @param {string} port - The port to check. + * @param {string} defaultPort - The default port to return if the given port is colliding. + * @example + * let port = getNetworkPort(Port, "2843"); // 2843 is default port (even if 80,443 etc is given in Port from input) + */ +function getNetworkPort(port, defaultPort) { + // implemented in go +}; + +/** + * isPortOpen checks if given port is open on host. timeout is optional and defaults to 5 seconds + * isPortOpen(host string, port string, [timeout int]) bool + * @function + * @param {string} host - The host to check. + * @param {string} port - The port to check. + * @param {number} [timeout=5] - The timeout in seconds. + * @example + * let open = isPortOpen("localhost", "80"); // returns true if port 80 is open on localhost + * let open = isPortOpen("localhost", "80", 10); // returns true if port 80 is open on localhost within 10 seconds + */ +function isPortOpen(host, port, timeout = 5) { + // implemented in go +}; + +/** + * ToBytes converts given input to byte slice + * ToBytes(...interface{}) []byte + * @function + * @param {...any} args - The input to convert. + * @example + * let mybytes = ToBytes("Hello World!"); // returns byte slice of "Hello World!" + */ +function ToBytes(...args) { + // implemented in go +}; + +/** + * ToString converts given input to string + * ToString(...interface{}) string + * @function + * @param {...any} args - The input to convert. + * @example + * let mystring = ToString([0x48, 0x65, 0x6c, 0x6c, 0x6f]); // returns "Hello" + */ +function ToString(...args) { + // implemented in go +}; \ No newline at end of file diff --git a/v2/pkg/js/generated/js/libbytes/bytes.js b/v2/pkg/js/generated/js/libbytes/bytes.js new file mode 100644 index 0000000000..9322711236 --- /dev/null +++ b/v2/pkg/js/generated/js/libbytes/bytes.js @@ -0,0 +1,91 @@ +/** + * @module bytes + */ + +/** + * @class Buffer + * @description Buffer is a minimal buffer implementation over a byte slice + * that is used to pack/unpack binary data in nuclei js integration. + */ +class Buffer { + /** + * @method Bytes + * @return {Array} byte slice of the buffer. + */ + Bytes() { + // implemented in go + }; + + /** + * @method Hex + * @return {string} hex representation of the buffer. + */ + Hex() { + // implemented in go + }; + + /** + * @method Hexdump + * @return {string} hexdump representation of the buffer. + */ + Hexdump() { + // implemented in go + }; + + /** + * @method Len + * @return {number} length of the buffer. + */ + Len() { + // implemented in go + }; + + /** + * @method Pack + * @param {string} formatStr - format string for packing data + * @param {string} msg - message to be packed + * @throws {Error} if packing fails + */ + Pack(formatStr, msg) { + // implemented in go + }; + + /** + * @method String + * @return {string} string representation of the buffer. + */ + String() { + // implemented in go + }; + + /** + * @method Write + * @param {Array} data - data to be appended to the buffer + * @return {Buffer} updated buffer + */ + Write(data) { + // implemented in go + }; + + /** + * @method WriteString + * @param {string} data - string to be appended to the buffer + * @return {Buffer} updated buffer + */ + WriteString(data) { + // implemented in go + }; +}; + +/** + * @function NewBuffer + * @param {any} call - parameter for creating new buffer + */ +function NewBuffer(call) { + // implemented in go +}; + +module.exports = { + Buffer: Buffer, + NewBuffer: NewBuffer, +}; \ No newline at end of file diff --git a/v2/pkg/js/generated/js/libgoconsole/goconsole.js b/v2/pkg/js/generated/js/libgoconsole/goconsole.js new file mode 100644 index 0000000000..b1d72d018b --- /dev/null +++ b/v2/pkg/js/generated/js/libgoconsole/goconsole.js @@ -0,0 +1,59 @@ +/** + * @module goconsole + */ + +/** + * @class + * GoConsolePrinter is a console printer for nuclei using gologger + */ +class GoConsolePrinter { + /** + * @method + * @param {string} msg - The message to be printed + * @throws {Error} If an error occurred + * @example + * let printer = new GoConsolePrinter(); + * printer.Error("This is an error message"); + */ + Error(msg) { + // implemented in go + }; + + /** + * @method + * @param {string} msg - The message to be logged + * @example + * let printer = new GoConsolePrinter(); + * printer.Log("This is a log message"); + */ + Log(msg) { + // implemented in go + }; + + /** + * @method + * @param {string} msg - The message to be warned + * @example + * let printer = new GoConsolePrinter(); + * printer.Warn("This is a warning message"); + */ + Warn(msg) { + // implemented in go + }; +}; + +/** + * @function + * @returns {GoConsolePrinter} A new instance of GoConsolePrinter + * @example + * let printer = NewGoConsolePrinter(); + */ +function NewGoConsolePrinter() { + // implemented in go +}; + +// ReadOnly DONOT EDIT +module.exports = { + GoConsolePrinter: GoConsolePrinter, + NewGoConsolePrinter: NewGoConsolePrinter, +}; \ No newline at end of file diff --git a/v2/pkg/js/generated/js/libikev2/ikev2.js b/v2/pkg/js/generated/js/libikev2/ikev2.js new file mode 100644 index 0000000000..7178d7a823 --- /dev/null +++ b/v2/pkg/js/generated/js/libikev2/ikev2.js @@ -0,0 +1,41 @@ +/** + * @module ikev2 + */ + +/** + * @class + * @description IKEMessage is the IKEv2 message. IKEv2 implements a limited subset of IKEv2 Protocol, specifically + * the IKE_NOTIFY and IKE_NONCE payloads and the IKE_SA_INIT exchange. + */ +class IKEMessage { + /** + * @method + * @description AppendPayload appends a payload to the IKE message + * @param {Object} payload - The payload to be appended + * @throws {Error} If the payload cannot be appended + * @example + * let ikeMessage = new IKEMessage(); + * ikeMessage.AppendPayload(payload); + */ + AppendPayload(payload) { + // implemented in go + }; + + /** + * @method + * @description Encode encodes the final IKE message + * @returns {Array} The encoded IKE message + * @throws {Error} If the message cannot be encoded + * @example + * let ikeMessage = new IKEMessage(); + * let encodedMessage = ikeMessage.Encode(); + */ + Encode() { + // implemented in go + }; +}; + +// ReadOnly DONOT EDIT +module.exports = { + IKEMessage: IKEMessage, +}; \ No newline at end of file diff --git a/v2/pkg/js/generated/js/libkerberos/kerberos.js b/v2/pkg/js/generated/js/libkerberos/kerberos.js new file mode 100644 index 0000000000..c9629d9915 --- /dev/null +++ b/v2/pkg/js/generated/js/libkerberos/kerberos.js @@ -0,0 +1,32 @@ +/** + * @module kerberos + */ + +/** + * @class + * @classdesc This class represents a kerberos client. + */ +class KerberosClient { + /** + * @method + * @name EnumerateUser + * @description This method returns true if the user exists in the domain. If the user is not found, false is returned. If the user is found, true is returned. Optionally, the AS-REP hash is also returned if discovered. + * @param {string} domain - The domain to be checked. + * @param {string} controller - The controller to be used. + * @param {string} username - The username to be checked. + * @returns {Object} EnumerateUserResponse - The response from the enumeration of the user. + * @throws {Error} If there is an error in the process. + * @example + * // Example usage of EnumerateUser + * let client = new KerberosClient(); + * let response = client.EnumerateUser('example.com', 'controller1', 'user1'); + */ + EnumerateUser(domain, controller, username) { + // implemented in go + }; +}; + +// ReadOnly DONOT EDIT +module.exports = { + KerberosClient: KerberosClient, +}; \ No newline at end of file diff --git a/v2/pkg/js/generated/js/libldap/ldap.js b/v2/pkg/js/generated/js/libldap/ldap.js new file mode 100644 index 0000000000..017f1f421c --- /dev/null +++ b/v2/pkg/js/generated/js/libldap/ldap.js @@ -0,0 +1,45 @@ +/** + * @module ldap + */ + +/** + * @class LdapClient + * @description Client is a client for ldap protocol in golang. + * It is a wrapper around the standard library ldap package. + */ +class LdapClient { + /** + * @method CollectLdapMetadata + * @description collects metadata from ldap server. + * @param {string} domain - The domain to collect metadata from. + * @param {string} controller - The controller to use for collection. + * @returns {Object} LDAPMetadata - The collected metadata. + * @throws {Error} If an error occurs during collection. + * @example + * let client = new LdapClient(); + * let metadata = client.CollectLdapMetadata("example.com", "controller1"); + */ + CollectLdapMetadata(domain, controller) { + // implemented in go + }; + + /** + * @method IsLdap + * @description checks if the given host and port are running ldap server. + * @param {string} host - The host to check. + * @param {number} port - The port to check. + * @returns {boolean} - Returns true if the host and port are running an ldap server, false otherwise. + * @throws {Error} If an error occurs during the check. + * @example + * let client = new LdapClient(); + * let isLdap = client.IsLdap("localhost", 389); + */ + IsLdap(host, port) { + // implemented in go + }; +}; + +// ReadOnly DONOT EDIT +module.exports = { + LdapClient: LdapClient, +}; \ No newline at end of file diff --git a/v2/pkg/js/generated/js/libmssql/mssql.js b/v2/pkg/js/generated/js/libmssql/mssql.js new file mode 100644 index 0000000000..c2d110cd1a --- /dev/null +++ b/v2/pkg/js/generated/js/libmssql/mssql.js @@ -0,0 +1,73 @@ +/** + * @module mssql + */ + +/** + * @class + * @classdesc Client is a client for MS SQL database. + * Internally client uses denisenkom/go-mssqldb driver. + */ +class MSSQLClient { + /** + * @method + * @description Connect connects to MS SQL database using given credentials. + * If connection is successful, it returns true. + * If connection is unsuccessful, it throws an error. + * The connection is closed after the function returns. + * @param {string} host - The host of the MS SQL database. + * @param {number} port - The port of the MS SQL database. + * @param {string} username - The username to connect to the MS SQL database. + * @param {string} password - The password to connect to the MS SQL database. + * @returns {boolean} - Returns true if connection is successful, otherwise throws an error. + * @throws {Error} If connection is unsuccessful. + * @example + * // returns true + * MSSQLClient.Connect('localhost', 1433, 'username', 'password'); + */ + Connect(host, port, username, password) { + // implemented in go + }; + + /** + * @method + * @description ConnectWithDB connects to MS SQL database using given credentials and database name. + * If connection is successful, it returns true. + * If connection is unsuccessful, it throws an error. + * The connection is closed after the function returns. + * @param {string} host - The host of the MS SQL database. + * @param {number} port - The port of the MS SQL database. + * @param {string} username - The username to connect to the MS SQL database. + * @param {string} password - The password to connect to the MS SQL database. + * @param {string} dbName - The name of the database to connect to. + * @returns {boolean} - Returns true if connection is successful, otherwise throws an error. + * @throws {Error} If connection is unsuccessful. + * @example + * // returns true + * MSSQLClient.ConnectWithDB('localhost', 1433, 'username', 'password', 'myDatabase'); + */ + ConnectWithDB(host, port, username, password, dbName) { + // implemented in go + }; + + /** + * @method + * @description IsMssql checks if the given host is running MS SQL database. + * If the host is running MS SQL database, it returns true. + * If the host is not running MS SQL database, it throws an error. + * @param {string} host - The host to check. + * @param {number} port - The port to check. + * @returns {boolean} - Returns true if the host is running MS SQL database, otherwise throws an error. + * @throws {Error} If the host is not running MS SQL database. + * @example + * // returns true + * MSSQLClient.IsMssql('localhost', 1433); + */ + IsMssql(host, port) { + // implemented in go + }; +}; + +// ReadOnly DONOT EDIT +module.exports = { + MSSQLClient: MSSQLClient, +}; \ No newline at end of file diff --git a/v2/pkg/js/generated/js/libmysql/mysql.js b/v2/pkg/js/generated/js/libmysql/mysql.js new file mode 100644 index 0000000000..0ee1b9f335 --- /dev/null +++ b/v2/pkg/js/generated/js/libmysql/mysql.js @@ -0,0 +1,87 @@ +/** + * @module mysql + */ + +/** + * @class + * @classdesc MySQLClient is a client for MySQL database. Internally client uses go-sql-driver/mysql driver. + */ +class MySQLClient { + /** + * @method + * @description Connects to MySQL database using given credentials. The connection is closed after the function returns. + * @param {string} host - The host of the MySQL database. + * @param {number} port - The port of the MySQL database. + * @param {string} username - The username for the MySQL database. + * @param {string} password - The password for the MySQL database. + * @returns {boolean} Returns true if connection is successful, otherwise false. + * @throws {Error} If connection is unsuccessful. + * @example + * // Connect to MySQL database + * let client = new MySQLClient(); + * client.Connect('localhost', 3306, 'root', 'password'); + */ + Connect(host, port, username, password) { + // implemented in go + }; + + /** + * @method + * @description Connects to MySQL database using given credentials and database name. The connection is closed after the function returns. + * @param {string} host - The host of the MySQL database. + * @param {number} port - The port of the MySQL database. + * @param {string} username - The username for the MySQL database. + * @param {string} password - The password for the MySQL database. + * @param {string} dbName - The name of the database. + * @returns {boolean} Returns true if connection is successful, otherwise false. + * @throws {Error} If connection is unsuccessful. + * @example + * // Connect to MySQL database with a specific database + * let client = new MySQLClient(); + * client.ConnectWithDB('localhost', 3306, 'root', 'password', 'myDatabase'); + */ + ConnectWithDB(host, port, username, password, dbName) { + // implemented in go + }; + + /** + * @method + * @description Connects to Mysql database using given credentials and database name and executes a query on the db. + * @param {string} host - The host of the MySQL database. + * @param {number} port - The port of the MySQL database. + * @param {string} username - The username for the MySQL database. + * @param {string} password - The password for the MySQL database. + * @param {string} dbName - The name of the database. + * @param {string} query - The query to execute. + * @returns {string} The result of the query. + * @throws {Error} If execution of query is unsuccessful. + * @example + * // Execute a query on the MySQL database + * let client = new MySQLClient(); + * client.ExecuteQuery('localhost', 3306, 'root', 'password', 'myDatabase', 'SELECT * FROM users'); + */ + ExecuteQuery(host, port, username, password, dbName, query) { + // implemented in go + }; + + /** + * @method + * @description Checks if the given host is running MySQL database. + * @param {string} host - The host to check. + * @param {number} port - The port to check. + * @returns {boolean} Returns true if the host is running MySQL database, otherwise false. + * @throws {Error} If check is unsuccessful. + * @example + * // Check if a host is running MySQL database + * let client = new MySQLClient(); + * client.IsMySQL('localhost', 3306); + */ + IsMySQL(host, port) { + // implemented in go + }; +}; + +// ReadOnly DONOT EDIT +module.exports = { + MySQLClient: MySQLClient, +}; \ No newline at end of file diff --git a/v2/pkg/js/generated/js/libnet/net.js b/v2/pkg/js/generated/js/libnet/net.js new file mode 100644 index 0000000000..e49e7d51b6 --- /dev/null +++ b/v2/pkg/js/generated/js/libnet/net.js @@ -0,0 +1,157 @@ +/** + * @module net + */ + +/** + * @class + * @classdesc NetConn is a connection to a remote host. + */ +class NetConn { + /** + * @method + * @description Close closes the connection. + * @throws {Error} If an error occurred while closing the connection. + * @example + * // Close the connection + * let conn = Open('tcp', 'localhost:80'); + * conn.Close(); + */ + Close() { + // implemented in go + }; + + /** + * @method + * @description Recv receives data from the connection with a timeout. If N is 0, it will read up to 4096 bytes. + * @param {number} N - The number of bytes to receive. + * @returns {Array} The received bytes. + * @throws {Error} If an error occurred while receiving data. + * @example + * // Receive data + * let conn = Open('tcp', 'localhost:80'); + * let data = conn.Recv(10); // Receive 10 bytes + * log(data); + */ + Recv(N) { + // implemented in go + }; + + /** + * @method + * @description RecvHex receives data from the connection with a timeout in hex format. If N is 0, it will read up to 4096 bytes. + * @param {number} N - The number of bytes to receive. + * @returns {string} The received data in hex format. + * @throws {Error} If an error occurred while receiving data. + * @example + * // Receive data in hex format + * let conn = Open('tcp', 'localhost:80'); + * let data = conn.RecvHex(10); // Receive 10 bytes + * log(data); + */ + RecvHex(N) { + // implemented in go + }; + + /** + * @method + * @description RecvString receives data from the connection with a timeout. Output is returned as a string. If N is 0, it will read up to 4096 bytes. + * @param {number} N - The number of bytes to receive. + * @returns {string} The received data as a string. + * @throws {Error} If an error occurred while receiving data. + * @example + * // Receive data + * let conn = Open('tcp', 'localhost:80'); + * let data = conn.RecvString(10); // Receive 10 bytes + * log(data); + */ + RecvString(N) { + // implemented in go + }; + + /** + * @method + * @description Send sends data to the connection with a timeout. + * @param {string} data - The data to send. + * @throws {Error} If an error occurred while sending data. + * @example + * // Send data + * let conn = Open('tcp', 'localhost:80'); + * conn.Send('Hello World!'); + */ + Send(data) { + // implemented in go + }; + + /** + * @method + * @description SendArray sends array data to connection. + * @param {Array} data - The array data to send. + * @throws {Error} If an error occurred while sending data. + * @example + * // Send array data + * let conn = Open('tcp', 'localhost:80'); + * conn.SendArray([0xde, 0x0b]); + */ + SendArray(data) { + // implemented in go + }; + + /** + * @method + * @description SendHex sends hex data to connection. + * @param {string} data - The hex data to send. + * @throws {Error} If an error occurred while sending data. + * @example + * // Send hex data + * let conn = Open('tcp', 'localhost:80'); + * conn.SendHex('0xde0b'); + */ + SendHex(data) { + // implemented in go + }; + + /** + * @method + * @description SetTimeout sets read/write timeout for the connection (in seconds). + * @param {number} value - The timeout value in seconds. + * @example + * // Set timeout for connection + * let conn = Open('tcp', 'localhost:80'); + * conn.SetTimeout(10); // 10 seconds + */ + SetTimeout(value) { + // implemented in go + }; +}; + +/** + * @function + * @description Open a connection with the specified protocol and address. + * @param {string} protocol - The protocol to use. + * @param {string} address - The address to connect to. + * @example + * // Open a connection + * let conn = Open('tcp', 'localhost:80'); + */ +function Open(protocol, address) { + // implemented in go +}; + +/** + * @function + * @description Open a TLS connection with the specified protocol and address. + * @param {string} protocol - The protocol to use. + * @param {string} address - The address to connect to. + * @example + * // Open a TLS connection + * let conn = OpenTLS('tcp', 'localhost:443'); + */ +function OpenTLS(protocol, address) { + // implemented in go +}; + +module.exports = { + NetConn: NetConn, + Open: Open, + OpenTLS: OpenTLS, +}; \ No newline at end of file diff --git a/v2/pkg/js/generated/js/liboracle/oracle.js b/v2/pkg/js/generated/js/liboracle/oracle.js new file mode 100644 index 0000000000..c436b56f92 --- /dev/null +++ b/v2/pkg/js/generated/js/liboracle/oracle.js @@ -0,0 +1,29 @@ +/** + * @module oracle + */ + +/** + * @class + * OracleClient is a minimal Oracle client for nuclei scripts. + */ +class OracleClient { + /** + * @method + * IsOracle checks if a host is running an Oracle server. + * @param {string} host - The host to check. + * @param {number} port - The port to check. + * @returns {IsOracleResponse} - The response from the Oracle server. + * @throws {error} If there is an error in the process. + * @example + * let oracleClient = new OracleClient(); + * oracleClient.IsOracle("localhost", 1521); + */ + IsOracle(host, port) { + // implemented in go + }; +}; + +// ReadOnly DONOT EDIT +module.exports = { + OracleClient: OracleClient, +}; \ No newline at end of file diff --git a/v2/pkg/js/generated/js/libpop3/pop3.js b/v2/pkg/js/generated/js/libpop3/pop3.js new file mode 100644 index 0000000000..bab839f331 --- /dev/null +++ b/v2/pkg/js/generated/js/libpop3/pop3.js @@ -0,0 +1,29 @@ +/** + * @module pop3 + */ + +/** + * @class + * @classdesc Pop3Client is a minimal POP3 client for nuclei scripts. + */ +class Pop3Client { + /** + * @method + * @name IsPOP3 + * @param {string} host - The host to check. + * @param {number} port - The port to check. + * @returns {boolean} IsPOP3Response - Returns true if the host is running a POP3 server, false otherwise. + * @throws {Error} If an error occurs during the check. + * @example + * let client = new Pop3Client(); + * let isPop3 = client.IsPOP3('localhost', 110); + */ + IsPOP3(host, port) { + // implemented in go + }; +}; + +// ReadOnly DONOT EDIT +module.exports = { + Pop3Client: Pop3Client, +}; \ No newline at end of file diff --git a/v2/pkg/js/generated/js/libpostgres/postgres.js b/v2/pkg/js/generated/js/libpostgres/postgres.js new file mode 100644 index 0000000000..b6dc0b3956 --- /dev/null +++ b/v2/pkg/js/generated/js/libpostgres/postgres.js @@ -0,0 +1,71 @@ +/** + * @module postgres + */ + +/** + * @class + * @classdesc PGClient is a client for Postgres database. Internally client uses go-pg/pg driver. + */ +class PGClient { + /** + * @method + * @description Connects to Postgres database using given credentials. The connection is closed after the function returns. + * @param {string} host - The host of the Postgres database. + * @param {number} port - The port of the Postgres database. + * @param {string} username - The username for the Postgres database. + * @param {string} password - The password for the Postgres database. + * @returns {boolean} Returns true if connection is successful, otherwise false. + * @throws {Error} If connection is unsuccessful. + */ + Connect(host, port, username, password) { + // implemented in go + }; + + /** + * @method + * @description Connects to Postgres database using given credentials and database name. The connection is closed after the function returns. + * @param {string} host - The host of the Postgres database. + * @param {number} port - The port of the Postgres database. + * @param {string} username - The username for the Postgres database. + * @param {string} password - The password for the Postgres database. + * @param {string} dbName - The name of the database. + * @returns {boolean} Returns true if connection is successful, otherwise false. + * @throws {Error} If connection is unsuccessful. + */ + ConnectWithDB(host, port, username, password, dbName) { + // implemented in go + }; + + /** + * @method + * @description Connects to Postgres database using given credentials and database name and executes a query on the db. + * @param {string} host - The host of the Postgres database. + * @param {number} port - The port of the Postgres database. + * @param {string} username - The username for the Postgres database. + * @param {string} password - The password for the Postgres database. + * @param {string} dbName - The name of the database. + * @param {string} query - The query to be executed. + * @returns {string} Returns the result of the query execution. + * @throws {Error} If connection is unsuccessful or query execution fails. + */ + ExecuteQuery(host, port, username, password, dbName, query) { + // implemented in go + }; + + /** + * @method + * @description Checks if the given host and port are running Postgres database. + * @param {string} host - The host of the Postgres database. + * @param {number} port - The port of the Postgres database. + * @returns {boolean} Returns true if connection is successful, otherwise false. + * @throws {Error} If connection is unsuccessful. + */ + IsPostgres(host, port) { + // implemented in go + }; +}; + +// ReadOnly DONOT EDIT +module.exports = { + PGClient: PGClient, +}; \ No newline at end of file diff --git a/v2/pkg/js/generated/js/librdp/rdp.js b/v2/pkg/js/generated/js/librdp/rdp.js new file mode 100644 index 0000000000..72a7305113 --- /dev/null +++ b/v2/pkg/js/generated/js/librdp/rdp.js @@ -0,0 +1,48 @@ +/** + * @module rdp + */ + +/** + * @class + * RDPClient is a client for rdp servers + */ +class RDPClient { + /** + * @method + * CheckRDPAuth checks if the given host and port are running rdp server + * with authentication and returns their metadata. + * @param {string} host - The host of the rdp server + * @param {number} port - The port of the rdp server + * @returns {CheckRDPAuthResponse} - The response from the rdp server + * @throws {error} If the rdp server is not running or there is a problem with the connection + * @example + * let client = new RDPClient(); + * let response = client.CheckRDPAuth("localhost", 3389); + */ + CheckRDPAuth(host, port) { + // implemented in go + }; + + /** + * @method + * IsRDP checks if the given host and port are running rdp server. + * If connection is successful, it returns true. + * If connection is unsuccessful, it throws an error. + * The Name of the OS is also returned if the connection is successful. + * @param {string} host - The host of the rdp server + * @param {number} port - The port of the rdp server + * @returns {IsRDPResponse} - The response from the rdp server + * @throws {error} If the rdp server is not running or there is a problem with the connection + * @example + * let client = new RDPClient(); + * let response = client.IsRDP("localhost", 3389); + */ + IsRDP(host, port) { + // implemented in go + }; +}; + +// ReadOnly DONOT EDIT +module.exports = { + RDPClient: RDPClient, +}; \ No newline at end of file diff --git a/v2/pkg/js/generated/js/libredis/redis.js b/v2/pkg/js/generated/js/libredis/redis.js new file mode 100644 index 0000000000..c70d5f96eb --- /dev/null +++ b/v2/pkg/js/generated/js/libredis/redis.js @@ -0,0 +1,70 @@ +/** + * @module redis + */ + +/** + * Connect to a Redis server. + * @function + * @param {string} host - The host of the Redis server. + * @param {number} port - The port of the Redis server. + * @param {string} password - The password for the Redis server. + */ +function Connect(host, port, password) { + // implemented in go +}; + +/** + * Get information about the Redis server. + * @function + * @param {string} host - The host of the Redis server. + * @param {number} port - The port of the Redis server. + * @returns {Object} An object containing information about the server. + */ +function GetServerInfo(host, port) { + // implemented in go +}; + +/** + * Get information about the Redis server with authentication. + * @function + * @param {string} host - The host of the Redis server. + * @param {number} port - The port of the Redis server. + * @param {string} password - The password for the Redis server. + * @returns {Object} An object containing information about the server. + */ +function GetServerInfoAuth(host, port, password) { + // implemented in go +}; + +/** + * Check if the Redis server is authenticated. + * @function + * @param {string} host - The host of the Redis server. + * @param {number} port - The port of the Redis server. + * @returns {boolean} True if the server is authenticated, false otherwise. + */ +function IsAuthenticated(host, port) { + // implemented in go +}; + +/** + * Run a Lua script on the Redis server. + * @function + * @param {string} host - The host of the Redis server. + * @param {number} port - The port of the Redis server. + * @param {string} password - The password for the Redis server. + * @param {string} script - The Lua script to run. + * @returns {Object} The result of the script execution. + */ +function RunLuaScript(host, port, password, script) { + // implemented in go +}; + +// ReadOnly DONOT EDIT +module.exports = { + Connect: Connect, + GetServerInfo: GetServerInfo, + GetServerInfoAuth: GetServerInfoAuth, + IsAuthenticated: IsAuthenticated, + RunLuaScript: RunLuaScript, +}; \ No newline at end of file diff --git a/v2/pkg/js/generated/js/librsync/rsync.js b/v2/pkg/js/generated/js/librsync/rsync.js new file mode 100644 index 0000000000..37101097e5 --- /dev/null +++ b/v2/pkg/js/generated/js/librsync/rsync.js @@ -0,0 +1,34 @@ +/** + * @module rsync + */ + +/** + * @class + * @classdesc RsyncClient is a minimal Rsync client for nuclei scripts. + */ +class RsyncClient { + /** + * @method + * @name IsRsync + * @param {string} host - The host to check. + * @param {number} port - The port to check. + * @returns {IsRsyncResponse} - The response from the Rsync server. + * @throws {error} - Throws an error if unable to check. + * @example + * let client = new RsyncClient(); + * try { + * let response = client.IsRsync("localhost", 22); + * console.log(response); + * } catch (error) { + * console.error(error); + * } + */ + IsRsync(host, port) { + // implemented in go + }; +}; + +// ReadOnly DONOT EDIT +module.exports = { + RsyncClient: RsyncClient, +}; \ No newline at end of file diff --git a/v2/pkg/js/generated/js/libsmb/smb.js b/v2/pkg/js/generated/js/libsmb/smb.js new file mode 100644 index 0000000000..26c902e8eb --- /dev/null +++ b/v2/pkg/js/generated/js/libsmb/smb.js @@ -0,0 +1,92 @@ +/** + * @module smb + */ + +/** + * @class + * @description SMBClient is a client for SMB servers. Internally client uses github.com/zmap/zgrab2/lib/smb/smb driver and github.com/hirochachacha/go-smb2 driver. + */ +class SMBClient { + /** + * @method + * @description ConnectSMBInfoMode tries to connect to provided host and port and discovery SMB information + * @param {string} host - The host to connect to + * @param {number} port - The port to connect to + * @returns {Object} SMBLog - The handshake log + * @throws {Error} If an error occurs, the error is thrown + * @example + * let client = new SMBClient(); + * try { + * let log = client.ConnectSMBInfoMode('localhost', 8080); + * } catch (error) { + * console.error(error); + * } + */ + ConnectSMBInfoMode(host, port) { + // implemented in go + }; + + /** + * @method + * @description DetectSMBGhost tries to detect SMBGhost vulnerability by using SMBv3 compression feature. + * @param {string} host - The host to connect to + * @param {number} port - The port to connect to + * @returns {boolean} - Returns true if vulnerability is detected, false otherwise + * @throws {Error} If an error occurs, the error is thrown + * @example + * let client = new SMBClient(); + * try { + * let isVulnerable = client.DetectSMBGhost('localhost', 8080); + * } catch (error) { + * console.error(error); + * } + */ + DetectSMBGhost(host, port) { + // implemented in go + }; + + /** + * @method + * @description ListSMBv2Metadata tries to connect to provided host and port and list SMBv2 metadata. + * @param {string} host - The host to connect to + * @param {number} port - The port to connect to + * @returns {Object} ServiceSMB - The metadata + * @throws {Error} If an error occurs, the error is thrown + * @example + * let client = new SMBClient(); + * try { + * let metadata = client.ListSMBv2Metadata('localhost', 8080); + * } catch (error) { + * console.error(error); + * } + */ + ListSMBv2Metadata(host, port) { + // implemented in go + }; + + /** + * @method + * @description ListShares tries to connect to provided host and port and list shares by using given credentials. Credentials cannot be blank. guest or anonymous credentials can be used by providing empty password. + * @param {string} host - The host to connect to + * @param {number} port - The port to connect to + * @param {string} user - The username + * @param {string} password - The password + * @returns {Array.} - The list of shares + * @throws {Error} If an error occurs, the error is thrown + * @example + * let client = new SMBClient(); + * try { + * let shares = client.ListShares('localhost', 8080, 'user', 'password'); + * } catch (error) { + * console.error(error); + * } + */ + ListShares(host, port, user, password) { + // implemented in go + }; +}; + +// ReadOnly DONOT EDIT +module.exports = { + SMBClient: SMBClient, +}; \ No newline at end of file diff --git a/v2/pkg/js/generated/js/libsmtp/smtp.js b/v2/pkg/js/generated/js/libsmtp/smtp.js new file mode 100644 index 0000000000..485236ff70 --- /dev/null +++ b/v2/pkg/js/generated/js/libsmtp/smtp.js @@ -0,0 +1,29 @@ +/** + * @module smtp + */ + +/** + * @class + * SMTPClient is a minimal SMTP client for nuclei scripts. + */ +class SMTPClient { + /** + * @method + * IsSMTP checks if a host is running a SMTP server. + * @param {string} host - The host to check. + * @param {number} port - The port to check. + * @returns {boolean} IsSMTPResponse - The response indicating if the host is running a SMTP server. + * @throws {Error} If an error occurs during the check. + * @example + * let client = new SMTPClient(); + * let isSMTP = client.IsSMTP("localhost", 25); + */ + IsSMTP(host, port) { + // implemented in go + }; +}; + +// ReadOnly DONOT EDIT +module.exports = { + SMTPClient: SMTPClient, +}; \ No newline at end of file diff --git a/v2/pkg/js/generated/js/libssh/ssh.js b/v2/pkg/js/generated/js/libssh/ssh.js new file mode 100644 index 0000000000..60ac1dd64a --- /dev/null +++ b/v2/pkg/js/generated/js/libssh/ssh.js @@ -0,0 +1,68 @@ +/** + * @module ssh + */ + +/** + * @class + * @classdesc SSHClient is a client for SSH servers. Internally client uses github.com/zmap/zgrab2/lib/ssh driver. + */ +class SSHClient { + /** + * @method + * @description Connect tries to connect to provided host and port with provided username and password with ssh. + * @param {string} host - The host to connect to. + * @param {number} port - The port to connect to. + * @param {string} username - The username for authentication. + * @param {string} password - The password for authentication. + * @returns {boolean} Returns state of connection. If error is thrown, state will be false. + * @throws Will throw an error if the connection fails. + * @example + * let client = new SSHClient(); + * client.Connect('localhost', 22, 'root', 'password'); + */ + Connect(host, port, username, password) { + // implemented in go + }; + + /** + * @typedef {Object} HandshakeLog + * @description HandshakeLog is a struct that contains information about the ssh connection. + */ + + /** + * @method + * @description ConnectSSHInfoMode tries to connect to provided host and port. + * @param {string} host - The host to connect to. + * @param {number} port - The port to connect to. + * @returns {HandshakeLog} Returns HandshakeLog. If error is thrown, state will be false. + * @throws Will throw an error if the connection fails. + * @example + * let client = new SSHClient(); + * client.ConnectSSHInfoMode('localhost', 22); + */ + ConnectSSHInfoMode(host, port) { + // implemented in go + }; + + /** + * @method + * @description ConnectWithKey tries to connect to provided host and port with provided username and private_key. + * @param {string} host - The host to connect to. + * @param {number} port - The port to connect to. + * @param {string} username - The username for authentication. + * @param {string} key - The private key for authentication. + * @returns {boolean} Returns state of connection. If error is thrown, state will be false. + * @throws Will throw an error if the connection fails. + * @example + * let client = new SSHClient(); + * client.ConnectWithKey('localhost', 22, 'root', 'private_key'); + */ + ConnectWithKey(host, port, username, key) { + // implemented in go + }; +}; + +// ReadOnly DONOT EDIT +module.exports = { + SSHClient: SSHClient, +}; \ No newline at end of file diff --git a/v2/pkg/js/generated/js/libstructs/structs.js b/v2/pkg/js/generated/js/libstructs/structs.js new file mode 100644 index 0000000000..42cf8e9627 --- /dev/null +++ b/v2/pkg/js/generated/js/libstructs/structs.js @@ -0,0 +1,47 @@ +/** + * @module structs + */ + +/** + * @class + * @name Pack + * @param {string} formatStr - The format string. + * @param {Object} msg - The message object. + * @method + * @example + * let data = structs.pack("H", 0) + */ +function Pack(formatStr, msg) { + // implemented in go +}; + +/** + * @function + * @name StructsCalcSize + * @param {string} format - The format string. + * @returns {number} The calculated size. + * @example + * let size = StructsCalcSize('formatString'); + */ +function StructsCalcSize(format) { + // implemented in go +}; + +/** + * @class + * @name Unpack + * @param {string} format - The format string. + * @param {Object} msg - The message object. + * @method + * @example + * let data = structs.Unpack(">I", buff[:nb]) + */ +function Unpack(format, msg) { + // implemented in go +}; + +module.exports = { + Pack: Pack, + StructsCalcSize: StructsCalcSize, + Unpack: Unpack, +}; \ No newline at end of file diff --git a/v2/pkg/js/generated/js/libtelnet/telnet.js b/v2/pkg/js/generated/js/libtelnet/telnet.js new file mode 100644 index 0000000000..f57800afad --- /dev/null +++ b/v2/pkg/js/generated/js/libtelnet/telnet.js @@ -0,0 +1,34 @@ +/** + * @module telnet + */ + +/** + * @class + * @classdesc TelnetClient is a minimal Telnet client for nuclei scripts. + */ +class TelnetClient { + /** + * @method + * @name IsTelnet + * @param {string} host - The host to check. + * @param {number} port - The port to check. + * @returns {boolean} IsTelnetResponse - Returns true if the host is running a Telnet server, false otherwise. + * @throws {Error} If an error occurred during the operation. + * @example + * let client = new TelnetClient(); + * let isTelnet = client.IsTelnet("localhost", 23); + * if (isTelnet) { + * console.log("The host is running a Telnet server."); + * } else { + * console.log("The host is not running a Telnet server."); + * } + */ + IsTelnet(host, port) { + // implemented in go + }; +}; + +// ReadOnly DONOT EDIT +module.exports = { + TelnetClient: TelnetClient, +}; \ No newline at end of file diff --git a/v2/pkg/js/generated/js/libvnc/vnc.js b/v2/pkg/js/generated/js/libvnc/vnc.js new file mode 100644 index 0000000000..79d517630b --- /dev/null +++ b/v2/pkg/js/generated/js/libvnc/vnc.js @@ -0,0 +1,29 @@ +/** + * @module vnc + */ + +/** + * @class VNCClient + * @description A minimal VNC client for nuclei scripts. + */ +class VNCClient { + /** + * @method IsVNC + * @description Checks if a host is running a VNC server. + * @param {string} host - The host to check. + * @param {number} port - The port to check. + * @returns {Object} IsVNCResponse - The response object. + * @throws {error} If an error occurs during the operation. + * @example + * let client = new VNCClient(); + * let response = client.IsVNC("localhost", 5900); + */ + IsVNC(host, port) { + // implemented in go + }; +}; + +// ReadOnly DONOT EDIT +module.exports = { + VNCClient: VNCClient, +}; \ No newline at end of file diff --git a/v2/pkg/js/global/exports.js b/v2/pkg/js/global/exports.js new file mode 100644 index 0000000000..b15a3dd813 --- /dev/null +++ b/v2/pkg/js/global/exports.js @@ -0,0 +1,9 @@ +exports = { + // General + dump_json: dump_json, + to_json: to_json, + hex_to_ascii: hex_to_ascii, + + // Active Directory + getDomainControllerName: getDomainControllerName, +}; diff --git a/v2/pkg/js/global/js/active_directory.js b/v2/pkg/js/global/js/active_directory.js new file mode 100644 index 0000000000..22a3e7f6b8 --- /dev/null +++ b/v2/pkg/js/global/js/active_directory.js @@ -0,0 +1,58 @@ +// getDomainControllerName returns the domain controller +// name for a host. +// +// If the name is not empty, it is returned. +// Otherwise, the host is used to query the domain controller name. +// from SMB, LDAP, etc +function getDomainControllerName(name, host) { + if (name != "") { + return name; + } + + // First try LDAP and then SMB + try { + var name = getDomainControllerNameByLDAP(host); + if (name != "") { + return name; + } + } catch (e) { + console.log("[ldap] Error getting domain controller name", e); + } + + try { + var name = getDomainControllerNameBySMB(host); + if (name != "") { + return name; + } + } catch (e) { + console.log("[smb] Error getting domain controller name", e); + } + + return ""; +} + +function getDomainControllerNameBySMB(host) { + const s = require("nuclei/libsmb"); + const sc = s.Client(); + var list = sc.ListSMBv2Metadata(host, 445); + if (!list) { + return ""; + } + if (list && list.DNSDomainName != "") { + console.log("[smb] Got domain controller", list.DNSDomainName); + return list.DNSDomainName; + } +} + +function getDomainControllerNameByLDAP(host) { + const l = require("nuclei/libldap"); + const lc = l.Client(); + var list = lc.CollectLdapMetadata("", host); + if (!list) { + return ""; + } + if (list && list.domain != "") { + console.log("[ldap] Got domain controller", list.domain); + return list.domain; + } +} diff --git a/v2/pkg/js/global/js/dump.js b/v2/pkg/js/global/js/dump.js new file mode 100644 index 0000000000..e5e0a0cedb --- /dev/null +++ b/v2/pkg/js/global/js/dump.js @@ -0,0 +1,20 @@ +// dump_json dumps the data as JSON to the console. +// It returns beautified JSON. +function dump_json(data) { + console.log(JSON.stringify(data, null, 2)); +} + +// to_json returns beautified JSON. +function to_json(data) { + return JSON.stringify(data, null, 2); +} + +// hex_to_ascii converts a hex string to ascii. +function hex_to_ascii(str1) { + var hex = str1.toString(); + var str = ""; + for (var n = 0; n < hex.length; n += 2) { + str += String.fromCharCode(parseInt(hex.substr(n, 2), 16)); + } + return str; +} diff --git a/v2/pkg/js/global/scripts.go b/v2/pkg/js/global/scripts.go new file mode 100644 index 0000000000..027767ab47 --- /dev/null +++ b/v2/pkg/js/global/scripts.go @@ -0,0 +1,224 @@ +package global + +import ( + "bytes" + "embed" + "math/rand" + "net" + "reflect" + "time" + + "github.com/dop251/goja" + "github.com/logrusorgru/aurora" + "github.com/projectdiscovery/gologger" + "github.com/projectdiscovery/nuclei/v2/pkg/js/gojs" + "github.com/projectdiscovery/nuclei/v2/pkg/protocols/common/utils/vardump" + "github.com/projectdiscovery/nuclei/v2/pkg/types" + errorutil "github.com/projectdiscovery/utils/errors" + stringsutil "github.com/projectdiscovery/utils/strings" +) + +var ( + //go:embed js + embedFS embed.FS + + //go:embed exports.js + exports string + // knownPorts is a list of known ports for protocols implemented in nuclei + knowPorts = []string{"80", "443", "8080", "8081", "8443", "53"} +) + +// default imported modules +// there might be other methods to achieve this +// but this is most straightforward +var ( + defaultImports = ` + var structs = require("nuclei/structs"); + var bytes = require("nuclei/bytes"); + ` +) + +// initBuiltInFunc initializes runtime with builtin functions +func initBuiltInFunc(runtime *goja.Runtime) { + + _ = gojs.RegisterFuncWithSignature(runtime, gojs.FuncOpts{ + Name: "Rand", + Signatures: []string{"Rand(n int) []byte"}, + Description: "Rand returns a random byte slice of length n", + FuncDecl: func(n int) []byte { + b := make([]byte, n) + for i := range b { + b[i] = byte(rand.Intn(255)) + } + return b + }, + }) + + _ = gojs.RegisterFuncWithSignature(runtime, gojs.FuncOpts{ + Name: "RandInt", + Signatures: []string{"RandInt() int"}, + Description: "RandInt returns a random int", + FuncDecl: func() int64 { + return rand.Int63() + }, + }) + + _ = gojs.RegisterFuncWithSignature(runtime, gojs.FuncOpts{ + Name: "log", + Signatures: []string{ + "log(msg string)", + "log(msg map[string]interface{})", + }, + Description: "log prints given input to stdout with [JS] prefix for debugging purposes ", + FuncDecl: func(call goja.FunctionCall) goja.Value { + arg := call.Argument(0).Export() + switch value := arg.(type) { + case string: + gologger.DefaultLogger.Print().Msgf("[%v] %v", aurora.BrightCyan("JS"), value) + case map[string]interface{}: + gologger.DefaultLogger.Print().Msgf("[%v] %v", aurora.BrightCyan("JS"), vardump.DumpVariables(value)) + default: + gologger.DefaultLogger.Print().Msgf("[%v] %v", aurora.BrightCyan("JS"), value) + } + return goja.Null() + }, + }) + + _ = gojs.RegisterFuncWithSignature(runtime, gojs.FuncOpts{ + Name: "getNetworkPort", + Signatures: []string{ + "getNetworkPort(port string, defaultPort string) string", + }, + Description: "getNetworkPort registers defaultPort and returns defaultPort if it is a colliding port with other protocols", + FuncDecl: func(call goja.FunctionCall) goja.Value { + inputPort := call.Argument(0).String() + if inputPort == "" || stringsutil.EqualFoldAny(inputPort, knowPorts...) { + // if inputPort is empty or a know port of other protocol + // return given defaultPort + return call.Argument(1) + } + return call.Argument(0) + }, + }) + + // is port open check is port is actually open + // it can be invoked as isPortOpen(host, port, [timeout]) + // where timeout is optional and defaults to 5 seconds + _ = gojs.RegisterFuncWithSignature(runtime, gojs.FuncOpts{ + Name: "isPortOpen", + Signatures: []string{ + "isPortOpen(host string, port string, [timeout int]) bool", + }, + Description: "isPortOpen checks if given port is open on host. timeout is optional and defaults to 5 seconds", + FuncDecl: func(call goja.FunctionCall) goja.Value { + host := call.Argument(0).String() + if host == "" { + return runtime.ToValue(false) + } + port := call.Argument(1).String() + if port == "" { + return runtime.ToValue(false) + } + timeoutinSec := call.Argument(2).ToInteger() + if timeoutinSec == 0 { + timeoutinSec = 5 + } + conn, err := net.DialTimeout("tcp", net.JoinHostPort(host, port), time.Duration(timeoutinSec)*time.Second) + if err != nil { + return runtime.ToValue(false) + } + _ = conn.Close() + return runtime.ToValue(true) + }, + }) + + _ = gojs.RegisterFuncWithSignature(runtime, gojs.FuncOpts{ + Name: "ToBytes", + Signatures: []string{ + "ToBytes(...interface{}) []byte", + }, + Description: "ToBytes converts given input to byte slice", + FuncDecl: func(call goja.FunctionCall) goja.Value { + var buff bytes.Buffer + allVars := []any{} + for _, v := range call.Arguments { + if v.Export() == nil { + continue + } + if v.ExportType().Kind() == reflect.Slice { + // convert []datatype to []interface{} + // since it cannot be type asserted to []interface{} directly + rfValue := reflect.ValueOf(v.Export()) + for i := 0; i < rfValue.Len(); i++ { + allVars = append(allVars, rfValue.Index(i).Interface()) + } + } else { + allVars = append(allVars, v.Export()) + } + } + for _, v := range allVars { + buff.WriteString(types.ToString(v)) + } + return runtime.ToValue(buff.Bytes()) + }, + }) + + _ = gojs.RegisterFuncWithSignature(runtime, gojs.FuncOpts{ + Name: "ToString", + Signatures: []string{ + "ToString(...interface{}) string", + }, + Description: "ToString converts given input to string", + FuncDecl: func(call goja.FunctionCall) goja.Value { + var buff bytes.Buffer + for _, v := range call.Arguments { + exported := v.Export() + if exported != nil { + buff.WriteString(types.ToString(exported)) + } + } + return runtime.ToValue(buff.String()) + }, + }) +} + +// RegisterNativeScripts are js scripts that were added for convenience +// and abstraction purposes we execute them in every runtime and make them +// available for use in any js script +// see: scripts/ for examples +func RegisterNativeScripts(runtime *goja.Runtime) error { + initBuiltInFunc(runtime) + + dirs, err := embedFS.ReadDir("js") + if err != nil { + return err + } + for _, dir := range dirs { + if dir.IsDir() { + continue + } + // embeds have / as path separator (on all os) + contents, err := embedFS.ReadFile("js" + "/" + dir.Name()) + if err != nil { + return err + } + // run all built in js helper functions or scripts + _, err = runtime.RunString(string(contents)) + if err != nil { + return err + } + } + // exports defines the exports object + _, err = runtime.RunString(exports) + if err != nil { + return err + } + + // import default modules + _, err = runtime.RunString(defaultImports) + if err != nil { + return errorutil.NewWithErr(err).Msgf("could not import default modules %v", defaultImports) + } + + return nil +} diff --git a/v2/pkg/js/global/scripts_test.go b/v2/pkg/js/global/scripts_test.go new file mode 100644 index 0000000000..4105695f6d --- /dev/null +++ b/v2/pkg/js/global/scripts_test.go @@ -0,0 +1,28 @@ +package global + +import ( + "testing" + + "github.com/dop251/goja" + "github.com/dop251/goja_nodejs/console" + "github.com/dop251/goja_nodejs/require" +) + +func TestScriptsRuntime(t *testing.T) { + defaultImports = "" + runtime := goja.New() + + registry := new(require.Registry) + registry.Enable(runtime) + console.Enable(runtime) + + err := RegisterNativeScripts(runtime) + if err != nil { + t.Fatal(err) + } + value, err := runtime.RunString("dump_json({a: 1, b: 2})") + if err != nil { + t.Fatal(err) + } + _ = value +} diff --git a/v2/pkg/js/gojs/gojs.go b/v2/pkg/js/gojs/gojs.go new file mode 100644 index 0000000000..0b47cbd1de --- /dev/null +++ b/v2/pkg/js/gojs/gojs.go @@ -0,0 +1,77 @@ +package gojs + +import ( + "sync" + + "github.com/dop251/goja" + "github.com/dop251/goja_nodejs/require" +) + +type Objects map[string]interface{} + +type Runtime interface { + Set(string, interface{}) error +} + +type Object interface { + Set(string, interface{}) + Get(string) interface{} +} + +type Module interface { + Name() string + Set(objects Objects) Module + Enable(Runtime) + Register() Module +} + +type GojaModule struct { + name string + sets map[string]interface{} + once sync.Once +} + +func NewGojaModule(name string) Module { + return &GojaModule{ + name: name, + sets: make(map[string]interface{}), + } +} + +func (p *GojaModule) String() string { + return p.name +} + +func (p *GojaModule) Name() string { + return p.name +} + +func (p *GojaModule) Set(objects Objects) Module { + + for k, v := range objects { + p.sets[k] = v + } + + return p +} + +func (p *GojaModule) Require(runtime *goja.Runtime, module *goja.Object) { + + o := module.Get("exports").(*goja.Object) + + for k, v := range p.sets { + _ = o.Set(k, v) + } +} + +func (p *GojaModule) Enable(runtime Runtime) { + _ = runtime.Set(p.Name(), require.Require(runtime.(*goja.Runtime), p.Name())) +} + +func (p *GojaModule) Register() Module { + p.once.Do(func() { + require.RegisterNativeModule(p.Name(), p.Require) + }) + + return p +} diff --git a/v2/pkg/js/gojs/set.go b/v2/pkg/js/gojs/set.go new file mode 100644 index 0000000000..38e45d8d72 --- /dev/null +++ b/v2/pkg/js/gojs/set.go @@ -0,0 +1,30 @@ +package gojs + +import ( + "github.com/dop251/goja" + errorutil "github.com/projectdiscovery/utils/errors" +) + +var ( + ErrInvalidFuncOpts = errorutil.NewWithFmt("invalid function options: %v") +) + +type FuncOpts struct { + Name string + Signatures []string + Description string + FuncDecl interface{} +} + +// valid checks if the function options are valid +func (f *FuncOpts) valid() bool { + return f.Name != "" && f.FuncDecl != nil && len(f.Signatures) > 0 && f.Description != "" +} + +// RegisterFunc registers a function with given name, signatures and description +func RegisterFuncWithSignature(runtime *goja.Runtime, opts FuncOpts) error { + if !opts.valid() { + return ErrInvalidFuncOpts.Msgf("name: %s, signatures: %v, description: %s", opts.Name, opts.Signatures, opts.Description) + } + return runtime.Set(opts.Name, opts.FuncDecl) +} diff --git a/v2/pkg/js/libs/LICENSE.md b/v2/pkg/js/libs/LICENSE.md new file mode 100644 index 0000000000..9a57875332 --- /dev/null +++ b/v2/pkg/js/libs/LICENSE.md @@ -0,0 +1,203 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +This project uses modules from praetorian/fingerprintx for detection of network protocols which is licensed under Apache 2.0. \ No newline at end of file diff --git a/v2/pkg/js/libs/bytes/buffer.go b/v2/pkg/js/libs/bytes/buffer.go new file mode 100644 index 0000000000..ab3b75eb1a --- /dev/null +++ b/v2/pkg/js/libs/bytes/buffer.go @@ -0,0 +1,78 @@ +package bytes + +import ( + "encoding/hex" + + "github.com/dop251/goja" + "github.com/projectdiscovery/nuclei/v2/pkg/js/libs/structs" +) + +// Buffer is a minimal buffer implementation over a byte slice +// that is used to pack/unpack binary data in nuclei js integration. +type Buffer struct { + buf []byte +} + +// NewBuffer creates a new buffer from a byte slice. +func NewBuffer(call goja.ConstructorCall) interface{} { + obj := &Buffer{} + + obj.buf = make([]byte, 0) + return map[string]interface{}{ + "Write": obj.Write, + "Pack": obj.Pack, + "Bytes": obj.Bytes, + "String": obj.String, + "Len": obj.Len, + "Hex": obj.Hex, + "Hexdump": obj.Hexdump, + } +} + +// Write appends a byte slice to the buffer. +func (b *Buffer) Write(data []byte) *Buffer { + b.buf = append(b.buf, data...) + return b +} + +// WriteString appends a string to the buffer. +func (b *Buffer) WriteString(data string) *Buffer { + b.buf = append(b.buf, []byte(data)...) + return b +} + +// Bytes returns the byte slice of the buffer. +func (b *Buffer) Bytes() []byte { + return b.buf +} + +// String returns the string representation of the buffer. +func (b *Buffer) String() string { + return string(b.buf) +} + +// Len returns the length of the buffer. +func (b *Buffer) Len() int { + return len(b.buf) +} + +// Hex returns the hex representation of the buffer. +func (b *Buffer) Hex() string { + return hex.EncodeToString(b.buf) +} + +// Hexdump returns the hexdump representation of the buffer. +func (b *Buffer) Hexdump() string { + return hex.Dump(b.buf) +} + +// Pack uses structs.Pack and packs given data and appends it to the buffer. +// it packs the data according to the given format. +func (b *Buffer) Pack(formatStr string, msg []interface{}) error { + bin, err := structs.Pack(formatStr, msg) + if err != nil { + return err + } + b.Write(bin) + return nil +} diff --git a/v2/pkg/js/libs/goconsole/log.go b/v2/pkg/js/libs/goconsole/log.go new file mode 100644 index 0000000000..994d6609a7 --- /dev/null +++ b/v2/pkg/js/libs/goconsole/log.go @@ -0,0 +1,31 @@ +package goconsole + +import ( + "github.com/dop251/goja_nodejs/console" + "github.com/projectdiscovery/gologger" +) + +var _ console.Printer = &GoConsolePrinter{} + +// GoConsolePrinter is a console printer for nuclei using gologger +type GoConsolePrinter struct { + logger *gologger.Logger +} + +func NewGoConsolePrinter() *GoConsolePrinter { + return &GoConsolePrinter{ + logger: gologger.DefaultLogger, + } +} + +func (p *GoConsolePrinter) Log(msg string) { + p.logger.Info().Msg(msg) +} + +func (p *GoConsolePrinter) Warn(msg string) { + p.logger.Warning().Msg(msg) +} + +func (p *GoConsolePrinter) Error(msg string) { + p.logger.Error().Msg(msg) +} diff --git a/v2/pkg/js/libs/ikev2/ikev2.go b/v2/pkg/js/libs/ikev2/ikev2.go new file mode 100644 index 0000000000..c41fedf2f7 --- /dev/null +++ b/v2/pkg/js/libs/ikev2/ikev2.go @@ -0,0 +1,104 @@ +package ikev2 + +import ( + "io" + + "github.com/projectdiscovery/n3iwf/pkg/ike/message" + "github.com/projectdiscovery/n3iwf/pkg/logger" +) + +func init() { + logger.Log.SetOutput(io.Discard) +} + +// IKEMessage is the IKEv2 message +// +// IKEv2 implements a limited subset of IKEv2 Protocol, specifically +// the IKE_NOTIFY and IKE_NONCE payloads and the IKE_SA_INIT exchange. +type IKEMessage struct { + InitiatorSPI uint64 + Version uint8 + ExchangeType uint8 + Flags uint8 + Payloads []IKEPayload +} + +// IKEPayload is the IKEv2 payload interface +// +// All the payloads like IKENotification, IKENonce, etc. implement +// this interface. +type IKEPayload interface { + encode() (message.IKEPayload, error) +} + +// IKEv2Notify is the IKEv2 Notification payload +type IKENotification struct { + NotifyMessageType uint16 + NotificationData []byte +} + +// encode encodes the IKEv2 Notification payload +func (i *IKENotification) encode() (message.IKEPayload, error) { + notify := message.Notification{ + NotifyMessageType: i.NotifyMessageType, + NotificationData: i.NotificationData, + } + return ¬ify, nil +} + +const ( + // Notify message types + IKE_NOTIFY_NO_PROPOSAL_CHOSEN = 14 + IKE_NOTIFY_USE_TRANSPORT_MODE = 16391 + + IKE_VERSION_2 = 0x20 + + // Exchange Type + IKE_EXCHANGE_SA_INIT = 34 + IKE_EXCHANGE_AUTH = 35 + IKE_EXCHANGE_CREATE_CHILD_SA = 36 + IKE_EXCHANGE_INFORMATIONAL = 37 + + // Flags + IKE_FLAGS_InitiatorBitCheck = 0x08 +) + +// IKENonce is the IKEv2 Nonce payload +type IKENonce struct { + NonceData []byte +} + +// encode encodes the IKEv2 Nonce payload +func (i *IKENonce) encode() (message.IKEPayload, error) { + nonce := message.Nonce{ + NonceData: i.NonceData, + } + return &nonce, nil +} + +// AppendPayload appends a payload to the IKE message +func (m *IKEMessage) AppendPayload(payload IKEPayload) { + m.Payloads = append(m.Payloads, payload) +} + +// Encode encodes the final IKE message +func (m *IKEMessage) Encode() ([]byte, error) { + var payloads message.IKEPayloadContainer + for _, payload := range m.Payloads { + p, err := payload.encode() + if err != nil { + return nil, err + } + payloads = append(payloads, p) + } + + msg := &message.IKEMessage{ + InitiatorSPI: m.InitiatorSPI, + Version: m.Version, + ExchangeType: m.ExchangeType, + Flags: m.Flags, + Payloads: payloads, + } + encoded, err := msg.Encode() + return encoded, err +} diff --git a/v2/pkg/js/libs/kerberos/kerberos.go b/v2/pkg/js/libs/kerberos/kerberos.go new file mode 100644 index 0000000000..ac5708a5c3 --- /dev/null +++ b/v2/pkg/js/libs/kerberos/kerberos.go @@ -0,0 +1,145 @@ +package kerberos + +import ( + "encoding/hex" + "fmt" + "html/template" + "strings" + + "github.com/projectdiscovery/nuclei/v2/pkg/protocols/common/protocolstate" + kclient "github.com/ropnop/gokrb5/v8/client" + kconfig "github.com/ropnop/gokrb5/v8/config" + "github.com/ropnop/gokrb5/v8/iana/errorcode" + "github.com/ropnop/gokrb5/v8/messages" +) + +// Client is a kerberos client +type KerberosClient struct{} + +type kerberosEnumUserOpts struct { + realm string + config *kconfig.Config + kdcs map[int]string +} + +// Taken from kerbrute: https://github.com/ropnop/kerbrute/blob/master/session/session.go + +const krb5ConfigTemplateDNS = `[libdefaults] +dns_lookup_kdc = true +default_realm = {{.Realm}} +` + +const krb5ConfigTemplateKDC = `[libdefaults] +default_realm = {{.Realm}} +[realms] +{{.Realm}} = { + kdc = {{.DomainController}} + admin_server = {{.DomainController}} +} +` + +func buildKrb5Template(realm, domainController string) string { + data := map[string]interface{}{ + "Realm": realm, + "DomainController": domainController, + } + var kTemplate string + if domainController == "" { + kTemplate = krb5ConfigTemplateDNS + } else { + kTemplate = krb5ConfigTemplateKDC + } + t := template.Must(template.New("krb5ConfigString").Parse(kTemplate)) + builder := &strings.Builder{} + if err := t.Execute(builder, data); err != nil { + panic(err) + } + return builder.String() +} + +func newKerbrosEnumUserOpts(domain, domainController string) (*kerberosEnumUserOpts, error) { + realm := strings.ToUpper(domain) + configstring := buildKrb5Template(realm, domainController) + Config, err := kconfig.NewFromString(configstring) + if err != nil { + return nil, err + } + _, kdcs, err := Config.GetKDCs(realm, false) + if err != nil { + err = fmt.Errorf("couldn't find any KDCs for realm %s. Please specify a Domain Controller", realm) + return nil, err + } + return &kerberosEnumUserOpts{realm: realm, config: Config, kdcs: kdcs}, nil +} + +// EnumerateUserResponse is the response from EnumerateUser +type EnumerateUserResponse struct { + Valid bool + ASREPHash string +} + +// EnumerateUser returns true if the user exists in the domain +// +// If the user is not found, false is returned. +// If the user is found, true is returned. Optionally, the AS-REP +// hash is also returned if discovered. +func (c *KerberosClient) EnumerateUser(domain, controller string, username string) (EnumerateUserResponse, error) { + + resp := EnumerateUserResponse{} + + if !protocolstate.IsHostAllowed(domain) { + // host is not valid according to network policy + return resp, protocolstate.ErrHostDenied.Msgf(domain) + } + + opts, err := newKerbrosEnumUserOpts(domain, controller) + if err != nil { + return resp, err + } + cl := kclient.NewWithPassword(username, opts.realm, "foobar", opts.config, kclient.DisablePAFXFAST(true)) + + req, err := messages.NewASReqForTGT(cl.Credentials.Domain(), cl.Config, cl.Credentials.CName()) + if err != nil { + return resp, err + } + b, err := req.Marshal() + if err != nil { + return resp, err + } + rb, err := cl.SendToKDC(b, opts.realm) + if err == nil { + var ASRep messages.ASRep + err = ASRep.Unmarshal(rb) + if err != nil { + // something went wrong, it's not a valid response + return resp, err + } + hashcatString, _ := asRepToHashcat(ASRep) + resp.Valid = true + resp.ASREPHash = hashcatString + return resp, nil + } + e, ok := err.(messages.KRBError) + if !ok { + return resp, nil + } + switch e.ErrorCode { + case errorcode.KDC_ERR_C_PRINCIPAL_UNKNOWN: + return resp, nil + case errorcode.KDC_ERR_PREAUTH_REQUIRED: + resp.Valid = true + return resp, nil + default: + return resp, err + + } +} + +func asRepToHashcat(asrep messages.ASRep) (string, error) { + return fmt.Sprintf("$krb5asrep$%d$%s@%s:%s$%s", + asrep.EncPart.EType, + asrep.CName.PrincipalNameString(), + asrep.CRealm, + hex.EncodeToString(asrep.EncPart.Cipher[:16]), + hex.EncodeToString(asrep.EncPart.Cipher[16:])), nil +} diff --git a/v2/pkg/js/libs/ldap/ldap.go b/v2/pkg/js/libs/ldap/ldap.go new file mode 100644 index 0000000000..d6ad339738 --- /dev/null +++ b/v2/pkg/js/libs/ldap/ldap.go @@ -0,0 +1,205 @@ +package ldap + +import ( + "context" + "fmt" + "strings" + "time" + + "github.com/go-ldap/ldap/v3" + "github.com/praetorian-inc/fingerprintx/pkg/plugins" + "github.com/projectdiscovery/nuclei/v2/pkg/protocols/common/protocolstate" + + pluginldap "github.com/praetorian-inc/fingerprintx/pkg/plugins/services/ldap" +) + +// Client is a client for ldap protocol in golang. +// +// It is a wrapper around the standard library ldap package. +type LdapClient struct{} + +// IsLdap checks if the given host and port are running ldap server. +func (c *LdapClient) IsLdap(host string, port int) (bool, error) { + + if !protocolstate.IsHostAllowed(host) { + // host is not valid according to network policy + return false, protocolstate.ErrHostDenied.Msgf(host) + } + + timeout := 10 * time.Second + + conn, err := protocolstate.Dialer.Dial(context.TODO(), "tcp", fmt.Sprintf("%s:%d", host, port)) + + if err != nil { + return false, err + } + defer conn.Close() + + _ = conn.SetDeadline(time.Now().Add(timeout)) + + plugin := &pluginldap.LDAPPlugin{} + service, err := plugin.Run(conn, timeout, plugins.Target{Host: host}) + if err != nil { + return false, err + } + if service == nil { + return false, nil + } + return true, nil +} + +// CollectLdapMetadata collects metadata from ldap server. +func (c *LdapClient) CollectLdapMetadata(domain string, controller string) (LDAPMetadata, error) { + opts := &ldapSessionOptions{ + domain: domain, + domainController: controller, + } + + if !protocolstate.IsHostAllowed(domain) { + // host is not valid according to network policy + return LDAPMetadata{}, protocolstate.ErrHostDenied.Msgf(domain) + } + + conn, err := c.newLdapSession(opts) + if err != nil { + return LDAPMetadata{}, err + } + defer c.close(conn) + + return c.collectLdapMetadata(conn, opts) +} + +type ldapSessionOptions struct { + domain string + domainController string + port int + username string + password string + baseDN string +} + +func (c *LdapClient) newLdapSession(opts *ldapSessionOptions) (*ldap.Conn, error) { + port := opts.port + dc := opts.domainController + if port == 0 { + port = 389 + } + + conn, err := protocolstate.Dialer.Dial(context.TODO(), "tcp", fmt.Sprintf("%s:%d", dc, port)) + if err != nil { + return nil, err + } + + lConn := ldap.NewConn(conn, false) + lConn.Start() + + return lConn, nil +} + +func (c *LdapClient) close(conn *ldap.Conn) { + conn.Close() +} + +// LDAPMetadata is the metadata for ldap server. +type LDAPMetadata struct { + BaseDN string + Domain string + DefaultNamingContext string + DomainFunctionality string + ForestFunctionality string + DomainControllerFunctionality string + DnsHostName string +} + +func (c *LdapClient) collectLdapMetadata(lConn *ldap.Conn, opts *ldapSessionOptions) (LDAPMetadata, error) { + metadata := LDAPMetadata{} + + var err error + if opts.username == "" { + err = lConn.UnauthenticatedBind("") + } else { + err = lConn.Bind(opts.username, opts.password) + } + if err != nil { + return metadata, err + } + + baseDN, _ := getBaseNamingContext(opts, lConn) + + metadata.BaseDN = baseDN + metadata.Domain = parseDC(baseDN) + + srMetadata := ldap.NewSearchRequest( + "", + ldap.ScopeBaseObject, + ldap.NeverDerefAliases, + 0, 0, false, + "(objectClass=*)", + []string{ + "defaultNamingContext", + "domainFunctionality", + "forestFunctionality", + "domainControllerFunctionality", + "dnsHostName", + }, + nil) + resMetadata, err := lConn.Search(srMetadata) + if err != nil { + return metadata, err + } + for _, entry := range resMetadata.Entries { + for _, attr := range entry.Attributes { + value := entry.GetAttributeValue(attr.Name) + switch attr.Name { + case "defaultNamingContext": + metadata.DefaultNamingContext = value + case "domainFunctionality": + metadata.DomainFunctionality = value + case "forestFunctionality": + metadata.ForestFunctionality = value + case "domainControllerFunctionality": + metadata.DomainControllerFunctionality = value + case "dnsHostName": + metadata.DnsHostName = value + } + } + } + return metadata, nil +} + +func parseDC(input string) string { + parts := strings.Split(strings.ToLower(input), ",") + + for i, part := range parts { + parts[i] = strings.TrimPrefix(part, "dc=") + } + + return strings.Join(parts, ".") +} + +func getBaseNamingContext(opts *ldapSessionOptions, conn *ldap.Conn) (string, error) { + if opts.baseDN != "" { + return opts.baseDN, nil + } + sr := ldap.NewSearchRequest( + "", + ldap.ScopeBaseObject, + ldap.NeverDerefAliases, + 0, 0, false, + "(objectClass=*)", + []string{"defaultNamingContext"}, + nil) + res, err := conn.Search(sr) + if err != nil { + return "", err + } + if len(res.Entries) == 0 { + return "", fmt.Errorf("error getting metadata: No LDAP responses from server") + } + defaultNamingContext := res.Entries[0].GetAttributeValue("defaultNamingContext") + if defaultNamingContext == "" { + return "", fmt.Errorf("error getting metadata: attribute defaultNamingContext missing") + } + opts.baseDN = defaultNamingContext + return opts.baseDN, nil +} diff --git a/v2/pkg/js/libs/mssql/mssql.go b/v2/pkg/js/libs/mssql/mssql.go new file mode 100644 index 0000000000..4855791ce9 --- /dev/null +++ b/v2/pkg/js/libs/mssql/mssql.go @@ -0,0 +1,110 @@ +package mssql + +import ( + "context" + "database/sql" + "fmt" + "net" + "net/url" + "strings" + "time" + + _ "github.com/denisenkom/go-mssqldb" + "github.com/praetorian-inc/fingerprintx/pkg/plugins/services/mssql" + "github.com/projectdiscovery/nuclei/v2/pkg/protocols/common/protocolstate" +) + +// Client is a client for MS SQL database. +// +// Internally client uses denisenkom/go-mssqldb driver. +type MSSQLClient struct{} + +// Connect connects to MS SQL database using given credentials. +// +// If connection is successful, it returns true. +// If connection is unsuccessful, it returns false and error. +// +// The connection is closed after the function returns. +func (c *MSSQLClient) Connect(host string, port int, username, password string) (bool, error) { + return connect(host, port, username, password, "master") +} + +// ConnectWithDB connects to MS SQL database using given credentials and database name. +// +// If connection is successful, it returns true. +// If connection is unsuccessful, it returns false and error. +// +// The connection is closed after the function returns. +func (c *MSSQLClient) ConnectWithDB(host string, port int, username, password, dbName string) (bool, error) { + return connect(host, port, username, password, dbName) +} + +func connect(host string, port int, username, password, dbName string) (bool, error) { + if host == "" || port <= 0 { + return false, fmt.Errorf("invalid host or port") + } + if !protocolstate.IsHostAllowed(host) { + // host is not valid according to network policy + return false, protocolstate.ErrHostDenied.Msgf(host) + } + + target := net.JoinHostPort(host, fmt.Sprintf("%d", port)) + + connString := fmt.Sprintf("sqlserver://%s:%s@%s?database=%s&connection+timeout=30", + url.PathEscape(username), + url.PathEscape(password), + target, + dbName) + + db, err := sql.Open("sqlserver", connString) + if err != nil { + return false, err + } + defer db.Close() + + _, err = db.Exec("select 1") + if err != nil { + switch { + case strings.Contains(err.Error(), "connect: connection refused"): + fallthrough + case strings.Contains(err.Error(), "no pg_hba.conf entry for host"): + fallthrough + case strings.Contains(err.Error(), "network unreachable"): + fallthrough + case strings.Contains(err.Error(), "reset"): + fallthrough + case strings.Contains(err.Error(), "i/o timeout"): + return false, err + } + return false, nil + } + return true, nil +} + +// IsMssql checks if the given host is running MS SQL database. +// +// If the host is running MS SQL database, it returns true. +// If the host is not running MS SQL database, it returns false. +func (c *MSSQLClient) IsMssql(host string, port int) (bool, error) { + if !protocolstate.IsHostAllowed(host) { + // host is not valid according to network policy + return false, protocolstate.ErrHostDenied.Msgf(host) + } + + conn, err := protocolstate.Dialer.Dial(context.TODO(), "tcp", net.JoinHostPort(host, fmt.Sprintf("%d", port))) + if err != nil { + return false, err + } + defer conn.Close() + + data, check, err := mssql.DetectMSSQL(conn, 5*time.Second) + if check && err != nil { + return false, nil + } else if !check && err != nil { + return false, err + } + if data.Version != "" { + return true, nil + } + return false, nil +} diff --git a/v2/pkg/js/libs/mysql/mysql.go b/v2/pkg/js/libs/mysql/mysql.go new file mode 100644 index 0000000000..6be976ab6c --- /dev/null +++ b/v2/pkg/js/libs/mysql/mysql.go @@ -0,0 +1,128 @@ +package mysql + +import ( + "context" + "database/sql" + "fmt" + "net" + "net/url" + "time" + + _ "github.com/go-sql-driver/mysql" + "github.com/praetorian-inc/fingerprintx/pkg/plugins" + mysqlplugin "github.com/praetorian-inc/fingerprintx/pkg/plugins/services/mysql" + utils "github.com/projectdiscovery/nuclei/v2/pkg/js/utils" + "github.com/projectdiscovery/nuclei/v2/pkg/protocols/common/protocolstate" +) + +// MySQLClient is a client for MySQL database. +// +// Internally client uses go-sql-driver/mysql driver. +type MySQLClient struct{} + +// Connect connects to MySQL database using given credentials. +// +// If connection is successful, it returns true. +// If connection is unsuccessful, it returns false and error. +// +// The connection is closed after the function returns. +func (c *MySQLClient) Connect(host string, port int, username, password string) (bool, error) { + return connect(host, port, username, password, "INFORMATION_SCHEMA") +} + +// IsMySQL checks if the given host is running MySQL database. +// +// If the host is running MySQL database, it returns true. +// If the host is not running MySQL database, it returns false. +func (c *MySQLClient) IsMySQL(host string, port int) (bool, error) { + if !protocolstate.IsHostAllowed(host) { + // host is not valid according to network policy + return false, protocolstate.ErrHostDenied.Msgf(host) + } + conn, err := protocolstate.Dialer.Dial(context.TODO(), "tcp", net.JoinHostPort(host, fmt.Sprintf("%d", port))) + if err != nil { + return false, err + } + defer conn.Close() + + plugin := &mysqlplugin.MYSQLPlugin{} + service, err := plugin.Run(conn, 5*time.Second, plugins.Target{Host: host}) + if err != nil { + return false, err + } + if service == nil { + return false, nil + } + return true, nil +} + +// ConnectWithDB connects to MySQL database using given credentials and database name. +// +// If connection is successful, it returns true. +// If connection is unsuccessful, it returns false and error. +// +// The connection is closed after the function returns. +func (c *MySQLClient) ConnectWithDB(host string, port int, username, password, dbName string) (bool, error) { + return connect(host, port, username, password, dbName) +} + +func connect(host string, port int, username, password, dbName string) (bool, error) { + if host == "" || port <= 0 { + return false, fmt.Errorf("invalid host or port") + } + + if !protocolstate.IsHostAllowed(host) { + // host is not valid according to network policy + return false, protocolstate.ErrHostDenied.Msgf(host) + } + + target := net.JoinHostPort(host, fmt.Sprintf("%d", port)) + + db, err := sql.Open("mysql", fmt.Sprintf("%v:%v@tcp(%v)/%s", + url.PathEscape(username), + url.PathEscape(password), + target, + dbName)) + if err != nil { + return false, err + } + defer db.Close() + + _, err = db.Exec("select 1") + if err != nil { + return false, err + } + return true, nil +} + +// ExecuteQuery connects to Mysql database using given credentials and database name. +// and executes a query on the db. +func (c *MySQLClient) ExecuteQuery(host string, port int, username, password, dbName, query string) (string, error) { + + if !protocolstate.IsHostAllowed(host) { + // host is not valid according to network policy + return "", protocolstate.ErrHostDenied.Msgf(host) + } + + target := net.JoinHostPort(host, fmt.Sprintf("%d", port)) + + db, err := sql.Open("mysql", fmt.Sprintf("%v:%v@tcp(%v)/%s", + url.PathEscape(username), + url.PathEscape(password), + target, + dbName)) + if err != nil { + return "", err + } + defer db.Close() + + rows, err := db.Query(query) + if err != nil { + return "", err + } + resp, err := utils.UnmarshalSQLRows(rows) + if err != nil { + return "", err + } + return string(resp), nil +} diff --git a/v2/pkg/js/libs/net/net.go b/v2/pkg/js/libs/net/net.go new file mode 100644 index 0000000000..0ae05a6d87 --- /dev/null +++ b/v2/pkg/js/libs/net/net.go @@ -0,0 +1,157 @@ +package net + +import ( + "context" + "crypto/tls" + "encoding/hex" + "errors" + "fmt" + "net" + "syscall" + "time" + + "github.com/projectdiscovery/nuclei/v2/pkg/protocols/common/protocolstate" + "github.com/projectdiscovery/nuclei/v2/pkg/types" +) + +// Open opens a new connection to the address with a timeout. +// supported protocols: tcp, udp +func Open(protocol, address string) (*NetConn, error) { + conn, err := protocolstate.Dialer.Dial(context.TODO(), protocol, address) + if err != nil { + return nil, err + } + return &NetConn{conn: conn}, nil +} + +// Open opens a new connection to the address with a timeout. +// supported protocols: tcp, udp +func OpenTLS(protocol, address string) (*NetConn, error) { + config := &tls.Config{InsecureSkipVerify: true} + host, _, _ := net.SplitHostPort(address) + if host != "" { + c := config.Clone() + c.ServerName = host + config = c + } + conn, err := protocolstate.Dialer.DialTLSWithConfig(context.TODO(), protocol, address, config) + if err != nil { + return nil, err + } + return &NetConn{conn: conn}, nil +} + +// NetConn is a connection to a remote host. +type NetConn struct { + conn net.Conn + timeout time.Duration +} + +// Close closes the connection. +func (c *NetConn) Close() error { + err := c.conn.Close() + return err +} + +// SetTimeout sets read/write timeout for the connection (in seconds). +func (c *NetConn) SetTimeout(value int) { + c.timeout = time.Duration(value) * time.Second +} + +// setDeadLine sets read/write deadline for the connection (in seconds). +// this is intended to be called before every read/write operation. +func (c *NetConn) setDeadLine() { + if c.timeout == 0 { + c.timeout = 5 * time.Second + } + _ = c.conn.SetDeadline(time.Now().Add(c.timeout)) +} + +// SendArray sends array data to connection +func (c *NetConn) SendArray(data []interface{}) error { + c.setDeadLine() + input := types.ToByteSlice(data) + length, err := c.conn.Write(input) + if err != nil { + return err + } + if length < len(input) { + return fmt.Errorf("failed to write all bytes (%d bytes written, %d bytes expected)", length, len(input)) + } + return nil +} + +// SendHex sends hex data to connection +func (c *NetConn) SendHex(data string) error { + c.setDeadLine() + bin, err := hex.DecodeString(data) + if err != nil { + return err + } + length, err := c.conn.Write(bin) + if err != nil { + return err + } + if length < len(bin) { + return fmt.Errorf("failed to write all bytes (%d bytes written, %d bytes expected)", length, len(bin)) + } + return nil +} + +// Send sends data to the connection with a timeout. +func (c *NetConn) Send(data string) error { + c.setDeadLine() + bin := []byte(data) + length, err := c.conn.Write(bin) + if err != nil { + return err + } + if length < len(bin) { + return fmt.Errorf("failed to write all bytes (%d bytes written, %d bytes expected)", length, len(data)) + } + return nil +} + +// Recv receives data from the connection with a timeout. +// If N is 0, it will read up to 4096 bytes. +func (c *NetConn) Recv(N int) ([]byte, error) { + c.setDeadLine() + var response []byte + if N > 0 { + response = make([]byte, N) + } else { + response = make([]byte, 4096) + } + length, err := c.conn.Read(response) + if err != nil { + var netErr net.Error + if (errors.As(err, &netErr) && netErr.Timeout()) || + errors.Is(err, syscall.ECONNREFUSED) { // timeout error or connection refused + return response, nil + } + return response[:length], err + } + return response[:length], nil +} + +// RecvString receives data from the connection with a timeout +// output is returned as a string. +// If N is 0, it will read up to 4096 bytes. +func (c *NetConn) RecvString(N int) (string, error) { + bin, err := c.Recv(N) + if err != nil { + return "", err + } + return string(bin), nil +} + +// RecvHex receives data from the connection with a timeout +// in hex format. +// If N is 0, it will read up to 4096 bytes. +func (c *NetConn) RecvHex(N int) (string, error) { + bin, err := c.Recv(N) + if err != nil { + return "", err + } + return hex.Dump(bin), nil +} diff --git a/v2/pkg/js/libs/oracle/oracle.go b/v2/pkg/js/libs/oracle/oracle.go new file mode 100644 index 0000000000..9c5a4a01a2 --- /dev/null +++ b/v2/pkg/js/libs/oracle/oracle.go @@ -0,0 +1,46 @@ +package oracle + +import ( + "context" + "net" + "strconv" + "time" + + "github.com/praetorian-inc/fingerprintx/pkg/plugins" + "github.com/praetorian-inc/fingerprintx/pkg/plugins/services/oracledb" + "github.com/projectdiscovery/nuclei/v2/pkg/protocols/common/protocolstate" +) + +// OracleClient is a minimal Oracle client for nuclei scripts. +type OracleClient struct{} + +// IsOracleResponse is the response from the IsOracle function. +type IsOracleResponse struct { + IsOracle bool + Banner string +} + +// IsOracle checks if a host is running an Oracle server. +func (c *OracleClient) IsOracle(host string, port int) (IsOracleResponse, error) { + resp := IsOracleResponse{} + + timeout := 5 * time.Second + conn, err := protocolstate.Dialer.Dial(context.TODO(), "tcp", net.JoinHostPort(host, strconv.Itoa(port))) + if err != nil { + return resp, err + } + defer conn.Close() + + oracledbPlugin := oracledb.ORACLEPlugin{} + service, err := oracledbPlugin.Run(conn, timeout, plugins.Target{Host: host}) + if err != nil { + return resp, err + } + if service == nil { + return resp, nil + } + resp.Banner = service.Version + resp.Banner = service.Metadata().(plugins.ServiceOracle).Info + resp.IsOracle = true + return resp, nil +} diff --git a/v2/pkg/js/libs/pop3/pop3.go b/v2/pkg/js/libs/pop3/pop3.go new file mode 100644 index 0000000000..c98b6454b7 --- /dev/null +++ b/v2/pkg/js/libs/pop3/pop3.go @@ -0,0 +1,45 @@ +package pop3 + +import ( + "context" + "net" + "strconv" + "time" + + "github.com/praetorian-inc/fingerprintx/pkg/plugins" + "github.com/praetorian-inc/fingerprintx/pkg/plugins/services/pop3" + "github.com/projectdiscovery/nuclei/v2/pkg/protocols/common/protocolstate" +) + +// Pop3Client is a minimal POP3 client for nuclei scripts. +type Pop3Client struct{} + +// IsPOP3Response is the response from the IsPOP3 function. +type IsPOP3Response struct { + IsPOP3 bool + Banner string +} + +// IsPOP3 checks if a host is running a POP3 server. +func (c *Pop3Client) IsPOP3(host string, port int) (IsPOP3Response, error) { + resp := IsPOP3Response{} + + timeout := 5 * time.Second + conn, err := protocolstate.Dialer.Dial(context.TODO(), "tcp", net.JoinHostPort(host, strconv.Itoa(port))) + if err != nil { + return resp, err + } + defer conn.Close() + + pop3Plugin := pop3.POP3Plugin{} + service, err := pop3Plugin.Run(conn, timeout, plugins.Target{Host: host}) + if err != nil { + return resp, err + } + if service == nil { + return resp, nil + } + resp.Banner = service.Metadata().(plugins.ServicePOP3).Banner + resp.IsPOP3 = true + return resp, nil +} diff --git a/v2/pkg/js/libs/postgres/postgres.go b/v2/pkg/js/libs/postgres/postgres.go new file mode 100644 index 0000000000..81e79d6a75 --- /dev/null +++ b/v2/pkg/js/libs/postgres/postgres.go @@ -0,0 +1,133 @@ +package postgres + +import ( + "context" + "database/sql" + "fmt" + "net" + "strings" + "time" + + "github.com/go-pg/pg" + _ "github.com/lib/pq" + "github.com/praetorian-inc/fingerprintx/pkg/plugins" + postgres "github.com/praetorian-inc/fingerprintx/pkg/plugins/services/postgresql" + utils "github.com/projectdiscovery/nuclei/v2/pkg/js/utils" + "github.com/projectdiscovery/nuclei/v2/pkg/protocols/common/protocolstate" +) + +// PGClient is a client for Postgres database. +// +// Internally client uses go-pg/pg driver. +type PGClient struct{} + +// IsPostgres checks if the given host and port are running Postgres database. +// +// If connection is successful, it returns true. +// If connection is unsuccessful, it returns false and error. +func (c *PGClient) IsPostgres(host string, port int) (bool, error) { + timeout := 10 * time.Second + + conn, err := protocolstate.Dialer.Dial(context.TODO(), "tcp", fmt.Sprintf("%s:%d", host, port)) + if err != nil { + return false, err + } + defer conn.Close() + + _ = conn.SetDeadline(time.Now().Add(timeout)) + + plugin := &postgres.POSTGRESPlugin{} + service, err := plugin.Run(conn, timeout, plugins.Target{Host: host}) + if err != nil { + return false, err + } + if service == nil { + return false, nil + } + return true, nil +} + +// Connect connects to Postgres database using given credentials. +// +// If connection is successful, it returns true. +// If connection is unsuccessful, it returns false and error. +// +// The connection is closed after the function returns. +func (c *PGClient) Connect(host string, port int, username, password string) (bool, error) { + return connect(host, port, username, password, "postgres") +} + +// ExecuteQuery connects to Postgres database using given credentials and database name. +// and executes a query on the db. +func (c *PGClient) ExecuteQuery(host string, port int, username, password, dbName, query string) (string, error) { + + if !protocolstate.IsHostAllowed(host) { + // host is not valid according to network policy + return "", protocolstate.ErrHostDenied.Msgf(host) + } + + target := net.JoinHostPort(host, fmt.Sprintf("%d", port)) + + connStr := fmt.Sprintf("postgres://%s:%s@%s/%s?sslmode=disable", username, password, target, dbName) + db, err := sql.Open("postgres", connStr) + if err != nil { + return "", err + } + + rows, err := db.Query(query) + if err != nil { + return "", err + } + resp, err := utils.UnmarshalSQLRows(rows) + if err != nil { + return "", err + } + return string(resp), nil +} + +// ConnectWithDB connects to Postgres database using given credentials and database name. +// +// If connection is successful, it returns true. +// If connection is unsuccessful, it returns false and error. +// +// The connection is closed after the function returns. +func (c *PGClient) ConnectWithDB(host string, port int, username, password, dbName string) (bool, error) { + return connect(host, port, username, password, dbName) +} + +func connect(host string, port int, username, password, dbName string) (bool, error) { + if host == "" || port <= 0 { + return false, fmt.Errorf("invalid host or port") + } + + if !protocolstate.IsHostAllowed(host) { + // host is not valid according to network policy + return false, protocolstate.ErrHostDenied.Msgf(host) + } + + target := net.JoinHostPort(host, fmt.Sprintf("%d", port)) + + db := pg.Connect(&pg.Options{ + Addr: target, + User: username, + Password: password, + Database: dbName, + }) + _, err := db.Exec("select 1") + if err != nil { + switch true { + case strings.Contains(err.Error(), "connect: connection refused"): + fallthrough + case strings.Contains(err.Error(), "no pg_hba.conf entry for host"): + fallthrough + case strings.Contains(err.Error(), "network unreachable"): + fallthrough + case strings.Contains(err.Error(), "reset"): + fallthrough + case strings.Contains(err.Error(), "i/o timeout"): + return false, err + } + return false, nil + } + return true, nil +} diff --git a/v2/pkg/js/libs/rdp/rdp.go b/v2/pkg/js/libs/rdp/rdp.go new file mode 100644 index 0000000000..5221a374ec --- /dev/null +++ b/v2/pkg/js/libs/rdp/rdp.go @@ -0,0 +1,76 @@ +package rdp + +import ( + "context" + "fmt" + "time" + + "github.com/praetorian-inc/fingerprintx/pkg/plugins" + "github.com/praetorian-inc/fingerprintx/pkg/plugins/services/rdp" + "github.com/projectdiscovery/nuclei/v2/pkg/protocols/common/protocolstate" +) + +// RDPClient is a client for rdp servers +type RDPClient struct{} + +type IsRDPResponse struct { + IsRDP bool + OS string +} + +// IsRDP checks if the given host and port are running rdp server. +// +// If connection is successful, it returns true. +// If connection is unsuccessful, it returns false and error. +// +// The Name of the OS is also returned if the connection is successful. +func (c *RDPClient) IsRDP(host string, port int) (IsRDPResponse, error) { + resp := IsRDPResponse{} + + timeout := 5 * time.Second + conn, err := protocolstate.Dialer.Dial(context.TODO(), "tcp", fmt.Sprintf("%s:%d", host, port)) + if err != nil { + return resp, err + } + defer conn.Close() + + server, isRDP, err := rdp.DetectRDP(conn, timeout) + if err != nil { + return resp, err + } + if !isRDP { + return resp, nil + } + resp.IsRDP = true + resp.OS = server + return resp, nil +} + +type CheckRDPAuthResponse struct { + PluginInfo *plugins.ServiceRDP + Auth bool +} + +// CheckRDPAuth checks if the given host and port are running rdp server +// with authentication and returns their metadata. +func (c *RDPClient) CheckRDPAuth(host string, port int) (CheckRDPAuthResponse, error) { + resp := CheckRDPAuthResponse{} + + timeout := 5 * time.Second + conn, err := protocolstate.Dialer.Dial(context.TODO(), "tcp", fmt.Sprintf("%s:%d", host, port)) + if err != nil { + return resp, err + } + defer conn.Close() + + pluginInfo, auth, err := rdp.DetectRDPAuth(conn, timeout) + if err != nil { + return resp, err + } + if !auth { + return resp, nil + } + resp.Auth = true + resp.PluginInfo = pluginInfo + return resp, nil +} diff --git a/v2/pkg/js/libs/redis/redis.go b/v2/pkg/js/libs/redis/redis.go new file mode 100644 index 0000000000..29818cba5d --- /dev/null +++ b/v2/pkg/js/libs/redis/redis.go @@ -0,0 +1,140 @@ +package redis + +import ( + "context" + "fmt" + "time" + + "github.com/projectdiscovery/nuclei/v2/pkg/protocols/common/protocolstate" + "github.com/redis/go-redis/v9" + + "github.com/praetorian-inc/fingerprintx/pkg/plugins" + pluginsredis "github.com/praetorian-inc/fingerprintx/pkg/plugins/services/redis" +) + +// GetServerInfo returns the server info for a redis server +func GetServerInfo(host string, port int) (string, error) { + if !protocolstate.IsHostAllowed(host) { + // host is not valid according to network policy + return "", protocolstate.ErrHostDenied.Msgf(host) + } + // create a new client + client := redis.NewClient(&redis.Options{ + Addr: fmt.Sprintf("%s:%d", host, port), + Password: "", // no password set + DB: 0, // use default DB + }) + + // Ping the Redis server + _, err := client.Ping(context.TODO()).Result() + if err != nil { + return "", err + } + + // Get Redis server info + infoCmd := client.Info(context.TODO()) + if infoCmd.Err() != nil { + return "", infoCmd.Err() + } + + return infoCmd.Val(), nil +} + +// Connect tries to connect redis server with password +func Connect(host string, port int, password string) (bool, error) { + if !protocolstate.IsHostAllowed(host) { + // host is not valid according to network policy + return false, protocolstate.ErrHostDenied.Msgf(host) + } + // create a new client + client := redis.NewClient(&redis.Options{ + Addr: fmt.Sprintf("%s:%d", host, port), + Password: password, // no password set + DB: 0, // use default DB + }) + _, err := client.Ping(context.TODO()).Result() + if err != nil { + return false, err + } + // Get Redis server info + infoCmd := client.Info(context.TODO()) + if infoCmd.Err() != nil { + return false, infoCmd.Err() + } + + return true, nil +} + +// GetServerInfoAuth returns the server info for a redis server +func GetServerInfoAuth(host string, port int, password string) (string, error) { + if !protocolstate.IsHostAllowed(host) { + // host is not valid according to network policy + return "", protocolstate.ErrHostDenied.Msgf(host) + } + // create a new client + client := redis.NewClient(&redis.Options{ + Addr: fmt.Sprintf("%s:%d", host, port), + Password: password, // no password set + DB: 0, // use default DB + }) + + // Ping the Redis server + _, err := client.Ping(context.TODO()).Result() + if err != nil { + return "", err + } + + // Get Redis server info + infoCmd := client.Info(context.TODO()) + if infoCmd.Err() != nil { + return "", infoCmd.Err() + } + + return infoCmd.Val(), nil +} + +// IsAuthenticated checks if the redis server requires authentication +func IsAuthenticated(host string, port int) (bool, error) { + plugin := pluginsredis.REDISPlugin{} + timeout := 5 * time.Second + conn, err := protocolstate.Dialer.Dial(context.TODO(), "tcp", fmt.Sprintf("%s:%d", host, port)) + if err != nil { + return false, err + } + defer conn.Close() + + _, err = plugin.Run(conn, timeout, plugins.Target{Host: host}) + if err != nil { + return false, err + } + return true, nil +} + +// RunLuaScript runs a lua script on +func RunLuaScript(host string, port int, password string, script string) (interface{}, error) { + if !protocolstate.IsHostAllowed(host) { + // host is not valid according to network policy + return false, protocolstate.ErrHostDenied.Msgf(host) + } + // create a new client + client := redis.NewClient(&redis.Options{ + Addr: fmt.Sprintf("%s:%d", host, port), + Password: password, + DB: 0, // use default DB + }) + + // Ping the Redis server + _, err := client.Ping(context.TODO()).Result() + if err != nil { + return "", err + } + + // Get Redis server info + infoCmd := client.Eval(context.Background(), script, []string{}) + + if infoCmd.Err() != nil { + return "", infoCmd.Err() + } + + return infoCmd.Val(), nil +} diff --git a/v2/pkg/js/libs/rsync/rsync.go b/v2/pkg/js/libs/rsync/rsync.go new file mode 100644 index 0000000000..4421138c62 --- /dev/null +++ b/v2/pkg/js/libs/rsync/rsync.go @@ -0,0 +1,45 @@ +package rsync + +import ( + "context" + "net" + "strconv" + "time" + + "github.com/praetorian-inc/fingerprintx/pkg/plugins" + "github.com/praetorian-inc/fingerprintx/pkg/plugins/services/rsync" + "github.com/projectdiscovery/nuclei/v2/pkg/protocols/common/protocolstate" +) + +// RsyncClient is a minimal Rsync client for nuclei scripts. +type RsyncClient struct{} + +// IsRsyncResponse is the response from the IsRsync function. +type IsRsyncResponse struct { + IsRsync bool + Banner string +} + +// IsRsync checks if a host is running a Rsync server. +func (c *RsyncClient) IsRsync(host string, port int) (IsRsyncResponse, error) { + resp := IsRsyncResponse{} + + timeout := 5 * time.Second + conn, err := protocolstate.Dialer.Dial(context.TODO(), "tcp", net.JoinHostPort(host, strconv.Itoa(port))) + if err != nil { + return resp, err + } + defer conn.Close() + + rsyncPlugin := rsync.RSYNCPlugin{} + service, err := rsyncPlugin.Run(conn, timeout, plugins.Target{Host: host}) + if err != nil { + return resp, err + } + if service == nil { + return resp, nil + } + resp.Banner = service.Version + resp.IsRsync = true + return resp, nil +} diff --git a/v2/pkg/js/libs/smb/metadata.go b/v2/pkg/js/libs/smb/metadata.go new file mode 100644 index 0000000000..1b98a8e6ac --- /dev/null +++ b/v2/pkg/js/libs/smb/metadata.go @@ -0,0 +1,30 @@ +package smb + +import ( + "context" + "fmt" + "net" + "time" + + "github.com/praetorian-inc/fingerprintx/pkg/plugins" + "github.com/praetorian-inc/fingerprintx/pkg/plugins/services/smb" + "github.com/projectdiscovery/nuclei/v2/pkg/protocols/common/protocolstate" +) + +// collectSMBv2Metadata collects metadata for SMBv2 services. +func collectSMBv2Metadata(host string, port int, timeout time.Duration) (*plugins.ServiceSMB, error) { + if timeout == 0 { + timeout = 5 * time.Second + } + conn, err := protocolstate.Dialer.Dial(context.TODO(), "tcp", net.JoinHostPort(host, fmt.Sprintf("%d", port))) + if err != nil { + return nil, err + } + defer conn.Close() + + metadata, err := smb.DetectSMBv2(conn, timeout) + if err != nil { + return nil, err + } + return metadata, nil +} diff --git a/v2/pkg/js/libs/smb/smb.go b/v2/pkg/js/libs/smb/smb.go new file mode 100644 index 0000000000..a524fc772d --- /dev/null +++ b/v2/pkg/js/libs/smb/smb.go @@ -0,0 +1,95 @@ +package smb + +import ( + "context" + "fmt" + "net" + "time" + + "github.com/hirochachacha/go-smb2" + "github.com/praetorian-inc/fingerprintx/pkg/plugins" + "github.com/projectdiscovery/nuclei/v2/pkg/protocols/common/protocolstate" + "github.com/zmap/zgrab2/lib/smb/smb" +) + +// SMBClient is a client for SMB servers. +// +// Internally client uses github.com/zmap/zgrab2/lib/smb/smb driver. +// github.com/hirochachacha/go-smb2 driver +type SMBClient struct{} + +// ConnectSMBInfoMode tries to connect to provided host and port +// and discovery SMB information +// +// Returns handshake log and error. If error is not nil, +// state will be false +func (c *SMBClient) ConnectSMBInfoMode(host string, port int) (*smb.SMBLog, error) { + conn, err := protocolstate.Dialer.Dial(context.TODO(), "tcp", fmt.Sprintf("%s:%d", host, port)) + if err != nil { + return nil, err + } + defer conn.Close() + + _ = conn.SetDeadline(time.Now().Add(10 * time.Second)) + setupSession := true + + result, err := smb.GetSMBLog(conn, setupSession, false, false) + if err != nil { + conn.Close() + conn, err = net.DialTimeout("tcp", fmt.Sprintf("%s:%d", host, port), 10*time.Second) + if err != nil { + return nil, err + } + result, err = smb.GetSMBLog(conn, setupSession, true, false) + if err != nil { + return nil, err + } + } + return result, nil +} + +// ListSMBv2Metadata tries to connect to provided host and port +// and list SMBv2 metadata. +// +// Returns metadata and error. If error is not nil, +// state will be false +func (c *SMBClient) ListSMBv2Metadata(host string, port int) (*plugins.ServiceSMB, error) { + if !protocolstate.IsHostAllowed(host) { + // host is not valid according to network policy + return nil, protocolstate.ErrHostDenied.Msgf(host) + } + return collectSMBv2Metadata(host, port, 5*time.Second) +} + +// ListShares tries to connect to provided host and port +// and list shares by using given credentials. +// +// Credentials cannot be blank. guest or anonymous credentials +// can be used by providing empty password. +func (c *SMBClient) ListShares(host string, port int, user, password string) ([]string, error) { + conn, err := protocolstate.Dialer.Dial(context.TODO(), "tcp", fmt.Sprintf("%s:%d", host, port)) + if err != nil { + return nil, err + } + defer conn.Close() + + d := &smb2.Dialer{ + Initiator: &smb2.NTLMInitiator{ + User: user, + Password: password, + }, + } + s, err := d.Dial(conn) + if err != nil { + return nil, err + } + defer func() { + _ = s.Logoff() + }() + + names, err := s.ListSharenames() + if err != nil { + return nil, err + } + return names, nil +} diff --git a/v2/pkg/js/libs/smb/smbghost.go b/v2/pkg/js/libs/smb/smbghost.go new file mode 100644 index 0000000000..79c28b301a --- /dev/null +++ b/v2/pkg/js/libs/smb/smbghost.go @@ -0,0 +1,58 @@ +package smb + +import ( + "bytes" + "context" + "errors" + "net" + "strconv" + "time" + + "github.com/projectdiscovery/nuclei/v2/pkg/js/libs/structs" + "github.com/projectdiscovery/nuclei/v2/pkg/protocols/common/protocolstate" +) + +const ( + pkt = "\x00\x00\x00\xc0\xfeSMB@\x00\x00\x00\x00\x00\x00\x00\x00\x00\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00$\x00\x08\x00\x01\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00x\x00\x00\x00\x02\x00\x00\x00\x02\x02\x10\x02\"\x02$\x02\x00\x03\x02\x03\x10\x03\x11\x03\x00\x00\x00\x00\x01\x00&\x00\x00\x00\x00\x00\x01\x00 \x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x03\x00\n\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00" +) + +// DetectSMBGhost tries to detect SMBGhost vulnerability +// by using SMBv3 compression feature. +func (c *SMBClient) DetectSMBGhost(host string, port int) (bool, error) { + addr := net.JoinHostPort(host, strconv.Itoa(port)) + conn, err := protocolstate.Dialer.Dial(context.TODO(), "tcp", addr) + if err != nil { + return false, err + + } + defer conn.Close() + + _, err = conn.Write([]byte(pkt)) + if err != nil { + return false, err + } + + buff := make([]byte, 4) + nb, _ := conn.Read(buff) + args, err := structs.Unpack(">I", buff[:nb]) + if err != nil { + return false, err + } + if len(args) != 1 { + return false, errors.New("invalid response") + } + + length := args[0].(int) + data := make([]byte, length) + _ = conn.SetReadDeadline(time.Now().Add(2 * time.Second)) + n, err := conn.Read(data) + if err != nil { + return false, err + } + data = data[:n] + + if !bytes.Equal(data[68:70], []byte("\x11\x03")) || !bytes.Equal(data[70:72], []byte("\x02\x00")) { + return false, nil + } + return true, nil +} diff --git a/v2/pkg/js/libs/smtp/smtp.go b/v2/pkg/js/libs/smtp/smtp.go new file mode 100644 index 0000000000..c4f943f0a2 --- /dev/null +++ b/v2/pkg/js/libs/smtp/smtp.go @@ -0,0 +1,45 @@ +package smtp + +import ( + "context" + "net" + "strconv" + "time" + + "github.com/praetorian-inc/fingerprintx/pkg/plugins" + "github.com/praetorian-inc/fingerprintx/pkg/plugins/services/smtp" + "github.com/projectdiscovery/nuclei/v2/pkg/protocols/common/protocolstate" +) + +// SMTPClient is a minimal SMTP client for nuclei scripts. +type SMTPClient struct{} + +// IsSMTPResponse is the response from the IsSMTP function. +type IsSMTPResponse struct { + IsSMTP bool + Banner string +} + +// IsSMTP checks if a host is running a SMTP server. +func (c *SMTPClient) IsSMTP(host string, port int) (IsSMTPResponse, error) { + resp := IsSMTPResponse{} + + timeout := 5 * time.Second + conn, err := protocolstate.Dialer.Dial(context.TODO(), "tcp", net.JoinHostPort(host, strconv.Itoa(port))) + if err != nil { + return resp, err + } + defer conn.Close() + + smtpPlugin := smtp.SMTPPlugin{} + service, err := smtpPlugin.Run(conn, timeout, plugins.Target{Host: host}) + if err != nil { + return resp, err + } + if service == nil { + return resp, nil + } + resp.Banner = service.Version + resp.IsSMTP = true + return resp, nil +} diff --git a/v2/pkg/js/libs/ssh/ssh.go b/v2/pkg/js/libs/ssh/ssh.go new file mode 100644 index 0000000000..8bc5d12414 --- /dev/null +++ b/v2/pkg/js/libs/ssh/ssh.go @@ -0,0 +1,114 @@ +package ssh + +import ( + "errors" + "fmt" + "strings" + "time" + + "github.com/projectdiscovery/nuclei/v2/pkg/protocols/common/protocolstate" + "github.com/zmap/zgrab2/lib/ssh" +) + +// SSHClient is a client for SSH servers. +// +// Internally client uses github.com/zmap/zgrab2/lib/ssh driver. +type SSHClient struct{} + +// Connect tries to connect to provided host and port +// with provided username and password with ssh. +// +// Returns state of connection and error. If error is not nil, +// state will be false +func (c *SSHClient) Connect(host string, port int, username, password string) (bool, error) { + conn, err := connect(host, port, username, password, "") + if err != nil { + return false, err + } + defer conn.Close() + + return true, nil +} + +// ConnectWithKey tries to connect to provided host and port +// with provided username and private_key. +// +// Returns state of connection and error. If error is not nil, +// state will be false +func (c *SSHClient) ConnectWithKey(host string, port int, username, key string) (bool, error) { + conn, err := connect(host, port, username, "", key) + if err != nil { + return false, err + } + defer conn.Close() + + return true, nil +} + +// ConnectSSHInfoMode tries to connect to provided host and port +// with provided host and port +// +// Returns HandshakeLog and error. If error is not nil, +// state will be false +// +// HandshakeLog is a struct that contains information about the +// ssh connection +func (c *SSHClient) ConnectSSHInfoMode(host string, port int) (*ssh.HandshakeLog, error) { + return connectSSHInfoMode(host, port) +} + +func connectSSHInfoMode(host string, port int) (*ssh.HandshakeLog, error) { + if !protocolstate.IsHostAllowed(host) { + // host is not valid according to network policy + return nil, protocolstate.ErrHostDenied.Msgf(host) + } + data := new(ssh.HandshakeLog) + + sshConfig := ssh.MakeSSHConfig() + sshConfig.Timeout = 10 * time.Second + sshConfig.ConnLog = data + sshConfig.DontAuthenticate = true + sshConfig.BannerCallback = func(banner string) error { + data.Banner = strings.TrimSpace(banner) + return nil + } + rhost := fmt.Sprintf("%s:%d", host, port) + client, err := ssh.Dial("tcp", rhost, sshConfig) + if err != nil { + return nil, err + } + defer client.Close() + + return data, nil +} + +func connect(host string, port int, user, password, privateKey string) (*ssh.Client, error) { + if !protocolstate.IsHostAllowed(host) { + // host is not valid according to network policy + return nil, protocolstate.ErrHostDenied.Msgf(host) + } + if host == "" || port <= 0 { + return nil, errors.New("invalid host or port") + } + + conf := &ssh.ClientConfig{ + User: user, + Auth: []ssh.AuthMethod{}, + } + if len(password) > 0 { + conf.Auth = append(conf.Auth, ssh.Password(password)) + } + if len(privateKey) > 0 { + signer, err := ssh.ParsePrivateKey([]byte(privateKey)) + if err != nil { + return nil, err + } + conf.Auth = append(conf.Auth, ssh.PublicKeys(signer)) + } + + client, err := ssh.Dial("tcp", fmt.Sprintf("%s:%d", host, port), conf) + if err != nil { + return nil, err + } + return client, nil +} diff --git a/v2/pkg/js/libs/structs/smbexploit.js b/v2/pkg/js/libs/structs/smbexploit.js new file mode 100644 index 0000000000..80f3b13ca6 --- /dev/null +++ b/v2/pkg/js/libs/structs/smbexploit.js @@ -0,0 +1,97 @@ +const header = bytes.Buffer(); + +// Create the SMB header first +header.append(structs.pack("B", 254)); // magic +header.append("SMB"); +header.append(structs.pack("H", 64)); // header size +header.append(structs.pack("H", 0)); // credit charge +header.append(structs.pack("H", 0)); // channel sequence +header.append(structs.pack("H", 0)); // reserved +header.append(structs.pack("H", 0)); // negotiate protocol command +header.append(structs.pack("H", 31)); // credits requested +header.append(structs.pack("I", 0)); // flags +header.append(structs.pack("I", 0)); // chain offset +header.append(structs.pack("Q", 0)); // message id +header.append(structs.pack("I", 0)); // process id +header.append(structs.pack("I", 0)); // tree id +header.append(structs.pack("Q", 0)); // session id +header.append(structs.pack("QQ", [0, 0])); // signature + +// Create negotiation packet +const negotiation = bytes.Buffer(); +negotiation.append(structs.pack("H", 0x24)); // struct size +negotiation.append(structs.pack("H", 8)); // amount of dialects +negotiation.append(structs.pack("H", 1)); // enable signing +negotiation.append(structs.pack("H", 0)); // reserved +negotiation.append(structs.pack("I", 0x7f)); // capabilities +negotiation.append(structs.pack("QQ", [0, 0])); // client guid +negotiation.append(structs.pack("I", 0x78)); // negotiation offset +negotiation.append(structs.pack("H", 2)); // negotiation context count +negotiation.append(structs.pack("H", 0)); // reserved +negotiation.append(structs.pack("H", 0x0202)); // smb 2.0.2 dialect +negotiation.append(structs.pack("H", 0x0210)); // smb 2.1.0 dialect +negotiation.append(structs.pack("H", 0x0222)); // smb 2.2.2 dialect +negotiation.append(structs.pack("H", 0x0224)); // smb 2.2.4 dialect +negotiation.append(structs.pack("H", 0x0300)); // smb 3.0.0 dialect +negotiation.append(structs.pack("H", 0x0302)); // smb 3.0.2 dialect +negotiation.append(structs.pack("H", 0x0310)); // smb 3.1.0 dialect +negotiation.append(structs.pack("H", 0x0311)); // smb 3.1.1 dialect +negotiation.append(structs.pack("I", 0)); // padding +negotiation.append(structs.pack("H", 1)); // negotiation context type +negotiation.append(structs.pack("H", 38)); // negotiation data length +negotiation.append(structs.pack("I", 0)); // reserved +negotiation.append(structs.pack("H", 1)); // negotiation hash algorithm count +negotiation.append(structs.pack("H", 32)); // negotiation salt length +negotiation.append(structs.pack("H", 1)); // negotiation hash algorithm SHA512 +negotiation.append(structs.pack("H", 1)); // negotiation hash algorithm SHA512 +negotiation.append(structs.pack("QQ", [0, 0])); // salt part 1 +negotiation.append(structs.pack("QQ", [0, 0])); // salt part 2 +negotiation.append(structs.pack("H", 3)); // unknown?? +negotiation.append(structs.pack("H", 10)); // data length unknown?? +negotiation.append(structs.pack("I", 0)); // reserved unknown?? +negotiation.append("\x01\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00"); // unknown + +const packet = bytes.Buffer(); +packet.append(header.bytes()); +packet.append(negotiation.bytes()); + +const netbios = bytes.Buffer(); +netbios.append(structs.pack("H", 0)); // NetBIOS sessions message (should be 1 byte but whatever) +netbios.append(structs.pack("B", 0)); // just a pad to make it 3 bytes +netbios.append(structs.pack("B", packet.len())); // NetBIOS length (should be 3 bytes but whatever, as long as the packet isn't 0xff+ bytes) + +const final = bytes.Buffer(); +final.append(netbios.bytes()); +final.append(packet.bytes()); + +console.log("Netbios", netbios.hex(), netbios.len()); +console.log("Header", header.hex(), header.len()); +console.log("Negotation", negotiation.hex(), negotiation.len()); +console.log("Packet", final.hex(), final.len()); + +const c = require("nuclei/libnet"); +let conn = c.Open("tcp", "118.68.186.114:445"); +conn.Send(final.bytes(), 0); +let bytesRecv = conn.Recv(0, 4); +console.log("recv Bytes", bytesRecv); +let size = structs.unpack("I", bytesRecv)[0]; +console.log("Size", size); +let data = conn.Recv(0, size); +console.log("Data", data); + +// TODO: Add hexdump helpers + +version = structs.unpack("H", data.slice(68,70))[0] +context = structs.unpack("H", data.slice(70,72))[0] + +console.log("Version", version); +console.log("Context", context); + +if (version != 0x0311){ + console.log("SMB version ", version, "was found which is not vulnerable!"); +} else if (context != 2) { + console.log("Server answered with context", context, " which indicates that the target may not have SMB compression enabled and is therefore not vulnerable!"); +} else { + console.log("SMB version ", version, " with context ", context, " was found which indicates SMBv3.1.1 is being used and SMB compression is enabled, therefore being vulnerable to CVE-2020-0796!"); +} +conn.Close(); \ No newline at end of file diff --git a/v2/pkg/js/libs/structs/structs.go b/v2/pkg/js/libs/structs/structs.go new file mode 100644 index 0000000000..eadc57634b --- /dev/null +++ b/v2/pkg/js/libs/structs/structs.go @@ -0,0 +1,71 @@ +package structs + +import ( + _ "embed" + + "github.com/projectdiscovery/gostruct" +) + +// StructsUnpack the byte slice (presumably packed by Pack(format, msg)) according to the given format. +// The result is a []interface{} slice even if it contains exactly one item. +// The byte slice must contain not less the amount of data required by the format +// (len(msg) must more or equal CalcSize(format)). +// Ex: structs.Unpack(">I", buff[:nb]) +func Unpack(format string, msg []byte) ([]interface{}, error) { + return gostruct.UnPack(buildFormatSliceFromStringFormat(format), msg) +} + +// StructsPack returns a byte slice containing the values of msg slice packed according to the given format. +// The items of msg slice must match the values required by the format exactly. +// Ex: structs.pack("H", 0) +func Pack(formatStr string, msg interface{}) ([]byte, error) { + var args []interface{} + switch v := msg.(type) { + case []interface{}: + args = v + default: + args = []interface{}{v} + } + format := buildFormatSliceFromStringFormat(formatStr) + + for i, f := range format { + if i >= len(args) { + break + } + switch f { + case "h", "H", "i", "I", "l", "L", "q", "Q", "b", "B": + switch v := args[i].(type) { + case int64: + args[i] = int(v) + } + } + } + return gostruct.Pack(format, args) +} + +// StructsCalcSize returns the number of bytes needed to pack the values according to the given format. +func StructsCalcSize(format string) (int, error) { + return gostruct.CalcSize(buildFormatSliceFromStringFormat(format)) +} + +func buildFormatSliceFromStringFormat(format string) []string { + var formats []string + temp := "" + + for _, c := range format { + if c >= '0' && c <= '9' { + temp += string(c) + } else { + if temp != "" { + formats = append(formats, temp+string(c)) + temp = "" + } else { + formats = append(formats, string(c)) + } + } + } + if temp != "" { + formats = append(formats, temp) + } + return formats +} diff --git a/v2/pkg/js/libs/telnet/telnet.go b/v2/pkg/js/libs/telnet/telnet.go new file mode 100644 index 0000000000..611b1170ed --- /dev/null +++ b/v2/pkg/js/libs/telnet/telnet.go @@ -0,0 +1,45 @@ +package telnet + +import ( + "context" + "net" + "strconv" + "time" + + "github.com/praetorian-inc/fingerprintx/pkg/plugins" + "github.com/praetorian-inc/fingerprintx/pkg/plugins/services/telnet" + "github.com/projectdiscovery/nuclei/v2/pkg/protocols/common/protocolstate" +) + +// TelnetClient is a minimal Telnet client for nuclei scripts. +type TelnetClient struct{} + +// IsTelnetResponse is the response from the IsTelnet function. +type IsTelnetResponse struct { + IsTelnet bool + Banner string +} + +// IsTelnet checks if a host is running a Telnet server. +func (c *TelnetClient) IsTelnet(host string, port int) (IsTelnetResponse, error) { + resp := IsTelnetResponse{} + + timeout := 5 * time.Second + conn, err := protocolstate.Dialer.Dial(context.TODO(), "tcp", net.JoinHostPort(host, strconv.Itoa(port))) + if err != nil { + return resp, err + } + defer conn.Close() + + telnetPlugin := telnet.TELNETPlugin{} + service, err := telnetPlugin.Run(conn, timeout, plugins.Target{Host: host}) + if err != nil { + return resp, err + } + if service == nil { + return resp, nil + } + resp.Banner = service.Metadata().(plugins.ServiceTelnet).ServerData + resp.IsTelnet = true + return resp, nil +} diff --git a/v2/pkg/js/libs/vnc/vnc.go b/v2/pkg/js/libs/vnc/vnc.go new file mode 100644 index 0000000000..ee0c4cba70 --- /dev/null +++ b/v2/pkg/js/libs/vnc/vnc.go @@ -0,0 +1,47 @@ +package vnc + +import ( + "context" + "net" + "strconv" + "time" + + "github.com/praetorian-inc/fingerprintx/pkg/plugins" + "github.com/praetorian-inc/fingerprintx/pkg/plugins/services/vnc" + "github.com/projectdiscovery/nuclei/v2/pkg/protocols/common/protocolstate" +) + +// VNCClient is a minimal VNC client for nuclei scripts. +type VNCClient struct{} + +// IsVNCResponse is the response from the IsVNC function. +type IsVNCResponse struct { + IsVNC bool + Banner string +} + +// IsVNC checks if a host is running a VNC server. +// It returns a boolean indicating if the host is running a VNC server +// and the banner of the VNC server. +func (c *VNCClient) IsVNC(host string, port int) (IsVNCResponse, error) { + resp := IsVNCResponse{} + + timeout := 5 * time.Second + conn, err := protocolstate.Dialer.Dial(context.TODO(), "tcp", net.JoinHostPort(host, strconv.Itoa(port))) + if err != nil { + return resp, err + } + defer conn.Close() + + vncPlugin := vnc.VNCPlugin{} + service, err := vncPlugin.Run(conn, timeout, plugins.Target{Host: host}) + if err != nil { + return resp, err + } + if service == nil { + return resp, nil + } + resp.Banner = service.Version + resp.IsVNC = true + return resp, nil +} diff --git a/v2/pkg/js/utils/util.go b/v2/pkg/js/utils/util.go new file mode 100644 index 0000000000..d801a51744 --- /dev/null +++ b/v2/pkg/js/utils/util.go @@ -0,0 +1,81 @@ +package utils + +import ( + "database/sql" + + jsoniter "github.com/json-iterator/go" +) + +// UnmarshalSQLRows unmarshals sql rows to json +// +// This function provides a way to unmarshal arbitrary sql rows +// to json. +func UnmarshalSQLRows(rows *sql.Rows) ([]byte, error) { + columnTypes, err := rows.ColumnTypes() + if err != nil { + return nil, err + } + + count := len(columnTypes) + finalRows := []interface{}{} + + for rows.Next() { + + scanArgs := make([]interface{}, count) + + for i, v := range columnTypes { + + switch v.DatabaseTypeName() { + case "VARCHAR", "TEXT", "UUID", "TIMESTAMP": + scanArgs[i] = new(sql.NullString) + case "BOOL": + scanArgs[i] = new(sql.NullBool) + case "INT4": + scanArgs[i] = new(sql.NullInt64) + default: + scanArgs[i] = new(sql.NullString) + } + } + + err := rows.Scan(scanArgs...) + + if err != nil { + return nil, err + } + + masterData := map[string]interface{}{} + + for i, v := range columnTypes { + + if z, ok := (scanArgs[i]).(*sql.NullBool); ok { + masterData[v.Name()] = z.Bool + continue + } + + if z, ok := (scanArgs[i]).(*sql.NullString); ok { + masterData[v.Name()] = z.String + continue + } + + if z, ok := (scanArgs[i]).(*sql.NullInt64); ok { + masterData[v.Name()] = z.Int64 + continue + } + + if z, ok := (scanArgs[i]).(*sql.NullFloat64); ok { + masterData[v.Name()] = z.Float64 + continue + } + + if z, ok := (scanArgs[i]).(*sql.NullInt32); ok { + masterData[v.Name()] = z.Int32 + continue + } + + masterData[v.Name()] = scanArgs[i] + } + + finalRows = append(finalRows, masterData) + } + return jsoniter.Marshal(finalRows) +} diff --git a/v2/pkg/operators/common/dsl/dsl.go b/v2/pkg/operators/common/dsl/dsl.go index 4047330f7c..eb9e277d34 100644 --- a/v2/pkg/operators/common/dsl/dsl.go +++ b/v2/pkg/operators/common/dsl/dsl.go @@ -11,11 +11,14 @@ import ( "github.com/projectdiscovery/nuclei/v2/pkg/protocols/dns/dnsclientpool" "github.com/projectdiscovery/nuclei/v2/pkg/types" sliceutil "github.com/projectdiscovery/utils/slice" + stringsutil "github.com/projectdiscovery/utils/strings" ) var ( HelperFunctions map[string]govaluate.ExpressionFunction FunctionNames []string + // knownPorts is a list of known ports for protocols implemented in nuclei + knowPorts = []string{"80", "443", "8080", "8081", "8443", "53"} ) func init() { @@ -95,6 +98,20 @@ func init() { return "", fmt.Errorf("no records found") })) + _ = dsl.AddFunction(dsl.NewWithMultipleSignatures("getNetworkPort", []string{ + "(Port string,defaultPort string) string)", + "(Port int,defaultPort int) int", + }, false, func(args ...interface{}) (interface{}, error) { + if len(args) != 2 { + return nil, dsl.ErrInvalidDslFunction + } + port := types.ToString(args[0]) + defaultPort := types.ToString(args[1]) + if port == "" || stringsutil.EqualFoldAny(port, knowPorts...) { + return defaultPort, nil + } + return port, nil + })) dsl.PrintDebugCallback = func(args ...interface{}) error { gologger.Info().Msgf("print_debug value: %s", fmt.Sprint(args)) diff --git a/v2/pkg/output/format_screen.go b/v2/pkg/output/format_screen.go index ab5220f8e0..6f727c343f 100644 --- a/v2/pkg/output/format_screen.go +++ b/v2/pkg/output/format_screen.go @@ -5,6 +5,7 @@ import ( "strconv" "github.com/projectdiscovery/nuclei/v2/pkg/types" + mapsutil "github.com/projectdiscovery/utils/maps" ) // formatScreen formats the output for showing on screen. @@ -83,7 +84,9 @@ func (w *StandardWriter) formatScreen(output *ResultEvent) []byte { builder.WriteString(" [") first := true - for name, value := range output.Metadata { + // sort to get predictable output + for _, name := range mapsutil.GetSortedKeys(output.Metadata) { + value := output.Metadata[name] if !first { builder.WriteRune(',') } diff --git a/v2/pkg/protocols/code/code.go b/v2/pkg/protocols/code/code.go index f93af3fc93..a4d18803c7 100644 --- a/v2/pkg/protocols/code/code.go +++ b/v2/pkg/protocols/code/code.go @@ -33,7 +33,7 @@ type Request struct { CompiledOperators *operators.Operators `yaml:"-"` // ID is the optional id of the request - ID string `yaml:"id,omitempty" json:"id,omitempty" jsonschema:"title=id of the dns request,description=ID is the optional ID of the DNS Request"` + ID string `yaml:"id,omitempty" json:"id,omitempty" jsonschema:"title=id of the request,description=ID is the optional ID of the Request"` // description: | // Engine type Engine []string `yaml:"engine,omitempty" jsonschema:"title=engine,description=Engine,enum=python,enum=powershell,enum=command"` diff --git a/v2/pkg/protocols/common/contextargs/contextargs.go b/v2/pkg/protocols/common/contextargs/contextargs.go index 2549285ff0..4ebaa15615 100644 --- a/v2/pkg/protocols/common/contextargs/contextargs.go +++ b/v2/pkg/protocols/common/contextargs/contextargs.go @@ -114,6 +114,15 @@ func (ctx *Context) UseNetworkPort(port string, excludePorts string) error { return nil } +// Port returns the port of the target +func (ctx *Context) Port() string { + target, err := urlutil.Parse(ctx.MetaInput.Input) + if err != nil { + return "" + } + return target.Port() +} + // Get the value with specific key if exists func (ctx *Context) Get(key string) (interface{}, bool) { if !ctx.hasArgs() { diff --git a/v2/pkg/protocols/common/protocolstate/headless.go b/v2/pkg/protocols/common/protocolstate/headless.go index 36689b3b8c..77e5d52cdd 100644 --- a/v2/pkg/protocols/common/protocolstate/headless.go +++ b/v2/pkg/protocols/common/protocolstate/headless.go @@ -16,6 +16,7 @@ import ( var ( ErrURLDenied = errorutil.NewWithFmt("headless: url %v dropped by rule: %v") + ErrHostDenied = errorutil.NewWithFmt("host %v dropped by network policy") networkPolicy *networkpolicy.NetworkPolicy allowLocalFileAccess bool ) @@ -77,3 +78,12 @@ func isValidHost(targetUrl string) bool { _, ok := networkPolicy.ValidateHost(targetUrl) return ok } + +// IsHostAllowed checks if the host is allowed by network policy +func IsHostAllowed(targetUrl string) bool { + if networkPolicy == nil { + return true + } + _, ok := networkPolicy.ValidateHost(targetUrl) + return ok +} diff --git a/v2/pkg/protocols/javascript/js.go b/v2/pkg/protocols/javascript/js.go new file mode 100644 index 0000000000..2a1d22bb76 --- /dev/null +++ b/v2/pkg/protocols/javascript/js.go @@ -0,0 +1,555 @@ +package javascript + +import ( + "bytes" + "context" + "fmt" + "net" + "strings" + "sync/atomic" + "time" + + "github.com/alecthomas/chroma/quick" + "github.com/ditashi/jsbeautifier-go/jsbeautifier" + "github.com/pkg/errors" + "github.com/projectdiscovery/gologger" + "github.com/projectdiscovery/nuclei/v2/pkg/js/compiler" + "github.com/projectdiscovery/nuclei/v2/pkg/model" + "github.com/projectdiscovery/nuclei/v2/pkg/operators" + "github.com/projectdiscovery/nuclei/v2/pkg/operators/extractors" + "github.com/projectdiscovery/nuclei/v2/pkg/operators/matchers" + "github.com/projectdiscovery/nuclei/v2/pkg/output" + "github.com/projectdiscovery/nuclei/v2/pkg/protocols" + "github.com/projectdiscovery/nuclei/v2/pkg/protocols/common/contextargs" + "github.com/projectdiscovery/nuclei/v2/pkg/protocols/common/expressions" + "github.com/projectdiscovery/nuclei/v2/pkg/protocols/common/generators" + "github.com/projectdiscovery/nuclei/v2/pkg/protocols/common/helpers/eventcreator" + "github.com/projectdiscovery/nuclei/v2/pkg/protocols/common/interactsh" + "github.com/projectdiscovery/nuclei/v2/pkg/protocols/common/utils/vardump" + protocolutils "github.com/projectdiscovery/nuclei/v2/pkg/protocols/utils" + templateTypes "github.com/projectdiscovery/nuclei/v2/pkg/templates/types" + "github.com/projectdiscovery/nuclei/v2/pkg/types" + errorutil "github.com/projectdiscovery/utils/errors" + urlutil "github.com/projectdiscovery/utils/url" + "github.com/remeh/sizedwaitgroup" +) + +// Request is a request for the javascript protocol +type Request struct { + // Operators for the current request go here. + operators.Operators `yaml:",inline,omitempty" json:",inline,omitempty"` + CompiledOperators *operators.Operators `yaml:"-" json:"-"` + + // description: | + // ID is request id in that protocol + ID string `yaml:"id,omitempty" json:"id,omitempty" jsonschema:"title=id of the request,description=ID is the optional ID of the Request"` + + // description: | + // PreCondition is a condition which is evaluated before sending the request. + PreCondition string `yaml:"pre-condition,omitempty" json:"pre-condition,omitempty" jsonschema:"title=pre-condition for the request,description=PreCondition is a condition which is evaluated before sending the request"` + + // description: | + // Args contains the arguments to pass to the javascript code. + Args map[string]interface{} `yaml:"args,omitempty" json:"args,omitempty"` + // description: | + // Code contains code to execute for the javascript request. + Code string `yaml:"code,omitempty" json:"code,omitempty" jsonschema:"title=code to execute in javascript,description=Executes inline javascript code for the request"` + + // description: | + // StopAtFirstMatch stops processing the request at first match. + StopAtFirstMatch bool `yaml:"stop-at-first-match,omitempty" json:"stop-at-first-match,omitempty" jsonschema:"title=stop at first match,description=Stop the execution after a match is found"` + // description: | + // Attack is the type of payload combinations to perform. + // + // Sniper is each payload once, pitchfork combines multiple payload sets and clusterbomb generates + // permutations and combinations for all payloads. + AttackType generators.AttackTypeHolder `yaml:"attack,omitempty" json:"attack,omitempty" jsonschema:"title=attack is the payload combination,description=Attack is the type of payload combinations to perform,enum=sniper,enum=pitchfork,enum=clusterbomb"` + // description: | + // Payload concurreny i.e threads for sending requests. + // examples: + // - name: Send requests using 10 concurrent threads + // value: 10 + Threads int `yaml:"threads,omitempty" json:"threads,omitempty" jsonschema:"title=threads for sending requests,description=Threads specifies number of threads to use sending requests. This enables Connection Pooling"` + // description: | + // Payloads contains any payloads for the current request. + // + // Payloads support both key-values combinations where a list + // of payloads is provided, or optionally a single file can also + // be provided as payload which will be read on run-time. + Payloads map[string]interface{} `yaml:"payloads,omitempty" json:"payloads,omitempty" jsonschema:"title=payloads for the webosocket request,description=Payloads contains any payloads for the current request"` + + generator *generators.PayloadGenerator + + // cache any variables that may be needed for operation. + options *protocols.ExecutorOptions `yaml:"-" json:"-"` +} + +// Compile compiles the request generators preparing any requests possible. +func (request *Request) Compile(options *protocols.ExecutorOptions) error { + request.options = options + + var err error + if len(request.Payloads) > 0 { + request.generator, err = generators.New(request.Payloads, request.AttackType.Value, request.options.TemplatePath, options.Catalog, options.Options.AttackType, options.Options) + if err != nil { + return errors.Wrap(err, "could not parse payloads") + } + } + + if len(request.Matchers) > 0 || len(request.Extractors) > 0 { + compiled := &request.Operators + compiled.ExcludeMatchers = options.ExcludeMatchers + compiled.TemplateID = options.TemplateID + for _, matcher := range compiled.Matchers { + if matcher.Part == "" && matcher.Type.MatcherType != matchers.DSLMatcher { + matcher.Part = "response" + } + } + if err := compiled.Compile(); err != nil { + return errorutil.NewWithTag(request.TemplateID, "could not compile operators got %v", err) + } + request.CompiledOperators = compiled + } + + // "Port" is a special variable and it should not contains any dsl expressions + if strings.Contains(request.getPort(), "{{") { + return errorutil.NewWithTag(request.TemplateID, "'Port' variable cannot contain any dsl expressions") + } + + return nil +} + +// Options returns executer options for http request +func (r *Request) Options() *protocols.ExecutorOptions { + return r.options +} + +// Requests returns the total number of requests the rule will perform +func (request *Request) Requests() int { + pre_conditions := 0 + if request.PreCondition != "" { + pre_conditions = 1 + } + if request.generator != nil { + payloadRequests := request.generator.NewIterator().Total() + return payloadRequests + pre_conditions + } + return 1 + pre_conditions +} + +// GetID returns the ID for the request if any. +func (request *Request) GetID() string { + return request.ID +} + +// ExecuteWithResults executes the protocol requests and returns results instead of writing them. +func (request *Request) ExecuteWithResults(target *contextargs.Context, dynamicValues, previous output.InternalEvent, callback protocols.OutputEventCallback) error { + + input := target.Clone() + // use network port updates input with new port requested in template file + // and it is ignored if input port is not standard http(s) ports like 80,8080,8081 etc + // idea is to reduce redundant dials to http ports + if err := input.UseNetworkPort(request.getPort(), request.getExcludePorts()); err != nil { + gologger.Debug().Msgf("Could not network port from constants: %s\n", err) + } + + hostPort, err := getAddress(input.MetaInput.Input) + if err != nil { + request.options.Progress.IncrementFailedRequestsBy(1) + return err + } + hostname, port, _ := net.SplitHostPort(hostPort) + if hostname == "" { + hostname = hostPort + } + + requestOptions := request.options + templateCtx := request.options.GetTemplateCtx(input.MetaInput) + + payloadValues := generators.BuildPayloadFromOptions(request.options.Options) + for k, v := range dynamicValues { + payloadValues[k] = v + } + + payloadValues["Hostname"] = hostPort + payloadValues["Host"] = hostname + payloadValues["Port"] = port + + hostnameVariables := protocolutils.GenerateDNSVariables(hostname) + values := generators.MergeMaps(payloadValues, hostnameVariables, request.options.Constants, templateCtx.GetAll()) + variablesMap := request.options.Variables.Evaluate(values) + payloadValues = generators.MergeMaps(variablesMap, payloadValues, request.options.Constants, hostnameVariables) + // export all variables to template context + templateCtx.Merge(payloadValues) + + if vardump.EnableVarDump { + gologger.Debug().Msgf("Protocol request variables: \n%s\n", vardump.DumpVariables(payloadValues)) + } + + if request.PreCondition != "" { + payloads := generators.MergeMaps(payloadValues, previous) + + if request.options.Options.Debug || request.options.Options.DebugRequests { + gologger.Debug().Msgf("[%s] Executing Precondition for request\n", request.TemplateID) + var highlightFormatter = "terminal256" + if requestOptions.Options.NoColor { + highlightFormatter = "text" + } + var buff bytes.Buffer + _ = quick.Highlight(&buff, beautifyJavascript(request.PreCondition), "javascript", highlightFormatter, "monokai") + prettyPrint(request.TemplateID, buff.String()) + } + + argsCopy, err := request.getArgsCopy(input, payloads, requestOptions, true) + if err != nil { + return err + } + argsCopy.TemplateCtx = templateCtx.GetAll() + + result, err := request.options.JsCompiler.ExecuteWithOptions(request.PreCondition, argsCopy, nil) + if err != nil { + return errorutil.NewWithTag(request.TemplateID, "could not execute pre-condition: %s", err) + } + if !result.GetSuccess() || types.ToString(result["error"]) != "" { + gologger.Warning().Msgf("[%s] Precondition for request %s was not satisfied\n", request.TemplateID, request.PreCondition) + request.options.Progress.IncrementFailedRequestsBy(1) + return nil + } + if request.options.Options.Debug || request.options.Options.DebugRequests { + request.options.Progress.IncrementRequests() + gologger.Debug().Msgf("[%s] Precondition for request was satisfied\n", request.TemplateID) + } + } + + if request.generator != nil && request.Threads > 1 { + request.executeRequestParallel(context.Background(), hostPort, hostname, input, payloadValues, callback) + return nil + } + + var gotMatches bool + if request.generator != nil { + iterator := request.generator.NewIterator() + + for { + value, ok := iterator.Value() + if !ok { + return nil + } + + if err := request.executeRequestWithPayloads(hostPort, input, hostname, value, payloadValues, func(result *output.InternalWrappedEvent) { + if result.OperatorsResult != nil && result.OperatorsResult.Matched { + gotMatches = true + request.options.Progress.IncrementMatched() + } + callback(result) + }, requestOptions); err != nil { + _ = err + // Review: should we log error here? + // it is technically not error as it is expected to fail + // gologger.Warning().Msgf("Could not execute request: %s\n", err) + // do not return even if error occured + } + // If this was a match, and we want to stop at first match, skip all further requests. + shouldStopAtFirstMatch := request.options.Options.StopAtFirstMatch || request.StopAtFirstMatch + if shouldStopAtFirstMatch && gotMatches { + return nil + } + } + } + return request.executeRequestWithPayloads(hostPort, input, hostname, nil, payloadValues, callback, requestOptions) +} + +func (request *Request) executeRequestParallel(ctxParent context.Context, hostPort, hostname string, input *contextargs.Context, payloadValues map[string]interface{}, callback protocols.OutputEventCallback) { + threads := request.Threads + if threads == 0 { + threads = 1 + } + ctx, cancel := context.WithCancel(ctxParent) + defer cancel() + requestOptions := request.options + gotmatches := &atomic.Bool{} + sg := sizedwaitgroup.New(threads) + if request.generator != nil { + iterator := request.generator.NewIterator() + + for { + value, ok := iterator.Value() + if !ok { + return + } + sg.Add() + go func() { + defer sg.Done() + if ctx.Err() != nil { + // work already done exit + return + } + shouldStopAtFirstMatch := request.options.Options.StopAtFirstMatch || request.StopAtFirstMatch + if err := request.executeRequestWithPayloads(hostPort, input, hostname, value, payloadValues, func(result *output.InternalWrappedEvent) { + if result.OperatorsResult != nil && result.OperatorsResult.Matched { + gotmatches.Store(true) + } + callback(result) + }, requestOptions); err != nil { + _ = err + // Review: should we log error here? + // it is technically not error as it is expected to fail + // gologger.Warning().Msgf("Could not execute request: %s\n", err) + // do not return even if error occured + } + // If this was a match, and we want to stop at first match, skip all further requests. + + if shouldStopAtFirstMatch && gotmatches.Load() { + cancel() + return + } + }() + } + } + sg.Wait() + if gotmatches.Load() { + request.options.Progress.IncrementMatched() + } +} + +func (request *Request) executeRequestWithPayloads(hostPort string, input *contextargs.Context, hostname string, payload map[string]interface{}, previous output.InternalEvent, callback protocols.OutputEventCallback, requestOptions *protocols.ExecutorOptions) error { + payloadValues := generators.MergeMaps(payload, previous) + argsCopy, err := request.getArgsCopy(input, payloadValues, requestOptions, false) + if err != nil { + return err + } + argsCopy.TemplateCtx = request.options.GetTemplateCtx(input.MetaInput).GetAll() + + var requestData = []byte(request.Code) + var interactshURLs []string + if request.options.Interactsh != nil { + var transformedData string + transformedData, interactshURLs = request.options.Interactsh.Replace(string(request.Code), []string{}) + requestData = []byte(transformedData) + } + + results, err := request.options.JsCompiler.ExecuteWithOptions(string(requestData), argsCopy, &compiler.ExecuteOptions{ + Pool: false, + }) + if err != nil { + // shouldn't fail even if it returned error instead create a failure event + results = compiler.ExecuteResult{"success": false, "error": err.Error()} + } + request.options.Progress.IncrementRequests() + + requestOptions.Output.Request(requestOptions.TemplateID, hostPort, request.Type().String(), err) + gologger.Verbose().Msgf("[%s] Sent Javascript request to %s", request.TemplateID, hostPort) + + if requestOptions.Options.Debug || requestOptions.Options.DebugRequests || requestOptions.Options.StoreResponse { + msg := fmt.Sprintf("[%s] Dumped Javascript request for %s:\nVariables:\n %v", requestOptions.TemplateID, input.MetaInput.Input, vardump.DumpVariables(argsCopy.Args)) + + if requestOptions.Options.Debug || requestOptions.Options.DebugRequests { + gologger.Debug().Str("address", input.MetaInput.Input).Msg(msg) + var highlightFormatter = "terminal256" + if requestOptions.Options.NoColor { + highlightFormatter = "text" + } + var buff bytes.Buffer + _ = quick.Highlight(&buff, beautifyJavascript(request.Code), "javascript", highlightFormatter, "monokai") + prettyPrint(request.TemplateID, buff.String()) + } + if requestOptions.Options.StoreResponse { + request.options.Output.WriteStoreDebugData(input.MetaInput.Input, request.options.TemplateID, request.Type().String(), msg) + } + } + + data := make(map[string]interface{}) + for k, v := range payloadValues { + data[k] = v + } + data["type"] = request.Type().String() + for k, v := range results { + data[k] = v + } + data["request"] = beautifyJavascript(request.Code) + data["host"] = input.MetaInput.Input + data["matched"] = hostPort + data["template-path"] = requestOptions.TemplatePath + data["template-id"] = requestOptions.TemplateID + data["template-info"] = requestOptions.TemplateInfo + if request.StopAtFirstMatch || request.options.StopAtFirstMatch { + data["stop-at-first-match"] = true + } + + // add and get values from templatectx + request.options.AddTemplateVars(input.MetaInput, request.Type(), request.GetID(), data) + data = generators.MergeMaps(data, request.options.GetTemplateCtx(input.MetaInput).GetAll()) + + if requestOptions.Options.Debug || requestOptions.Options.DebugRequests || requestOptions.Options.StoreResponse { + msg := fmt.Sprintf("[%s] Dumped Javascript response for %s:\n%v", requestOptions.TemplateID, input.MetaInput.Input, vardump.DumpVariables(results)) + if requestOptions.Options.Debug || requestOptions.Options.DebugRequests { + gologger.Debug().Str("address", input.MetaInput.Input).Msg(msg) + } + if requestOptions.Options.StoreResponse { + request.options.Output.WriteStoreDebugData(input.MetaInput.Input, request.options.TemplateID, request.Type().String(), msg) + } + } + + if _, ok := data["error"]; ok { + event := eventcreator.CreateEventWithAdditionalOptions(request, generators.MergeMaps(data, payloadValues), request.options.Options.Debug || request.options.Options.DebugResponse, func(wrappedEvent *output.InternalWrappedEvent) { + wrappedEvent.OperatorsResult.PayloadValues = payload + }) + callback(event) + return err + } + + if request.options.Interactsh != nil { + request.options.Interactsh.MakePlaceholders(interactshURLs, data) + } + + var event *output.InternalWrappedEvent + if len(interactshURLs) == 0 { + event = eventcreator.CreateEventWithAdditionalOptions(request, generators.MergeMaps(data, payloadValues), request.options.Options.Debug || request.options.Options.DebugResponse, func(wrappedEvent *output.InternalWrappedEvent) { + wrappedEvent.OperatorsResult.PayloadValues = payload + }) + callback(event) + } else if request.options.Interactsh != nil { + event = &output.InternalWrappedEvent{InternalEvent: data, UsesInteractsh: true} + request.options.Interactsh.RequestEvent(interactshURLs, &interactsh.RequestData{ + MakeResultFunc: request.MakeResultEvent, + Event: event, + Operators: request.CompiledOperators, + MatchFunc: request.Match, + ExtractFunc: request.Extract, + }) + } + return nil +} + +func (request *Request) getArgsCopy(input *contextargs.Context, payloadValues map[string]interface{}, requestOptions *protocols.ExecutorOptions, ignoreErrors bool) (*compiler.ExecuteArgs, error) { + // Template args from payloads + argsCopy := make(map[string]interface{}) +mainLoop: + for k, v := range request.Args { + if vVal, ok := v.(string); ok && strings.Contains(vVal, "{") { + finalAddress, dataErr := expressions.Evaluate(vVal, payloadValues) + if dataErr != nil { + requestOptions.Output.Request(requestOptions.TemplateID, input.MetaInput.Input, request.Type().String(), dataErr) + requestOptions.Progress.IncrementFailedRequestsBy(1) + return nil, errors.Wrap(dataErr, "could not evaluate template expressions") + } + if finalAddress == vVal && ignoreErrors { + argsCopy[k] = "" + continue mainLoop + } + argsCopy[k] = finalAddress + } else { + argsCopy[k] = v + } + } + + // "Port" is a special variable that is considered as network port + // and is conditional based on input port and default port specified in input + argsCopy["Port"] = input.Port() + + return &compiler.ExecuteArgs{Args: argsCopy}, nil +} + +// RequestPartDefinitions contains a mapping of request part definitions and their +// description. Multiple definitions are separated by commas. +// Definitions not having a name (generated on runtime) are prefixed & suffixed by <>. +var RequestPartDefinitions = map[string]string{ + "type": "Type is the type of request made", + "response": "Javascript protocol result response", + "host": "Host is the input to the template", + "matched": "Matched is the input which was matched upon", +} + +// getAddress returns the address of the host to make request to +func getAddress(toTest string) (string, error) { + urlx, err := urlutil.Parse(toTest) + if err != nil { + // use given input instead of url parsing failure + return toTest, nil + } + return urlx.Host, nil +} + +// Match performs matching operation for a matcher on model and returns: +// true and a list of matched snippets if the matcher type is supports it +// otherwise false and an empty string slice +func (request *Request) Match(data map[string]interface{}, matcher *matchers.Matcher) (bool, []string) { + return protocols.MakeDefaultMatchFunc(data, matcher) +} + +// Extract performs extracting operation for an extractor on model and returns true or false. +func (request *Request) Extract(data map[string]interface{}, matcher *extractors.Extractor) map[string]struct{} { + return protocols.MakeDefaultExtractFunc(data, matcher) +} + +// MakeResultEvent creates a result event from internal wrapped event +func (request *Request) MakeResultEvent(wrapped *output.InternalWrappedEvent) []*output.ResultEvent { + return protocols.MakeDefaultResultEvent(request, wrapped) +} + +// GetCompiledOperators returns a list of the compiled operators +func (request *Request) GetCompiledOperators() []*operators.Operators { + return []*operators.Operators{request.CompiledOperators} +} + +// Type returns the type of the protocol request +func (request *Request) Type() templateTypes.ProtocolType { + return templateTypes.JavascriptProtocol +} + +func (request *Request) getPort() string { + for k, v := range request.Args { + if strings.EqualFold(k, "Port") { + return types.ToString(v) + } + } + return "" +} + +func (request *Request) getExcludePorts() string { + for k, v := range request.Args { + if strings.EqualFold(k, "exclude-ports") { + return types.ToString(v) + } + } + return "" +} + +func (request *Request) MakeResultEventItem(wrapped *output.InternalWrappedEvent) *output.ResultEvent { + data := &output.ResultEvent{ + TemplateID: types.ToString(wrapped.InternalEvent["template-id"]), + TemplatePath: types.ToString(wrapped.InternalEvent["template-path"]), + Info: wrapped.InternalEvent["template-info"].(model.Info), + Type: types.ToString(wrapped.InternalEvent["type"]), + Host: types.ToString(wrapped.InternalEvent["host"]), + Matched: types.ToString(wrapped.InternalEvent["matched"]), + Metadata: wrapped.OperatorsResult.PayloadValues, + ExtractedResults: wrapped.OperatorsResult.OutputExtracts, + Timestamp: time.Now(), + MatcherStatus: true, + Request: types.ToString(wrapped.InternalEvent["request"]), + Response: types.ToString(wrapped.InternalEvent["response"]), + IP: types.ToString(wrapped.InternalEvent["ip"]), + } + return data +} + +func beautifyJavascript(code string) string { + opts := jsbeautifier.DefaultOptions() + beautified, err := jsbeautifier.Beautify(&code, opts) + if err != nil { + return code + } + return beautified +} + +func prettyPrint(templateId string, buff string) { + lines := strings.Split(buff, "\n") + final := []string{} + for _, v := range lines { + if v != "" { + final = append(final, "\t"+v) + } + } + gologger.Debug().Msgf(" [%v] Javascript Code:\n\n%v\n\n", templateId, strings.Join(final, "\n")) +} diff --git a/v2/pkg/protocols/javascript/js_test.go b/v2/pkg/protocols/javascript/js_test.go new file mode 100644 index 0000000000..a2216e3611 --- /dev/null +++ b/v2/pkg/protocols/javascript/js_test.go @@ -0,0 +1,74 @@ +package javascript_test + +import ( + "context" + "log" + "testing" + "time" + + "github.com/projectdiscovery/nuclei/v2/pkg/catalog/config" + "github.com/projectdiscovery/nuclei/v2/pkg/catalog/disk" + "github.com/projectdiscovery/nuclei/v2/pkg/parsers" + "github.com/projectdiscovery/nuclei/v2/pkg/progress" + "github.com/projectdiscovery/nuclei/v2/pkg/protocols" + "github.com/projectdiscovery/nuclei/v2/pkg/templates" + "github.com/projectdiscovery/nuclei/v2/pkg/testutils" + "github.com/projectdiscovery/ratelimit" + "github.com/stretchr/testify/require" +) + +var ( + testcases = []string{ + "testcases/ms-sql-detect.yaml", + "testcases/redis-pass-brute.yaml", + "testcases/ssh-server-fingerprint.yaml", + } + executerOpts protocols.ExecutorOptions +) + +func setup() { + options := testutils.DefaultOptions + testutils.Init(options) + progressImpl, _ := progress.NewStatsTicker(0, false, false, false, 0) + + executerOpts = protocols.ExecutorOptions{ + Output: testutils.NewMockOutputWriter(), + Options: options, + Progress: progressImpl, + ProjectFile: nil, + IssuesClient: nil, + Browser: nil, + Catalog: disk.NewCatalog(config.DefaultConfig.TemplatesDirectory), + RateLimiter: ratelimit.New(context.Background(), uint(options.RateLimit), time.Second), + } + workflowLoader, err := parsers.NewLoader(&executerOpts) + if err != nil { + log.Fatalf("Could not create workflow loader: %s\n", err) + } + executerOpts.WorkflowLoader = workflowLoader +} + +func TestCompile(t *testing.T) { + setup() + for index, tpl := range testcases { + // parse template + template, err := templates.Parse(tpl, nil, executerOpts) + require.Nilf(t, err, "failed to parse %v", tpl) + + // compile template + err = template.Executer.Compile() + require.Nilf(t, err, "failed to compile %v", tpl) + + switch index { + case 0: + // requests count should be 1 + require.Equal(t, 1, template.TotalRequests, "template : %v", tpl) + case 1: + // requests count should be 6 i.e 5 generator payloads + 1 precondition request + require.Equal(t, 5+1, template.TotalRequests, "template : %v", tpl) + case 2: + // requests count should be 1 + require.Equal(t, 1, template.TotalRequests, "template : %v", tpl) + } + } +} diff --git a/v2/pkg/protocols/javascript/testcases/ms-sql-detect.yaml b/v2/pkg/protocols/javascript/testcases/ms-sql-detect.yaml new file mode 100644 index 0000000000..5865573ad0 --- /dev/null +++ b/v2/pkg/protocols/javascript/testcases/ms-sql-detect.yaml @@ -0,0 +1,29 @@ +id: ms-sql-detect + +info: + name: microsoft sql server(mssql) detection + author: Ice3man543,tarunKoyalwar + severity: info + description: | + ms sql detection template + metadata: + shodan-query: "port:1433" + +javascript: + - code: | + var m = require("nuclei/mssql"); + var c = m.MSSQLClient(); + c.IsMssql(Host, Port); + + args: + Host: "{{Host}}" + Port: "1433" + + matchers: + - type: dsl + dsl: + - "response == true" + - "success == true" + condition: and + + diff --git a/v2/pkg/protocols/javascript/testcases/redis-pass-brute.yaml b/v2/pkg/protocols/javascript/testcases/redis-pass-brute.yaml new file mode 100644 index 0000000000..d4d092305d --- /dev/null +++ b/v2/pkg/protocols/javascript/testcases/redis-pass-brute.yaml @@ -0,0 +1,43 @@ +id: redis-pass-brute +info: + name: redis password bruteforce + author: tarunKoyalwar + severity: high + description: | + This template bruteforces passwords for protected redis instances. + If redis is not protected with password. it is also matched + metadata: + shodan-query: product:"redis" + + +javascript: + - pre-condition: | + isPortOpen(Host,Port) + + code: | + var m = require("nuclei/redis"); + m.GetServerInfoAuth(Host,Port,Password); + + args: + Host: "{{Host}}" + Port: "6379" + Password: "{{passwords}}" + + payloads: + passwords: + - "" + - root + - password + - admin + - iamadmin + stop-at-first-match: true + + matchers-condition: and + matchers: + - type: word + words: + - "redis_version" + - type: word + negative: true + words: + - "redis_mode:sentinel" diff --git a/v2/pkg/protocols/javascript/testcases/ssh-server-fingerprint.yaml b/v2/pkg/protocols/javascript/testcases/ssh-server-fingerprint.yaml new file mode 100644 index 0000000000..a5f4ff4cb4 --- /dev/null +++ b/v2/pkg/protocols/javascript/testcases/ssh-server-fingerprint.yaml @@ -0,0 +1,24 @@ +id: ssh-server-fingerprint + +info: + name: Fingerprint SSH Server Software + author: Ice3man543,tarunKoyalwar + severity: info + + +javascript: + - code: | + var m = require("nuclei/ssh"); + var c = m.SSHClient(); + var response = c.ConnectSSHInfoMode(Host, Port); + to_json(response); + args: + Host: "{{Host}}" + Port: "22" + + extractors: + - type: json + name: server + json: + - '.ServerID.Raw' + part: response diff --git a/v2/pkg/protocols/protocols.go b/v2/pkg/protocols/protocols.go index edeef8c112..226f0937ca 100644 --- a/v2/pkg/protocols/protocols.go +++ b/v2/pkg/protocols/protocols.go @@ -11,6 +11,7 @@ import ( "github.com/projectdiscovery/nuclei/v2/pkg/catalog" "github.com/projectdiscovery/nuclei/v2/pkg/input" + "github.com/projectdiscovery/nuclei/v2/pkg/js/compiler" "github.com/projectdiscovery/nuclei/v2/pkg/model" "github.com/projectdiscovery/nuclei/v2/pkg/operators" "github.com/projectdiscovery/nuclei/v2/pkg/operators/extractors" @@ -97,6 +98,9 @@ type ExecutorOptions struct { IsMultiProtocol bool // templateStore is a map which contains template context for each scan (i.e input * template-id pair) templateCtxStore *mapsutil.SyncLockMap[string, *contextargs.Context] + // JsCompiler is abstracted javascript compiler which adds node modules and provides execution + // environment for javascript templates + JsCompiler *compiler.Compiler } // CreateTemplateCtxStore creates template context store (which contains templateCtx for every scan) diff --git a/v2/pkg/protocols/ssl/ssl.go b/v2/pkg/protocols/ssl/ssl.go index dd8b1faf3f..26f0818054 100644 --- a/v2/pkg/protocols/ssl/ssl.go +++ b/v2/pkg/protocols/ssl/ssl.go @@ -42,7 +42,7 @@ type Request struct { CompiledOperators *operators.Operators `yaml:"-" json:"-"` // ID is the optional id of the request - ID string `yaml:"id,omitempty" json:"id,omitempty" jsonschema:"title=id of the request,description=ID of the network request"` + ID string `yaml:"id,omitempty" json:"id,omitempty" jsonschema:"title=id of the request,description=ID of the request"` // description: | // Address contains address for the request diff --git a/v2/pkg/templates/compile.go b/v2/pkg/templates/compile.go index 0b2d643ca3..2a95527590 100644 --- a/v2/pkg/templates/compile.go +++ b/v2/pkg/templates/compile.go @@ -10,6 +10,7 @@ import ( "github.com/pkg/errors" "gopkg.in/yaml.v2" + "github.com/projectdiscovery/nuclei/v2/pkg/js/compiler" "github.com/projectdiscovery/nuclei/v2/pkg/operators" "github.com/projectdiscovery/nuclei/v2/pkg/protocols" "github.com/projectdiscovery/nuclei/v2/pkg/protocols/offlinehttp" @@ -110,7 +111,8 @@ func (template *Template) Requests() int { len(template.RequestsSSL) + len(template.RequestsWebsocket) + len(template.RequestsWHOIS) + - len(template.RequestsCode) + len(template.RequestsCode) + + len(template.RequestsJavascript) } // compileProtocolRequests compiles all the protocol requests for the template @@ -162,6 +164,9 @@ func (template *Template) compileProtocolRequests(options protocols.ExecutorOpti if len(template.RequestsCode) > 0 { requests = append(requests, template.convertRequestToProtocolsRequest(template.RequestsCode)...) } + if len(template.RequestsJavascript) > 0 { + requests = append(requests, template.convertRequestToProtocolsRequest(template.RequestsJavascript)...) + } } template.Executer = tmplexec.NewTemplateExecuter(requests, &options) return nil @@ -278,6 +283,11 @@ func ParseTemplateFromReader(reader io.Reader, preprocessor Preprocessor, option options.ProtocolType = template.Type() options.Constants = template.Constants + // initialize the js compiler if missing + if options.JsCompiler == nil { + options.JsCompiler = compiler.New() + } + template.Options = &options // If no requests, and it is also not a workflow, return error. if template.Requests() == 0 { diff --git a/v2/pkg/templates/templates.go b/v2/pkg/templates/templates.go index 72a3cb069b..8aea97b52e 100644 --- a/v2/pkg/templates/templates.go +++ b/v2/pkg/templates/templates.go @@ -14,6 +14,7 @@ import ( "github.com/projectdiscovery/nuclei/v2/pkg/protocols/file" "github.com/projectdiscovery/nuclei/v2/pkg/protocols/headless" "github.com/projectdiscovery/nuclei/v2/pkg/protocols/http" + "github.com/projectdiscovery/nuclei/v2/pkg/protocols/javascript" "github.com/projectdiscovery/nuclei/v2/pkg/protocols/network" "github.com/projectdiscovery/nuclei/v2/pkg/protocols/ssl" "github.com/projectdiscovery/nuclei/v2/pkg/protocols/websocket" @@ -109,6 +110,9 @@ type Template struct { // description: | // Code contains code snippets. RequestsCode []*code.Request `yaml:"code,omitempty" json:"code,omitempty" jsonschema:"title=code snippets to make,description=Code snippets"` + // description: | + // Javascript contains the javascript request to make in the template. + RequestsJavascript []*javascript.Request `yaml:"javascript,omitempty" json:"javascript,omitempty" jsonschema:"title=javascript requests to make,description=Javascript requests to make for the template"` // description: | // Workflows is a yaml based workflow declaration code. @@ -173,6 +177,8 @@ func (template *Template) Type() types.ProtocolType { return types.WHOISProtocol case len(template.RequestsCode) > 0: return types.CodeProtocol + case len(template.RequestsJavascript) > 0: + return types.JavascriptProtocol default: return types.InvalidProtocol } @@ -248,6 +254,13 @@ func (template *Template) validateAllRequestIDs() { } } } + if len(template.RequestsJavascript) > 1 { + for i, req := range template.RequestsJavascript { + if req.ID == "" { + req.ID = req.Type().String() + "_" + strconv.Itoa(i) + } + } + } } // MarshalYAML forces recursive struct validation during marshal operation @@ -334,6 +347,8 @@ func (template *Template) addRequestsToQueue(keys ...string) { template.RequestsQueue = append(template.RequestsQueue, template.convertRequestToProtocolsRequest(template.RequestsWHOIS)...) case types.CodeProtocol.String(): template.RequestsQueue = append(template.RequestsQueue, template.convertRequestToProtocolsRequest(template.RequestsCode)...) + case types.JavascriptProtocol.String(): + template.RequestsQueue = append(template.RequestsQueue, template.convertRequestToProtocolsRequest(template.RequestsJavascript)...) // for deprecated protocols case "requests": template.RequestsQueue = append(template.RequestsQueue, template.convertRequestToProtocolsRequest(template.RequestsHTTP)...) @@ -349,7 +364,8 @@ func (template *Template) hasMultipleRequests() bool { counter := len(template.RequestsDNS) + len(template.RequestsFile) + len(template.RequestsHTTP) + len(template.RequestsHeadless) + len(template.RequestsNetwork) + len(template.RequestsSSL) + - len(template.RequestsWebsocket) + len(template.RequestsWHOIS) + len(template.RequestsWebsocket) + len(template.RequestsWHOIS) + + len(template.RequestsCode) + len(template.RequestsJavascript) return counter > 1 } diff --git a/v2/pkg/templates/types/types.go b/v2/pkg/templates/types/types.go index 8fb0315777..b51fd2bde3 100644 --- a/v2/pkg/templates/types/types.go +++ b/v2/pkg/templates/types/types.go @@ -23,6 +23,7 @@ const ( FileProtocol // name:http HTTPProtocol + // name:offline-http OfflineHTTPProtocol // name:headless HeadlessProtocol @@ -38,23 +39,26 @@ const ( WHOISProtocol // name:code CodeProtocol + // name: js + JavascriptProtocol limit InvalidProtocol ) // ExtractorTypes is a table for conversion of extractor type from string. var protocolMappings = map[ProtocolType]string{ - InvalidProtocol: "invalid", - DNSProtocol: "dns", - FileProtocol: "file", - HTTPProtocol: "http", - HeadlessProtocol: "headless", - NetworkProtocol: "tcp", - WorkflowProtocol: "workflow", - SSLProtocol: "ssl", - WebsocketProtocol: "websocket", - WHOISProtocol: "whois", - CodeProtocol: "code", + InvalidProtocol: "invalid", + DNSProtocol: "dns", + FileProtocol: "file", + HTTPProtocol: "http", + HeadlessProtocol: "headless", + NetworkProtocol: "tcp", + WorkflowProtocol: "workflow", + SSLProtocol: "ssl", + WebsocketProtocol: "websocket", + WHOISProtocol: "whois", + CodeProtocol: "code", + JavascriptProtocol: "js", } func GetSupportedProtocolTypes() ProtocolTypes { diff --git a/v2/pkg/types/interfaces.go b/v2/pkg/types/interfaces.go index 7b5bcd2ae8..8b3812bb93 100644 --- a/v2/pkg/types/interfaces.go +++ b/v2/pkg/types/interfaces.go @@ -3,6 +3,7 @@ package types import ( + "bytes" "encoding/hex" "fmt" "strconv" @@ -120,13 +121,32 @@ func ToStringSlice(i interface{}) []string { return v case string: return strings.Fields(v) - case interface{}: - return []string{ToString(v)} default: return nil } } +// ToByteSlice casts an interface to a []byte type. +func ToByteSlice(i interface{}) []byte { + switch v := i.(type) { + case []byte: + return v + case []string: + return []byte(strings.Join(v, "")) + case string: + return []byte(v) + case []interface{}: + var buff bytes.Buffer + for _, u := range v { + buff.WriteString(ToString(u)) + } + return buff.Bytes() + default: + strValue := ToString(i) + return []byte(strValue) + } +} + // ToStringMap casts an interface to a map[string]interface{} type. func ToStringMap(i interface{}) map[string]interface{} { var m = map[string]interface{}{}