mirror of
https://github.com/rclone/rclone
synced 2024-12-22 13:03:02 +01:00
parent
3ef9f6f016
commit
8ec57d145e
306
Godeps/Godeps.json
generated
306
Godeps/Godeps.json
generated
@ -20,13 +20,13 @@
|
||||
},
|
||||
{
|
||||
"ImportPath": "cloud.google.com/go/compute/metadata",
|
||||
"Comment": "v0.6.0-23-ge0ba508",
|
||||
"Rev": "e0ba5081473dca0a69826693dca7f03fc0e3d086"
|
||||
"Comment": "v0.6.0-68-g0b87d14",
|
||||
"Rev": "0b87d14d90086b53a97dfbd66f3000f7f112b494"
|
||||
},
|
||||
{
|
||||
"ImportPath": "cloud.google.com/go/internal",
|
||||
"Comment": "v0.6.0-23-ge0ba508",
|
||||
"Rev": "e0ba5081473dca0a69826693dca7f03fc0e3d086"
|
||||
"Comment": "v0.6.0-68-g0b87d14",
|
||||
"Rev": "0b87d14d90086b53a97dfbd66f3000f7f112b494"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/Unknwon/goconfig",
|
||||
@ -39,138 +39,138 @@
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/aws/aws-sdk-go/aws",
|
||||
"Comment": "v1.6.9-2-g6ad900d",
|
||||
"Rev": "6ad900d30b0f1a41b14ee02300f7268bdabea1eb"
|
||||
"Comment": "v1.6.24-1-g2d3b3bc",
|
||||
"Rev": "2d3b3bc3aae6a09a9b194aa6eb71326fcbe2e918"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/aws/aws-sdk-go/aws/awserr",
|
||||
"Comment": "v1.6.9-2-g6ad900d",
|
||||
"Rev": "6ad900d30b0f1a41b14ee02300f7268bdabea1eb"
|
||||
"Comment": "v1.6.24-1-g2d3b3bc",
|
||||
"Rev": "2d3b3bc3aae6a09a9b194aa6eb71326fcbe2e918"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/aws/aws-sdk-go/aws/awsutil",
|
||||
"Comment": "v1.6.9-2-g6ad900d",
|
||||
"Rev": "6ad900d30b0f1a41b14ee02300f7268bdabea1eb"
|
||||
"Comment": "v1.6.24-1-g2d3b3bc",
|
||||
"Rev": "2d3b3bc3aae6a09a9b194aa6eb71326fcbe2e918"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/aws/aws-sdk-go/aws/client",
|
||||
"Comment": "v1.6.9-2-g6ad900d",
|
||||
"Rev": "6ad900d30b0f1a41b14ee02300f7268bdabea1eb"
|
||||
"Comment": "v1.6.24-1-g2d3b3bc",
|
||||
"Rev": "2d3b3bc3aae6a09a9b194aa6eb71326fcbe2e918"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/aws/aws-sdk-go/aws/client/metadata",
|
||||
"Comment": "v1.6.9-2-g6ad900d",
|
||||
"Rev": "6ad900d30b0f1a41b14ee02300f7268bdabea1eb"
|
||||
"Comment": "v1.6.24-1-g2d3b3bc",
|
||||
"Rev": "2d3b3bc3aae6a09a9b194aa6eb71326fcbe2e918"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/aws/aws-sdk-go/aws/corehandlers",
|
||||
"Comment": "v1.6.9-2-g6ad900d",
|
||||
"Rev": "6ad900d30b0f1a41b14ee02300f7268bdabea1eb"
|
||||
"Comment": "v1.6.24-1-g2d3b3bc",
|
||||
"Rev": "2d3b3bc3aae6a09a9b194aa6eb71326fcbe2e918"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/aws/aws-sdk-go/aws/credentials",
|
||||
"Comment": "v1.6.9-2-g6ad900d",
|
||||
"Rev": "6ad900d30b0f1a41b14ee02300f7268bdabea1eb"
|
||||
"Comment": "v1.6.24-1-g2d3b3bc",
|
||||
"Rev": "2d3b3bc3aae6a09a9b194aa6eb71326fcbe2e918"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/aws/aws-sdk-go/aws/credentials/ec2rolecreds",
|
||||
"Comment": "v1.6.9-2-g6ad900d",
|
||||
"Rev": "6ad900d30b0f1a41b14ee02300f7268bdabea1eb"
|
||||
"Comment": "v1.6.24-1-g2d3b3bc",
|
||||
"Rev": "2d3b3bc3aae6a09a9b194aa6eb71326fcbe2e918"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/aws/aws-sdk-go/aws/credentials/endpointcreds",
|
||||
"Comment": "v1.6.9-2-g6ad900d",
|
||||
"Rev": "6ad900d30b0f1a41b14ee02300f7268bdabea1eb"
|
||||
"Comment": "v1.6.24-1-g2d3b3bc",
|
||||
"Rev": "2d3b3bc3aae6a09a9b194aa6eb71326fcbe2e918"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/aws/aws-sdk-go/aws/credentials/stscreds",
|
||||
"Comment": "v1.6.9-2-g6ad900d",
|
||||
"Rev": "6ad900d30b0f1a41b14ee02300f7268bdabea1eb"
|
||||
"Comment": "v1.6.24-1-g2d3b3bc",
|
||||
"Rev": "2d3b3bc3aae6a09a9b194aa6eb71326fcbe2e918"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/aws/aws-sdk-go/aws/defaults",
|
||||
"Comment": "v1.6.9-2-g6ad900d",
|
||||
"Rev": "6ad900d30b0f1a41b14ee02300f7268bdabea1eb"
|
||||
"Comment": "v1.6.24-1-g2d3b3bc",
|
||||
"Rev": "2d3b3bc3aae6a09a9b194aa6eb71326fcbe2e918"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/aws/aws-sdk-go/aws/ec2metadata",
|
||||
"Comment": "v1.6.9-2-g6ad900d",
|
||||
"Rev": "6ad900d30b0f1a41b14ee02300f7268bdabea1eb"
|
||||
"Comment": "v1.6.24-1-g2d3b3bc",
|
||||
"Rev": "2d3b3bc3aae6a09a9b194aa6eb71326fcbe2e918"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/aws/aws-sdk-go/aws/endpoints",
|
||||
"Comment": "v1.6.9-2-g6ad900d",
|
||||
"Rev": "6ad900d30b0f1a41b14ee02300f7268bdabea1eb"
|
||||
"Comment": "v1.6.24-1-g2d3b3bc",
|
||||
"Rev": "2d3b3bc3aae6a09a9b194aa6eb71326fcbe2e918"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/aws/aws-sdk-go/aws/request",
|
||||
"Comment": "v1.6.9-2-g6ad900d",
|
||||
"Rev": "6ad900d30b0f1a41b14ee02300f7268bdabea1eb"
|
||||
"Comment": "v1.6.24-1-g2d3b3bc",
|
||||
"Rev": "2d3b3bc3aae6a09a9b194aa6eb71326fcbe2e918"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/aws/aws-sdk-go/aws/session",
|
||||
"Comment": "v1.6.9-2-g6ad900d",
|
||||
"Rev": "6ad900d30b0f1a41b14ee02300f7268bdabea1eb"
|
||||
"Comment": "v1.6.24-1-g2d3b3bc",
|
||||
"Rev": "2d3b3bc3aae6a09a9b194aa6eb71326fcbe2e918"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/aws/aws-sdk-go/aws/signer/v4",
|
||||
"Comment": "v1.6.9-2-g6ad900d",
|
||||
"Rev": "6ad900d30b0f1a41b14ee02300f7268bdabea1eb"
|
||||
"Comment": "v1.6.24-1-g2d3b3bc",
|
||||
"Rev": "2d3b3bc3aae6a09a9b194aa6eb71326fcbe2e918"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/aws/aws-sdk-go/private/protocol",
|
||||
"Comment": "v1.6.9-2-g6ad900d",
|
||||
"Rev": "6ad900d30b0f1a41b14ee02300f7268bdabea1eb"
|
||||
"Comment": "v1.6.24-1-g2d3b3bc",
|
||||
"Rev": "2d3b3bc3aae6a09a9b194aa6eb71326fcbe2e918"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/aws/aws-sdk-go/private/protocol/query",
|
||||
"Comment": "v1.6.9-2-g6ad900d",
|
||||
"Rev": "6ad900d30b0f1a41b14ee02300f7268bdabea1eb"
|
||||
"Comment": "v1.6.24-1-g2d3b3bc",
|
||||
"Rev": "2d3b3bc3aae6a09a9b194aa6eb71326fcbe2e918"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/aws/aws-sdk-go/private/protocol/query/queryutil",
|
||||
"Comment": "v1.6.9-2-g6ad900d",
|
||||
"Rev": "6ad900d30b0f1a41b14ee02300f7268bdabea1eb"
|
||||
"Comment": "v1.6.24-1-g2d3b3bc",
|
||||
"Rev": "2d3b3bc3aae6a09a9b194aa6eb71326fcbe2e918"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/aws/aws-sdk-go/private/protocol/rest",
|
||||
"Comment": "v1.6.9-2-g6ad900d",
|
||||
"Rev": "6ad900d30b0f1a41b14ee02300f7268bdabea1eb"
|
||||
"Comment": "v1.6.24-1-g2d3b3bc",
|
||||
"Rev": "2d3b3bc3aae6a09a9b194aa6eb71326fcbe2e918"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/aws/aws-sdk-go/private/protocol/restxml",
|
||||
"Comment": "v1.6.9-2-g6ad900d",
|
||||
"Rev": "6ad900d30b0f1a41b14ee02300f7268bdabea1eb"
|
||||
"Comment": "v1.6.24-1-g2d3b3bc",
|
||||
"Rev": "2d3b3bc3aae6a09a9b194aa6eb71326fcbe2e918"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/aws/aws-sdk-go/private/protocol/xml/xmlutil",
|
||||
"Comment": "v1.6.9-2-g6ad900d",
|
||||
"Rev": "6ad900d30b0f1a41b14ee02300f7268bdabea1eb"
|
||||
"Comment": "v1.6.24-1-g2d3b3bc",
|
||||
"Rev": "2d3b3bc3aae6a09a9b194aa6eb71326fcbe2e918"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/aws/aws-sdk-go/private/waiter",
|
||||
"Comment": "v1.6.9-2-g6ad900d",
|
||||
"Rev": "6ad900d30b0f1a41b14ee02300f7268bdabea1eb"
|
||||
"Comment": "v1.6.24-1-g2d3b3bc",
|
||||
"Rev": "2d3b3bc3aae6a09a9b194aa6eb71326fcbe2e918"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/aws/aws-sdk-go/service/s3",
|
||||
"Comment": "v1.6.9-2-g6ad900d",
|
||||
"Rev": "6ad900d30b0f1a41b14ee02300f7268bdabea1eb"
|
||||
"Comment": "v1.6.24-1-g2d3b3bc",
|
||||
"Rev": "2d3b3bc3aae6a09a9b194aa6eb71326fcbe2e918"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/aws/aws-sdk-go/service/s3/s3iface",
|
||||
"Comment": "v1.6.9-2-g6ad900d",
|
||||
"Rev": "6ad900d30b0f1a41b14ee02300f7268bdabea1eb"
|
||||
"Comment": "v1.6.24-1-g2d3b3bc",
|
||||
"Rev": "2d3b3bc3aae6a09a9b194aa6eb71326fcbe2e918"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/aws/aws-sdk-go/service/s3/s3manager",
|
||||
"Comment": "v1.6.9-2-g6ad900d",
|
||||
"Rev": "6ad900d30b0f1a41b14ee02300f7268bdabea1eb"
|
||||
"Comment": "v1.6.24-1-g2d3b3bc",
|
||||
"Rev": "2d3b3bc3aae6a09a9b194aa6eb71326fcbe2e918"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/aws/aws-sdk-go/service/sts",
|
||||
"Comment": "v1.6.9-2-g6ad900d",
|
||||
"Rev": "6ad900d30b0f1a41b14ee02300f7268bdabea1eb"
|
||||
"Comment": "v1.6.24-1-g2d3b3bc",
|
||||
"Rev": "2d3b3bc3aae6a09a9b194aa6eb71326fcbe2e918"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/cpuguy83/go-md2man/md2man",
|
||||
@ -179,12 +179,13 @@
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/davecgh/go-spew/spew",
|
||||
"Rev": "5215b55f46b2b919f50a1df0eaa5886afe4e3b3d"
|
||||
"Comment": "v1.1.0",
|
||||
"Rev": "346938d642f2ec3594ed81d874461961cd0faa76"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/go-ini/ini",
|
||||
"Comment": "v1.9.0",
|
||||
"Rev": "193d1ecb466bf97aae8b454a5cfc192941c64809"
|
||||
"Comment": "v1.24.0-2-gee900ca",
|
||||
"Rev": "ee900ca565931451fe4e4409bcbd4316331cec1c"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/golang/protobuf/proto",
|
||||
@ -192,7 +193,7 @@
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/google/go-querystring/query",
|
||||
"Rev": "9235644dd9e52eeae6fa48efd539fdc351a0af53"
|
||||
"Rev": "53e6ce116135b80d037921a7fdd5138cf32d7a8a"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/googleapis/gax-go",
|
||||
@ -204,8 +205,12 @@
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/jmespath/go-jmespath",
|
||||
"Comment": "0.2.2-12-g0b12d6b",
|
||||
"Rev": "0b12d6b521d83fc7f755e7cfc1b1fbdd35a01a74"
|
||||
"Comment": "0.2.2-14-gbd40a43",
|
||||
"Rev": "bd40a432e4c76585ef6b72d3fd96fb9b6dc7b68d"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/kr/fs",
|
||||
"Rev": "2788f0dbd16903de03cb8186e5c7d97b69ad387b"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/ncw/go-acd",
|
||||
@ -222,25 +227,26 @@
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/pkg/sftp",
|
||||
"Rev": "bf1c2bb0012cdea62d6c5ae7212a1bb04cfa4d89"
|
||||
"Rev": "ff7e52ffd762466ebd2c4e710d5436dccc539f54"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/pmezard/go-difflib/difflib",
|
||||
"Comment": "v1.0.0",
|
||||
"Rev": "792786c7400a136282c1664665ae0a8db921c6c2"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/rfjakob/eme",
|
||||
"Comment": "v1.0-10-g601d0e2",
|
||||
"Rev": "601d0e278ceda9aa2085a61c9265f6e690ef5255"
|
||||
"Comment": "v1.0-15-gfd00240",
|
||||
"Rev": "fd00240838d2e0fe6b2c58bf5b27db843d828ad5"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/russross/blackfriday",
|
||||
"Comment": "v1.4-38-g93622da",
|
||||
"Rev": "93622da34e54fb6529bfb7c57e710f37a8d9cbd8"
|
||||
"Comment": "v1.4-40-g5f33e7b",
|
||||
"Rev": "5f33e7b7878355cd2b7e6b8eefc48a5472c69f70"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/shurcooL/sanitized_anchor_name",
|
||||
"Rev": "10ef21a441db47d8b13ebcc5fd2310f636973c77"
|
||||
"Rev": "1dba4b3954bc059efc3991ec364f9f9a35f597d2"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/skratchdot/open-golang/open",
|
||||
@ -248,15 +254,15 @@
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/spf13/cobra",
|
||||
"Rev": "1dd5ff2e11b6dca62fdcb275eb804b94607d8b06"
|
||||
"Rev": "b5d8e8f46a2f829f755b6e33b454e25c61c935e1"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/spf13/cobra/doc",
|
||||
"Rev": "1dd5ff2e11b6dca62fdcb275eb804b94607d8b06"
|
||||
"Rev": "b5d8e8f46a2f829f755b6e33b454e25c61c935e1"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/spf13/pflag",
|
||||
"Rev": "25f8b5b07aece3207895bf19f7ab517eb3b22a40"
|
||||
"Rev": "9ff6c6923cfffbcd502984b8e0c80539a94968b7"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/stacktic/dropbox",
|
||||
@ -264,216 +270,244 @@
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/stretchr/testify/assert",
|
||||
"Comment": "v1.1.4-25-g2402e8e",
|
||||
"Rev": "2402e8e7a02fc811447d11f881aa9746cdc57983"
|
||||
"Comment": "v1.1.4-27-g4d4bfba",
|
||||
"Rev": "4d4bfba8f1d1027c4fdbe371823030df51419987"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/stretchr/testify/require",
|
||||
"Comment": "v1.1.4-25-g2402e8e",
|
||||
"Rev": "2402e8e7a02fc811447d11f881aa9746cdc57983"
|
||||
"Comment": "v1.1.4-27-g4d4bfba",
|
||||
"Rev": "4d4bfba8f1d1027c4fdbe371823030df51419987"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/tsenart/tb",
|
||||
"Rev": "19f4c3d79d2bd67d0911b2e310b999eeea4454c1"
|
||||
},
|
||||
{
|
||||
"ImportPath": "golang.org/x/crypto/curve25519",
|
||||
"Rev": "453249f01cfeb54c3d549ddb75ff152ca243f9d8"
|
||||
},
|
||||
{
|
||||
"ImportPath": "golang.org/x/crypto/ed25519",
|
||||
"Rev": "453249f01cfeb54c3d549ddb75ff152ca243f9d8"
|
||||
},
|
||||
{
|
||||
"ImportPath": "golang.org/x/crypto/ed25519/internal/edwards25519",
|
||||
"Rev": "453249f01cfeb54c3d549ddb75ff152ca243f9d8"
|
||||
},
|
||||
{
|
||||
"ImportPath": "golang.org/x/crypto/nacl/secretbox",
|
||||
"Rev": "f6b343c37ca80bfa8ea539da67a0b621f84fab1d"
|
||||
"Rev": "453249f01cfeb54c3d549ddb75ff152ca243f9d8"
|
||||
},
|
||||
{
|
||||
"ImportPath": "golang.org/x/crypto/pbkdf2",
|
||||
"Rev": "f6b343c37ca80bfa8ea539da67a0b621f84fab1d"
|
||||
"Rev": "453249f01cfeb54c3d549ddb75ff152ca243f9d8"
|
||||
},
|
||||
{
|
||||
"ImportPath": "golang.org/x/crypto/poly1305",
|
||||
"Rev": "f6b343c37ca80bfa8ea539da67a0b621f84fab1d"
|
||||
"Rev": "453249f01cfeb54c3d549ddb75ff152ca243f9d8"
|
||||
},
|
||||
{
|
||||
"ImportPath": "golang.org/x/crypto/salsa20/salsa",
|
||||
"Rev": "f6b343c37ca80bfa8ea539da67a0b621f84fab1d"
|
||||
"Rev": "453249f01cfeb54c3d549ddb75ff152ca243f9d8"
|
||||
},
|
||||
{
|
||||
"ImportPath": "golang.org/x/crypto/scrypt",
|
||||
"Rev": "f6b343c37ca80bfa8ea539da67a0b621f84fab1d"
|
||||
"Rev": "453249f01cfeb54c3d549ddb75ff152ca243f9d8"
|
||||
},
|
||||
{
|
||||
"ImportPath": "golang.org/x/crypto/ssh",
|
||||
"Rev": "453249f01cfeb54c3d549ddb75ff152ca243f9d8"
|
||||
},
|
||||
{
|
||||
"ImportPath": "golang.org/x/crypto/ssh/agent",
|
||||
"Rev": "453249f01cfeb54c3d549ddb75ff152ca243f9d8"
|
||||
},
|
||||
{
|
||||
"ImportPath": "golang.org/x/crypto/ssh/terminal",
|
||||
"Rev": "f6b343c37ca80bfa8ea539da67a0b621f84fab1d"
|
||||
"Rev": "453249f01cfeb54c3d549ddb75ff152ca243f9d8"
|
||||
},
|
||||
{
|
||||
"ImportPath": "golang.org/x/net/context",
|
||||
"Rev": "8fd7f25955530b92e73e9e1932a41b522b22ccd9"
|
||||
"Rev": "b4690f45fa1cafc47b1c280c2e75116efe40cc13"
|
||||
},
|
||||
{
|
||||
"ImportPath": "golang.org/x/net/context/ctxhttp",
|
||||
"Rev": "8fd7f25955530b92e73e9e1932a41b522b22ccd9"
|
||||
"Rev": "b4690f45fa1cafc47b1c280c2e75116efe40cc13"
|
||||
},
|
||||
{
|
||||
"ImportPath": "golang.org/x/net/http2",
|
||||
"Rev": "8fd7f25955530b92e73e9e1932a41b522b22ccd9"
|
||||
"Rev": "b4690f45fa1cafc47b1c280c2e75116efe40cc13"
|
||||
},
|
||||
{
|
||||
"ImportPath": "golang.org/x/net/http2/hpack",
|
||||
"Rev": "8fd7f25955530b92e73e9e1932a41b522b22ccd9"
|
||||
"Rev": "b4690f45fa1cafc47b1c280c2e75116efe40cc13"
|
||||
},
|
||||
{
|
||||
"ImportPath": "golang.org/x/net/idna",
|
||||
"Rev": "8fd7f25955530b92e73e9e1932a41b522b22ccd9"
|
||||
"Rev": "b4690f45fa1cafc47b1c280c2e75116efe40cc13"
|
||||
},
|
||||
{
|
||||
"ImportPath": "golang.org/x/net/internal/timeseries",
|
||||
"Rev": "8fd7f25955530b92e73e9e1932a41b522b22ccd9"
|
||||
"Rev": "b4690f45fa1cafc47b1c280c2e75116efe40cc13"
|
||||
},
|
||||
{
|
||||
"ImportPath": "golang.org/x/net/lex/httplex",
|
||||
"Rev": "8fd7f25955530b92e73e9e1932a41b522b22ccd9"
|
||||
"Rev": "b4690f45fa1cafc47b1c280c2e75116efe40cc13"
|
||||
},
|
||||
{
|
||||
"ImportPath": "golang.org/x/net/trace",
|
||||
"Rev": "8fd7f25955530b92e73e9e1932a41b522b22ccd9"
|
||||
"Rev": "b4690f45fa1cafc47b1c280c2e75116efe40cc13"
|
||||
},
|
||||
{
|
||||
"ImportPath": "golang.org/x/oauth2",
|
||||
"Rev": "314dd2c0bf3ebd592ec0d20847d27e79d0dbe8dd"
|
||||
"Rev": "b9780ec78894ab900c062d58ee3076cd9b2a4501"
|
||||
},
|
||||
{
|
||||
"ImportPath": "golang.org/x/oauth2/google",
|
||||
"Rev": "314dd2c0bf3ebd592ec0d20847d27e79d0dbe8dd"
|
||||
"Rev": "b9780ec78894ab900c062d58ee3076cd9b2a4501"
|
||||
},
|
||||
{
|
||||
"ImportPath": "golang.org/x/oauth2/internal",
|
||||
"Rev": "314dd2c0bf3ebd592ec0d20847d27e79d0dbe8dd"
|
||||
"Rev": "b9780ec78894ab900c062d58ee3076cd9b2a4501"
|
||||
},
|
||||
{
|
||||
"ImportPath": "golang.org/x/oauth2/jws",
|
||||
"Rev": "314dd2c0bf3ebd592ec0d20847d27e79d0dbe8dd"
|
||||
"Rev": "b9780ec78894ab900c062d58ee3076cd9b2a4501"
|
||||
},
|
||||
{
|
||||
"ImportPath": "golang.org/x/oauth2/jwt",
|
||||
"Rev": "314dd2c0bf3ebd592ec0d20847d27e79d0dbe8dd"
|
||||
"Rev": "b9780ec78894ab900c062d58ee3076cd9b2a4501"
|
||||
},
|
||||
{
|
||||
"ImportPath": "golang.org/x/sys/unix",
|
||||
"Rev": "d75a52659825e75fff6158388dddc6a5b04f9ba5"
|
||||
"Rev": "075e574b89e4c2d22f2286a7e2b919519c6f3547"
|
||||
},
|
||||
{
|
||||
"ImportPath": "golang.org/x/text/transform",
|
||||
"Rev": "fd889fe3a20f4878f5f47672fd3ca5b86db005e2"
|
||||
"Rev": "85c29909967d7f171f821e7a42e7b7af76fb9598"
|
||||
},
|
||||
{
|
||||
"ImportPath": "golang.org/x/text/unicode/norm",
|
||||
"Rev": "fd889fe3a20f4878f5f47672fd3ca5b86db005e2"
|
||||
"Rev": "85c29909967d7f171f821e7a42e7b7af76fb9598"
|
||||
},
|
||||
{
|
||||
"ImportPath": "google.golang.org/api/drive/v2",
|
||||
"Rev": "55146ba61254fdb1c26d65ff3c04bc1611ad73fb"
|
||||
"Rev": "bc20c61134e1d25265dd60049f5735381e79b631"
|
||||
},
|
||||
{
|
||||
"ImportPath": "google.golang.org/api/gensupport",
|
||||
"Rev": "55146ba61254fdb1c26d65ff3c04bc1611ad73fb"
|
||||
"Rev": "bc20c61134e1d25265dd60049f5735381e79b631"
|
||||
},
|
||||
{
|
||||
"ImportPath": "google.golang.org/api/googleapi",
|
||||
"Rev": "55146ba61254fdb1c26d65ff3c04bc1611ad73fb"
|
||||
"Rev": "bc20c61134e1d25265dd60049f5735381e79b631"
|
||||
},
|
||||
{
|
||||
"ImportPath": "google.golang.org/api/googleapi/internal/uritemplates",
|
||||
"Rev": "55146ba61254fdb1c26d65ff3c04bc1611ad73fb"
|
||||
"Rev": "bc20c61134e1d25265dd60049f5735381e79b631"
|
||||
},
|
||||
{
|
||||
"ImportPath": "google.golang.org/api/storage/v1",
|
||||
"Rev": "55146ba61254fdb1c26d65ff3c04bc1611ad73fb"
|
||||
"Rev": "bc20c61134e1d25265dd60049f5735381e79b631"
|
||||
},
|
||||
{
|
||||
"ImportPath": "google.golang.org/appengine",
|
||||
"Rev": "c98f627282072b1230c8795abe98e2914c8a1de9"
|
||||
"Comment": "v1.0.0-28-g2e4a801",
|
||||
"Rev": "2e4a801b39fc199db615bfca7d0b9f8cd9580599"
|
||||
},
|
||||
{
|
||||
"ImportPath": "google.golang.org/appengine/internal",
|
||||
"Rev": "c98f627282072b1230c8795abe98e2914c8a1de9"
|
||||
"Comment": "v1.0.0-28-g2e4a801",
|
||||
"Rev": "2e4a801b39fc199db615bfca7d0b9f8cd9580599"
|
||||
},
|
||||
{
|
||||
"ImportPath": "google.golang.org/appengine/internal/app_identity",
|
||||
"Rev": "c98f627282072b1230c8795abe98e2914c8a1de9"
|
||||
"Comment": "v1.0.0-28-g2e4a801",
|
||||
"Rev": "2e4a801b39fc199db615bfca7d0b9f8cd9580599"
|
||||
},
|
||||
{
|
||||
"ImportPath": "google.golang.org/appengine/internal/base",
|
||||
"Rev": "c98f627282072b1230c8795abe98e2914c8a1de9"
|
||||
"Comment": "v1.0.0-28-g2e4a801",
|
||||
"Rev": "2e4a801b39fc199db615bfca7d0b9f8cd9580599"
|
||||
},
|
||||
{
|
||||
"ImportPath": "google.golang.org/appengine/internal/datastore",
|
||||
"Rev": "c98f627282072b1230c8795abe98e2914c8a1de9"
|
||||
"Comment": "v1.0.0-28-g2e4a801",
|
||||
"Rev": "2e4a801b39fc199db615bfca7d0b9f8cd9580599"
|
||||
},
|
||||
{
|
||||
"ImportPath": "google.golang.org/appengine/internal/log",
|
||||
"Rev": "c98f627282072b1230c8795abe98e2914c8a1de9"
|
||||
"Comment": "v1.0.0-28-g2e4a801",
|
||||
"Rev": "2e4a801b39fc199db615bfca7d0b9f8cd9580599"
|
||||
},
|
||||
{
|
||||
"ImportPath": "google.golang.org/appengine/internal/modules",
|
||||
"Rev": "c98f627282072b1230c8795abe98e2914c8a1de9"
|
||||
"Comment": "v1.0.0-28-g2e4a801",
|
||||
"Rev": "2e4a801b39fc199db615bfca7d0b9f8cd9580599"
|
||||
},
|
||||
{
|
||||
"ImportPath": "google.golang.org/appengine/internal/remote_api",
|
||||
"Rev": "c98f627282072b1230c8795abe98e2914c8a1de9"
|
||||
"Comment": "v1.0.0-28-g2e4a801",
|
||||
"Rev": "2e4a801b39fc199db615bfca7d0b9f8cd9580599"
|
||||
},
|
||||
{
|
||||
"ImportPath": "google.golang.org/grpc",
|
||||
"Comment": "v1.0.5-9-gc810507",
|
||||
"Rev": "c8105071640ef29fce843ed96983e864bb18eb0e"
|
||||
"Comment": "v1.0.5-52-gd0c32ee",
|
||||
"Rev": "d0c32ee6a441117d49856d6120ca9552af413ee0"
|
||||
},
|
||||
{
|
||||
"ImportPath": "google.golang.org/grpc/codes",
|
||||
"Comment": "v1.0.5-9-gc810507",
|
||||
"Rev": "c8105071640ef29fce843ed96983e864bb18eb0e"
|
||||
"Comment": "v1.0.5-52-gd0c32ee",
|
||||
"Rev": "d0c32ee6a441117d49856d6120ca9552af413ee0"
|
||||
},
|
||||
{
|
||||
"ImportPath": "google.golang.org/grpc/credentials",
|
||||
"Comment": "v1.0.5-9-gc810507",
|
||||
"Rev": "c8105071640ef29fce843ed96983e864bb18eb0e"
|
||||
"Comment": "v1.0.5-52-gd0c32ee",
|
||||
"Rev": "d0c32ee6a441117d49856d6120ca9552af413ee0"
|
||||
},
|
||||
{
|
||||
"ImportPath": "google.golang.org/grpc/grpclog",
|
||||
"Comment": "v1.0.5-9-gc810507",
|
||||
"Rev": "c8105071640ef29fce843ed96983e864bb18eb0e"
|
||||
"Comment": "v1.0.5-52-gd0c32ee",
|
||||
"Rev": "d0c32ee6a441117d49856d6120ca9552af413ee0"
|
||||
},
|
||||
{
|
||||
"ImportPath": "google.golang.org/grpc/internal",
|
||||
"Comment": "v1.0.5-9-gc810507",
|
||||
"Rev": "c8105071640ef29fce843ed96983e864bb18eb0e"
|
||||
"Comment": "v1.0.5-52-gd0c32ee",
|
||||
"Rev": "d0c32ee6a441117d49856d6120ca9552af413ee0"
|
||||
},
|
||||
{
|
||||
"ImportPath": "google.golang.org/grpc/metadata",
|
||||
"Comment": "v1.0.5-9-gc810507",
|
||||
"Rev": "c8105071640ef29fce843ed96983e864bb18eb0e"
|
||||
"Comment": "v1.0.5-52-gd0c32ee",
|
||||
"Rev": "d0c32ee6a441117d49856d6120ca9552af413ee0"
|
||||
},
|
||||
{
|
||||
"ImportPath": "google.golang.org/grpc/naming",
|
||||
"Comment": "v1.0.5-9-gc810507",
|
||||
"Rev": "c8105071640ef29fce843ed96983e864bb18eb0e"
|
||||
"Comment": "v1.0.5-52-gd0c32ee",
|
||||
"Rev": "d0c32ee6a441117d49856d6120ca9552af413ee0"
|
||||
},
|
||||
{
|
||||
"ImportPath": "google.golang.org/grpc/peer",
|
||||
"Comment": "v1.0.5-9-gc810507",
|
||||
"Rev": "c8105071640ef29fce843ed96983e864bb18eb0e"
|
||||
"Comment": "v1.0.5-52-gd0c32ee",
|
||||
"Rev": "d0c32ee6a441117d49856d6120ca9552af413ee0"
|
||||
},
|
||||
{
|
||||
"ImportPath": "google.golang.org/grpc/stats",
|
||||
"Comment": "v1.0.5-9-gc810507",
|
||||
"Rev": "c8105071640ef29fce843ed96983e864bb18eb0e"
|
||||
"Comment": "v1.0.5-52-gd0c32ee",
|
||||
"Rev": "d0c32ee6a441117d49856d6120ca9552af413ee0"
|
||||
},
|
||||
{
|
||||
"ImportPath": "google.golang.org/grpc/tap",
|
||||
"Comment": "v1.0.5-9-gc810507",
|
||||
"Rev": "c8105071640ef29fce843ed96983e864bb18eb0e"
|
||||
"Comment": "v1.0.5-52-gd0c32ee",
|
||||
"Rev": "d0c32ee6a441117d49856d6120ca9552af413ee0"
|
||||
},
|
||||
{
|
||||
"ImportPath": "google.golang.org/grpc/transport",
|
||||
"Comment": "v1.0.5-9-gc810507",
|
||||
"Rev": "c8105071640ef29fce843ed96983e864bb18eb0e"
|
||||
"Comment": "v1.0.5-52-gd0c32ee",
|
||||
"Rev": "d0c32ee6a441117d49856d6120ca9552af413ee0"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/kr/fs",
|
||||
"Rev": "2788f0dbd16903de03cb8186e5c7d97b69ad387b"
|
||||
"ImportPath": "gopkg.in/yaml.v2",
|
||||
"Rev": "a3f3340b5840cee44f372bddb5880fcbc419b46a"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
3
vendor/cloud.google.com/go/CONTRIBUTORS
generated
vendored
3
vendor/cloud.google.com/go/CONTRIBUTORS
generated
vendored
@ -11,6 +11,7 @@
|
||||
|
||||
# Keep the list alphabetically sorted.
|
||||
|
||||
Alexis Hunt <lexer@google.com>
|
||||
Andreas Litt <andreas.litt@gmail.com>
|
||||
Andrew Gerrand <adg@golang.org>
|
||||
Brad Fitzpatrick <bradfitz@golang.org>
|
||||
@ -24,11 +25,13 @@ Ingo Oeser <nightlyone@googlemail.com>
|
||||
Johan Euphrosine <proppy@google.com>
|
||||
Jonathan Amsterdam <jba@google.com>
|
||||
Luna Duclos <luna.duclos@palmstonegames.com>
|
||||
Magnus Hiie <magnus.hiie@gmail.com>
|
||||
Michael McGreevy <mcgreevy@golang.org>
|
||||
Omar Jarjur <ojarjur@google.com>
|
||||
Paweł Knap <pawelknap88@gmail.com>
|
||||
Péter Szilágyi <peterke@gmail.com>
|
||||
Sarah Adams <shadams@google.com>
|
||||
Thanatat Tamtan <acoshift@gmail.com>
|
||||
Toby Burress <kurin@google.com>
|
||||
Tuo Shan <shantuo@google.com>
|
||||
Tyler Treat <ttreat31@gmail.com>
|
||||
|
7
vendor/github.com/aws/aws-sdk-go/aws/client/client.go
generated
vendored
7
vendor/github.com/aws/aws-sdk-go/aws/client/client.go
generated
vendored
@ -24,6 +24,13 @@ type ConfigProvider interface {
|
||||
ClientConfig(serviceName string, cfgs ...*aws.Config) Config
|
||||
}
|
||||
|
||||
// ConfigNoResolveEndpointProvider same as ConfigProvider except it will not
|
||||
// resolve the endpoint automatically. The service client's endpoint must be
|
||||
// provided via the aws.Config.Endpoint field.
|
||||
type ConfigNoResolveEndpointProvider interface {
|
||||
ClientConfigNoResolveEndpoint(cfgs ...*aws.Config) Config
|
||||
}
|
||||
|
||||
// A Client implements the base client request and response handling
|
||||
// used by all service clients.
|
||||
type Client struct {
|
||||
|
58
vendor/github.com/aws/aws-sdk-go/aws/endpoints/defaults.go
generated
vendored
58
vendor/github.com/aws/aws-sdk-go/aws/endpoints/defaults.go
generated
vendored
@ -46,10 +46,11 @@ const (
|
||||
AcmServiceID = "acm" // Acm.
|
||||
ApigatewayServiceID = "apigateway" // Apigateway.
|
||||
ApplicationAutoscalingServiceID = "application-autoscaling" // ApplicationAutoscaling.
|
||||
AppstreamServiceID = "appstream" // Appstream.
|
||||
Appstream2ServiceID = "appstream2" // Appstream2.
|
||||
AutoscalingServiceID = "autoscaling" // Autoscaling.
|
||||
BatchServiceID = "batch" // Batch.
|
||||
BudgetsServiceID = "budgets" // Budgets.
|
||||
ClouddirectoryServiceID = "clouddirectory" // Clouddirectory.
|
||||
CloudformationServiceID = "cloudformation" // Cloudformation.
|
||||
CloudfrontServiceID = "cloudfront" // Cloudfront.
|
||||
CloudhsmServiceID = "cloudhsm" // Cloudhsm.
|
||||
@ -63,6 +64,7 @@ const (
|
||||
CognitoIdpServiceID = "cognito-idp" // CognitoIdp.
|
||||
CognitoSyncServiceID = "cognito-sync" // CognitoSync.
|
||||
ConfigServiceID = "config" // Config.
|
||||
CurServiceID = "cur" // Cur.
|
||||
DatapipelineServiceID = "datapipeline" // Datapipeline.
|
||||
DevicefarmServiceID = "devicefarm" // Devicefarm.
|
||||
DirectconnectServiceID = "directconnect" // Directconnect.
|
||||
@ -111,6 +113,7 @@ const (
|
||||
RekognitionServiceID = "rekognition" // Rekognition.
|
||||
Route53ServiceID = "route53" // Route53.
|
||||
Route53domainsServiceID = "route53domains" // Route53domains.
|
||||
RuntimeLexServiceID = "runtime.lex" // RuntimeLex.
|
||||
S3ServiceID = "s3" // S3.
|
||||
SdbServiceID = "sdb" // Sdb.
|
||||
ServicecatalogServiceID = "servicecatalog" // Servicecatalog.
|
||||
@ -247,6 +250,7 @@ var awsPartition = partition{
|
||||
"ap-southeast-2": endpoint{},
|
||||
"eu-central-1": endpoint{},
|
||||
"eu-west-1": endpoint{},
|
||||
"eu-west-2": endpoint{},
|
||||
"us-east-1": endpoint{},
|
||||
"us-east-2": endpoint{},
|
||||
"us-west-1": endpoint{},
|
||||
@ -278,13 +282,6 @@ var awsPartition = partition{
|
||||
"us-west-2": endpoint{},
|
||||
},
|
||||
},
|
||||
"appstream": service{
|
||||
|
||||
Endpoints: endpoints{
|
||||
"ap-northeast-1": endpoint{},
|
||||
"us-east-1": endpoint{},
|
||||
},
|
||||
},
|
||||
"appstream2": service{
|
||||
Defaults: endpoint{
|
||||
Protocols: []string{"https"},
|
||||
@ -320,6 +317,12 @@ var awsPartition = partition{
|
||||
"us-west-2": endpoint{},
|
||||
},
|
||||
},
|
||||
"batch": service{
|
||||
|
||||
Endpoints: endpoints{
|
||||
"us-east-1": endpoint{},
|
||||
},
|
||||
},
|
||||
"budgets": service{
|
||||
PartitionEndpoint: "aws-global",
|
||||
IsRegionalized: boxedFalse,
|
||||
@ -333,6 +336,17 @@ var awsPartition = partition{
|
||||
},
|
||||
},
|
||||
},
|
||||
"clouddirectory": service{
|
||||
|
||||
Endpoints: endpoints{
|
||||
"ap-southeast-1": endpoint{},
|
||||
"ap-southeast-2": endpoint{},
|
||||
"eu-west-1": endpoint{},
|
||||
"us-east-1": endpoint{},
|
||||
"us-east-2": endpoint{},
|
||||
"us-west-2": endpoint{},
|
||||
},
|
||||
},
|
||||
"cloudformation": service{
|
||||
|
||||
Endpoints: endpoints{
|
||||
@ -420,6 +434,7 @@ var awsPartition = partition{
|
||||
Endpoints: endpoints{
|
||||
"eu-west-1": endpoint{},
|
||||
"us-east-1": endpoint{},
|
||||
"us-east-2": endpoint{},
|
||||
"us-west-2": endpoint{},
|
||||
},
|
||||
},
|
||||
@ -523,6 +538,12 @@ var awsPartition = partition{
|
||||
"us-west-2": endpoint{},
|
||||
},
|
||||
},
|
||||
"cur": service{
|
||||
|
||||
Endpoints: endpoints{
|
||||
"us-east-1": endpoint{},
|
||||
},
|
||||
},
|
||||
"datapipeline": service{
|
||||
|
||||
Endpoints: endpoints{
|
||||
@ -829,6 +850,7 @@ var awsPartition = partition{
|
||||
"ap-southeast-2": endpoint{},
|
||||
"eu-central-1": endpoint{},
|
||||
"eu-west-1": endpoint{},
|
||||
"eu-west-2": endpoint{},
|
||||
"sa-east-1": endpoint{},
|
||||
"us-east-1": endpoint{},
|
||||
"us-east-2": endpoint{},
|
||||
@ -996,6 +1018,7 @@ var awsPartition = partition{
|
||||
"ap-southeast-2": endpoint{},
|
||||
"eu-central-1": endpoint{},
|
||||
"eu-west-1": endpoint{},
|
||||
"eu-west-2": endpoint{},
|
||||
"us-east-1": endpoint{},
|
||||
"us-east-2": endpoint{},
|
||||
"us-west-1": endpoint{},
|
||||
@ -1041,13 +1064,20 @@ var awsPartition = partition{
|
||||
},
|
||||
},
|
||||
"metering.marketplace": service{
|
||||
|
||||
Defaults: endpoint{
|
||||
CredentialScope: credentialScope{
|
||||
Service: "aws-marketplace",
|
||||
},
|
||||
},
|
||||
Endpoints: endpoints{
|
||||
"ap-northeast-1": endpoint{},
|
||||
"ap-northeast-2": endpoint{},
|
||||
"ap-south-1": endpoint{},
|
||||
"ap-southeast-1": endpoint{},
|
||||
"ap-southeast-2": endpoint{},
|
||||
"eu-central-1": endpoint{},
|
||||
"eu-west-1": endpoint{},
|
||||
"sa-east-1": endpoint{},
|
||||
"us-east-1": endpoint{},
|
||||
"us-west-1": endpoint{},
|
||||
"us-west-2": endpoint{},
|
||||
@ -1192,6 +1222,16 @@ var awsPartition = partition{
|
||||
"us-east-1": endpoint{},
|
||||
},
|
||||
},
|
||||
"runtime.lex": service{
|
||||
Defaults: endpoint{
|
||||
CredentialScope: credentialScope{
|
||||
Service: "lex",
|
||||
},
|
||||
},
|
||||
Endpoints: endpoints{
|
||||
"us-east-1": endpoint{},
|
||||
},
|
||||
},
|
||||
"s3": service{
|
||||
PartitionEndpoint: "us-east-1",
|
||||
IsRegionalized: boxedTrue,
|
||||
|
34
vendor/github.com/aws/aws-sdk-go/aws/endpoints/endpoints.go
generated
vendored
34
vendor/github.com/aws/aws-sdk-go/aws/endpoints/endpoints.go
generated
vendored
@ -27,6 +27,25 @@ type Options struct {
|
||||
// error will be returned. This option will prevent returning endpoints
|
||||
// that look valid, but may not resolve to any real endpoint.
|
||||
StrictMatching bool
|
||||
|
||||
// Enables resolving a service endpoint based on the region provided if the
|
||||
// service does not exist. The service endpoint ID will be used as the service
|
||||
// domain name prefix. By default the endpoint resolver requires the service
|
||||
// to be known when resolving endpoints.
|
||||
//
|
||||
// If resolving an endpoint on the partition list the provided region will
|
||||
// be used to determine which partition's domain name pattern to the service
|
||||
// endpoint ID with. If both the service and region are unkonwn and resolving
|
||||
// the endpoint on partition list an UnknownEndpointError error will be returned.
|
||||
//
|
||||
// If resolving and endpoint on a partition specific resolver that partition's
|
||||
// domain name pattern will be used with the service endpoint ID. If both
|
||||
// region and service do not exist when resolving an endpoint on a specific
|
||||
// partition the partition's domain pattern will be used to combine the
|
||||
// endpoint and region together.
|
||||
//
|
||||
// This option is ignored if StrictMatching is enabled.
|
||||
ResolveUnknownService bool
|
||||
}
|
||||
|
||||
// Set combines all of the option functions together.
|
||||
@ -54,6 +73,12 @@ func StrictMatchingOption(o *Options) {
|
||||
o.StrictMatching = true
|
||||
}
|
||||
|
||||
// ResolveUnknownServiceOption sets the ResolveUnknownService option. Can be used
|
||||
// as a functional option when resolving endpoints.
|
||||
func ResolveUnknownServiceOption(o *Options) {
|
||||
o.ResolveUnknownService = true
|
||||
}
|
||||
|
||||
// A Resolver provides the interface for functionality to resolve endpoints.
|
||||
// The build in Partition and DefaultResolver return value satisfy this interface.
|
||||
type Resolver interface {
|
||||
@ -114,15 +139,18 @@ func (p *Partition) ID() string { return p.id }
|
||||
//
|
||||
// If the service cannot be found in the metadata the UnknownServiceError
|
||||
// error will be returned. This validation will occur regardless if
|
||||
// StrictMatching is enabled.
|
||||
// StrictMatching is enabled. To enable resolving unknown services set the
|
||||
// "ResolveUnknownService" option to true. When StrictMatching is disabled
|
||||
// this option allows the partition resolver to resolve a endpoint based on
|
||||
// the service endpoint ID provided.
|
||||
//
|
||||
// When resolving endpoints you can choose to enable StrictMatching. This will
|
||||
// require the provided service and region to be known by the partition.
|
||||
// If the endpoint cannot be strictly resolved an error will be returned. This
|
||||
// mode is useful to ensure the endpoint resolved is valid. Without
|
||||
// StrictMatching enabled the enpoint returned my look valid but may not work.
|
||||
// StrictMatching enabled the endpoint returned my look valid but may not work.
|
||||
// StrictMatching requires the SDK to be updated if you want to take advantage
|
||||
// of new regions and services expantions.
|
||||
// of new regions and services expansions.
|
||||
//
|
||||
// Errors that can be returned.
|
||||
// * UnknownServiceError
|
||||
|
4
vendor/github.com/aws/aws-sdk-go/aws/endpoints/v3model.go
generated
vendored
4
vendor/github.com/aws/aws-sdk-go/aws/endpoints/v3model.go
generated
vendored
@ -79,7 +79,9 @@ func (p partition) EndpointFor(service, region string, opts ...func(*Options)) (
|
||||
opt.Set(opts...)
|
||||
|
||||
s, hasService := p.Services[service]
|
||||
if !hasService {
|
||||
if !(hasService || opt.ResolveUnknownService) {
|
||||
// Only return error if the resolver will not fallback to creating
|
||||
// endpoint based on service endpoint ID passed in.
|
||||
return resolved, NewUnknownServiceError(p.ID, service, serviceList(p.Services))
|
||||
}
|
||||
|
||||
|
34
vendor/github.com/aws/aws-sdk-go/aws/session/session.go
generated
vendored
34
vendor/github.com/aws/aws-sdk-go/aws/session/session.go
generated
vendored
@ -40,7 +40,7 @@ type Session struct {
|
||||
//
|
||||
// If the AWS_SDK_LOAD_CONFIG environment variable is set to a truthy value
|
||||
// the shared config file (~/.aws/config) will also be loaded, in addition to
|
||||
// the shared credentials file (~/.aws/config). Values set in both the
|
||||
// the shared credentials file (~/.aws/credentials). Values set in both the
|
||||
// shared config, and shared credentials will be taken from the shared
|
||||
// credentials file.
|
||||
//
|
||||
@ -83,7 +83,7 @@ func New(cfgs ...*aws.Config) *Session {
|
||||
//
|
||||
// If the AWS_SDK_LOAD_CONFIG environment variable is set to a truthy value
|
||||
// the shared config file (~/.aws/config) will also be loaded in addition to
|
||||
// the shared credentials file (~/.aws/config). Values set in both the
|
||||
// the shared credentials file (~/.aws/credentials). Values set in both the
|
||||
// shared config, and shared credentials will be taken from the shared
|
||||
// credentials file. Enabling the Shared Config will also allow the Session
|
||||
// to be built with retrieving credentials with AssumeRole set in the config.
|
||||
@ -155,7 +155,7 @@ type Options struct {
|
||||
//
|
||||
// If the AWS_SDK_LOAD_CONFIG environment variable is set to a truthy value
|
||||
// the shared config file (~/.aws/config) will also be loaded in addition to
|
||||
// the shared credentials file (~/.aws/config). Values set in both the
|
||||
// the shared credentials file (~/.aws/credentials). Values set in both the
|
||||
// shared config, and shared credentials will be taken from the shared
|
||||
// credentials file. Enabling the Shared Config will also allow the Session
|
||||
// to be built with retrieving credentials with AssumeRole set in the config.
|
||||
@ -404,6 +404,10 @@ func (s *Session) clientConfigWithErr(serviceName string, cfgs ...*aws.Config) (
|
||||
func(opt *endpoints.Options) {
|
||||
opt.DisableSSL = aws.BoolValue(s.Config.DisableSSL)
|
||||
opt.UseDualStack = aws.BoolValue(s.Config.UseDualStack)
|
||||
|
||||
// Support the condition where the service is modeled but its
|
||||
// endpoint metadata is not available.
|
||||
opt.ResolveUnknownService = true
|
||||
},
|
||||
)
|
||||
}
|
||||
@ -416,3 +420,27 @@ func (s *Session) clientConfigWithErr(serviceName string, cfgs ...*aws.Config) (
|
||||
SigningName: resolved.SigningName,
|
||||
}, err
|
||||
}
|
||||
|
||||
// ClientConfigNoResolveEndpoint is the same as ClientConfig with the exception
|
||||
// that the EndpointResolver will not be used to resolve the endpoint. The only
|
||||
// endpoint set must come from the aws.Config.Endpoint field.
|
||||
func (s *Session) ClientConfigNoResolveEndpoint(cfgs ...*aws.Config) client.Config {
|
||||
s = s.Copy(cfgs...)
|
||||
|
||||
var resolved endpoints.ResolvedEndpoint
|
||||
|
||||
region := aws.StringValue(s.Config.Region)
|
||||
|
||||
if ep := aws.StringValue(s.Config.Endpoint); len(ep) > 0 {
|
||||
resolved.URL = endpoints.AddScheme(ep, aws.BoolValue(s.Config.DisableSSL))
|
||||
resolved.SigningRegion = region
|
||||
}
|
||||
|
||||
return client.Config{
|
||||
Config: s.Config,
|
||||
Handlers: s.Handlers,
|
||||
Endpoint: resolved.URL,
|
||||
SigningRegion: resolved.SigningRegion,
|
||||
SigningName: resolved.SigningName,
|
||||
}
|
||||
}
|
||||
|
2
vendor/github.com/aws/aws-sdk-go/aws/types.go
generated
vendored
2
vendor/github.com/aws/aws-sdk-go/aws/types.go
generated
vendored
@ -114,5 +114,5 @@ func (b *WriteAtBuffer) WriteAt(p []byte, pos int64) (n int, err error) {
|
||||
func (b *WriteAtBuffer) Bytes() []byte {
|
||||
b.m.Lock()
|
||||
defer b.m.Unlock()
|
||||
return b.buf[:len(b.buf):len(b.buf)]
|
||||
return b.buf
|
||||
}
|
||||
|
2
vendor/github.com/aws/aws-sdk-go/aws/version.go
generated
vendored
2
vendor/github.com/aws/aws-sdk-go/aws/version.go
generated
vendored
@ -5,4 +5,4 @@ package aws
|
||||
const SDKName = "aws-sdk-go"
|
||||
|
||||
// SDKVersion is the version of this SDK
|
||||
const SDKVersion = "1.6.9"
|
||||
const SDKVersion = "1.6.24"
|
||||
|
25
vendor/github.com/aws/aws-sdk-go/service/s3/api.go
generated
vendored
25
vendor/github.com/aws/aws-sdk-go/service/s3/api.go
generated
vendored
@ -73,7 +73,7 @@ func (c *S3) AbortMultipartUploadRequest(input *AbortMultipartUploadInput) (req
|
||||
// API operation AbortMultipartUpload for usage and error information.
|
||||
//
|
||||
// Returned Error Codes:
|
||||
// * NoSuchUpload
|
||||
// * ErrCodeNoSuchUpload "NoSuchUpload"
|
||||
// The specified multipart upload does not exist.
|
||||
//
|
||||
// Please also see https://docs.aws.amazon.com/goto/WebAPI/s3-2006-03-01/AbortMultipartUpload
|
||||
@ -198,7 +198,7 @@ func (c *S3) CopyObjectRequest(input *CopyObjectInput) (req *request.Request, ou
|
||||
// API operation CopyObject for usage and error information.
|
||||
//
|
||||
// Returned Error Codes:
|
||||
// * ObjectNotInActiveTierError
|
||||
// * ErrCodeObjectNotInActiveTierError "ObjectNotInActiveTierError"
|
||||
// The source object of the COPY operation is not in the active tier and is
|
||||
// only stored in Amazon Glacier.
|
||||
//
|
||||
@ -264,12 +264,11 @@ func (c *S3) CreateBucketRequest(input *CreateBucketInput) (req *request.Request
|
||||
// API operation CreateBucket for usage and error information.
|
||||
//
|
||||
// Returned Error Codes:
|
||||
// * BucketAlreadyExists
|
||||
// * ErrCodeBucketAlreadyExists "BucketAlreadyExists"
|
||||
// The requested bucket name is not available. The bucket namespace is shared
|
||||
// by all users of the system. Please select a different name and try again.
|
||||
//
|
||||
// * BucketAlreadyOwnedByYou
|
||||
|
||||
// * ErrCodeBucketAlreadyOwnedByYou "BucketAlreadyOwnedByYou"
|
||||
//
|
||||
// Please also see https://docs.aws.amazon.com/goto/WebAPI/s3-2006-03-01/CreateBucket
|
||||
func (c *S3) CreateBucket(input *CreateBucketInput) (*CreateBucketOutput, error) {
|
||||
@ -2296,7 +2295,7 @@ func (c *S3) GetObjectRequest(input *GetObjectInput) (req *request.Request, outp
|
||||
// API operation GetObject for usage and error information.
|
||||
//
|
||||
// Returned Error Codes:
|
||||
// * NoSuchKey
|
||||
// * ErrCodeNoSuchKey "NoSuchKey"
|
||||
// The specified key does not exist.
|
||||
//
|
||||
// Please also see https://docs.aws.amazon.com/goto/WebAPI/s3-2006-03-01/GetObject
|
||||
@ -2361,7 +2360,7 @@ func (c *S3) GetObjectAclRequest(input *GetObjectAclInput) (req *request.Request
|
||||
// API operation GetObjectAcl for usage and error information.
|
||||
//
|
||||
// Returned Error Codes:
|
||||
// * NoSuchKey
|
||||
// * ErrCodeNoSuchKey "NoSuchKey"
|
||||
// The specified key does not exist.
|
||||
//
|
||||
// Please also see https://docs.aws.amazon.com/goto/WebAPI/s3-2006-03-01/GetObjectAcl
|
||||
@ -2549,7 +2548,7 @@ func (c *S3) HeadBucketRequest(input *HeadBucketInput) (req *request.Request, ou
|
||||
// API operation HeadBucket for usage and error information.
|
||||
//
|
||||
// Returned Error Codes:
|
||||
// * NoSuchBucket
|
||||
// * ErrCodeNoSuchBucket "NoSuchBucket"
|
||||
// The specified bucket does not exist.
|
||||
//
|
||||
// Please also see https://docs.aws.amazon.com/goto/WebAPI/s3-2006-03-01/HeadBucket
|
||||
@ -2616,7 +2615,7 @@ func (c *S3) HeadObjectRequest(input *HeadObjectInput) (req *request.Request, ou
|
||||
// API operation HeadObject for usage and error information.
|
||||
//
|
||||
// Returned Error Codes:
|
||||
// * NoSuchKey
|
||||
// * ErrCodeNoSuchKey "NoSuchKey"
|
||||
// The specified key does not exist.
|
||||
//
|
||||
// Please also see https://docs.aws.amazon.com/goto/WebAPI/s3-2006-03-01/HeadObject
|
||||
@ -3111,7 +3110,7 @@ func (c *S3) ListObjectsRequest(input *ListObjectsInput) (req *request.Request,
|
||||
// API operation ListObjects for usage and error information.
|
||||
//
|
||||
// Returned Error Codes:
|
||||
// * NoSuchBucket
|
||||
// * ErrCodeNoSuchBucket "NoSuchBucket"
|
||||
// The specified bucket does not exist.
|
||||
//
|
||||
// Please also see https://docs.aws.amazon.com/goto/WebAPI/s3-2006-03-01/ListObjects
|
||||
@ -3210,7 +3209,7 @@ func (c *S3) ListObjectsV2Request(input *ListObjectsV2Input) (req *request.Reque
|
||||
// API operation ListObjectsV2 for usage and error information.
|
||||
//
|
||||
// Returned Error Codes:
|
||||
// * NoSuchBucket
|
||||
// * ErrCodeNoSuchBucket "NoSuchBucket"
|
||||
// The specified bucket does not exist.
|
||||
//
|
||||
// Please also see https://docs.aws.amazon.com/goto/WebAPI/s3-2006-03-01/ListObjectsV2
|
||||
@ -4525,7 +4524,7 @@ func (c *S3) PutObjectAclRequest(input *PutObjectAclInput) (req *request.Request
|
||||
// API operation PutObjectAcl for usage and error information.
|
||||
//
|
||||
// Returned Error Codes:
|
||||
// * NoSuchKey
|
||||
// * ErrCodeNoSuchKey "NoSuchKey"
|
||||
// The specified key does not exist.
|
||||
//
|
||||
// Please also see https://docs.aws.amazon.com/goto/WebAPI/s3-2006-03-01/PutObjectAcl
|
||||
@ -4650,7 +4649,7 @@ func (c *S3) RestoreObjectRequest(input *RestoreObjectInput) (req *request.Reque
|
||||
// API operation RestoreObject for usage and error information.
|
||||
//
|
||||
// Returned Error Codes:
|
||||
// * ObjectAlreadyInActiveTierError
|
||||
// * ErrCodeObjectAlreadyInActiveTierError "ObjectAlreadyInActiveTierError"
|
||||
// This operation is not allowed against this storage tier
|
||||
//
|
||||
// Please also see https://docs.aws.amazon.com/goto/WebAPI/s3-2006-03-01/RestoreObject
|
||||
|
48
vendor/github.com/aws/aws-sdk-go/service/s3/errors.go
generated
vendored
Normal file
48
vendor/github.com/aws/aws-sdk-go/service/s3/errors.go
generated
vendored
Normal file
@ -0,0 +1,48 @@
|
||||
// THIS FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT.
|
||||
|
||||
package s3
|
||||
|
||||
const (
|
||||
|
||||
// ErrCodeBucketAlreadyExists for service response error code
|
||||
// "BucketAlreadyExists".
|
||||
//
|
||||
// The requested bucket name is not available. The bucket namespace is shared
|
||||
// by all users of the system. Please select a different name and try again.
|
||||
ErrCodeBucketAlreadyExists = "BucketAlreadyExists"
|
||||
|
||||
// ErrCodeBucketAlreadyOwnedByYou for service response error code
|
||||
// "BucketAlreadyOwnedByYou".
|
||||
ErrCodeBucketAlreadyOwnedByYou = "BucketAlreadyOwnedByYou"
|
||||
|
||||
// ErrCodeNoSuchBucket for service response error code
|
||||
// "NoSuchBucket".
|
||||
//
|
||||
// The specified bucket does not exist.
|
||||
ErrCodeNoSuchBucket = "NoSuchBucket"
|
||||
|
||||
// ErrCodeNoSuchKey for service response error code
|
||||
// "NoSuchKey".
|
||||
//
|
||||
// The specified key does not exist.
|
||||
ErrCodeNoSuchKey = "NoSuchKey"
|
||||
|
||||
// ErrCodeNoSuchUpload for service response error code
|
||||
// "NoSuchUpload".
|
||||
//
|
||||
// The specified multipart upload does not exist.
|
||||
ErrCodeNoSuchUpload = "NoSuchUpload"
|
||||
|
||||
// ErrCodeObjectAlreadyInActiveTierError for service response error code
|
||||
// "ObjectAlreadyInActiveTierError".
|
||||
//
|
||||
// This operation is not allowed against this storage tier
|
||||
ErrCodeObjectAlreadyInActiveTierError = "ObjectAlreadyInActiveTierError"
|
||||
|
||||
// ErrCodeObjectNotInActiveTierError for service response error code
|
||||
// "ObjectNotInActiveTierError".
|
||||
//
|
||||
// The source object of the COPY operation is not in the active tier and is
|
||||
// only stored in Amazon Glacier.
|
||||
ErrCodeObjectNotInActiveTierError = "ObjectNotInActiveTierError"
|
||||
)
|
42
vendor/github.com/aws/aws-sdk-go/service/sts/api.go
generated
vendored
42
vendor/github.com/aws/aws-sdk-go/service/sts/api.go
generated
vendored
@ -153,16 +153,16 @@ func (c *STS) AssumeRoleRequest(input *AssumeRoleInput) (req *request.Request, o
|
||||
// API operation AssumeRole for usage and error information.
|
||||
//
|
||||
// Returned Error Codes:
|
||||
// * MalformedPolicyDocument
|
||||
// * ErrCodeMalformedPolicyDocumentException "MalformedPolicyDocument"
|
||||
// The request was rejected because the policy document was malformed. The error
|
||||
// message describes the specific error.
|
||||
//
|
||||
// * PackedPolicyTooLarge
|
||||
// * ErrCodePackedPolicyTooLargeException "PackedPolicyTooLarge"
|
||||
// The request was rejected because the policy document was too large. The error
|
||||
// message describes how big the policy document is, in packed form, as a percentage
|
||||
// of what the API allows.
|
||||
//
|
||||
// * RegionDisabledException
|
||||
// * ErrCodeRegionDisabledException "RegionDisabledException"
|
||||
// STS is not activated in the requested region for the account that is being
|
||||
// asked to generate credentials. The account administrator must use the IAM
|
||||
// console to activate STS in that region. For more information, see Activating
|
||||
@ -297,31 +297,31 @@ func (c *STS) AssumeRoleWithSAMLRequest(input *AssumeRoleWithSAMLInput) (req *re
|
||||
// API operation AssumeRoleWithSAML for usage and error information.
|
||||
//
|
||||
// Returned Error Codes:
|
||||
// * MalformedPolicyDocument
|
||||
// * ErrCodeMalformedPolicyDocumentException "MalformedPolicyDocument"
|
||||
// The request was rejected because the policy document was malformed. The error
|
||||
// message describes the specific error.
|
||||
//
|
||||
// * PackedPolicyTooLarge
|
||||
// * ErrCodePackedPolicyTooLargeException "PackedPolicyTooLarge"
|
||||
// The request was rejected because the policy document was too large. The error
|
||||
// message describes how big the policy document is, in packed form, as a percentage
|
||||
// of what the API allows.
|
||||
//
|
||||
// * IDPRejectedClaim
|
||||
// * ErrCodeIDPRejectedClaimException "IDPRejectedClaim"
|
||||
// The identity provider (IdP) reported that authentication failed. This might
|
||||
// be because the claim is invalid.
|
||||
//
|
||||
// If this error is returned for the AssumeRoleWithWebIdentity operation, it
|
||||
// can also mean that the claim has expired or has been explicitly revoked.
|
||||
//
|
||||
// * InvalidIdentityToken
|
||||
// * ErrCodeInvalidIdentityTokenException "InvalidIdentityToken"
|
||||
// The web identity token that was passed could not be validated by AWS. Get
|
||||
// a new identity token from the identity provider and then retry the request.
|
||||
//
|
||||
// * ExpiredTokenException
|
||||
// * ErrCodeExpiredTokenException "ExpiredTokenException"
|
||||
// The web identity token that was passed is expired or is not valid. Get a
|
||||
// new identity token from the identity provider and then retry the request.
|
||||
//
|
||||
// * RegionDisabledException
|
||||
// * ErrCodeRegionDisabledException "RegionDisabledException"
|
||||
// STS is not activated in the requested region for the account that is being
|
||||
// asked to generate credentials. The account administrator must use the IAM
|
||||
// console to activate STS in that region. For more information, see Activating
|
||||
@ -478,38 +478,38 @@ func (c *STS) AssumeRoleWithWebIdentityRequest(input *AssumeRoleWithWebIdentityI
|
||||
// API operation AssumeRoleWithWebIdentity for usage and error information.
|
||||
//
|
||||
// Returned Error Codes:
|
||||
// * MalformedPolicyDocument
|
||||
// * ErrCodeMalformedPolicyDocumentException "MalformedPolicyDocument"
|
||||
// The request was rejected because the policy document was malformed. The error
|
||||
// message describes the specific error.
|
||||
//
|
||||
// * PackedPolicyTooLarge
|
||||
// * ErrCodePackedPolicyTooLargeException "PackedPolicyTooLarge"
|
||||
// The request was rejected because the policy document was too large. The error
|
||||
// message describes how big the policy document is, in packed form, as a percentage
|
||||
// of what the API allows.
|
||||
//
|
||||
// * IDPRejectedClaim
|
||||
// * ErrCodeIDPRejectedClaimException "IDPRejectedClaim"
|
||||
// The identity provider (IdP) reported that authentication failed. This might
|
||||
// be because the claim is invalid.
|
||||
//
|
||||
// If this error is returned for the AssumeRoleWithWebIdentity operation, it
|
||||
// can also mean that the claim has expired or has been explicitly revoked.
|
||||
//
|
||||
// * IDPCommunicationError
|
||||
// * ErrCodeIDPCommunicationErrorException "IDPCommunicationError"
|
||||
// The request could not be fulfilled because the non-AWS identity provider
|
||||
// (IDP) that was asked to verify the incoming identity token could not be reached.
|
||||
// This is often a transient error caused by network conditions. Retry the request
|
||||
// a limited number of times so that you don't exceed the request rate. If the
|
||||
// error persists, the non-AWS identity provider might be down or not responding.
|
||||
//
|
||||
// * InvalidIdentityToken
|
||||
// * ErrCodeInvalidIdentityTokenException "InvalidIdentityToken"
|
||||
// The web identity token that was passed could not be validated by AWS. Get
|
||||
// a new identity token from the identity provider and then retry the request.
|
||||
//
|
||||
// * ExpiredTokenException
|
||||
// * ErrCodeExpiredTokenException "ExpiredTokenException"
|
||||
// The web identity token that was passed is expired or is not valid. Get a
|
||||
// new identity token from the identity provider and then retry the request.
|
||||
//
|
||||
// * RegionDisabledException
|
||||
// * ErrCodeRegionDisabledException "RegionDisabledException"
|
||||
// STS is not activated in the requested region for the account that is being
|
||||
// asked to generate credentials. The account administrator must use the IAM
|
||||
// console to activate STS in that region. For more information, see Activating
|
||||
@ -609,7 +609,7 @@ func (c *STS) DecodeAuthorizationMessageRequest(input *DecodeAuthorizationMessag
|
||||
// API operation DecodeAuthorizationMessage for usage and error information.
|
||||
//
|
||||
// Returned Error Codes:
|
||||
// * InvalidAuthorizationMessageException
|
||||
// * ErrCodeInvalidAuthorizationMessageException "InvalidAuthorizationMessageException"
|
||||
// The error returned if the message passed to DecodeAuthorizationMessage was
|
||||
// invalid. This can happen if the token contains invalid characters, such as
|
||||
// linebreaks.
|
||||
@ -814,16 +814,16 @@ func (c *STS) GetFederationTokenRequest(input *GetFederationTokenInput) (req *re
|
||||
// API operation GetFederationToken for usage and error information.
|
||||
//
|
||||
// Returned Error Codes:
|
||||
// * MalformedPolicyDocument
|
||||
// * ErrCodeMalformedPolicyDocumentException "MalformedPolicyDocument"
|
||||
// The request was rejected because the policy document was malformed. The error
|
||||
// message describes the specific error.
|
||||
//
|
||||
// * PackedPolicyTooLarge
|
||||
// * ErrCodePackedPolicyTooLargeException "PackedPolicyTooLarge"
|
||||
// The request was rejected because the policy document was too large. The error
|
||||
// message describes how big the policy document is, in packed form, as a percentage
|
||||
// of what the API allows.
|
||||
//
|
||||
// * RegionDisabledException
|
||||
// * ErrCodeRegionDisabledException "RegionDisabledException"
|
||||
// STS is not activated in the requested region for the account that is being
|
||||
// asked to generate credentials. The account administrator must use the IAM
|
||||
// console to activate STS in that region. For more information, see Activating
|
||||
@ -937,7 +937,7 @@ func (c *STS) GetSessionTokenRequest(input *GetSessionTokenInput) (req *request.
|
||||
// API operation GetSessionToken for usage and error information.
|
||||
//
|
||||
// Returned Error Codes:
|
||||
// * RegionDisabledException
|
||||
// * ErrCodeRegionDisabledException "RegionDisabledException"
|
||||
// STS is not activated in the requested region for the account that is being
|
||||
// asked to generate credentials. The account administrator must use the IAM
|
||||
// console to activate STS in that region. For more information, see Activating
|
||||
|
73
vendor/github.com/aws/aws-sdk-go/service/sts/errors.go
generated
vendored
Normal file
73
vendor/github.com/aws/aws-sdk-go/service/sts/errors.go
generated
vendored
Normal file
@ -0,0 +1,73 @@
|
||||
// THIS FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT.
|
||||
|
||||
package sts
|
||||
|
||||
const (
|
||||
|
||||
// ErrCodeExpiredTokenException for service response error code
|
||||
// "ExpiredTokenException".
|
||||
//
|
||||
// The web identity token that was passed is expired or is not valid. Get a
|
||||
// new identity token from the identity provider and then retry the request.
|
||||
ErrCodeExpiredTokenException = "ExpiredTokenException"
|
||||
|
||||
// ErrCodeIDPCommunicationErrorException for service response error code
|
||||
// "IDPCommunicationError".
|
||||
//
|
||||
// The request could not be fulfilled because the non-AWS identity provider
|
||||
// (IDP) that was asked to verify the incoming identity token could not be reached.
|
||||
// This is often a transient error caused by network conditions. Retry the request
|
||||
// a limited number of times so that you don't exceed the request rate. If the
|
||||
// error persists, the non-AWS identity provider might be down or not responding.
|
||||
ErrCodeIDPCommunicationErrorException = "IDPCommunicationError"
|
||||
|
||||
// ErrCodeIDPRejectedClaimException for service response error code
|
||||
// "IDPRejectedClaim".
|
||||
//
|
||||
// The identity provider (IdP) reported that authentication failed. This might
|
||||
// be because the claim is invalid.
|
||||
//
|
||||
// If this error is returned for the AssumeRoleWithWebIdentity operation, it
|
||||
// can also mean that the claim has expired or has been explicitly revoked.
|
||||
ErrCodeIDPRejectedClaimException = "IDPRejectedClaim"
|
||||
|
||||
// ErrCodeInvalidAuthorizationMessageException for service response error code
|
||||
// "InvalidAuthorizationMessageException".
|
||||
//
|
||||
// The error returned if the message passed to DecodeAuthorizationMessage was
|
||||
// invalid. This can happen if the token contains invalid characters, such as
|
||||
// linebreaks.
|
||||
ErrCodeInvalidAuthorizationMessageException = "InvalidAuthorizationMessageException"
|
||||
|
||||
// ErrCodeInvalidIdentityTokenException for service response error code
|
||||
// "InvalidIdentityToken".
|
||||
//
|
||||
// The web identity token that was passed could not be validated by AWS. Get
|
||||
// a new identity token from the identity provider and then retry the request.
|
||||
ErrCodeInvalidIdentityTokenException = "InvalidIdentityToken"
|
||||
|
||||
// ErrCodeMalformedPolicyDocumentException for service response error code
|
||||
// "MalformedPolicyDocument".
|
||||
//
|
||||
// The request was rejected because the policy document was malformed. The error
|
||||
// message describes the specific error.
|
||||
ErrCodeMalformedPolicyDocumentException = "MalformedPolicyDocument"
|
||||
|
||||
// ErrCodePackedPolicyTooLargeException for service response error code
|
||||
// "PackedPolicyTooLarge".
|
||||
//
|
||||
// The request was rejected because the policy document was too large. The error
|
||||
// message describes how big the policy document is, in packed form, as a percentage
|
||||
// of what the API allows.
|
||||
ErrCodePackedPolicyTooLargeException = "PackedPolicyTooLarge"
|
||||
|
||||
// ErrCodeRegionDisabledException for service response error code
|
||||
// "RegionDisabledException".
|
||||
//
|
||||
// STS is not activated in the requested region for the account that is being
|
||||
// asked to generate credentials. The account administrator must use the IAM
|
||||
// console to activate STS in that region. For more information, see Activating
|
||||
// and Deactivating AWS STS in an AWS Region (http://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_enable-regions.html)
|
||||
// in the IAM User Guide.
|
||||
ErrCodeRegionDisabledException = "RegionDisabledException"
|
||||
)
|
4
vendor/github.com/davecgh/go-spew/LICENSE
generated
vendored
4
vendor/github.com/davecgh/go-spew/LICENSE
generated
vendored
@ -1,4 +1,6 @@
|
||||
Copyright (c) 2012-2013 Dave Collins <dave@davec.name>
|
||||
ISC License
|
||||
|
||||
Copyright (c) 2012-2016 Dave Collins <dave@davec.name>
|
||||
|
||||
Permission to use, copy, modify, and distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
|
9
vendor/github.com/davecgh/go-spew/spew/bypass.go
generated
vendored
9
vendor/github.com/davecgh/go-spew/spew/bypass.go
generated
vendored
@ -1,4 +1,4 @@
|
||||
// Copyright (c) 2015 Dave Collins <dave@davec.name>
|
||||
// Copyright (c) 2015-2016 Dave Collins <dave@davec.name>
|
||||
//
|
||||
// Permission to use, copy, modify, and distribute this software for any
|
||||
// purpose with or without fee is hereby granted, provided that the above
|
||||
@ -13,9 +13,10 @@
|
||||
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
// NOTE: Due to the following build constraints, this file will only be compiled
|
||||
// when the code is not running on Google App Engine and "-tags disableunsafe"
|
||||
// is not added to the go build command line.
|
||||
// +build !appengine,!disableunsafe
|
||||
// when the code is not running on Google App Engine, compiled by GopherJS, and
|
||||
// "-tags safe" is not added to the go build command line. The "disableunsafe"
|
||||
// tag is deprecated and thus should not be used.
|
||||
// +build !js,!appengine,!safe,!disableunsafe
|
||||
|
||||
package spew
|
||||
|
||||
|
9
vendor/github.com/davecgh/go-spew/spew/bypasssafe.go
generated
vendored
9
vendor/github.com/davecgh/go-spew/spew/bypasssafe.go
generated
vendored
@ -1,4 +1,4 @@
|
||||
// Copyright (c) 2015 Dave Collins <dave@davec.name>
|
||||
// Copyright (c) 2015-2016 Dave Collins <dave@davec.name>
|
||||
//
|
||||
// Permission to use, copy, modify, and distribute this software for any
|
||||
// purpose with or without fee is hereby granted, provided that the above
|
||||
@ -13,9 +13,10 @@
|
||||
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
// NOTE: Due to the following build constraints, this file will only be compiled
|
||||
// when either the code is running on Google App Engine or "-tags disableunsafe"
|
||||
// is added to the go build command line.
|
||||
// +build appengine disableunsafe
|
||||
// when the code is running on Google App Engine, compiled by GopherJS, or
|
||||
// "-tags safe" is added to the go build command line. The "disableunsafe"
|
||||
// tag is deprecated and thus should not be used.
|
||||
// +build js appengine safe disableunsafe
|
||||
|
||||
package spew
|
||||
|
||||
|
2
vendor/github.com/davecgh/go-spew/spew/common.go
generated
vendored
2
vendor/github.com/davecgh/go-spew/spew/common.go
generated
vendored
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2013 Dave Collins <dave@davec.name>
|
||||
* Copyright (c) 2013-2016 Dave Collins <dave@davec.name>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
|
13
vendor/github.com/davecgh/go-spew/spew/config.go
generated
vendored
13
vendor/github.com/davecgh/go-spew/spew/config.go
generated
vendored
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2013 Dave Collins <dave@davec.name>
|
||||
* Copyright (c) 2013-2016 Dave Collins <dave@davec.name>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
@ -64,9 +64,18 @@ type ConfigState struct {
|
||||
// inside these interface methods. As a result, this option relies on
|
||||
// access to the unsafe package, so it will not have any effect when
|
||||
// running in environments without access to the unsafe package such as
|
||||
// Google App Engine or with the "disableunsafe" build tag specified.
|
||||
// Google App Engine or with the "safe" build tag specified.
|
||||
DisablePointerMethods bool
|
||||
|
||||
// DisablePointerAddresses specifies whether to disable the printing of
|
||||
// pointer addresses. This is useful when diffing data structures in tests.
|
||||
DisablePointerAddresses bool
|
||||
|
||||
// DisableCapacities specifies whether to disable the printing of capacities
|
||||
// for arrays, slices, maps and channels. This is useful when diffing
|
||||
// data structures in tests.
|
||||
DisableCapacities bool
|
||||
|
||||
// ContinueOnMethod specifies whether or not recursion should continue once
|
||||
// a custom error or Stringer interface is invoked. The default, false,
|
||||
// means it will print the results of invoking the custom error or Stringer
|
||||
|
11
vendor/github.com/davecgh/go-spew/spew/doc.go
generated
vendored
11
vendor/github.com/davecgh/go-spew/spew/doc.go
generated
vendored
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2013 Dave Collins <dave@davec.name>
|
||||
* Copyright (c) 2013-2016 Dave Collins <dave@davec.name>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
@ -91,6 +91,15 @@ The following configuration options are available:
|
||||
which only accept pointer receivers from non-pointer variables.
|
||||
Pointer method invocation is enabled by default.
|
||||
|
||||
* DisablePointerAddresses
|
||||
DisablePointerAddresses specifies whether to disable the printing of
|
||||
pointer addresses. This is useful when diffing data structures in tests.
|
||||
|
||||
* DisableCapacities
|
||||
DisableCapacities specifies whether to disable the printing of
|
||||
capacities for arrays, slices, maps and channels. This is useful when
|
||||
diffing data structures in tests.
|
||||
|
||||
* ContinueOnMethod
|
||||
Enables recursion into types after invoking error and Stringer interface
|
||||
methods. Recursion after method invocation is disabled by default.
|
||||
|
8
vendor/github.com/davecgh/go-spew/spew/dump.go
generated
vendored
8
vendor/github.com/davecgh/go-spew/spew/dump.go
generated
vendored
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2013 Dave Collins <dave@davec.name>
|
||||
* Copyright (c) 2013-2016 Dave Collins <dave@davec.name>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
@ -129,7 +129,7 @@ func (d *dumpState) dumpPtr(v reflect.Value) {
|
||||
d.w.Write(closeParenBytes)
|
||||
|
||||
// Display pointer information.
|
||||
if len(pointerChain) > 0 {
|
||||
if !d.cs.DisablePointerAddresses && len(pointerChain) > 0 {
|
||||
d.w.Write(openParenBytes)
|
||||
for i, addr := range pointerChain {
|
||||
if i > 0 {
|
||||
@ -282,13 +282,13 @@ func (d *dumpState) dump(v reflect.Value) {
|
||||
case reflect.Map, reflect.String:
|
||||
valueLen = v.Len()
|
||||
}
|
||||
if valueLen != 0 || valueCap != 0 {
|
||||
if valueLen != 0 || !d.cs.DisableCapacities && valueCap != 0 {
|
||||
d.w.Write(openParenBytes)
|
||||
if valueLen != 0 {
|
||||
d.w.Write(lenEqualsBytes)
|
||||
printInt(d.w, int64(valueLen), 10)
|
||||
}
|
||||
if valueCap != 0 {
|
||||
if !d.cs.DisableCapacities && valueCap != 0 {
|
||||
if valueLen != 0 {
|
||||
d.w.Write(spaceBytes)
|
||||
}
|
||||
|
2
vendor/github.com/davecgh/go-spew/spew/format.go
generated
vendored
2
vendor/github.com/davecgh/go-spew/spew/format.go
generated
vendored
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2013 Dave Collins <dave@davec.name>
|
||||
* Copyright (c) 2013-2016 Dave Collins <dave@davec.name>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
|
2
vendor/github.com/davecgh/go-spew/spew/spew.go
generated
vendored
2
vendor/github.com/davecgh/go-spew/spew/spew.go
generated
vendored
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2013 Dave Collins <dave@davec.name>
|
||||
* Copyright (c) 2013-2016 Dave Collins <dave@davec.name>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
|
1
vendor/github.com/go-ini/ini/.gitignore
generated
vendored
1
vendor/github.com/go-ini/ini/.gitignore
generated
vendored
@ -2,3 +2,4 @@ testdata/conf_out.ini
|
||||
ini.sublime-project
|
||||
ini.sublime-workspace
|
||||
testdata/conf_reflect.ini
|
||||
.idea
|
||||
|
17
vendor/github.com/go-ini/ini/.travis.yml
generated
vendored
Normal file
17
vendor/github.com/go-ini/ini/.travis.yml
generated
vendored
Normal file
@ -0,0 +1,17 @@
|
||||
sudo: false
|
||||
language: go
|
||||
go:
|
||||
- 1.4.x
|
||||
- 1.5.x
|
||||
- 1.6.x
|
||||
- 1.7.x
|
||||
- master
|
||||
|
||||
script:
|
||||
- go get golang.org/x/tools/cmd/cover
|
||||
- go get github.com/smartystreets/goconvey
|
||||
- go test -v -cover -race
|
||||
|
||||
notifications:
|
||||
email:
|
||||
- u@gogs.io
|
12
vendor/github.com/go-ini/ini/Makefile
generated
vendored
Normal file
12
vendor/github.com/go-ini/ini/Makefile
generated
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
.PHONY: build test bench vet
|
||||
|
||||
build: vet bench
|
||||
|
||||
test:
|
||||
go test -v -cover -race
|
||||
|
||||
bench:
|
||||
go test -v -cover -race -test.bench=. -test.benchmem
|
||||
|
||||
vet:
|
||||
go vet
|
138
vendor/github.com/go-ini/ini/README.md
generated
vendored
138
vendor/github.com/go-ini/ini/README.md
generated
vendored
@ -1,4 +1,4 @@
|
||||
ini [![Build Status](https://drone.io/github.com/go-ini/ini/status.png)](https://drone.io/github.com/go-ini/ini/latest) [![](http://gocover.io/_badge/github.com/go-ini/ini)](http://gocover.io/github.com/go-ini/ini)
|
||||
INI [![Build Status](https://travis-ci.org/go-ini/ini.svg?branch=master)](https://travis-ci.org/go-ini/ini) [![Sourcegraph](https://sourcegraph.com/github.com/go-ini/ini/-/badge.svg)](https://sourcegraph.com/github.com/go-ini/ini?badge)
|
||||
===
|
||||
|
||||
![](https://avatars0.githubusercontent.com/u/10216035?v=3&s=200)
|
||||
@ -9,7 +9,7 @@ Package ini provides INI file read and write functionality in Go.
|
||||
|
||||
## Feature
|
||||
|
||||
- Load multiple data sources(`[]byte` or file) with overwrites.
|
||||
- Load multiple data sources(`[]byte`, file and `io.ReadCloser`) with overwrites.
|
||||
- Read with recursion values.
|
||||
- Read with parent-child sections.
|
||||
- Read with auto-increment key names.
|
||||
@ -44,10 +44,10 @@ Please add `-u` flag to update in the future.
|
||||
|
||||
### Loading from data sources
|
||||
|
||||
A **Data Source** is either raw data in type `[]byte` or a file name with type `string` and you can load **as many as** data sources you want. Passing other types will simply return an error.
|
||||
A **Data Source** is either raw data in type `[]byte`, a file name with type `string` or `io.ReadCloser`. You can load **as many data sources as you want**. Passing other types will simply return an error.
|
||||
|
||||
```go
|
||||
cfg, err := ini.Load([]byte("raw data"), "filename")
|
||||
cfg, err := ini.Load([]byte("raw data"), "filename", ioutil.NopCloser(bytes.NewReader([]byte("some other data"))))
|
||||
```
|
||||
|
||||
Or start with an empty object:
|
||||
@ -56,12 +56,72 @@ Or start with an empty object:
|
||||
cfg := ini.Empty()
|
||||
```
|
||||
|
||||
When you cannot decide how many data sources to load at the beginning, you still able to **Append()** them later.
|
||||
When you cannot decide how many data sources to load at the beginning, you will still be able to **Append()** them later.
|
||||
|
||||
```go
|
||||
err := cfg.Append("other file", []byte("other raw data"))
|
||||
```
|
||||
|
||||
If you have a list of files with possibilities that some of them may not available at the time, and you don't know exactly which ones, you can use `LooseLoad` to ignore nonexistent files without returning error.
|
||||
|
||||
```go
|
||||
cfg, err := ini.LooseLoad("filename", "filename_404")
|
||||
```
|
||||
|
||||
The cool thing is, whenever the file is available to load while you're calling `Reload` method, it will be counted as usual.
|
||||
|
||||
#### Ignore cases of key name
|
||||
|
||||
When you do not care about cases of section and key names, you can use `InsensitiveLoad` to force all names to be lowercased while parsing.
|
||||
|
||||
```go
|
||||
cfg, err := ini.InsensitiveLoad("filename")
|
||||
//...
|
||||
|
||||
// sec1 and sec2 are the exactly same section object
|
||||
sec1, err := cfg.GetSection("Section")
|
||||
sec2, err := cfg.GetSection("SecTIOn")
|
||||
|
||||
// key1 and key2 are the exactly same key object
|
||||
key1, err := cfg.GetKey("Key")
|
||||
key2, err := cfg.GetKey("KeY")
|
||||
```
|
||||
|
||||
#### MySQL-like boolean key
|
||||
|
||||
MySQL's configuration allows a key without value as follows:
|
||||
|
||||
```ini
|
||||
[mysqld]
|
||||
...
|
||||
skip-host-cache
|
||||
skip-name-resolve
|
||||
```
|
||||
|
||||
By default, this is considered as missing value. But if you know you're going to deal with those cases, you can assign advanced load options:
|
||||
|
||||
```go
|
||||
cfg, err := LoadSources(LoadOptions{AllowBooleanKeys: true}, "my.cnf"))
|
||||
```
|
||||
|
||||
The value of those keys are always `true`, and when you save to a file, it will keep in the same foramt as you read.
|
||||
|
||||
To generate such keys in your program, you could use `NewBooleanKey`:
|
||||
|
||||
```go
|
||||
key, err := sec.NewBooleanKey("skip-host-cache")
|
||||
```
|
||||
|
||||
#### Comment
|
||||
|
||||
Take care that following format will be treated as comment:
|
||||
|
||||
1. Line begins with `#` or `;`
|
||||
2. Words after `#` or `;`
|
||||
3. Words after section name (i.e words after `[some section name]`)
|
||||
|
||||
If you want to save a value with `#` or `;`, please quote them with ``` ` ``` or ``` """ ```.
|
||||
|
||||
### Working with sections
|
||||
|
||||
To get a section, you would need to:
|
||||
@ -79,7 +139,7 @@ section, err := cfg.GetSection("")
|
||||
When you're pretty sure the section exists, following code could make your life easier:
|
||||
|
||||
```go
|
||||
section := cfg.Section("")
|
||||
section := cfg.Section("section name")
|
||||
```
|
||||
|
||||
What happens when the section somehow does not exist? Don't panic, it automatically creates and returns a new section to you.
|
||||
@ -133,7 +193,7 @@ names := cfg.Section("").KeyStrings()
|
||||
To get a clone hash of keys and corresponding values:
|
||||
|
||||
```go
|
||||
hash := cfg.GetSection("").KeysHash()
|
||||
hash := cfg.Section("").KeysHash()
|
||||
```
|
||||
|
||||
### Working with values
|
||||
@ -246,6 +306,16 @@ cfg.Section("advance").Key("two_lines").String() // how about continuation lines
|
||||
cfg.Section("advance").Key("lots_of_lines").String() // 1 2 3 4
|
||||
```
|
||||
|
||||
Well, I hate continuation lines, how do I disable that?
|
||||
|
||||
```go
|
||||
cfg, err := ini.LoadSources(ini.LoadOptions{
|
||||
IgnoreContinuation: true,
|
||||
}, "filename")
|
||||
```
|
||||
|
||||
Holy crap!
|
||||
|
||||
Note that single quotes around values will be stripped:
|
||||
|
||||
```ini
|
||||
@ -346,6 +416,12 @@ cfg.WriteTo(writer)
|
||||
cfg.WriteToIndent(writer, "\t")
|
||||
```
|
||||
|
||||
By default, spaces are used to align "=" sign between key and values, to disable that:
|
||||
|
||||
```go
|
||||
ini.PrettyFormat = false
|
||||
```
|
||||
|
||||
## Advanced Usage
|
||||
|
||||
### Recursive Values
|
||||
@ -387,6 +463,27 @@ CLONE_URL = https://%(IMPORT_PATH)s
|
||||
cfg.Section("package.sub").Key("CLONE_URL").String() // https://gopkg.in/ini.v1
|
||||
```
|
||||
|
||||
#### Retrieve parent keys available to a child section
|
||||
|
||||
```go
|
||||
cfg.Section("package.sub").ParentKeys() // ["CLONE_URL"]
|
||||
```
|
||||
|
||||
### Unparseable Sections
|
||||
|
||||
Sometimes, you have sections that do not contain key-value pairs but raw content, to handle such case, you can use `LoadOptions.UnparsableSections`:
|
||||
|
||||
```go
|
||||
cfg, err := LoadSources(LoadOptions{UnparseableSections: []string{"COMMENTS"}}, `[COMMENTS]
|
||||
<1><L.Slide#2> This slide has the fuel listed in the wrong units <e.1>`))
|
||||
|
||||
body := cfg.Section("COMMENTS").Body()
|
||||
|
||||
/* --- start ---
|
||||
<1><L.Slide#2> This slide has the fuel listed in the wrong units <e.1>
|
||||
------ end --- */
|
||||
```
|
||||
|
||||
### Auto-increment Key Names
|
||||
|
||||
If key name is `-` in data source, then it would be seen as special syntax for auto-increment key name start from 1, and every section is independent on counter.
|
||||
@ -471,8 +568,8 @@ Why not?
|
||||
```go
|
||||
type Embeded struct {
|
||||
Dates []time.Time `delim:"|"`
|
||||
Places []string
|
||||
None []int
|
||||
Places []string `ini:"places,omitempty"`
|
||||
None []int `ini:",omitempty"`
|
||||
}
|
||||
|
||||
type Author struct {
|
||||
@ -507,8 +604,7 @@ GPA = 2.8
|
||||
|
||||
[Embeded]
|
||||
Dates = 2015-08-07T22:14:22+08:00|2015-08-07T22:14:22+08:00
|
||||
Places = HangZhou,Boston
|
||||
None =
|
||||
places = HangZhou,Boston
|
||||
```
|
||||
|
||||
#### Name Mapper
|
||||
@ -542,6 +638,26 @@ func main() {
|
||||
|
||||
Same rules of name mapper apply to `ini.ReflectFromWithMapper` function.
|
||||
|
||||
#### Value Mapper
|
||||
|
||||
To expand values (e.g. from environment variables), you can use the `ValueMapper` to transform values:
|
||||
|
||||
```go
|
||||
type Env struct {
|
||||
Foo string `ini:"foo"`
|
||||
}
|
||||
|
||||
func main() {
|
||||
cfg, err := ini.Load([]byte("[env]\nfoo = ${MY_VAR}\n")
|
||||
cfg.ValueMapper = os.ExpandEnv
|
||||
// ...
|
||||
env := &Env{}
|
||||
err = cfg.Section("env").MapTo(env)
|
||||
}
|
||||
```
|
||||
|
||||
This would set the value of `env.Foo` to the value of the environment variable `MY_VAR`.
|
||||
|
||||
#### Other Notes On Map/Reflect
|
||||
|
||||
Any embedded struct is treated as a section by default, and there is no automatic parent-child relations in map/reflect feature:
|
||||
|
142
vendor/github.com/go-ini/ini/README_ZH.md
generated
vendored
142
vendor/github.com/go-ini/ini/README_ZH.md
generated
vendored
@ -2,7 +2,7 @@
|
||||
|
||||
## 功能特性
|
||||
|
||||
- 支持覆盖加载多个数据源(`[]byte` 或文件)
|
||||
- 支持覆盖加载多个数据源(`[]byte`、文件和 `io.ReadCloser`)
|
||||
- 支持递归读取键值
|
||||
- 支持读取父子分区
|
||||
- 支持读取自增键名
|
||||
@ -37,10 +37,10 @@
|
||||
|
||||
### 从数据源加载
|
||||
|
||||
一个 **数据源** 可以是 `[]byte` 类型的原始数据,或 `string` 类型的文件路径。您可以加载 **任意多个** 数据源。如果您传递其它类型的数据源,则会直接返回错误。
|
||||
一个 **数据源** 可以是 `[]byte` 类型的原始数据,`string` 类型的文件路径或 `io.ReadCloser`。您可以加载 **任意多个** 数据源。如果您传递其它类型的数据源,则会直接返回错误。
|
||||
|
||||
```go
|
||||
cfg, err := ini.Load([]byte("raw data"), "filename")
|
||||
cfg, err := ini.Load([]byte("raw data"), "filename", ioutil.NopCloser(bytes.NewReader([]byte("some other data"))))
|
||||
```
|
||||
|
||||
或者从一个空白的文件开始:
|
||||
@ -55,6 +55,66 @@ cfg := ini.Empty()
|
||||
err := cfg.Append("other file", []byte("other raw data"))
|
||||
```
|
||||
|
||||
当您想要加载一系列文件,但是不能够确定其中哪些文件是不存在的,可以通过调用函数 `LooseLoad` 来忽略它们(`Load` 会因为文件不存在而返回错误):
|
||||
|
||||
```go
|
||||
cfg, err := ini.LooseLoad("filename", "filename_404")
|
||||
```
|
||||
|
||||
更牛逼的是,当那些之前不存在的文件在重新调用 `Reload` 方法的时候突然出现了,那么它们会被正常加载。
|
||||
|
||||
#### 忽略键名的大小写
|
||||
|
||||
有时候分区和键的名称大小写混合非常烦人,这个时候就可以通过 `InsensitiveLoad` 将所有分区和键名在读取里强制转换为小写:
|
||||
|
||||
```go
|
||||
cfg, err := ini.InsensitiveLoad("filename")
|
||||
//...
|
||||
|
||||
// sec1 和 sec2 指向同一个分区对象
|
||||
sec1, err := cfg.GetSection("Section")
|
||||
sec2, err := cfg.GetSection("SecTIOn")
|
||||
|
||||
// key1 和 key2 指向同一个键对象
|
||||
key1, err := cfg.GetKey("Key")
|
||||
key2, err := cfg.GetKey("KeY")
|
||||
```
|
||||
|
||||
#### 类似 MySQL 配置中的布尔值键
|
||||
|
||||
MySQL 的配置文件中会出现没有具体值的布尔类型的键:
|
||||
|
||||
```ini
|
||||
[mysqld]
|
||||
...
|
||||
skip-host-cache
|
||||
skip-name-resolve
|
||||
```
|
||||
|
||||
默认情况下这被认为是缺失值而无法完成解析,但可以通过高级的加载选项对它们进行处理:
|
||||
|
||||
```go
|
||||
cfg, err := LoadSources(LoadOptions{AllowBooleanKeys: true}, "my.cnf"))
|
||||
```
|
||||
|
||||
这些键的值永远为 `true`,且在保存到文件时也只会输出键名。
|
||||
|
||||
如果您想要通过程序来生成此类键,则可以使用 `NewBooleanKey`:
|
||||
|
||||
```go
|
||||
key, err := sec.NewBooleanKey("skip-host-cache")
|
||||
```
|
||||
|
||||
#### 关于注释
|
||||
|
||||
下述几种情况的内容将被视为注释:
|
||||
|
||||
1. 所有以 `#` 或 `;` 开头的行
|
||||
2. 所有在 `#` 或 `;` 之后的内容
|
||||
3. 分区标签后的文字 (即 `[分区名]` 之后的内容)
|
||||
|
||||
如果你希望使用包含 `#` 或 `;` 的值,请使用 ``` ` ``` 或 ``` """ ``` 进行包覆。
|
||||
|
||||
### 操作分区(Section)
|
||||
|
||||
获取指定分区:
|
||||
@ -72,7 +132,7 @@ section, err := cfg.GetSection("")
|
||||
当您非常确定某个分区是存在的,可以使用以下简便方法:
|
||||
|
||||
```go
|
||||
section := cfg.Section("")
|
||||
section := cfg.Section("section name")
|
||||
```
|
||||
|
||||
如果不小心判断错了,要获取的分区其实是不存在的,那会发生什么呢?没事的,它会自动创建并返回一个对应的分区对象给您。
|
||||
@ -126,7 +186,7 @@ names := cfg.Section("").KeyStrings()
|
||||
获取分区下的所有键值对的克隆:
|
||||
|
||||
```go
|
||||
hash := cfg.GetSection("").KeysHash()
|
||||
hash := cfg.Section("").KeysHash()
|
||||
```
|
||||
|
||||
### 操作键值(Value)
|
||||
@ -239,6 +299,16 @@ cfg.Section("advance").Key("two_lines").String() // how about continuation lines
|
||||
cfg.Section("advance").Key("lots_of_lines").String() // 1 2 3 4
|
||||
```
|
||||
|
||||
可是我有时候觉得两行连在一起特别没劲,怎么才能不自动连接两行呢?
|
||||
|
||||
```go
|
||||
cfg, err := ini.LoadSources(ini.LoadOptions{
|
||||
IgnoreContinuation: true,
|
||||
}, "filename")
|
||||
```
|
||||
|
||||
哇靠给力啊!
|
||||
|
||||
需要注意的是,值两侧的单引号会被自动剔除:
|
||||
|
||||
```ini
|
||||
@ -339,9 +409,15 @@ cfg.WriteTo(writer)
|
||||
cfg.WriteToIndent(writer, "\t")
|
||||
```
|
||||
|
||||
### 高级用法
|
||||
默认情况下,空格将被用于对齐键值之间的等号以美化输出结果,以下代码可以禁用该功能:
|
||||
|
||||
#### 递归读取键值
|
||||
```go
|
||||
ini.PrettyFormat = false
|
||||
```
|
||||
|
||||
## 高级用法
|
||||
|
||||
### 递归读取键值
|
||||
|
||||
在获取所有键值的过程中,特殊语法 `%(<name>)s` 会被应用,其中 `<name>` 可以是相同分区或者默认分区下的键名。字符串 `%(<name>)s` 会被相应的键值所替代,如果指定的键不存在,则会用空字符串替代。您可以最多使用 99 层的递归嵌套。
|
||||
|
||||
@ -361,7 +437,7 @@ cfg.Section("author").Key("GITHUB").String() // https://github.com/Unknwon
|
||||
cfg.Section("package").Key("FULL_NAME").String() // github.com/go-ini/ini
|
||||
```
|
||||
|
||||
#### 读取父子分区
|
||||
### 读取父子分区
|
||||
|
||||
您可以在分区名称中使用 `.` 来表示两个或多个分区之间的父子关系。如果某个键在子分区中不存在,则会去它的父分区中再次寻找,直到没有父分区为止。
|
||||
|
||||
@ -380,7 +456,28 @@ CLONE_URL = https://%(IMPORT_PATH)s
|
||||
cfg.Section("package.sub").Key("CLONE_URL").String() // https://gopkg.in/ini.v1
|
||||
```
|
||||
|
||||
#### 读取自增键名
|
||||
#### 获取上级父分区下的所有键名
|
||||
|
||||
```go
|
||||
cfg.Section("package.sub").ParentKeys() // ["CLONE_URL"]
|
||||
```
|
||||
|
||||
### 无法解析的分区
|
||||
|
||||
如果遇到一些比较特殊的分区,它们不包含常见的键值对,而是没有固定格式的纯文本,则可以使用 `LoadOptions.UnparsableSections` 进行处理:
|
||||
|
||||
```go
|
||||
cfg, err := LoadSources(LoadOptions{UnparseableSections: []string{"COMMENTS"}}, `[COMMENTS]
|
||||
<1><L.Slide#2> This slide has the fuel listed in the wrong units <e.1>`))
|
||||
|
||||
body := cfg.Section("COMMENTS").Body()
|
||||
|
||||
/* --- start ---
|
||||
<1><L.Slide#2> This slide has the fuel listed in the wrong units <e.1>
|
||||
------ end --- */
|
||||
```
|
||||
|
||||
### 读取自增键名
|
||||
|
||||
如果数据源中的键名为 `-`,则认为该键使用了自增键名的特殊语法。计数器从 1 开始,并且分区之间是相互独立的。
|
||||
|
||||
@ -462,8 +559,8 @@ p := &Person{
|
||||
```go
|
||||
type Embeded struct {
|
||||
Dates []time.Time `delim:"|"`
|
||||
Places []string
|
||||
None []int
|
||||
Places []string `ini:"places,omitempty"`
|
||||
None []int `ini:",omitempty"`
|
||||
}
|
||||
|
||||
type Author struct {
|
||||
@ -498,8 +595,7 @@ GPA = 2.8
|
||||
|
||||
[Embeded]
|
||||
Dates = 2015-08-07T22:14:22+08:00|2015-08-07T22:14:22+08:00
|
||||
Places = HangZhou,Boston
|
||||
None =
|
||||
places = HangZhou,Boston
|
||||
```
|
||||
|
||||
#### 名称映射器(Name Mapper)
|
||||
@ -533,6 +629,26 @@ func main() {
|
||||
|
||||
使用函数 `ini.ReflectFromWithMapper` 时也可应用相同的规则。
|
||||
|
||||
#### 值映射器(Value Mapper)
|
||||
|
||||
值映射器允许使用一个自定义函数自动展开值的具体内容,例如:运行时获取环境变量:
|
||||
|
||||
```go
|
||||
type Env struct {
|
||||
Foo string `ini:"foo"`
|
||||
}
|
||||
|
||||
func main() {
|
||||
cfg, err := ini.Load([]byte("[env]\nfoo = ${MY_VAR}\n")
|
||||
cfg.ValueMapper = os.ExpandEnv
|
||||
// ...
|
||||
env := &Env{}
|
||||
err = cfg.Section("env").MapTo(env)
|
||||
}
|
||||
```
|
||||
|
||||
本例中,`env.Foo` 将会是运行时所获取到环境变量 `MY_VAR` 的值。
|
||||
|
||||
#### 映射/反射的其它说明
|
||||
|
||||
任何嵌入的结构都会被默认认作一个不同的分区,并且不会自动产生所谓的父子分区关联:
|
||||
|
32
vendor/github.com/go-ini/ini/error.go
generated
vendored
Normal file
32
vendor/github.com/go-ini/ini/error.go
generated
vendored
Normal file
@ -0,0 +1,32 @@
|
||||
// Copyright 2016 Unknwon
|
||||
//
|
||||
// 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.
|
||||
|
||||
package ini
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
type ErrDelimiterNotFound struct {
|
||||
Line string
|
||||
}
|
||||
|
||||
func IsErrDelimiterNotFound(err error) bool {
|
||||
_, ok := err.(ErrDelimiterNotFound)
|
||||
return ok
|
||||
}
|
||||
|
||||
func (err ErrDelimiterNotFound) Error() string {
|
||||
return fmt.Sprintf("key-value delimiter not found: %s", err.Line)
|
||||
}
|
925
vendor/github.com/go-ini/ini/ini.go
generated
vendored
925
vendor/github.com/go-ini/ini/ini.go
generated
vendored
File diff suppressed because it is too large
Load Diff
633
vendor/github.com/go-ini/ini/key.go
generated
vendored
Normal file
633
vendor/github.com/go-ini/ini/key.go
generated
vendored
Normal file
@ -0,0 +1,633 @@
|
||||
// Copyright 2014 Unknwon
|
||||
//
|
||||
// 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.
|
||||
|
||||
package ini
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
// Key represents a key under a section.
|
||||
type Key struct {
|
||||
s *Section
|
||||
name string
|
||||
value string
|
||||
isAutoIncrement bool
|
||||
isBooleanType bool
|
||||
|
||||
Comment string
|
||||
}
|
||||
|
||||
// ValueMapper represents a mapping function for values, e.g. os.ExpandEnv
|
||||
type ValueMapper func(string) string
|
||||
|
||||
// Name returns name of key.
|
||||
func (k *Key) Name() string {
|
||||
return k.name
|
||||
}
|
||||
|
||||
// Value returns raw value of key for performance purpose.
|
||||
func (k *Key) Value() string {
|
||||
return k.value
|
||||
}
|
||||
|
||||
// String returns string representation of value.
|
||||
func (k *Key) String() string {
|
||||
val := k.value
|
||||
if k.s.f.ValueMapper != nil {
|
||||
val = k.s.f.ValueMapper(val)
|
||||
}
|
||||
if strings.Index(val, "%") == -1 {
|
||||
return val
|
||||
}
|
||||
|
||||
for i := 0; i < _DEPTH_VALUES; i++ {
|
||||
vr := varPattern.FindString(val)
|
||||
if len(vr) == 0 {
|
||||
break
|
||||
}
|
||||
|
||||
// Take off leading '%(' and trailing ')s'.
|
||||
noption := strings.TrimLeft(vr, "%(")
|
||||
noption = strings.TrimRight(noption, ")s")
|
||||
|
||||
// Search in the same section.
|
||||
nk, err := k.s.GetKey(noption)
|
||||
if err != nil {
|
||||
// Search again in default section.
|
||||
nk, _ = k.s.f.Section("").GetKey(noption)
|
||||
}
|
||||
|
||||
// Substitute by new value and take off leading '%(' and trailing ')s'.
|
||||
val = strings.Replace(val, vr, nk.value, -1)
|
||||
}
|
||||
return val
|
||||
}
|
||||
|
||||
// Validate accepts a validate function which can
|
||||
// return modifed result as key value.
|
||||
func (k *Key) Validate(fn func(string) string) string {
|
||||
return fn(k.String())
|
||||
}
|
||||
|
||||
// parseBool returns the boolean value represented by the string.
|
||||
//
|
||||
// It accepts 1, t, T, TRUE, true, True, YES, yes, Yes, y, ON, on, On,
|
||||
// 0, f, F, FALSE, false, False, NO, no, No, n, OFF, off, Off.
|
||||
// Any other value returns an error.
|
||||
func parseBool(str string) (value bool, err error) {
|
||||
switch str {
|
||||
case "1", "t", "T", "true", "TRUE", "True", "YES", "yes", "Yes", "y", "ON", "on", "On":
|
||||
return true, nil
|
||||
case "0", "f", "F", "false", "FALSE", "False", "NO", "no", "No", "n", "OFF", "off", "Off":
|
||||
return false, nil
|
||||
}
|
||||
return false, fmt.Errorf("parsing \"%s\": invalid syntax", str)
|
||||
}
|
||||
|
||||
// Bool returns bool type value.
|
||||
func (k *Key) Bool() (bool, error) {
|
||||
return parseBool(k.String())
|
||||
}
|
||||
|
||||
// Float64 returns float64 type value.
|
||||
func (k *Key) Float64() (float64, error) {
|
||||
return strconv.ParseFloat(k.String(), 64)
|
||||
}
|
||||
|
||||
// Int returns int type value.
|
||||
func (k *Key) Int() (int, error) {
|
||||
return strconv.Atoi(k.String())
|
||||
}
|
||||
|
||||
// Int64 returns int64 type value.
|
||||
func (k *Key) Int64() (int64, error) {
|
||||
return strconv.ParseInt(k.String(), 10, 64)
|
||||
}
|
||||
|
||||
// Uint returns uint type valued.
|
||||
func (k *Key) Uint() (uint, error) {
|
||||
u, e := strconv.ParseUint(k.String(), 10, 64)
|
||||
return uint(u), e
|
||||
}
|
||||
|
||||
// Uint64 returns uint64 type value.
|
||||
func (k *Key) Uint64() (uint64, error) {
|
||||
return strconv.ParseUint(k.String(), 10, 64)
|
||||
}
|
||||
|
||||
// Duration returns time.Duration type value.
|
||||
func (k *Key) Duration() (time.Duration, error) {
|
||||
return time.ParseDuration(k.String())
|
||||
}
|
||||
|
||||
// TimeFormat parses with given format and returns time.Time type value.
|
||||
func (k *Key) TimeFormat(format string) (time.Time, error) {
|
||||
return time.Parse(format, k.String())
|
||||
}
|
||||
|
||||
// Time parses with RFC3339 format and returns time.Time type value.
|
||||
func (k *Key) Time() (time.Time, error) {
|
||||
return k.TimeFormat(time.RFC3339)
|
||||
}
|
||||
|
||||
// MustString returns default value if key value is empty.
|
||||
func (k *Key) MustString(defaultVal string) string {
|
||||
val := k.String()
|
||||
if len(val) == 0 {
|
||||
k.value = defaultVal
|
||||
return defaultVal
|
||||
}
|
||||
return val
|
||||
}
|
||||
|
||||
// MustBool always returns value without error,
|
||||
// it returns false if error occurs.
|
||||
func (k *Key) MustBool(defaultVal ...bool) bool {
|
||||
val, err := k.Bool()
|
||||
if len(defaultVal) > 0 && err != nil {
|
||||
k.value = strconv.FormatBool(defaultVal[0])
|
||||
return defaultVal[0]
|
||||
}
|
||||
return val
|
||||
}
|
||||
|
||||
// MustFloat64 always returns value without error,
|
||||
// it returns 0.0 if error occurs.
|
||||
func (k *Key) MustFloat64(defaultVal ...float64) float64 {
|
||||
val, err := k.Float64()
|
||||
if len(defaultVal) > 0 && err != nil {
|
||||
k.value = strconv.FormatFloat(defaultVal[0], 'f', -1, 64)
|
||||
return defaultVal[0]
|
||||
}
|
||||
return val
|
||||
}
|
||||
|
||||
// MustInt always returns value without error,
|
||||
// it returns 0 if error occurs.
|
||||
func (k *Key) MustInt(defaultVal ...int) int {
|
||||
val, err := k.Int()
|
||||
if len(defaultVal) > 0 && err != nil {
|
||||
k.value = strconv.FormatInt(int64(defaultVal[0]), 10)
|
||||
return defaultVal[0]
|
||||
}
|
||||
return val
|
||||
}
|
||||
|
||||
// MustInt64 always returns value without error,
|
||||
// it returns 0 if error occurs.
|
||||
func (k *Key) MustInt64(defaultVal ...int64) int64 {
|
||||
val, err := k.Int64()
|
||||
if len(defaultVal) > 0 && err != nil {
|
||||
k.value = strconv.FormatInt(defaultVal[0], 10)
|
||||
return defaultVal[0]
|
||||
}
|
||||
return val
|
||||
}
|
||||
|
||||
// MustUint always returns value without error,
|
||||
// it returns 0 if error occurs.
|
||||
func (k *Key) MustUint(defaultVal ...uint) uint {
|
||||
val, err := k.Uint()
|
||||
if len(defaultVal) > 0 && err != nil {
|
||||
k.value = strconv.FormatUint(uint64(defaultVal[0]), 10)
|
||||
return defaultVal[0]
|
||||
}
|
||||
return val
|
||||
}
|
||||
|
||||
// MustUint64 always returns value without error,
|
||||
// it returns 0 if error occurs.
|
||||
func (k *Key) MustUint64(defaultVal ...uint64) uint64 {
|
||||
val, err := k.Uint64()
|
||||
if len(defaultVal) > 0 && err != nil {
|
||||
k.value = strconv.FormatUint(defaultVal[0], 10)
|
||||
return defaultVal[0]
|
||||
}
|
||||
return val
|
||||
}
|
||||
|
||||
// MustDuration always returns value without error,
|
||||
// it returns zero value if error occurs.
|
||||
func (k *Key) MustDuration(defaultVal ...time.Duration) time.Duration {
|
||||
val, err := k.Duration()
|
||||
if len(defaultVal) > 0 && err != nil {
|
||||
k.value = defaultVal[0].String()
|
||||
return defaultVal[0]
|
||||
}
|
||||
return val
|
||||
}
|
||||
|
||||
// MustTimeFormat always parses with given format and returns value without error,
|
||||
// it returns zero value if error occurs.
|
||||
func (k *Key) MustTimeFormat(format string, defaultVal ...time.Time) time.Time {
|
||||
val, err := k.TimeFormat(format)
|
||||
if len(defaultVal) > 0 && err != nil {
|
||||
k.value = defaultVal[0].Format(format)
|
||||
return defaultVal[0]
|
||||
}
|
||||
return val
|
||||
}
|
||||
|
||||
// MustTime always parses with RFC3339 format and returns value without error,
|
||||
// it returns zero value if error occurs.
|
||||
func (k *Key) MustTime(defaultVal ...time.Time) time.Time {
|
||||
return k.MustTimeFormat(time.RFC3339, defaultVal...)
|
||||
}
|
||||
|
||||
// In always returns value without error,
|
||||
// it returns default value if error occurs or doesn't fit into candidates.
|
||||
func (k *Key) In(defaultVal string, candidates []string) string {
|
||||
val := k.String()
|
||||
for _, cand := range candidates {
|
||||
if val == cand {
|
||||
return val
|
||||
}
|
||||
}
|
||||
return defaultVal
|
||||
}
|
||||
|
||||
// InFloat64 always returns value without error,
|
||||
// it returns default value if error occurs or doesn't fit into candidates.
|
||||
func (k *Key) InFloat64(defaultVal float64, candidates []float64) float64 {
|
||||
val := k.MustFloat64()
|
||||
for _, cand := range candidates {
|
||||
if val == cand {
|
||||
return val
|
||||
}
|
||||
}
|
||||
return defaultVal
|
||||
}
|
||||
|
||||
// InInt always returns value without error,
|
||||
// it returns default value if error occurs or doesn't fit into candidates.
|
||||
func (k *Key) InInt(defaultVal int, candidates []int) int {
|
||||
val := k.MustInt()
|
||||
for _, cand := range candidates {
|
||||
if val == cand {
|
||||
return val
|
||||
}
|
||||
}
|
||||
return defaultVal
|
||||
}
|
||||
|
||||
// InInt64 always returns value without error,
|
||||
// it returns default value if error occurs or doesn't fit into candidates.
|
||||
func (k *Key) InInt64(defaultVal int64, candidates []int64) int64 {
|
||||
val := k.MustInt64()
|
||||
for _, cand := range candidates {
|
||||
if val == cand {
|
||||
return val
|
||||
}
|
||||
}
|
||||
return defaultVal
|
||||
}
|
||||
|
||||
// InUint always returns value without error,
|
||||
// it returns default value if error occurs or doesn't fit into candidates.
|
||||
func (k *Key) InUint(defaultVal uint, candidates []uint) uint {
|
||||
val := k.MustUint()
|
||||
for _, cand := range candidates {
|
||||
if val == cand {
|
||||
return val
|
||||
}
|
||||
}
|
||||
return defaultVal
|
||||
}
|
||||
|
||||
// InUint64 always returns value without error,
|
||||
// it returns default value if error occurs or doesn't fit into candidates.
|
||||
func (k *Key) InUint64(defaultVal uint64, candidates []uint64) uint64 {
|
||||
val := k.MustUint64()
|
||||
for _, cand := range candidates {
|
||||
if val == cand {
|
||||
return val
|
||||
}
|
||||
}
|
||||
return defaultVal
|
||||
}
|
||||
|
||||
// InTimeFormat always parses with given format and returns value without error,
|
||||
// it returns default value if error occurs or doesn't fit into candidates.
|
||||
func (k *Key) InTimeFormat(format string, defaultVal time.Time, candidates []time.Time) time.Time {
|
||||
val := k.MustTimeFormat(format)
|
||||
for _, cand := range candidates {
|
||||
if val == cand {
|
||||
return val
|
||||
}
|
||||
}
|
||||
return defaultVal
|
||||
}
|
||||
|
||||
// InTime always parses with RFC3339 format and returns value without error,
|
||||
// it returns default value if error occurs or doesn't fit into candidates.
|
||||
func (k *Key) InTime(defaultVal time.Time, candidates []time.Time) time.Time {
|
||||
return k.InTimeFormat(time.RFC3339, defaultVal, candidates)
|
||||
}
|
||||
|
||||
// RangeFloat64 checks if value is in given range inclusively,
|
||||
// and returns default value if it's not.
|
||||
func (k *Key) RangeFloat64(defaultVal, min, max float64) float64 {
|
||||
val := k.MustFloat64()
|
||||
if val < min || val > max {
|
||||
return defaultVal
|
||||
}
|
||||
return val
|
||||
}
|
||||
|
||||
// RangeInt checks if value is in given range inclusively,
|
||||
// and returns default value if it's not.
|
||||
func (k *Key) RangeInt(defaultVal, min, max int) int {
|
||||
val := k.MustInt()
|
||||
if val < min || val > max {
|
||||
return defaultVal
|
||||
}
|
||||
return val
|
||||
}
|
||||
|
||||
// RangeInt64 checks if value is in given range inclusively,
|
||||
// and returns default value if it's not.
|
||||
func (k *Key) RangeInt64(defaultVal, min, max int64) int64 {
|
||||
val := k.MustInt64()
|
||||
if val < min || val > max {
|
||||
return defaultVal
|
||||
}
|
||||
return val
|
||||
}
|
||||
|
||||
// RangeTimeFormat checks if value with given format is in given range inclusively,
|
||||
// and returns default value if it's not.
|
||||
func (k *Key) RangeTimeFormat(format string, defaultVal, min, max time.Time) time.Time {
|
||||
val := k.MustTimeFormat(format)
|
||||
if val.Unix() < min.Unix() || val.Unix() > max.Unix() {
|
||||
return defaultVal
|
||||
}
|
||||
return val
|
||||
}
|
||||
|
||||
// RangeTime checks if value with RFC3339 format is in given range inclusively,
|
||||
// and returns default value if it's not.
|
||||
func (k *Key) RangeTime(defaultVal, min, max time.Time) time.Time {
|
||||
return k.RangeTimeFormat(time.RFC3339, defaultVal, min, max)
|
||||
}
|
||||
|
||||
// Strings returns list of string divided by given delimiter.
|
||||
func (k *Key) Strings(delim string) []string {
|
||||
str := k.String()
|
||||
if len(str) == 0 {
|
||||
return []string{}
|
||||
}
|
||||
|
||||
vals := strings.Split(str, delim)
|
||||
for i := range vals {
|
||||
vals[i] = strings.TrimSpace(vals[i])
|
||||
}
|
||||
return vals
|
||||
}
|
||||
|
||||
// Float64s returns list of float64 divided by given delimiter. Any invalid input will be treated as zero value.
|
||||
func (k *Key) Float64s(delim string) []float64 {
|
||||
vals, _ := k.getFloat64s(delim, true, false)
|
||||
return vals
|
||||
}
|
||||
|
||||
// Ints returns list of int divided by given delimiter. Any invalid input will be treated as zero value.
|
||||
func (k *Key) Ints(delim string) []int {
|
||||
vals, _ := k.getInts(delim, true, false)
|
||||
return vals
|
||||
}
|
||||
|
||||
// Int64s returns list of int64 divided by given delimiter. Any invalid input will be treated as zero value.
|
||||
func (k *Key) Int64s(delim string) []int64 {
|
||||
vals, _ := k.getInt64s(delim, true, false)
|
||||
return vals
|
||||
}
|
||||
|
||||
// Uints returns list of uint divided by given delimiter. Any invalid input will be treated as zero value.
|
||||
func (k *Key) Uints(delim string) []uint {
|
||||
vals, _ := k.getUints(delim, true, false)
|
||||
return vals
|
||||
}
|
||||
|
||||
// Uint64s returns list of uint64 divided by given delimiter. Any invalid input will be treated as zero value.
|
||||
func (k *Key) Uint64s(delim string) []uint64 {
|
||||
vals, _ := k.getUint64s(delim, true, false)
|
||||
return vals
|
||||
}
|
||||
|
||||
// TimesFormat parses with given format and returns list of time.Time divided by given delimiter.
|
||||
// Any invalid input will be treated as zero value (0001-01-01 00:00:00 +0000 UTC).
|
||||
func (k *Key) TimesFormat(format, delim string) []time.Time {
|
||||
vals, _ := k.getTimesFormat(format, delim, true, false)
|
||||
return vals
|
||||
}
|
||||
|
||||
// Times parses with RFC3339 format and returns list of time.Time divided by given delimiter.
|
||||
// Any invalid input will be treated as zero value (0001-01-01 00:00:00 +0000 UTC).
|
||||
func (k *Key) Times(delim string) []time.Time {
|
||||
return k.TimesFormat(time.RFC3339, delim)
|
||||
}
|
||||
|
||||
// ValidFloat64s returns list of float64 divided by given delimiter. If some value is not float, then
|
||||
// it will not be included to result list.
|
||||
func (k *Key) ValidFloat64s(delim string) []float64 {
|
||||
vals, _ := k.getFloat64s(delim, false, false)
|
||||
return vals
|
||||
}
|
||||
|
||||
// ValidInts returns list of int divided by given delimiter. If some value is not integer, then it will
|
||||
// not be included to result list.
|
||||
func (k *Key) ValidInts(delim string) []int {
|
||||
vals, _ := k.getInts(delim, false, false)
|
||||
return vals
|
||||
}
|
||||
|
||||
// ValidInt64s returns list of int64 divided by given delimiter. If some value is not 64-bit integer,
|
||||
// then it will not be included to result list.
|
||||
func (k *Key) ValidInt64s(delim string) []int64 {
|
||||
vals, _ := k.getInt64s(delim, false, false)
|
||||
return vals
|
||||
}
|
||||
|
||||
// ValidUints returns list of uint divided by given delimiter. If some value is not unsigned integer,
|
||||
// then it will not be included to result list.
|
||||
func (k *Key) ValidUints(delim string) []uint {
|
||||
vals, _ := k.getUints(delim, false, false)
|
||||
return vals
|
||||
}
|
||||
|
||||
// ValidUint64s returns list of uint64 divided by given delimiter. If some value is not 64-bit unsigned
|
||||
// integer, then it will not be included to result list.
|
||||
func (k *Key) ValidUint64s(delim string) []uint64 {
|
||||
vals, _ := k.getUint64s(delim, false, false)
|
||||
return vals
|
||||
}
|
||||
|
||||
// ValidTimesFormat parses with given format and returns list of time.Time divided by given delimiter.
|
||||
func (k *Key) ValidTimesFormat(format, delim string) []time.Time {
|
||||
vals, _ := k.getTimesFormat(format, delim, false, false)
|
||||
return vals
|
||||
}
|
||||
|
||||
// ValidTimes parses with RFC3339 format and returns list of time.Time divided by given delimiter.
|
||||
func (k *Key) ValidTimes(delim string) []time.Time {
|
||||
return k.ValidTimesFormat(time.RFC3339, delim)
|
||||
}
|
||||
|
||||
// StrictFloat64s returns list of float64 divided by given delimiter or error on first invalid input.
|
||||
func (k *Key) StrictFloat64s(delim string) ([]float64, error) {
|
||||
return k.getFloat64s(delim, false, true)
|
||||
}
|
||||
|
||||
// StrictInts returns list of int divided by given delimiter or error on first invalid input.
|
||||
func (k *Key) StrictInts(delim string) ([]int, error) {
|
||||
return k.getInts(delim, false, true)
|
||||
}
|
||||
|
||||
// StrictInt64s returns list of int64 divided by given delimiter or error on first invalid input.
|
||||
func (k *Key) StrictInt64s(delim string) ([]int64, error) {
|
||||
return k.getInt64s(delim, false, true)
|
||||
}
|
||||
|
||||
// StrictUints returns list of uint divided by given delimiter or error on first invalid input.
|
||||
func (k *Key) StrictUints(delim string) ([]uint, error) {
|
||||
return k.getUints(delim, false, true)
|
||||
}
|
||||
|
||||
// StrictUint64s returns list of uint64 divided by given delimiter or error on first invalid input.
|
||||
func (k *Key) StrictUint64s(delim string) ([]uint64, error) {
|
||||
return k.getUint64s(delim, false, true)
|
||||
}
|
||||
|
||||
// StrictTimesFormat parses with given format and returns list of time.Time divided by given delimiter
|
||||
// or error on first invalid input.
|
||||
func (k *Key) StrictTimesFormat(format, delim string) ([]time.Time, error) {
|
||||
return k.getTimesFormat(format, delim, false, true)
|
||||
}
|
||||
|
||||
// StrictTimes parses with RFC3339 format and returns list of time.Time divided by given delimiter
|
||||
// or error on first invalid input.
|
||||
func (k *Key) StrictTimes(delim string) ([]time.Time, error) {
|
||||
return k.StrictTimesFormat(time.RFC3339, delim)
|
||||
}
|
||||
|
||||
// getFloat64s returns list of float64 divided by given delimiter.
|
||||
func (k *Key) getFloat64s(delim string, addInvalid, returnOnInvalid bool) ([]float64, error) {
|
||||
strs := k.Strings(delim)
|
||||
vals := make([]float64, 0, len(strs))
|
||||
for _, str := range strs {
|
||||
val, err := strconv.ParseFloat(str, 64)
|
||||
if err != nil && returnOnInvalid {
|
||||
return nil, err
|
||||
}
|
||||
if err == nil || addInvalid {
|
||||
vals = append(vals, val)
|
||||
}
|
||||
}
|
||||
return vals, nil
|
||||
}
|
||||
|
||||
// getInts returns list of int divided by given delimiter.
|
||||
func (k *Key) getInts(delim string, addInvalid, returnOnInvalid bool) ([]int, error) {
|
||||
strs := k.Strings(delim)
|
||||
vals := make([]int, 0, len(strs))
|
||||
for _, str := range strs {
|
||||
val, err := strconv.Atoi(str)
|
||||
if err != nil && returnOnInvalid {
|
||||
return nil, err
|
||||
}
|
||||
if err == nil || addInvalid {
|
||||
vals = append(vals, val)
|
||||
}
|
||||
}
|
||||
return vals, nil
|
||||
}
|
||||
|
||||
// getInt64s returns list of int64 divided by given delimiter.
|
||||
func (k *Key) getInt64s(delim string, addInvalid, returnOnInvalid bool) ([]int64, error) {
|
||||
strs := k.Strings(delim)
|
||||
vals := make([]int64, 0, len(strs))
|
||||
for _, str := range strs {
|
||||
val, err := strconv.ParseInt(str, 10, 64)
|
||||
if err != nil && returnOnInvalid {
|
||||
return nil, err
|
||||
}
|
||||
if err == nil || addInvalid {
|
||||
vals = append(vals, val)
|
||||
}
|
||||
}
|
||||
return vals, nil
|
||||
}
|
||||
|
||||
// getUints returns list of uint divided by given delimiter.
|
||||
func (k *Key) getUints(delim string, addInvalid, returnOnInvalid bool) ([]uint, error) {
|
||||
strs := k.Strings(delim)
|
||||
vals := make([]uint, 0, len(strs))
|
||||
for _, str := range strs {
|
||||
val, err := strconv.ParseUint(str, 10, 0)
|
||||
if err != nil && returnOnInvalid {
|
||||
return nil, err
|
||||
}
|
||||
if err == nil || addInvalid {
|
||||
vals = append(vals, uint(val))
|
||||
}
|
||||
}
|
||||
return vals, nil
|
||||
}
|
||||
|
||||
// getUint64s returns list of uint64 divided by given delimiter.
|
||||
func (k *Key) getUint64s(delim string, addInvalid, returnOnInvalid bool) ([]uint64, error) {
|
||||
strs := k.Strings(delim)
|
||||
vals := make([]uint64, 0, len(strs))
|
||||
for _, str := range strs {
|
||||
val, err := strconv.ParseUint(str, 10, 64)
|
||||
if err != nil && returnOnInvalid {
|
||||
return nil, err
|
||||
}
|
||||
if err == nil || addInvalid {
|
||||
vals = append(vals, val)
|
||||
}
|
||||
}
|
||||
return vals, nil
|
||||
}
|
||||
|
||||
// getTimesFormat parses with given format and returns list of time.Time divided by given delimiter.
|
||||
func (k *Key) getTimesFormat(format, delim string, addInvalid, returnOnInvalid bool) ([]time.Time, error) {
|
||||
strs := k.Strings(delim)
|
||||
vals := make([]time.Time, 0, len(strs))
|
||||
for _, str := range strs {
|
||||
val, err := time.Parse(format, str)
|
||||
if err != nil && returnOnInvalid {
|
||||
return nil, err
|
||||
}
|
||||
if err == nil || addInvalid {
|
||||
vals = append(vals, val)
|
||||
}
|
||||
}
|
||||
return vals, nil
|
||||
}
|
||||
|
||||
// SetValue changes key value.
|
||||
func (k *Key) SetValue(v string) {
|
||||
if k.s.f.BlockMode {
|
||||
k.s.f.lock.Lock()
|
||||
defer k.s.f.lock.Unlock()
|
||||
}
|
||||
|
||||
k.value = v
|
||||
k.s.keysHash[k.name] = v
|
||||
}
|
73
vendor/github.com/go-ini/ini/parser.go
generated
vendored
73
vendor/github.com/go-ini/ini/parser.go
generated
vendored
@ -48,16 +48,31 @@ func newParser(r io.Reader) *parser {
|
||||
}
|
||||
}
|
||||
|
||||
// BOM handles header of BOM-UTF8 format.
|
||||
// BOM handles header of UTF-8, UTF-16 LE and UTF-16 BE's BOM format.
|
||||
// http://en.wikipedia.org/wiki/Byte_order_mark#Representations_of_byte_order_marks_by_encoding
|
||||
func (p *parser) BOM() error {
|
||||
mask, err := p.buf.Peek(3)
|
||||
mask, err := p.buf.Peek(2)
|
||||
if err != nil && err != io.EOF {
|
||||
return err
|
||||
} else if len(mask) < 3 {
|
||||
} else if len(mask) < 2 {
|
||||
return nil
|
||||
} else if mask[0] == 239 && mask[1] == 187 && mask[2] == 191 {
|
||||
}
|
||||
|
||||
switch {
|
||||
case mask[0] == 254 && mask[1] == 255:
|
||||
fallthrough
|
||||
case mask[0] == 255 && mask[1] == 254:
|
||||
p.buf.Read(mask)
|
||||
case mask[0] == 239 && mask[1] == 187:
|
||||
mask, err := p.buf.Peek(3)
|
||||
if err != nil && err != io.EOF {
|
||||
return err
|
||||
} else if len(mask) < 3 {
|
||||
return nil
|
||||
}
|
||||
if mask[2] == 191 {
|
||||
p.buf.Read(mask)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@ -111,7 +126,7 @@ func readKeyName(in []byte) (string, int, error) {
|
||||
// Find key-value delimiter
|
||||
i := strings.IndexAny(line[pos+startIdx:], "=:")
|
||||
if i < 0 {
|
||||
return "", -1, fmt.Errorf("key-value delimiter not found: %s", line)
|
||||
return "", -1, ErrDelimiterNotFound{line}
|
||||
}
|
||||
endIdx = pos + i
|
||||
return strings.TrimSpace(line[startIdx:pos]), endIdx + startIdx + 1, nil
|
||||
@ -119,7 +134,7 @@ func readKeyName(in []byte) (string, int, error) {
|
||||
|
||||
endIdx = strings.IndexAny(line, "=:")
|
||||
if endIdx < 0 {
|
||||
return "", -1, fmt.Errorf("key-value delimiter not found: %s", line)
|
||||
return "", -1, ErrDelimiterNotFound{line}
|
||||
}
|
||||
return strings.TrimSpace(line[0:endIdx]), endIdx + 1, nil
|
||||
}
|
||||
@ -178,7 +193,7 @@ func hasSurroundedQuote(in string, quote byte) bool {
|
||||
strings.IndexByte(in[1:], quote) == len(in)-2
|
||||
}
|
||||
|
||||
func (p *parser) readValue(in []byte) (string, error) {
|
||||
func (p *parser) readValue(in []byte, ignoreContinuation bool) (string, error) {
|
||||
line := strings.TrimLeftFunc(string(in), unicode.IsSpace)
|
||||
if len(line) == 0 {
|
||||
return "", nil
|
||||
@ -205,8 +220,8 @@ func (p *parser) readValue(in []byte) (string, error) {
|
||||
// Won't be able to reach here if value only contains whitespace.
|
||||
line = strings.TrimSpace(line)
|
||||
|
||||
// Check continuation lines
|
||||
if line[len(line)-1] == '\\' {
|
||||
// Check continuation lines when desired.
|
||||
if !ignoreContinuation && line[len(line)-1] == '\\' {
|
||||
return p.readContinuationLines(line[:len(line)-1])
|
||||
}
|
||||
|
||||
@ -235,6 +250,7 @@ func (f *File) parse(reader io.Reader) (err error) {
|
||||
section, _ := f.NewSection(DEFAULT_SECTION)
|
||||
|
||||
var line []byte
|
||||
var inUnparseableSection bool
|
||||
for !p.isEOF {
|
||||
line, err = p.readUntil('\n')
|
||||
if err != nil {
|
||||
@ -258,12 +274,14 @@ func (f *File) parse(reader io.Reader) (err error) {
|
||||
// Section
|
||||
if line[0] == '[' {
|
||||
// Read to the next ']' (TODO: support quoted strings)
|
||||
closeIdx := bytes.IndexByte(line, ']')
|
||||
// TODO(unknwon): use LastIndexByte when stop supporting Go1.4
|
||||
closeIdx := bytes.LastIndex(line, []byte("]"))
|
||||
if closeIdx == -1 {
|
||||
return fmt.Errorf("unclosed section: %s", line)
|
||||
}
|
||||
|
||||
section, err = f.NewSection(string(line[1:closeIdx]))
|
||||
name := string(line[1:closeIdx])
|
||||
section, err = f.NewSection(name)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -278,11 +296,40 @@ func (f *File) parse(reader io.Reader) (err error) {
|
||||
// Reset aotu-counter and comments
|
||||
p.comment.Reset()
|
||||
p.count = 1
|
||||
|
||||
inUnparseableSection = false
|
||||
for i := range f.options.UnparseableSections {
|
||||
if f.options.UnparseableSections[i] == name ||
|
||||
(f.options.Insensitive && strings.ToLower(f.options.UnparseableSections[i]) == strings.ToLower(name)) {
|
||||
inUnparseableSection = true
|
||||
continue
|
||||
}
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
if inUnparseableSection {
|
||||
section.isRawSection = true
|
||||
section.rawBody += string(line)
|
||||
continue
|
||||
}
|
||||
|
||||
kname, offset, err := readKeyName(line)
|
||||
if err != nil {
|
||||
// Treat as boolean key when desired, and whole line is key name.
|
||||
if IsErrDelimiterNotFound(err) && f.options.AllowBooleanKeys {
|
||||
kname, err := p.readValue(line, f.options.IgnoreContinuation)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
key, err := section.NewBooleanKey(kname)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
key.Comment = strings.TrimSpace(p.comment.String())
|
||||
p.comment.Reset()
|
||||
continue
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
@ -298,9 +345,9 @@ func (f *File) parse(reader io.Reader) (err error) {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
key.isAutoIncr = isAutoIncr
|
||||
key.isAutoIncrement = isAutoIncr
|
||||
|
||||
value, err := p.readValue(line[offset:])
|
||||
value, err := p.readValue(line[offset:], f.options.IgnoreContinuation)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
232
vendor/github.com/go-ini/ini/section.go
generated
vendored
Normal file
232
vendor/github.com/go-ini/ini/section.go
generated
vendored
Normal file
@ -0,0 +1,232 @@
|
||||
// Copyright 2014 Unknwon
|
||||
//
|
||||
// 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.
|
||||
|
||||
package ini
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// Section represents a config section.
|
||||
type Section struct {
|
||||
f *File
|
||||
Comment string
|
||||
name string
|
||||
keys map[string]*Key
|
||||
keyList []string
|
||||
keysHash map[string]string
|
||||
|
||||
isRawSection bool
|
||||
rawBody string
|
||||
}
|
||||
|
||||
func newSection(f *File, name string) *Section {
|
||||
return &Section{
|
||||
f: f,
|
||||
name: name,
|
||||
keys: make(map[string]*Key),
|
||||
keyList: make([]string, 0, 10),
|
||||
keysHash: make(map[string]string),
|
||||
}
|
||||
}
|
||||
|
||||
// Name returns name of Section.
|
||||
func (s *Section) Name() string {
|
||||
return s.name
|
||||
}
|
||||
|
||||
// Body returns rawBody of Section if the section was marked as unparseable.
|
||||
// It still follows the other rules of the INI format surrounding leading/trailing whitespace.
|
||||
func (s *Section) Body() string {
|
||||
return strings.TrimSpace(s.rawBody)
|
||||
}
|
||||
|
||||
// NewKey creates a new key to given section.
|
||||
func (s *Section) NewKey(name, val string) (*Key, error) {
|
||||
if len(name) == 0 {
|
||||
return nil, errors.New("error creating new key: empty key name")
|
||||
} else if s.f.options.Insensitive {
|
||||
name = strings.ToLower(name)
|
||||
}
|
||||
|
||||
if s.f.BlockMode {
|
||||
s.f.lock.Lock()
|
||||
defer s.f.lock.Unlock()
|
||||
}
|
||||
|
||||
if inSlice(name, s.keyList) {
|
||||
s.keys[name].value = val
|
||||
return s.keys[name], nil
|
||||
}
|
||||
|
||||
s.keyList = append(s.keyList, name)
|
||||
s.keys[name] = &Key{
|
||||
s: s,
|
||||
name: name,
|
||||
value: val,
|
||||
}
|
||||
s.keysHash[name] = val
|
||||
return s.keys[name], nil
|
||||
}
|
||||
|
||||
// NewBooleanKey creates a new boolean type key to given section.
|
||||
func (s *Section) NewBooleanKey(name string) (*Key, error) {
|
||||
key, err := s.NewKey(name, "true")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
key.isBooleanType = true
|
||||
return key, nil
|
||||
}
|
||||
|
||||
// GetKey returns key in section by given name.
|
||||
func (s *Section) GetKey(name string) (*Key, error) {
|
||||
// FIXME: change to section level lock?
|
||||
if s.f.BlockMode {
|
||||
s.f.lock.RLock()
|
||||
}
|
||||
if s.f.options.Insensitive {
|
||||
name = strings.ToLower(name)
|
||||
}
|
||||
key := s.keys[name]
|
||||
if s.f.BlockMode {
|
||||
s.f.lock.RUnlock()
|
||||
}
|
||||
|
||||
if key == nil {
|
||||
// Check if it is a child-section.
|
||||
sname := s.name
|
||||
for {
|
||||
if i := strings.LastIndex(sname, "."); i > -1 {
|
||||
sname = sname[:i]
|
||||
sec, err := s.f.GetSection(sname)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
return sec.GetKey(name)
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
return nil, fmt.Errorf("error when getting key of section '%s': key '%s' not exists", s.name, name)
|
||||
}
|
||||
return key, nil
|
||||
}
|
||||
|
||||
// HasKey returns true if section contains a key with given name.
|
||||
func (s *Section) HasKey(name string) bool {
|
||||
key, _ := s.GetKey(name)
|
||||
return key != nil
|
||||
}
|
||||
|
||||
// Haskey is a backwards-compatible name for HasKey.
|
||||
func (s *Section) Haskey(name string) bool {
|
||||
return s.HasKey(name)
|
||||
}
|
||||
|
||||
// HasValue returns true if section contains given raw value.
|
||||
func (s *Section) HasValue(value string) bool {
|
||||
if s.f.BlockMode {
|
||||
s.f.lock.RLock()
|
||||
defer s.f.lock.RUnlock()
|
||||
}
|
||||
|
||||
for _, k := range s.keys {
|
||||
if value == k.value {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// Key assumes named Key exists in section and returns a zero-value when not.
|
||||
func (s *Section) Key(name string) *Key {
|
||||
key, err := s.GetKey(name)
|
||||
if err != nil {
|
||||
// It's OK here because the only possible error is empty key name,
|
||||
// but if it's empty, this piece of code won't be executed.
|
||||
key, _ = s.NewKey(name, "")
|
||||
return key
|
||||
}
|
||||
return key
|
||||
}
|
||||
|
||||
// Keys returns list of keys of section.
|
||||
func (s *Section) Keys() []*Key {
|
||||
keys := make([]*Key, len(s.keyList))
|
||||
for i := range s.keyList {
|
||||
keys[i] = s.Key(s.keyList[i])
|
||||
}
|
||||
return keys
|
||||
}
|
||||
|
||||
// ParentKeys returns list of keys of parent section.
|
||||
func (s *Section) ParentKeys() []*Key {
|
||||
var parentKeys []*Key
|
||||
sname := s.name
|
||||
for {
|
||||
if i := strings.LastIndex(sname, "."); i > -1 {
|
||||
sname = sname[:i]
|
||||
sec, err := s.f.GetSection(sname)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
parentKeys = append(parentKeys, sec.Keys()...)
|
||||
} else {
|
||||
break
|
||||
}
|
||||
|
||||
}
|
||||
return parentKeys
|
||||
}
|
||||
|
||||
// KeyStrings returns list of key names of section.
|
||||
func (s *Section) KeyStrings() []string {
|
||||
list := make([]string, len(s.keyList))
|
||||
copy(list, s.keyList)
|
||||
return list
|
||||
}
|
||||
|
||||
// KeysHash returns keys hash consisting of names and values.
|
||||
func (s *Section) KeysHash() map[string]string {
|
||||
if s.f.BlockMode {
|
||||
s.f.lock.RLock()
|
||||
defer s.f.lock.RUnlock()
|
||||
}
|
||||
|
||||
hash := map[string]string{}
|
||||
for key, value := range s.keysHash {
|
||||
hash[key] = value
|
||||
}
|
||||
return hash
|
||||
}
|
||||
|
||||
// DeleteKey deletes a key from section.
|
||||
func (s *Section) DeleteKey(name string) {
|
||||
if s.f.BlockMode {
|
||||
s.f.lock.Lock()
|
||||
defer s.f.lock.Unlock()
|
||||
}
|
||||
|
||||
for i, k := range s.keyList {
|
||||
if k == name {
|
||||
s.keyList = append(s.keyList[:i], s.keyList[i+1:]...)
|
||||
delete(s.keys, name)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
186
vendor/github.com/go-ini/ini/struct.go
generated
vendored
186
vendor/github.com/go-ini/ini/struct.go
generated
vendored
@ -19,6 +19,7 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"reflect"
|
||||
"strings"
|
||||
"time"
|
||||
"unicode"
|
||||
)
|
||||
@ -76,6 +77,59 @@ func parseDelim(actual string) string {
|
||||
|
||||
var reflectTime = reflect.TypeOf(time.Now()).Kind()
|
||||
|
||||
// setSliceWithProperType sets proper values to slice based on its type.
|
||||
func setSliceWithProperType(key *Key, field reflect.Value, delim string) error {
|
||||
strs := key.Strings(delim)
|
||||
numVals := len(strs)
|
||||
if numVals == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
var vals interface{}
|
||||
|
||||
sliceOf := field.Type().Elem().Kind()
|
||||
switch sliceOf {
|
||||
case reflect.String:
|
||||
vals = strs
|
||||
case reflect.Int:
|
||||
vals = key.Ints(delim)
|
||||
case reflect.Int64:
|
||||
vals = key.Int64s(delim)
|
||||
case reflect.Uint:
|
||||
vals = key.Uints(delim)
|
||||
case reflect.Uint64:
|
||||
vals = key.Uint64s(delim)
|
||||
case reflect.Float64:
|
||||
vals = key.Float64s(delim)
|
||||
case reflectTime:
|
||||
vals = key.Times(delim)
|
||||
default:
|
||||
return fmt.Errorf("unsupported type '[]%s'", sliceOf)
|
||||
}
|
||||
|
||||
slice := reflect.MakeSlice(field.Type(), numVals, numVals)
|
||||
for i := 0; i < numVals; i++ {
|
||||
switch sliceOf {
|
||||
case reflect.String:
|
||||
slice.Index(i).Set(reflect.ValueOf(vals.([]string)[i]))
|
||||
case reflect.Int:
|
||||
slice.Index(i).Set(reflect.ValueOf(vals.([]int)[i]))
|
||||
case reflect.Int64:
|
||||
slice.Index(i).Set(reflect.ValueOf(vals.([]int64)[i]))
|
||||
case reflect.Uint:
|
||||
slice.Index(i).Set(reflect.ValueOf(vals.([]uint)[i]))
|
||||
case reflect.Uint64:
|
||||
slice.Index(i).Set(reflect.ValueOf(vals.([]uint64)[i]))
|
||||
case reflect.Float64:
|
||||
slice.Index(i).Set(reflect.ValueOf(vals.([]float64)[i]))
|
||||
case reflectTime:
|
||||
slice.Index(i).Set(reflect.ValueOf(vals.([]time.Time)[i]))
|
||||
}
|
||||
}
|
||||
field.Set(slice)
|
||||
return nil
|
||||
}
|
||||
|
||||
// setWithProperType sets proper value to field based on its type,
|
||||
// but it does not return error for failing parsing,
|
||||
// because we want to use default value that is already assigned to strcut.
|
||||
@ -108,7 +162,8 @@ func setWithProperType(t reflect.Type, key *Key, field reflect.Value, delim stri
|
||||
// byte is an alias for uint8, so supporting uint8 breaks support for byte
|
||||
case reflect.Uint, reflect.Uint16, reflect.Uint32, reflect.Uint64:
|
||||
durationVal, err := key.Duration()
|
||||
if err == nil {
|
||||
// Skip zero value
|
||||
if err == nil && int(durationVal) > 0 {
|
||||
field.Set(reflect.ValueOf(durationVal))
|
||||
return nil
|
||||
}
|
||||
@ -119,7 +174,7 @@ func setWithProperType(t reflect.Type, key *Key, field reflect.Value, delim stri
|
||||
}
|
||||
field.SetUint(uintVal)
|
||||
|
||||
case reflect.Float64:
|
||||
case reflect.Float32, reflect.Float64:
|
||||
floatVal, err := key.Float64()
|
||||
if err != nil {
|
||||
return nil
|
||||
@ -132,29 +187,7 @@ func setWithProperType(t reflect.Type, key *Key, field reflect.Value, delim stri
|
||||
}
|
||||
field.Set(reflect.ValueOf(timeVal))
|
||||
case reflect.Slice:
|
||||
vals := key.Strings(delim)
|
||||
numVals := len(vals)
|
||||
if numVals == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
sliceOf := field.Type().Elem().Kind()
|
||||
|
||||
var times []time.Time
|
||||
if sliceOf == reflectTime {
|
||||
times = key.Times(delim)
|
||||
}
|
||||
|
||||
slice := reflect.MakeSlice(field.Type(), numVals, numVals)
|
||||
for i := 0; i < numVals; i++ {
|
||||
switch sliceOf {
|
||||
case reflectTime:
|
||||
slice.Index(i).Set(reflect.ValueOf(times[i]))
|
||||
default:
|
||||
slice.Index(i).Set(reflect.ValueOf(vals[i]))
|
||||
}
|
||||
}
|
||||
field.Set(slice)
|
||||
return setSliceWithProperType(key, field, delim)
|
||||
default:
|
||||
return fmt.Errorf("unsupported type '%s'", t)
|
||||
}
|
||||
@ -176,7 +209,8 @@ func (s *Section) mapTo(val reflect.Value) error {
|
||||
continue
|
||||
}
|
||||
|
||||
fieldName := s.parseFieldName(tpField.Name, tag)
|
||||
opts := strings.SplitN(tag, ",", 2) // strip off possible omitempty
|
||||
fieldName := s.parseFieldName(tpField.Name, opts[0])
|
||||
if len(fieldName) == 0 || !field.CanSet() {
|
||||
continue
|
||||
}
|
||||
@ -239,40 +273,81 @@ func MapTo(v, source interface{}, others ...interface{}) error {
|
||||
return MapToWithMapper(v, nil, source, others...)
|
||||
}
|
||||
|
||||
// reflectWithProperType does the opposite thing with setWithProperType.
|
||||
// reflectSliceWithProperType does the opposite thing as setSliceWithProperType.
|
||||
func reflectSliceWithProperType(key *Key, field reflect.Value, delim string) error {
|
||||
slice := field.Slice(0, field.Len())
|
||||
if field.Len() == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
var buf bytes.Buffer
|
||||
sliceOf := field.Type().Elem().Kind()
|
||||
for i := 0; i < field.Len(); i++ {
|
||||
switch sliceOf {
|
||||
case reflect.String:
|
||||
buf.WriteString(slice.Index(i).String())
|
||||
case reflect.Int, reflect.Int64:
|
||||
buf.WriteString(fmt.Sprint(slice.Index(i).Int()))
|
||||
case reflect.Uint, reflect.Uint64:
|
||||
buf.WriteString(fmt.Sprint(slice.Index(i).Uint()))
|
||||
case reflect.Float64:
|
||||
buf.WriteString(fmt.Sprint(slice.Index(i).Float()))
|
||||
case reflectTime:
|
||||
buf.WriteString(slice.Index(i).Interface().(time.Time).Format(time.RFC3339))
|
||||
default:
|
||||
return fmt.Errorf("unsupported type '[]%s'", sliceOf)
|
||||
}
|
||||
buf.WriteString(delim)
|
||||
}
|
||||
key.SetValue(buf.String()[:buf.Len()-1])
|
||||
return nil
|
||||
}
|
||||
|
||||
// reflectWithProperType does the opposite thing as setWithProperType.
|
||||
func reflectWithProperType(t reflect.Type, key *Key, field reflect.Value, delim string) error {
|
||||
switch t.Kind() {
|
||||
case reflect.String:
|
||||
key.SetValue(field.String())
|
||||
case reflect.Bool,
|
||||
reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64,
|
||||
reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64,
|
||||
reflect.Float64,
|
||||
reflectTime:
|
||||
key.SetValue(fmt.Sprint(field))
|
||||
case reflect.Bool:
|
||||
key.SetValue(fmt.Sprint(field.Bool()))
|
||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||
key.SetValue(fmt.Sprint(field.Int()))
|
||||
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
|
||||
key.SetValue(fmt.Sprint(field.Uint()))
|
||||
case reflect.Float32, reflect.Float64:
|
||||
key.SetValue(fmt.Sprint(field.Float()))
|
||||
case reflectTime:
|
||||
key.SetValue(fmt.Sprint(field.Interface().(time.Time).Format(time.RFC3339)))
|
||||
case reflect.Slice:
|
||||
vals := field.Slice(0, field.Len())
|
||||
if field.Len() == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
var buf bytes.Buffer
|
||||
isTime := fmt.Sprint(field.Type()) == "[]time.Time"
|
||||
for i := 0; i < field.Len(); i++ {
|
||||
if isTime {
|
||||
buf.WriteString(vals.Index(i).Interface().(time.Time).Format(time.RFC3339))
|
||||
} else {
|
||||
buf.WriteString(fmt.Sprint(vals.Index(i)))
|
||||
}
|
||||
buf.WriteString(delim)
|
||||
}
|
||||
key.SetValue(buf.String()[:buf.Len()-1])
|
||||
return reflectSliceWithProperType(key, field, delim)
|
||||
default:
|
||||
return fmt.Errorf("unsupported type '%s'", t)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// CR: copied from encoding/json/encode.go with modifications of time.Time support.
|
||||
// TODO: add more test coverage.
|
||||
func isEmptyValue(v reflect.Value) bool {
|
||||
switch v.Kind() {
|
||||
case reflect.Array, reflect.Map, reflect.Slice, reflect.String:
|
||||
return v.Len() == 0
|
||||
case reflect.Bool:
|
||||
return !v.Bool()
|
||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||
return v.Int() == 0
|
||||
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
|
||||
return v.Uint() == 0
|
||||
case reflect.Float32, reflect.Float64:
|
||||
return v.Float() == 0
|
||||
case reflectTime:
|
||||
return v.Interface().(time.Time).IsZero()
|
||||
case reflect.Interface, reflect.Ptr:
|
||||
return v.IsNil()
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (s *Section) reflectFrom(val reflect.Value) error {
|
||||
if val.Kind() == reflect.Ptr {
|
||||
val = val.Elem()
|
||||
@ -288,13 +363,18 @@ func (s *Section) reflectFrom(val reflect.Value) error {
|
||||
continue
|
||||
}
|
||||
|
||||
fieldName := s.parseFieldName(tpField.Name, tag)
|
||||
opts := strings.SplitN(tag, ",", 2)
|
||||
if len(opts) == 2 && opts[1] == "omitempty" && isEmptyValue(field) {
|
||||
continue
|
||||
}
|
||||
|
||||
fieldName := s.parseFieldName(tpField.Name, opts[0])
|
||||
if len(fieldName) == 0 || !field.CanSet() {
|
||||
continue
|
||||
}
|
||||
|
||||
if (tpField.Type.Kind() == reflect.Ptr && tpField.Anonymous) ||
|
||||
(tpField.Type.Kind() == reflect.Struct) {
|
||||
(tpField.Type.Kind() == reflect.Struct && tpField.Type.Name() != "Time") {
|
||||
// Note: The only error here is section doesn't exist.
|
||||
sec, err := s.f.GetSection(fieldName)
|
||||
if err != nil {
|
||||
@ -302,7 +382,7 @@ func (s *Section) reflectFrom(val reflect.Value) error {
|
||||
sec, _ = s.f.NewSection(fieldName)
|
||||
}
|
||||
if err = sec.reflectFrom(field); err != nil {
|
||||
return fmt.Errorf("error reflecting field(%s): %v", fieldName, err)
|
||||
return fmt.Errorf("error reflecting field (%s): %v", fieldName, err)
|
||||
}
|
||||
continue
|
||||
}
|
||||
@ -313,7 +393,7 @@ func (s *Section) reflectFrom(val reflect.Value) error {
|
||||
key, _ = s.NewKey(fieldName, "")
|
||||
}
|
||||
if err = reflectWithProperType(tpField.Type, key, field, parseDelim(tpField.Tag.Get("delim"))); err != nil {
|
||||
return fmt.Errorf("error reflecting field(%s): %v", fieldName, err)
|
||||
return fmt.Errorf("error reflecting field (%s): %v", fieldName, err)
|
||||
}
|
||||
|
||||
}
|
||||
|
10
vendor/github.com/google/go-querystring/query/encode.go
generated
vendored
10
vendor/github.com/google/go-querystring/query/encode.go
generated
vendored
@ -217,11 +217,6 @@ func reflectValue(values url.Values, val reflect.Value, scope string) error {
|
||||
continue
|
||||
}
|
||||
|
||||
if sv.Type() == timeType {
|
||||
values.Add(name, valueString(sv, opts))
|
||||
continue
|
||||
}
|
||||
|
||||
for sv.Kind() == reflect.Ptr {
|
||||
if sv.IsNil() {
|
||||
break
|
||||
@ -229,6 +224,11 @@ func reflectValue(values url.Values, val reflect.Value, scope string) error {
|
||||
sv = sv.Elem()
|
||||
}
|
||||
|
||||
if sv.Type() == timeType {
|
||||
values.Add(name, valueString(sv, opts))
|
||||
continue
|
||||
}
|
||||
|
||||
if sv.Kind() == reflect.Struct {
|
||||
reflectValue(values, sv, name)
|
||||
continue
|
||||
|
2
vendor/github.com/jmespath/go-jmespath/.gitignore
generated
vendored
2
vendor/github.com/jmespath/go-jmespath/.gitignore
generated
vendored
@ -1,4 +1,4 @@
|
||||
jpgo
|
||||
/jpgo
|
||||
jmespath-fuzz.zip
|
||||
cpu.out
|
||||
go-jmespath.test
|
||||
|
51
vendor/github.com/pkg/sftp/client.go
generated
vendored
51
vendor/github.com/pkg/sftp/client.go
generated
vendored
@ -495,7 +495,7 @@ func (c *Client) Remove(path string) error {
|
||||
// some servers, *cough* osx *cough*, return EPERM, not ENODIR.
|
||||
// serv-u returns ssh_FX_FILE_IS_A_DIRECTORY
|
||||
case ssh_FX_PERMISSION_DENIED, ssh_FX_FAILURE, ssh_FX_FILE_IS_A_DIRECTORY:
|
||||
return c.removeDirectory(path)
|
||||
return c.RemoveDirectory(path)
|
||||
}
|
||||
}
|
||||
return err
|
||||
@ -518,7 +518,8 @@ func (c *Client) removeFile(path string) error {
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Client) removeDirectory(path string) error {
|
||||
// RemoveDirectory removes a directory path.
|
||||
func (c *Client) RemoveDirectory(path string) error {
|
||||
id := c.nextID()
|
||||
typ, data, err := c.sendPacket(sshFxpRmdirPacket{
|
||||
ID: id,
|
||||
@ -652,7 +653,7 @@ func (f *File) Read(b []byte) (int, error) {
|
||||
inFlight := 0
|
||||
desiredInFlight := 1
|
||||
offset := f.offset
|
||||
ch := make(chan result, 1)
|
||||
ch := make(chan result, 2)
|
||||
type inflightRead struct {
|
||||
b []byte
|
||||
offset uint64
|
||||
@ -751,7 +752,7 @@ func (f *File) WriteTo(w io.Writer) (int64, error) {
|
||||
offset := f.offset
|
||||
writeOffset := offset
|
||||
fileSize := uint64(fi.Size())
|
||||
ch := make(chan result, 1)
|
||||
ch := make(chan result, 2)
|
||||
type inflightRead struct {
|
||||
b []byte
|
||||
offset uint64
|
||||
@ -778,16 +779,21 @@ func (f *File) WriteTo(w io.Writer) (int64, error) {
|
||||
|
||||
var copied int64
|
||||
for firstErr.err == nil || inFlight > 0 {
|
||||
for inFlight < desiredInFlight && firstErr.err == nil {
|
||||
b := make([]byte, f.c.maxPacket)
|
||||
sendReq(b, offset)
|
||||
offset += uint64(f.c.maxPacket)
|
||||
if offset > fileSize {
|
||||
desiredInFlight = 1
|
||||
if firstErr.err == nil {
|
||||
for inFlight+len(pendingWrites) < desiredInFlight {
|
||||
b := make([]byte, f.c.maxPacket)
|
||||
sendReq(b, offset)
|
||||
offset += uint64(f.c.maxPacket)
|
||||
if offset > fileSize {
|
||||
desiredInFlight = 1
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if inFlight == 0 {
|
||||
if firstErr.err == nil && len(pendingWrites) > 0 {
|
||||
return copied, errors.New("internal inconsistency")
|
||||
}
|
||||
break
|
||||
}
|
||||
select {
|
||||
@ -816,6 +822,8 @@ func (f *File) WriteTo(w io.Writer) (int64, error) {
|
||||
nbytes, err := w.Write(data)
|
||||
copied += int64(nbytes)
|
||||
if err != nil {
|
||||
// We will never receive another DATA with offset==writeOffset, so
|
||||
// the loop will drain inFlight and then exit.
|
||||
firstErr = offsetErr{offset: req.offset + uint64(nbytes), err: err}
|
||||
break
|
||||
}
|
||||
@ -830,8 +838,16 @@ func (f *File) WriteTo(w io.Writer) (int64, error) {
|
||||
desiredInFlight++
|
||||
}
|
||||
writeOffset += uint64(nbytes)
|
||||
for pendingData, ok := pendingWrites[writeOffset]; ok; pendingData, ok = pendingWrites[writeOffset] {
|
||||
for {
|
||||
pendingData, ok := pendingWrites[writeOffset]
|
||||
if !ok {
|
||||
break
|
||||
}
|
||||
// Give go a chance to free the memory.
|
||||
delete(pendingWrites, writeOffset)
|
||||
nbytes, err := w.Write(pendingData)
|
||||
// Do not move writeOffset on error so subsequent iterations won't trigger
|
||||
// any writes.
|
||||
if err != nil {
|
||||
firstErr = offsetErr{offset: writeOffset + uint64(nbytes), err: err}
|
||||
break
|
||||
@ -841,14 +857,12 @@ func (f *File) WriteTo(w io.Writer) (int64, error) {
|
||||
break
|
||||
}
|
||||
writeOffset += uint64(nbytes)
|
||||
inFlight--
|
||||
}
|
||||
} else {
|
||||
// Don't write the data yet because
|
||||
// this response came in out of order
|
||||
// and we need to wait for responses
|
||||
// for earlier segments of the file.
|
||||
inFlight++ // Pending writes should still be considered inFlight.
|
||||
pendingWrites[req.offset] = data
|
||||
}
|
||||
default:
|
||||
@ -884,7 +898,8 @@ func (f *File) Write(b []byte) (int, error) {
|
||||
inFlight := 0
|
||||
desiredInFlight := 1
|
||||
offset := f.offset
|
||||
ch := make(chan result, 1)
|
||||
// chan must have a buffer of max value of (desiredInFlight - inFlight)
|
||||
ch := make(chan result, 2)
|
||||
var firstErr error
|
||||
written := len(b)
|
||||
for len(b) > 0 || inFlight > 0 {
|
||||
@ -947,7 +962,8 @@ func (f *File) ReadFrom(r io.Reader) (int64, error) {
|
||||
inFlight := 0
|
||||
desiredInFlight := 1
|
||||
offset := f.offset
|
||||
ch := make(chan result, 1)
|
||||
// chan must have a buffer of max value of (desiredInFlight - inFlight)
|
||||
ch := make(chan result, 2)
|
||||
var firstErr error
|
||||
read := int64(0)
|
||||
b := make([]byte, f.c.maxPacket)
|
||||
@ -1081,10 +1097,7 @@ func unmarshalStatus(id uint32, data []byte) error {
|
||||
return &unexpectedIDErr{id, sid}
|
||||
}
|
||||
code, data := unmarshalUint32(data)
|
||||
msg, data, err := unmarshalStringSafe(data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
msg, data, _ := unmarshalStringSafe(data)
|
||||
lang, _, _ := unmarshalStringSafe(data)
|
||||
return &StatusError{
|
||||
Code: code,
|
||||
|
5
vendor/github.com/pkg/sftp/conn.go
generated
vendored
5
vendor/github.com/pkg/sftp/conn.go
generated
vendored
@ -14,6 +14,8 @@ type conn struct {
|
||||
io.Reader
|
||||
io.WriteCloser
|
||||
sync.Mutex // used to serialise writes to sendPacket
|
||||
// sendPacketTest is needed to replicate packet issues in testing
|
||||
sendPacketTest func(w io.Writer, m encoding.BinaryMarshaler) error
|
||||
}
|
||||
|
||||
func (c *conn) recvPacket() (uint8, []byte, error) {
|
||||
@ -23,6 +25,9 @@ func (c *conn) recvPacket() (uint8, []byte, error) {
|
||||
func (c *conn) sendPacket(m encoding.BinaryMarshaler) error {
|
||||
c.Lock()
|
||||
defer c.Unlock()
|
||||
if c.sendPacketTest != nil {
|
||||
return c.sendPacketTest(c, m)
|
||||
}
|
||||
return sendPacket(c, m)
|
||||
}
|
||||
|
||||
|
1
vendor/github.com/rfjakob/eme/.travis.yml
generated
vendored
Normal file
1
vendor/github.com/rfjakob/eme/.travis.yml
generated
vendored
Normal file
@ -0,0 +1 @@
|
||||
language: go
|
24
vendor/github.com/rfjakob/eme/README.md
generated
vendored
24
vendor/github.com/rfjakob/eme/README.md
generated
vendored
@ -1,13 +1,15 @@
|
||||
EME for Go [![Build Status](https://drone.io/github.com/rfjakob/eme/status.png)](https://drone.io/github.com/rfjakob/eme/latest) [![GoDoc](https://godoc.org/github.com/rfjakob/eme?status.svg)](https://godoc.org/github.com/rfjakob/eme) ![MIT License](https://img.shields.io/badge/license-MIT-blue.svg)
|
||||
EME for Go [![Build Status](https://travis-ci.org/rfjakob/eme.svg?branch=master)](https://travis-ci.org/rfjakob/eme) [![GoDoc](https://godoc.org/github.com/rfjakob/eme?status.svg)](https://godoc.org/github.com/rfjakob/eme) ![MIT License](https://img.shields.io/badge/license-MIT-blue.svg)
|
||||
==========
|
||||
|
||||
EME (ECB-Mix-ECB) is a wide-block encryption mode developed by Halevi
|
||||
and Rogaway in 2003 [eme]. (see references below)
|
||||
**EME** (ECB-Mix-ECB or, clearer, **Encrypt-Mix-Encrypt**) is a wide-block
|
||||
encryption mode developed by Halevi
|
||||
and Rogaway in 2003 _[eme]_ (square-bracketed italics like _[this]_ are literature references, detailed in the
|
||||
References secion).
|
||||
|
||||
EME uses multiple invocations of a block cipher to construct a new
|
||||
cipher of bigger block size (in multiples of 16 bytes, up to 2048 bytes).
|
||||
|
||||
Quoting from the original [eme] paper:
|
||||
Quoting from the original _[eme]_ paper:
|
||||
|
||||
> We describe a block-cipher mode of operation, EME, that turns an n-bit block cipher into
|
||||
> a tweakable enciphering scheme that acts on strings of mn bits, where m ∈ [1..n]. The mode is
|
||||
@ -16,24 +18,28 @@ Quoting from the original [eme] paper:
|
||||
> and a “lightweight mixing” in between. We prove EME secure, in the reduction-based sense of
|
||||
> modern cryptography.
|
||||
|
||||
Figure 2 from the _[eme]_ paper shows an overview of the transformation:
|
||||
|
||||
[![Figure 2 form [eme]](paper-eme-fig2.png)](#)
|
||||
|
||||
This is an implementation of EME in Go, complete with test vectors from IEEE.
|
||||
|
||||
Is it patentend?
|
||||
----------------
|
||||
|
||||
In 2007, the UC Davis has decided to abandon [patabandon] the patent
|
||||
application for EME [patappl].
|
||||
In 2007, the UC Davis has decided to abandon _[patabandon]_ the patent
|
||||
application for EME _[patappl]_.
|
||||
|
||||
Related algorithms
|
||||
------------------
|
||||
|
||||
**EME-32** is EME with the cipher set to AES and the length set to 512.
|
||||
That is, EME-32 [eme-32-pdf] is a subset of EME.
|
||||
That is, EME-32 _[eme-32-pdf]_ is a subset of EME.
|
||||
|
||||
**EME2**, also known as EME* [emestar], is an extended version of EME
|
||||
**EME2**, also known as EME* _[emestar]_, is an extended version of EME
|
||||
that has built-in handling for data that is not a multiple of 16 bytes
|
||||
long.
|
||||
EME2 has been selected for standardization in IEEE P1619.2 [p1619.2].
|
||||
EME2 has been selected for standardization in IEEE P1619.2 _[p1619.2]_.
|
||||
|
||||
References
|
||||
----------
|
||||
|
BIN
vendor/github.com/rfjakob/eme/paper-eme-fig2.png
generated
vendored
Normal file
BIN
vendor/github.com/rfjakob/eme/paper-eme-fig2.png
generated
vendored
Normal file
Binary file not shown.
After Width: | Height: | Size: 9.4 KiB |
9
vendor/github.com/russross/blackfriday/README.md
generated
vendored
9
vendor/github.com/russross/blackfriday/README.md
generated
vendored
@ -169,6 +169,15 @@ implements the following extensions:
|
||||
You can use 3 or more backticks to mark the beginning of the
|
||||
block, and the same number to mark the end of the block.
|
||||
|
||||
To preserve classes of fenced code blocks while using the bluemonday
|
||||
HTML sanitizer, use the following policy:
|
||||
|
||||
``` go
|
||||
p := bluemonday.UGCPolicy()
|
||||
p.AllowAttrs("class").Matching(regexp.MustCompile("^language-[a-zA-Z0-9]+$")).OnElements("code")
|
||||
html := p.SanitizeBytes(unsafe)
|
||||
```
|
||||
|
||||
* **Definition lists**. A simple definition list is made of a single-line
|
||||
term followed by a colon and the definition for that term.
|
||||
|
||||
|
6
vendor/github.com/russross/blackfriday/block.go
generated
vendored
6
vendor/github.com/russross/blackfriday/block.go
generated
vendored
@ -1244,6 +1244,12 @@ gatherlines:
|
||||
line = i
|
||||
}
|
||||
|
||||
// If reached end of data, the Renderer.ListItem call we're going to make below
|
||||
// is definitely the last in the list.
|
||||
if line >= len(data) {
|
||||
*flags |= LIST_ITEM_END_OF_LIST
|
||||
}
|
||||
|
||||
rawBytes := raw.Bytes()
|
||||
|
||||
// render the contents of the list item
|
||||
|
10
vendor/github.com/shurcooL/sanitized_anchor_name/.travis.yml
generated
vendored
10
vendor/github.com/shurcooL/sanitized_anchor_name/.travis.yml
generated
vendored
@ -1,8 +1,14 @@
|
||||
sudo: false
|
||||
language: go
|
||||
go:
|
||||
- 1.5
|
||||
- 1.7
|
||||
- tip
|
||||
matrix:
|
||||
allow_failures:
|
||||
- go: tip
|
||||
fast_finish: true
|
||||
install:
|
||||
- go get golang.org/x/tools/cmd/vet
|
||||
- # Do nothing. This is needed to prevent default install action "go get -t -v ./..." from happening here (we want it to happen inside script step).
|
||||
script:
|
||||
- go get -t -v ./...
|
||||
- diff -u <(echo -n) <(gofmt -d -s .)
|
||||
|
7
vendor/github.com/shurcooL/sanitized_anchor_name/README.md
generated
vendored
7
vendor/github.com/shurcooL/sanitized_anchor_name/README.md
generated
vendored
@ -1,4 +1,7 @@
|
||||
# sanitized_anchor_name [![Build Status](https://travis-ci.org/shurcooL/sanitized_anchor_name.svg?branch=master)](https://travis-ci.org/shurcooL/sanitized_anchor_name) [![GoDoc](https://godoc.org/github.com/shurcooL/sanitized_anchor_name?status.svg)](https://godoc.org/github.com/shurcooL/sanitized_anchor_name)
|
||||
sanitized_anchor_name
|
||||
=====================
|
||||
|
||||
[![Build Status](https://travis-ci.org/shurcooL/sanitized_anchor_name.svg?branch=master)](https://travis-ci.org/shurcooL/sanitized_anchor_name) [![GoDoc](https://godoc.org/github.com/shurcooL/sanitized_anchor_name?status.svg)](https://godoc.org/github.com/shurcooL/sanitized_anchor_name)
|
||||
|
||||
Package sanitized_anchor_name provides a func to create sanitized anchor names.
|
||||
|
||||
@ -28,4 +31,4 @@ fmt.Println(anchorName)
|
||||
License
|
||||
-------
|
||||
|
||||
- [MIT License](LICENSE)
|
||||
- [MIT License](LICENSE)
|
||||
|
8
vendor/github.com/spf13/cobra/bash_completions.go
generated
vendored
8
vendor/github.com/spf13/cobra/bash_completions.go
generated
vendored
@ -10,6 +10,7 @@ import (
|
||||
"github.com/spf13/pflag"
|
||||
)
|
||||
|
||||
// Annotations for Bash completion.
|
||||
const (
|
||||
BashCompFilenameExt = "cobra_annotation_bash_completion_filename_extensions"
|
||||
BashCompCustom = "cobra_annotation_bash_completion_custom"
|
||||
@ -22,7 +23,7 @@ func preamble(out io.Writer, name string) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = fmt.Fprint(out, `
|
||||
preamStr := `
|
||||
__debug()
|
||||
{
|
||||
if [[ -n ${BASH_COMP_DEBUG_FILE} ]]; then
|
||||
@ -246,7 +247,8 @@ __handle_word()
|
||||
__handle_word
|
||||
}
|
||||
|
||||
`)
|
||||
`
|
||||
_, err = fmt.Fprint(out, preamStr)
|
||||
return err
|
||||
}
|
||||
|
||||
@ -566,6 +568,7 @@ func gen(cmd *Command, w io.Writer) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// GenBashCompletion generates bash completion file and writes to the passed writer.
|
||||
func (cmd *Command) GenBashCompletion(w io.Writer) error {
|
||||
if err := preamble(w, cmd.Name()); err != nil {
|
||||
return err
|
||||
@ -585,6 +588,7 @@ func nonCompletableFlag(flag *pflag.Flag) bool {
|
||||
return flag.Hidden || len(flag.Deprecated) > 0
|
||||
}
|
||||
|
||||
// GenBashCompletionFile generates bash completion file.
|
||||
func (cmd *Command) GenBashCompletionFile(filename string) error {
|
||||
outFile, err := os.Create(filename)
|
||||
if err != nil {
|
||||
|
2
vendor/github.com/spf13/cobra/bash_completions.md
generated
vendored
2
vendor/github.com/spf13/cobra/bash_completions.md
generated
vendored
@ -18,7 +18,7 @@ func main() {
|
||||
}
|
||||
```
|
||||
|
||||
That will get you completions of subcommands and flags. If you make additional annotations to your code, you can get even more intelligent and flexible behavior.
|
||||
`out.sh` will get you completions of subcommands and flags. Copy it to `/etc/bash_completion.d/` as described [here](https://debian-administration.org/article/316/An_introduction_to_bash_completion_part_1) and reset your terminal to use autocompletion. If you make additional annotations to your code, you can get even more intelligent and flexible behavior.
|
||||
|
||||
## Creating your own custom functions
|
||||
|
||||
|
3
vendor/github.com/spf13/cobra/cobra.go
generated
vendored
3
vendor/github.com/spf13/cobra/cobra.go
generated
vendored
@ -37,7 +37,8 @@ var templateFuncs = template.FuncMap{
|
||||
|
||||
var initializers []func()
|
||||
|
||||
// Automatic prefix matching can be a dangerous thing to automatically enable in CLI tools.
|
||||
// EnablePrefixMatching allows to set automatic prefix matching. Automatic prefix matching can be a dangerous thing
|
||||
// to automatically enable in CLI tools.
|
||||
// Set this to true to enable it.
|
||||
var EnablePrefixMatching = false
|
||||
|
||||
|
60
vendor/github.com/spf13/cobra/command.go
generated
vendored
60
vendor/github.com/spf13/cobra/command.go
generated
vendored
@ -57,6 +57,9 @@ type Command struct {
|
||||
Deprecated string
|
||||
// Is this command hidden and should NOT show up in the list of available commands?
|
||||
Hidden bool
|
||||
// Annotations are key/value pairs that can be used by applications to identify or
|
||||
// group commands
|
||||
Annotations map[string]string
|
||||
// Full set of flags
|
||||
flags *flag.FlagSet
|
||||
// Set of flags childrens of this command will inherit
|
||||
@ -129,7 +132,7 @@ type Command struct {
|
||||
DisableFlagParsing bool
|
||||
}
|
||||
|
||||
// os.Args[1:] by default, if desired, can be overridden
|
||||
// SetArgs sets arguments for the command. It is set to os.Args[1:] by default, if desired, can be overridden
|
||||
// particularly useful when testing.
|
||||
func (c *Command) SetArgs(a []string) {
|
||||
c.args = a
|
||||
@ -141,12 +144,12 @@ func (c *Command) SetOutput(output io.Writer) {
|
||||
c.output = &output
|
||||
}
|
||||
|
||||
// Usage can be defined by application.
|
||||
// SetUsageFunc sets usage function. Usage can be defined by application.
|
||||
func (c *Command) SetUsageFunc(f func(*Command) error) {
|
||||
c.usageFunc = f
|
||||
}
|
||||
|
||||
// Can be defined by Application.
|
||||
// SetUsageTemplate sets usage template. Can be defined by Application.
|
||||
func (c *Command) SetUsageTemplate(s string) {
|
||||
c.usageTemplate = s
|
||||
}
|
||||
@ -157,16 +160,17 @@ func (c *Command) SetFlagErrorFunc(f func(*Command, error) error) {
|
||||
c.flagErrorFunc = f
|
||||
}
|
||||
|
||||
// Can be defined by Application
|
||||
// SetHelpFunc sets help function. Can be defined by Application
|
||||
func (c *Command) SetHelpFunc(f func(*Command, []string)) {
|
||||
c.helpFunc = f
|
||||
}
|
||||
|
||||
// SetHelpCommand sets help command.
|
||||
func (c *Command) SetHelpCommand(cmd *Command) {
|
||||
c.helpCommand = cmd
|
||||
}
|
||||
|
||||
// Can be defined by Application.
|
||||
// SetHelpTemplate sets help template to be used. Application can use it to set custom template.
|
||||
func (c *Command) SetHelpTemplate(s string) {
|
||||
c.helpTemplate = s
|
||||
}
|
||||
@ -183,10 +187,12 @@ func (c *Command) SetGlobalNormalizationFunc(n func(f *flag.FlagSet, name string
|
||||
}
|
||||
}
|
||||
|
||||
// OutOrStdout returns output to stdout
|
||||
func (c *Command) OutOrStdout() io.Writer {
|
||||
return c.getOut(os.Stdout)
|
||||
}
|
||||
|
||||
// OutOrStderr returns output to stderr
|
||||
func (c *Command) OutOrStderr() io.Writer {
|
||||
return c.getOut(os.Stderr)
|
||||
}
|
||||
@ -265,6 +271,7 @@ func (c *Command) Help() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// UsageString return usage string.
|
||||
func (c *Command) UsageString() string {
|
||||
tmpOutput := c.output
|
||||
bb := new(bytes.Buffer)
|
||||
@ -292,6 +299,7 @@ func (c *Command) FlagErrorFunc() (f func(*Command, error) error) {
|
||||
|
||||
var minUsagePadding = 25
|
||||
|
||||
// UsagePadding return padding for the usage.
|
||||
func (c *Command) UsagePadding() int {
|
||||
if c.parent == nil || minUsagePadding > c.parent.commandsMaxUseLen {
|
||||
return minUsagePadding
|
||||
@ -301,7 +309,7 @@ func (c *Command) UsagePadding() int {
|
||||
|
||||
var minCommandPathPadding = 11
|
||||
|
||||
//
|
||||
// CommandPathPadding return padding for the command path.
|
||||
func (c *Command) CommandPathPadding() int {
|
||||
if c.parent == nil || minCommandPathPadding > c.parent.commandsMaxCommandPathLen {
|
||||
return minCommandPathPadding
|
||||
@ -311,6 +319,7 @@ func (c *Command) CommandPathPadding() int {
|
||||
|
||||
var minNamePadding = 11
|
||||
|
||||
// NamePadding returns padding for the name.
|
||||
func (c *Command) NamePadding() int {
|
||||
if c.parent == nil || minNamePadding > c.parent.commandsMaxNameLen {
|
||||
return minNamePadding
|
||||
@ -318,6 +327,7 @@ func (c *Command) NamePadding() int {
|
||||
return c.parent.commandsMaxNameLen
|
||||
}
|
||||
|
||||
// UsageTemplate returns usage template for the command.
|
||||
func (c *Command) UsageTemplate() string {
|
||||
if c.usageTemplate != "" {
|
||||
return c.usageTemplate
|
||||
@ -353,6 +363,7 @@ Use "{{.CommandPath}} [command] --help" for more information about a command.{{e
|
||||
`
|
||||
}
|
||||
|
||||
// HelpTemplate return help template for the command.
|
||||
func (c *Command) HelpTemplate() string {
|
||||
if c.helpTemplate != "" {
|
||||
return c.helpTemplate
|
||||
@ -416,7 +427,7 @@ func stripFlags(args []string, c *Command) []string {
|
||||
case inFlag:
|
||||
inFlag = false
|
||||
case y == "":
|
||||
// strip empty commands, as the go tests expect this to be ok....
|
||||
// strip empty commands, as the go tests expect this to be ok....
|
||||
case !strings.HasPrefix(y, "-"):
|
||||
commands = append(commands, y)
|
||||
inFlag = false
|
||||
@ -445,7 +456,7 @@ func argsMinusFirstX(args []string, x string) []string {
|
||||
return args
|
||||
}
|
||||
|
||||
// find the target command given the args and command tree
|
||||
// Find the target command given the args and command tree
|
||||
// Meant to be run on the highest node. Only searches down.
|
||||
func (c *Command) Find(args []string) (*Command, []string, error) {
|
||||
if c == nil {
|
||||
@ -513,6 +524,7 @@ func (c *Command) Find(args []string) (*Command, []string, error) {
|
||||
return commandFound, a, nil
|
||||
}
|
||||
|
||||
// SuggestionsFor provides suggestions for the typedName.
|
||||
func (c *Command) SuggestionsFor(typedName string) []string {
|
||||
suggestions := []string{}
|
||||
for _, cmd := range c.commands {
|
||||
@ -533,6 +545,7 @@ func (c *Command) SuggestionsFor(typedName string) []string {
|
||||
return suggestions
|
||||
}
|
||||
|
||||
// VisitParents visits all parents of the command and invokes fn on each parent.
|
||||
func (c *Command) VisitParents(fn func(*Command)) {
|
||||
var traverse func(*Command) *Command
|
||||
|
||||
@ -548,6 +561,7 @@ func (c *Command) VisitParents(fn func(*Command)) {
|
||||
traverse(c)
|
||||
}
|
||||
|
||||
// Root finds root command.
|
||||
func (c *Command) Root() *Command {
|
||||
var findRoot func(*Command) *Command
|
||||
|
||||
@ -672,7 +686,7 @@ func (c *Command) errorMsgFromParse() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
// Call execute to use the args (os.Args[1:] by default)
|
||||
// Execute Call execute to use the args (os.Args[1:] by default)
|
||||
// and run through the command tree finding appropriate matches
|
||||
// for commands and then corresponding flags.
|
||||
func (c *Command) Execute() error {
|
||||
@ -680,6 +694,7 @@ func (c *Command) Execute() error {
|
||||
return err
|
||||
}
|
||||
|
||||
// ExecuteC executes the command.
|
||||
func (c *Command) ExecuteC() (cmd *Command, err error) {
|
||||
|
||||
// Regardless of what command execute is called on, run on Root only
|
||||
@ -777,7 +792,7 @@ func (c *Command) initHelpCmd() {
|
||||
c.AddCommand(c.helpCommand)
|
||||
}
|
||||
|
||||
// Used for testing.
|
||||
// ResetCommands used for testing.
|
||||
func (c *Command) ResetCommands() {
|
||||
c.commands = nil
|
||||
c.helpCommand = nil
|
||||
@ -900,7 +915,7 @@ func (c *Command) UseLine() string {
|
||||
return str + c.Use
|
||||
}
|
||||
|
||||
// For use in determining which flags have been assigned to which commands
|
||||
// DebugFlags used to determine which flags have been assigned to which commands
|
||||
// and which persist.
|
||||
func (c *Command) DebugFlags() {
|
||||
c.Println("DebugFlags called on", c.Name())
|
||||
@ -955,7 +970,8 @@ func (c *Command) Name() string {
|
||||
if i >= 0 {
|
||||
name = name[:i]
|
||||
}
|
||||
return name
|
||||
c.name = name
|
||||
return c.name
|
||||
}
|
||||
|
||||
// HasAlias determines if a given string is an alias of the command.
|
||||
@ -968,10 +984,12 @@ func (c *Command) HasAlias(s string) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// NameAndAliases returns string containing name and all aliases
|
||||
func (c *Command) NameAndAliases() string {
|
||||
return strings.Join(append([]string{c.Name()}, c.Aliases...), ", ")
|
||||
}
|
||||
|
||||
// HasExample determines if the command has example.
|
||||
func (c *Command) HasExample() bool {
|
||||
return len(c.Example) > 0
|
||||
}
|
||||
@ -1068,7 +1086,7 @@ func (c *Command) GlobalNormalizationFunc() func(f *flag.FlagSet, name string) f
|
||||
return c.globNormFunc
|
||||
}
|
||||
|
||||
// Flage returns the complete FlagSet that applies
|
||||
// Flags returns the complete FlagSet that applies
|
||||
// to this command (local and persistent declared here and by all parents).
|
||||
func (c *Command) Flags() *flag.FlagSet {
|
||||
if c.flags == nil {
|
||||
@ -1168,44 +1186,44 @@ func (c *Command) ResetFlags() {
|
||||
c.pflags.SetOutput(c.flagErrorBuf)
|
||||
}
|
||||
|
||||
// Does the command contain any flags (local plus persistent from the entire structure).
|
||||
// HasFlags checks if the command contains any flags (local plus persistent from the entire structure).
|
||||
func (c *Command) HasFlags() bool {
|
||||
return c.Flags().HasFlags()
|
||||
}
|
||||
|
||||
// Does the command contain persistent flags.
|
||||
// HasPersistentFlags checks if the command contains persistent flags.
|
||||
func (c *Command) HasPersistentFlags() bool {
|
||||
return c.PersistentFlags().HasFlags()
|
||||
}
|
||||
|
||||
// Does the command has flags specifically declared locally.
|
||||
// HasLocalFlags checks if the command has flags specifically declared locally.
|
||||
func (c *Command) HasLocalFlags() bool {
|
||||
return c.LocalFlags().HasFlags()
|
||||
}
|
||||
|
||||
// Does the command have flags inherited from its parent command.
|
||||
// HasInheritedFlags checks if the command has flags inherited from its parent command.
|
||||
func (c *Command) HasInheritedFlags() bool {
|
||||
return c.InheritedFlags().HasFlags()
|
||||
}
|
||||
|
||||
// Does the command contain any flags (local plus persistent from the entire
|
||||
// HasAvailableFlags checks if the command contains any flags (local plus persistent from the entire
|
||||
// structure) which are not hidden or deprecated.
|
||||
func (c *Command) HasAvailableFlags() bool {
|
||||
return c.Flags().HasAvailableFlags()
|
||||
}
|
||||
|
||||
// Does the command contain persistent flags which are not hidden or deprecated.
|
||||
// HasAvailablePersistentFlags checks if the command contains persistent flags which are not hidden or deprecated.
|
||||
func (c *Command) HasAvailablePersistentFlags() bool {
|
||||
return c.PersistentFlags().HasAvailableFlags()
|
||||
}
|
||||
|
||||
// Does the command has flags specifically declared locally which are not hidden
|
||||
// HasAvailableLocalFlags checks if the command has flags specifically declared locally which are not hidden
|
||||
// or deprecated.
|
||||
func (c *Command) HasAvailableLocalFlags() bool {
|
||||
return c.LocalFlags().HasAvailableFlags()
|
||||
}
|
||||
|
||||
// Does the command have flags inherited from its parent command which are
|
||||
// HasAvailableInheritedFlags checks if the command has flags inherited from its parent command which are
|
||||
// not hidden or deprecated.
|
||||
func (c *Command) HasAvailableInheritedFlags() bool {
|
||||
return c.InheritedFlags().HasAvailableFlags()
|
||||
|
6
vendor/github.com/spf13/cobra/doc/md_docs.md
generated
vendored
6
vendor/github.com/spf13/cobra/doc/md_docs.md
generated
vendored
@ -32,15 +32,15 @@ import (
|
||||
"io/ioutil"
|
||||
"os"
|
||||
|
||||
kubectlcmd "k8s.io/kubernetes/pkg/kubectl/cmd"
|
||||
"k8s.io/kubernetes/pkg/kubectl/cmd"
|
||||
cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util"
|
||||
|
||||
"github.com/spf13/cobra/doc"
|
||||
)
|
||||
|
||||
func main() {
|
||||
cmd := kubectlcmd.NewKubectlCommand(cmdutil.NewFactory(nil), os.Stdin, ioutil.Discard, ioutil.Discard)
|
||||
doc.GenMarkdownTree(cmd, "./")
|
||||
kubectl := cmd.NewKubectlCommand(cmdutil.NewFactory(nil), os.Stdin, ioutil.Discard, ioutil.Discard)
|
||||
doc.GenMarkdownTree(kubectl, "./")
|
||||
}
|
||||
```
|
||||
|
||||
|
15
vendor/github.com/spf13/cobra/doc/util.go
generated
vendored
15
vendor/github.com/spf13/cobra/doc/util.go
generated
vendored
@ -13,7 +13,11 @@
|
||||
|
||||
package doc
|
||||
|
||||
import "github.com/spf13/cobra"
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
// Test to see if we have a reason to print See Also information in docs
|
||||
// Basically this is a test for a parent commend or a subcommand which is
|
||||
@ -31,6 +35,15 @@ func hasSeeAlso(cmd *cobra.Command) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// Temporary workaround for yaml lib generating incorrect yaml with long strings
|
||||
// that do not contain \n.
|
||||
func forceMultiLine(s string) string {
|
||||
if len(s) > 60 && !strings.Contains(s, "\n") {
|
||||
s = s + "\n"
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
type byName []*cobra.Command
|
||||
|
||||
func (s byName) Len() int { return len(s) }
|
||||
|
165
vendor/github.com/spf13/cobra/doc/yaml_docs.go
generated
vendored
Normal file
165
vendor/github.com/spf13/cobra/doc/yaml_docs.go
generated
vendored
Normal file
@ -0,0 +1,165 @@
|
||||
// Copyright 2016 French Ben. All rights reserved.
|
||||
//
|
||||
// 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.
|
||||
|
||||
package doc
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/pflag"
|
||||
"gopkg.in/yaml.v2"
|
||||
)
|
||||
|
||||
type cmdOption struct {
|
||||
Name string
|
||||
Shorthand string `yaml:",omitempty"`
|
||||
DefaultValue string `yaml:"default_value,omitempty"`
|
||||
Usage string `yaml:",omitempty"`
|
||||
}
|
||||
|
||||
type cmdDoc struct {
|
||||
Name string
|
||||
Synopsis string `yaml:",omitempty"`
|
||||
Description string `yaml:",omitempty"`
|
||||
Options []cmdOption `yaml:",omitempty"`
|
||||
InheritedOptions []cmdOption `yaml:"inherited_options,omitempty"`
|
||||
Example string `yaml:",omitempty"`
|
||||
SeeAlso []string `yaml:"see_also,omitempty"`
|
||||
}
|
||||
|
||||
// GenYamlTree creates yaml structured ref files for this command and all descendants
|
||||
// in the directory given. This function may not work
|
||||
// correctly if your command names have - in them. If you have `cmd` with two
|
||||
// subcmds, `sub` and `sub-third`. And `sub` has a subcommand called `third`
|
||||
// it is undefined which help output will be in the file `cmd-sub-third.1`.
|
||||
func GenYamlTree(cmd *cobra.Command, dir string) error {
|
||||
identity := func(s string) string { return s }
|
||||
emptyStr := func(s string) string { return "" }
|
||||
return GenYamlTreeCustom(cmd, dir, emptyStr, identity)
|
||||
}
|
||||
|
||||
// GenYamlTreeCustom creates yaml structured ref files
|
||||
func GenYamlTreeCustom(cmd *cobra.Command, dir string, filePrepender, linkHandler func(string) string) error {
|
||||
for _, c := range cmd.Commands() {
|
||||
if !c.IsAvailableCommand() || c.IsHelpCommand() {
|
||||
continue
|
||||
}
|
||||
if err := GenYamlTreeCustom(c, dir, filePrepender, linkHandler); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
basename := strings.Replace(cmd.CommandPath(), " ", "_", -1) + ".yaml"
|
||||
filename := filepath.Join(dir, basename)
|
||||
f, err := os.Create(filename)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
if _, err := io.WriteString(f, filePrepender(filename)); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := GenYamlCustom(cmd, f, linkHandler); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// GenYaml creates yaml output
|
||||
func GenYaml(cmd *cobra.Command, w io.Writer) error {
|
||||
return GenYamlCustom(cmd, w, func(s string) string { return s })
|
||||
}
|
||||
|
||||
// GenYamlCustom creates custom yaml output
|
||||
func GenYamlCustom(cmd *cobra.Command, w io.Writer, linkHandler func(string) string) error {
|
||||
yamlDoc := cmdDoc{}
|
||||
yamlDoc.Name = cmd.CommandPath()
|
||||
|
||||
yamlDoc.Synopsis = forceMultiLine(cmd.Short)
|
||||
yamlDoc.Description = forceMultiLine(cmd.Long)
|
||||
|
||||
if len(cmd.Example) > 0 {
|
||||
yamlDoc.Example = cmd.Example
|
||||
}
|
||||
|
||||
flags := cmd.NonInheritedFlags()
|
||||
if flags.HasFlags() {
|
||||
yamlDoc.Options = genFlagResult(flags)
|
||||
}
|
||||
flags = cmd.InheritedFlags()
|
||||
if flags.HasFlags() {
|
||||
yamlDoc.InheritedOptions = genFlagResult(flags)
|
||||
}
|
||||
|
||||
if hasSeeAlso(cmd) {
|
||||
result := []string{}
|
||||
if cmd.HasParent() {
|
||||
parent := cmd.Parent()
|
||||
result = append(result, parent.CommandPath()+" - "+parent.Short)
|
||||
}
|
||||
children := cmd.Commands()
|
||||
sort.Sort(byName(children))
|
||||
for _, child := range children {
|
||||
if !child.IsAvailableCommand() || child.IsHelpCommand() {
|
||||
continue
|
||||
}
|
||||
result = append(result, child.Name()+" - "+child.Short)
|
||||
}
|
||||
yamlDoc.SeeAlso = result
|
||||
}
|
||||
|
||||
final, err := yaml.Marshal(&yamlDoc)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
if _, err := fmt.Fprintf(w, string(final)); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func genFlagResult(flags *pflag.FlagSet) []cmdOption {
|
||||
var result []cmdOption
|
||||
|
||||
flags.VisitAll(func(flag *pflag.Flag) {
|
||||
// Todo, when we mark a shorthand is deprecated, but specify an empty message.
|
||||
// The flag.ShorthandDeprecated is empty as the shorthand is deprecated.
|
||||
// Using len(flag.ShorthandDeprecated) > 0 can't handle this, others are ok.
|
||||
if !(len(flag.ShorthandDeprecated) > 0) && len(flag.Shorthand) > 0 {
|
||||
opt := cmdOption{
|
||||
flag.Name,
|
||||
flag.Shorthand,
|
||||
flag.DefValue,
|
||||
forceMultiLine(flag.Usage),
|
||||
}
|
||||
result = append(result, opt)
|
||||
} else {
|
||||
opt := cmdOption{
|
||||
Name: flag.Name,
|
||||
DefaultValue: forceMultiLine(flag.DefValue),
|
||||
Usage: forceMultiLine(flag.Usage),
|
||||
}
|
||||
result = append(result, opt)
|
||||
}
|
||||
})
|
||||
|
||||
return result
|
||||
}
|
103
vendor/github.com/spf13/cobra/doc/yaml_docs.md
generated
vendored
Normal file
103
vendor/github.com/spf13/cobra/doc/yaml_docs.md
generated
vendored
Normal file
@ -0,0 +1,103 @@
|
||||
# Generating Yaml Docs For Your Own cobra.Command
|
||||
|
||||
Generating yaml files from a cobra command is incredibly easy. An example is as follows:
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/cobra/doc"
|
||||
)
|
||||
|
||||
func main() {
|
||||
cmd := &cobra.Command{
|
||||
Use: "test",
|
||||
Short: "my test program",
|
||||
}
|
||||
doc.GenYamlTree(cmd, "/tmp")
|
||||
}
|
||||
```
|
||||
|
||||
That will get you a Yaml document `/tmp/test.yaml`
|
||||
|
||||
## Generate yaml docs for the entire command tree
|
||||
|
||||
This program can actually generate docs for the kubectl command in the kubernetes project
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"os"
|
||||
|
||||
"k8s.io/kubernetes/pkg/kubectl/cmd"
|
||||
cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util"
|
||||
|
||||
"github.com/spf13/cobra/doc"
|
||||
)
|
||||
|
||||
func main() {
|
||||
kubectl := cmd.NewKubectlCommand(cmdutil.NewFactory(nil), os.Stdin, ioutil.Discard, ioutil.Discard)
|
||||
doc.GenYamlTree(kubectl, "./")
|
||||
}
|
||||
```
|
||||
|
||||
This will generate a whole series of files, one for each command in the tree, in the directory specified (in this case "./")
|
||||
|
||||
## Generate yaml docs for a single command
|
||||
|
||||
You may wish to have more control over the output, or only generate for a single command, instead of the entire command tree. If this is the case you may prefer to `GenYaml` instead of `GenYamlTree`
|
||||
|
||||
```go
|
||||
out := new(bytes.Buffer)
|
||||
doc.GenYaml(cmd, out)
|
||||
```
|
||||
|
||||
This will write the yaml doc for ONLY "cmd" into the out, buffer.
|
||||
|
||||
## Customize the output
|
||||
|
||||
Both `GenYaml` and `GenYamlTree` have alternate versions with callbacks to get some control of the output:
|
||||
|
||||
```go
|
||||
func GenYamlTreeCustom(cmd *Command, dir string, filePrepender, linkHandler func(string) string) error {
|
||||
//...
|
||||
}
|
||||
```
|
||||
|
||||
```go
|
||||
func GenYamlCustom(cmd *Command, out *bytes.Buffer, linkHandler func(string) string) error {
|
||||
//...
|
||||
}
|
||||
```
|
||||
|
||||
The `filePrepender` will prepend the return value given the full filepath to the rendered Yaml file. A common use case is to add front matter to use the generated documentation with [Hugo](http://gohugo.io/):
|
||||
|
||||
```go
|
||||
const fmTemplate = `---
|
||||
date: %s
|
||||
title: "%s"
|
||||
slug: %s
|
||||
url: %s
|
||||
---
|
||||
`
|
||||
|
||||
filePrepender := func(filename string) string {
|
||||
now := time.Now().Format(time.RFC3339)
|
||||
name := filepath.Base(filename)
|
||||
base := strings.TrimSuffix(name, path.Ext(name))
|
||||
url := "/commands/" + strings.ToLower(base) + "/"
|
||||
return fmt.Sprintf(fmTemplate, now, strings.Replace(base, "_", " ", -1), base, url)
|
||||
}
|
||||
```
|
||||
|
||||
The `linkHandler` can be used to customize the rendered internal links to the commands, given a filename:
|
||||
|
||||
```go
|
||||
linkHandler := func(name string) string {
|
||||
base := strings.TrimSuffix(name, path.Ext(name))
|
||||
return "/commands/" + strings.ToLower(base) + "/"
|
||||
}
|
||||
```
|
2
vendor/github.com/spf13/pflag/.gitignore
generated
vendored
Normal file
2
vendor/github.com/spf13/pflag/.gitignore
generated
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
.idea/*
|
||||
|
2
vendor/github.com/spf13/pflag/README.md
generated
vendored
2
vendor/github.com/spf13/pflag/README.md
generated
vendored
@ -1,4 +1,6 @@
|
||||
[![Build Status](https://travis-ci.org/spf13/pflag.svg?branch=master)](https://travis-ci.org/spf13/pflag)
|
||||
[![Go Report Card](https://goreportcard.com/badge/github.com/spf13/pflag)](https://goreportcard.com/report/github.com/spf13/pflag)
|
||||
[![GoDoc](https://godoc.org/github.com/spf13/pflag?status.svg)](https://godoc.org/github.com/spf13/pflag)
|
||||
|
||||
## Description
|
||||
|
||||
|
147
vendor/github.com/spf13/pflag/bool_slice.go
generated
vendored
Normal file
147
vendor/github.com/spf13/pflag/bool_slice.go
generated
vendored
Normal file
@ -0,0 +1,147 @@
|
||||
package pflag
|
||||
|
||||
import (
|
||||
"io"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// -- boolSlice Value
|
||||
type boolSliceValue struct {
|
||||
value *[]bool
|
||||
changed bool
|
||||
}
|
||||
|
||||
func newBoolSliceValue(val []bool, p *[]bool) *boolSliceValue {
|
||||
bsv := new(boolSliceValue)
|
||||
bsv.value = p
|
||||
*bsv.value = val
|
||||
return bsv
|
||||
}
|
||||
|
||||
// Set converts, and assigns, the comma-separated boolean argument string representation as the []bool value of this flag.
|
||||
// If Set is called on a flag that already has a []bool assigned, the newly converted values will be appended.
|
||||
func (s *boolSliceValue) Set(val string) error {
|
||||
|
||||
// remove all quote characters
|
||||
rmQuote := strings.NewReplacer(`"`, "", `'`, "", "`", "")
|
||||
|
||||
// read flag arguments with CSV parser
|
||||
boolStrSlice, err := readAsCSV(rmQuote.Replace(val))
|
||||
if err != nil && err != io.EOF {
|
||||
return err
|
||||
}
|
||||
|
||||
// parse boolean values into slice
|
||||
out := make([]bool, 0, len(boolStrSlice))
|
||||
for _, boolStr := range boolStrSlice {
|
||||
b, err := strconv.ParseBool(strings.TrimSpace(boolStr))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
out = append(out, b)
|
||||
}
|
||||
|
||||
if !s.changed {
|
||||
*s.value = out
|
||||
} else {
|
||||
*s.value = append(*s.value, out...)
|
||||
}
|
||||
|
||||
s.changed = true
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Type returns a string that uniquely represents this flag's type.
|
||||
func (s *boolSliceValue) Type() string {
|
||||
return "boolSlice"
|
||||
}
|
||||
|
||||
// String defines a "native" format for this boolean slice flag value.
|
||||
func (s *boolSliceValue) String() string {
|
||||
|
||||
boolStrSlice := make([]string, len(*s.value))
|
||||
for i, b := range *s.value {
|
||||
boolStrSlice[i] = strconv.FormatBool(b)
|
||||
}
|
||||
|
||||
out, _ := writeAsCSV(boolStrSlice)
|
||||
|
||||
return "[" + out + "]"
|
||||
}
|
||||
|
||||
func boolSliceConv(val string) (interface{}, error) {
|
||||
val = strings.Trim(val, "[]")
|
||||
// Empty string would cause a slice with one (empty) entry
|
||||
if len(val) == 0 {
|
||||
return []bool{}, nil
|
||||
}
|
||||
ss := strings.Split(val, ",")
|
||||
out := make([]bool, len(ss))
|
||||
for i, t := range ss {
|
||||
var err error
|
||||
out[i], err = strconv.ParseBool(t)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// GetBoolSlice returns the []bool value of a flag with the given name.
|
||||
func (f *FlagSet) GetBoolSlice(name string) ([]bool, error) {
|
||||
val, err := f.getFlagType(name, "boolSlice", boolSliceConv)
|
||||
if err != nil {
|
||||
return []bool{}, err
|
||||
}
|
||||
return val.([]bool), nil
|
||||
}
|
||||
|
||||
// BoolSliceVar defines a boolSlice flag with specified name, default value, and usage string.
|
||||
// The argument p points to a []bool variable in which to store the value of the flag.
|
||||
func (f *FlagSet) BoolSliceVar(p *[]bool, name string, value []bool, usage string) {
|
||||
f.VarP(newBoolSliceValue(value, p), name, "", usage)
|
||||
}
|
||||
|
||||
// BoolSliceVarP is like BoolSliceVar, but accepts a shorthand letter that can be used after a single dash.
|
||||
func (f *FlagSet) BoolSliceVarP(p *[]bool, name, shorthand string, value []bool, usage string) {
|
||||
f.VarP(newBoolSliceValue(value, p), name, shorthand, usage)
|
||||
}
|
||||
|
||||
// BoolSliceVar defines a []bool flag with specified name, default value, and usage string.
|
||||
// The argument p points to a []bool variable in which to store the value of the flag.
|
||||
func BoolSliceVar(p *[]bool, name string, value []bool, usage string) {
|
||||
CommandLine.VarP(newBoolSliceValue(value, p), name, "", usage)
|
||||
}
|
||||
|
||||
// BoolSliceVarP is like BoolSliceVar, but accepts a shorthand letter that can be used after a single dash.
|
||||
func BoolSliceVarP(p *[]bool, name, shorthand string, value []bool, usage string) {
|
||||
CommandLine.VarP(newBoolSliceValue(value, p), name, shorthand, usage)
|
||||
}
|
||||
|
||||
// BoolSlice defines a []bool flag with specified name, default value, and usage string.
|
||||
// The return value is the address of a []bool variable that stores the value of the flag.
|
||||
func (f *FlagSet) BoolSlice(name string, value []bool, usage string) *[]bool {
|
||||
p := []bool{}
|
||||
f.BoolSliceVarP(&p, name, "", value, usage)
|
||||
return &p
|
||||
}
|
||||
|
||||
// BoolSliceP is like BoolSlice, but accepts a shorthand letter that can be used after a single dash.
|
||||
func (f *FlagSet) BoolSliceP(name, shorthand string, value []bool, usage string) *[]bool {
|
||||
p := []bool{}
|
||||
f.BoolSliceVarP(&p, name, shorthand, value, usage)
|
||||
return &p
|
||||
}
|
||||
|
||||
// BoolSlice defines a []bool flag with specified name, default value, and usage string.
|
||||
// The return value is the address of a []bool variable that stores the value of the flag.
|
||||
func BoolSlice(name string, value []bool, usage string) *[]bool {
|
||||
return CommandLine.BoolSliceP(name, "", value, usage)
|
||||
}
|
||||
|
||||
// BoolSliceP is like BoolSlice, but accepts a shorthand letter that can be used after a single dash.
|
||||
func BoolSliceP(name, shorthand string, value []bool, usage string) *[]bool {
|
||||
return CommandLine.BoolSliceP(name, shorthand, value, usage)
|
||||
}
|
146
vendor/github.com/spf13/pflag/flag.go
generated
vendored
146
vendor/github.com/spf13/pflag/flag.go
generated
vendored
@ -487,9 +487,76 @@ func UnquoteUsage(flag *Flag) (name string, usage string) {
|
||||
return
|
||||
}
|
||||
|
||||
// FlagUsages Returns a string containing the usage information for all flags in
|
||||
// the FlagSet
|
||||
func (f *FlagSet) FlagUsages() string {
|
||||
// Splits the string `s` on whitespace into an initial substring up to
|
||||
// `i` runes in length and the remainder. Will go `slop` over `i` if
|
||||
// that encompasses the entire string (which allows the caller to
|
||||
// avoid short orphan words on the final line).
|
||||
func wrapN(i, slop int, s string) (string, string) {
|
||||
if i+slop > len(s) {
|
||||
return s, ""
|
||||
}
|
||||
|
||||
w := strings.LastIndexAny(s[:i], " \t")
|
||||
if w <= 0 {
|
||||
return s, ""
|
||||
}
|
||||
|
||||
return s[:w], s[w+1:]
|
||||
}
|
||||
|
||||
// Wraps the string `s` to a maximum width `w` with leading indent
|
||||
// `i`. The first line is not indented (this is assumed to be done by
|
||||
// caller). Pass `w` == 0 to do no wrapping
|
||||
func wrap(i, w int, s string) string {
|
||||
if w == 0 {
|
||||
return s
|
||||
}
|
||||
|
||||
// space between indent i and end of line width w into which
|
||||
// we should wrap the text.
|
||||
wrap := w - i
|
||||
|
||||
var r, l string
|
||||
|
||||
// Not enough space for sensible wrapping. Wrap as a block on
|
||||
// the next line instead.
|
||||
if wrap < 24 {
|
||||
i = 16
|
||||
wrap = w - i
|
||||
r += "\n" + strings.Repeat(" ", i)
|
||||
}
|
||||
// If still not enough space then don't even try to wrap.
|
||||
if wrap < 24 {
|
||||
return s
|
||||
}
|
||||
|
||||
// Try to avoid short orphan words on the final line, by
|
||||
// allowing wrapN to go a bit over if that would fit in the
|
||||
// remainder of the line.
|
||||
slop := 5
|
||||
wrap = wrap - slop
|
||||
|
||||
// Handle first line, which is indented by the caller (or the
|
||||
// special case above)
|
||||
l, s = wrapN(wrap, slop, s)
|
||||
r = r + l
|
||||
|
||||
// Now wrap the rest
|
||||
for s != "" {
|
||||
var t string
|
||||
|
||||
t, s = wrapN(wrap, slop, s)
|
||||
r = r + "\n" + strings.Repeat(" ", i) + t
|
||||
}
|
||||
|
||||
return r
|
||||
|
||||
}
|
||||
|
||||
// FlagUsagesWrapped returns a string containing the usage information
|
||||
// for all flags in the FlagSet. Wrapped to `cols` columns (0 for no
|
||||
// wrapping)
|
||||
func (f *FlagSet) FlagUsagesWrapped(cols int) string {
|
||||
x := new(bytes.Buffer)
|
||||
|
||||
lines := make([]string, 0, len(f.formal))
|
||||
@ -546,12 +613,19 @@ func (f *FlagSet) FlagUsages() string {
|
||||
for _, line := range lines {
|
||||
sidx := strings.Index(line, "\x00")
|
||||
spacing := strings.Repeat(" ", maxlen-sidx)
|
||||
fmt.Fprintln(x, line[:sidx], spacing, line[sidx+1:])
|
||||
// maxlen + 2 comes from + 1 for the \x00 and + 1 for the (deliberate) off-by-one in maxlen-sidx
|
||||
fmt.Fprintln(x, line[:sidx], spacing, wrap(maxlen+2, cols, line[sidx+1:]))
|
||||
}
|
||||
|
||||
return x.String()
|
||||
}
|
||||
|
||||
// FlagUsages returns a string containing the usage information for all flags in
|
||||
// the FlagSet
|
||||
func (f *FlagSet) FlagUsages() string {
|
||||
return f.FlagUsagesWrapped(0)
|
||||
}
|
||||
|
||||
// PrintDefaults prints to standard error the default values of all defined command-line flags.
|
||||
func PrintDefaults() {
|
||||
CommandLine.PrintDefaults()
|
||||
@ -635,7 +709,7 @@ func (f *FlagSet) VarPF(value Value, name, shorthand, usage string) *Flag {
|
||||
|
||||
// VarP is like Var, but accepts a shorthand letter that can be used after a single dash.
|
||||
func (f *FlagSet) VarP(value Value, name, shorthand, usage string) {
|
||||
_ = f.VarPF(value, name, shorthand, usage)
|
||||
f.VarPF(value, name, shorthand, usage)
|
||||
}
|
||||
|
||||
// AddFlag will add the flag to the FlagSet
|
||||
@ -752,7 +826,7 @@ func containsShorthand(arg, shorthand string) bool {
|
||||
return strings.Contains(arg, shorthand)
|
||||
}
|
||||
|
||||
func (f *FlagSet) parseLongArg(s string, args []string) (a []string, err error) {
|
||||
func (f *FlagSet) parseLongArg(s string, args []string, fn parseFunc) (a []string, err error) {
|
||||
a = args
|
||||
name := s[2:]
|
||||
if len(name) == 0 || name[0] == '-' || name[0] == '=' {
|
||||
@ -786,11 +860,11 @@ func (f *FlagSet) parseLongArg(s string, args []string) (a []string, err error)
|
||||
err = f.failf("flag needs an argument: %s", s)
|
||||
return
|
||||
}
|
||||
err = f.setFlag(flag, value, s)
|
||||
err = fn(flag, value, s)
|
||||
return
|
||||
}
|
||||
|
||||
func (f *FlagSet) parseSingleShortArg(shorthands string, args []string) (outShorts string, outArgs []string, err error) {
|
||||
func (f *FlagSet) parseSingleShortArg(shorthands string, args []string, fn parseFunc) (outShorts string, outArgs []string, err error) {
|
||||
if strings.HasPrefix(shorthands, "test.") {
|
||||
return
|
||||
}
|
||||
@ -825,16 +899,16 @@ func (f *FlagSet) parseSingleShortArg(shorthands string, args []string) (outShor
|
||||
err = f.failf("flag needs an argument: %q in -%s", c, shorthands)
|
||||
return
|
||||
}
|
||||
err = f.setFlag(flag, value, shorthands)
|
||||
err = fn(flag, value, shorthands)
|
||||
return
|
||||
}
|
||||
|
||||
func (f *FlagSet) parseShortArg(s string, args []string) (a []string, err error) {
|
||||
func (f *FlagSet) parseShortArg(s string, args []string, fn parseFunc) (a []string, err error) {
|
||||
a = args
|
||||
shorthands := s[1:]
|
||||
|
||||
for len(shorthands) > 0 {
|
||||
shorthands, a, err = f.parseSingleShortArg(shorthands, args)
|
||||
shorthands, a, err = f.parseSingleShortArg(shorthands, args, fn)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
@ -843,7 +917,7 @@ func (f *FlagSet) parseShortArg(s string, args []string) (a []string, err error)
|
||||
return
|
||||
}
|
||||
|
||||
func (f *FlagSet) parseArgs(args []string) (err error) {
|
||||
func (f *FlagSet) parseArgs(args []string, fn parseFunc) (err error) {
|
||||
for len(args) > 0 {
|
||||
s := args[0]
|
||||
args = args[1:]
|
||||
@ -863,9 +937,9 @@ func (f *FlagSet) parseArgs(args []string) (err error) {
|
||||
f.args = append(f.args, args...)
|
||||
break
|
||||
}
|
||||
args, err = f.parseLongArg(s, args)
|
||||
args, err = f.parseLongArg(s, args, fn)
|
||||
} else {
|
||||
args, err = f.parseShortArg(s, args)
|
||||
args, err = f.parseShortArg(s, args, fn)
|
||||
}
|
||||
if err != nil {
|
||||
return
|
||||
@ -881,7 +955,41 @@ func (f *FlagSet) parseArgs(args []string) (err error) {
|
||||
func (f *FlagSet) Parse(arguments []string) error {
|
||||
f.parsed = true
|
||||
f.args = make([]string, 0, len(arguments))
|
||||
err := f.parseArgs(arguments)
|
||||
|
||||
assign := func(flag *Flag, value, origArg string) error {
|
||||
return f.setFlag(flag, value, origArg)
|
||||
}
|
||||
|
||||
err := f.parseArgs(arguments, assign)
|
||||
if err != nil {
|
||||
switch f.errorHandling {
|
||||
case ContinueOnError:
|
||||
return err
|
||||
case ExitOnError:
|
||||
os.Exit(2)
|
||||
case PanicOnError:
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type parseFunc func(flag *Flag, value, origArg string) error
|
||||
|
||||
// ParseAll parses flag definitions from the argument list, which should not
|
||||
// include the command name. The arguments for fn are flag and value. Must be
|
||||
// called after all flags in the FlagSet are defined and before flags are
|
||||
// accessed by the program. The return value will be ErrHelp if -help was set
|
||||
// but not defined.
|
||||
func (f *FlagSet) ParseAll(arguments []string, fn func(flag *Flag, value string) error) error {
|
||||
f.parsed = true
|
||||
f.args = make([]string, 0, len(arguments))
|
||||
|
||||
assign := func(flag *Flag, value, origArg string) error {
|
||||
return fn(flag, value)
|
||||
}
|
||||
|
||||
err := f.parseArgs(arguments, assign)
|
||||
if err != nil {
|
||||
switch f.errorHandling {
|
||||
case ContinueOnError:
|
||||
@ -907,6 +1015,14 @@ func Parse() {
|
||||
CommandLine.Parse(os.Args[1:])
|
||||
}
|
||||
|
||||
// ParseAll parses the command-line flags from os.Args[1:] and called fn for each.
|
||||
// The arguments for fn are flag and value. Must be called after all flags are
|
||||
// defined and before flags are accessed by the program.
|
||||
func ParseAll(fn func(flag *Flag, value string) error) {
|
||||
// Ignore errors; CommandLine is set for ExitOnError.
|
||||
CommandLine.ParseAll(os.Args[1:], fn)
|
||||
}
|
||||
|
||||
// SetInterspersed sets whether to support interspersed option/non-option arguments.
|
||||
func SetInterspersed(interspersed bool) {
|
||||
CommandLine.SetInterspersed(interspersed)
|
||||
|
3
vendor/github.com/spf13/pflag/golangflag.go
generated
vendored
3
vendor/github.com/spf13/pflag/golangflag.go
generated
vendored
@ -6,13 +6,10 @@ package pflag
|
||||
|
||||
import (
|
||||
goflag "flag"
|
||||
"fmt"
|
||||
"reflect"
|
||||
"strings"
|
||||
)
|
||||
|
||||
var _ = fmt.Print
|
||||
|
||||
// flagValueWrapper implements pflag.Value around a flag.Value. The main
|
||||
// difference here is the addition of the Type method that returns a string
|
||||
// name of the type. As this is generally unknown, we approximate that with
|
||||
|
2
vendor/github.com/spf13/pflag/ip.go
generated
vendored
2
vendor/github.com/spf13/pflag/ip.go
generated
vendored
@ -6,8 +6,6 @@ import (
|
||||
"strings"
|
||||
)
|
||||
|
||||
var _ = strings.TrimSpace
|
||||
|
||||
// -- net.IP value
|
||||
type ipValue net.IP
|
||||
|
||||
|
148
vendor/github.com/spf13/pflag/ip_slice.go
generated
vendored
Normal file
148
vendor/github.com/spf13/pflag/ip_slice.go
generated
vendored
Normal file
@ -0,0 +1,148 @@
|
||||
package pflag
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"net"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// -- ipSlice Value
|
||||
type ipSliceValue struct {
|
||||
value *[]net.IP
|
||||
changed bool
|
||||
}
|
||||
|
||||
func newIPSliceValue(val []net.IP, p *[]net.IP) *ipSliceValue {
|
||||
ipsv := new(ipSliceValue)
|
||||
ipsv.value = p
|
||||
*ipsv.value = val
|
||||
return ipsv
|
||||
}
|
||||
|
||||
// Set converts, and assigns, the comma-separated IP argument string representation as the []net.IP value of this flag.
|
||||
// If Set is called on a flag that already has a []net.IP assigned, the newly converted values will be appended.
|
||||
func (s *ipSliceValue) Set(val string) error {
|
||||
|
||||
// remove all quote characters
|
||||
rmQuote := strings.NewReplacer(`"`, "", `'`, "", "`", "")
|
||||
|
||||
// read flag arguments with CSV parser
|
||||
ipStrSlice, err := readAsCSV(rmQuote.Replace(val))
|
||||
if err != nil && err != io.EOF {
|
||||
return err
|
||||
}
|
||||
|
||||
// parse ip values into slice
|
||||
out := make([]net.IP, 0, len(ipStrSlice))
|
||||
for _, ipStr := range ipStrSlice {
|
||||
ip := net.ParseIP(strings.TrimSpace(ipStr))
|
||||
if ip == nil {
|
||||
return fmt.Errorf("invalid string being converted to IP address: %s", ipStr)
|
||||
}
|
||||
out = append(out, ip)
|
||||
}
|
||||
|
||||
if !s.changed {
|
||||
*s.value = out
|
||||
} else {
|
||||
*s.value = append(*s.value, out...)
|
||||
}
|
||||
|
||||
s.changed = true
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Type returns a string that uniquely represents this flag's type.
|
||||
func (s *ipSliceValue) Type() string {
|
||||
return "ipSlice"
|
||||
}
|
||||
|
||||
// String defines a "native" format for this net.IP slice flag value.
|
||||
func (s *ipSliceValue) String() string {
|
||||
|
||||
ipStrSlice := make([]string, len(*s.value))
|
||||
for i, ip := range *s.value {
|
||||
ipStrSlice[i] = ip.String()
|
||||
}
|
||||
|
||||
out, _ := writeAsCSV(ipStrSlice)
|
||||
|
||||
return "[" + out + "]"
|
||||
}
|
||||
|
||||
func ipSliceConv(val string) (interface{}, error) {
|
||||
val = strings.Trim(val, "[]")
|
||||
// Emtpy string would cause a slice with one (empty) entry
|
||||
if len(val) == 0 {
|
||||
return []net.IP{}, nil
|
||||
}
|
||||
ss := strings.Split(val, ",")
|
||||
out := make([]net.IP, len(ss))
|
||||
for i, sval := range ss {
|
||||
ip := net.ParseIP(strings.TrimSpace(sval))
|
||||
if ip == nil {
|
||||
return nil, fmt.Errorf("invalid string being converted to IP address: %s", sval)
|
||||
}
|
||||
out[i] = ip
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// GetIPSlice returns the []net.IP value of a flag with the given name
|
||||
func (f *FlagSet) GetIPSlice(name string) ([]net.IP, error) {
|
||||
val, err := f.getFlagType(name, "ipSlice", ipSliceConv)
|
||||
if err != nil {
|
||||
return []net.IP{}, err
|
||||
}
|
||||
return val.([]net.IP), nil
|
||||
}
|
||||
|
||||
// IPSliceVar defines a ipSlice flag with specified name, default value, and usage string.
|
||||
// The argument p points to a []net.IP variable in which to store the value of the flag.
|
||||
func (f *FlagSet) IPSliceVar(p *[]net.IP, name string, value []net.IP, usage string) {
|
||||
f.VarP(newIPSliceValue(value, p), name, "", usage)
|
||||
}
|
||||
|
||||
// IPSliceVarP is like IPSliceVar, but accepts a shorthand letter that can be used after a single dash.
|
||||
func (f *FlagSet) IPSliceVarP(p *[]net.IP, name, shorthand string, value []net.IP, usage string) {
|
||||
f.VarP(newIPSliceValue(value, p), name, shorthand, usage)
|
||||
}
|
||||
|
||||
// IPSliceVar defines a []net.IP flag with specified name, default value, and usage string.
|
||||
// The argument p points to a []net.IP variable in which to store the value of the flag.
|
||||
func IPSliceVar(p *[]net.IP, name string, value []net.IP, usage string) {
|
||||
CommandLine.VarP(newIPSliceValue(value, p), name, "", usage)
|
||||
}
|
||||
|
||||
// IPSliceVarP is like IPSliceVar, but accepts a shorthand letter that can be used after a single dash.
|
||||
func IPSliceVarP(p *[]net.IP, name, shorthand string, value []net.IP, usage string) {
|
||||
CommandLine.VarP(newIPSliceValue(value, p), name, shorthand, usage)
|
||||
}
|
||||
|
||||
// IPSlice defines a []net.IP flag with specified name, default value, and usage string.
|
||||
// The return value is the address of a []net.IP variable that stores the value of that flag.
|
||||
func (f *FlagSet) IPSlice(name string, value []net.IP, usage string) *[]net.IP {
|
||||
p := []net.IP{}
|
||||
f.IPSliceVarP(&p, name, "", value, usage)
|
||||
return &p
|
||||
}
|
||||
|
||||
// IPSliceP is like IPSlice, but accepts a shorthand letter that can be used after a single dash.
|
||||
func (f *FlagSet) IPSliceP(name, shorthand string, value []net.IP, usage string) *[]net.IP {
|
||||
p := []net.IP{}
|
||||
f.IPSliceVarP(&p, name, shorthand, value, usage)
|
||||
return &p
|
||||
}
|
||||
|
||||
// IPSlice defines a []net.IP flag with specified name, default value, and usage string.
|
||||
// The return value is the address of a []net.IP variable that stores the value of the flag.
|
||||
func IPSlice(name string, value []net.IP, usage string) *[]net.IP {
|
||||
return CommandLine.IPSliceP(name, "", value, usage)
|
||||
}
|
||||
|
||||
// IPSliceP is like IPSlice, but accepts a shorthand letter that can be used after a single dash.
|
||||
func IPSliceP(name, shorthand string, value []net.IP, usage string) *[]net.IP {
|
||||
return CommandLine.IPSliceP(name, shorthand, value, usage)
|
||||
}
|
2
vendor/github.com/spf13/pflag/ipnet.go
generated
vendored
2
vendor/github.com/spf13/pflag/ipnet.go
generated
vendored
@ -27,8 +27,6 @@ func (*ipNetValue) Type() string {
|
||||
return "ipNet"
|
||||
}
|
||||
|
||||
var _ = strings.TrimSpace
|
||||
|
||||
func newIPNetValue(val net.IPNet, p *net.IPNet) *ipNetValue {
|
||||
*p = val
|
||||
return (*ipNetValue)(p)
|
||||
|
6
vendor/github.com/spf13/pflag/string_array.go
generated
vendored
6
vendor/github.com/spf13/pflag/string_array.go
generated
vendored
@ -1,11 +1,5 @@
|
||||
package pflag
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
var _ = fmt.Fprint
|
||||
|
||||
// -- stringArray Value
|
||||
type stringArrayValue struct {
|
||||
value *[]string
|
||||
|
5
vendor/github.com/spf13/pflag/string_slice.go
generated
vendored
5
vendor/github.com/spf13/pflag/string_slice.go
generated
vendored
@ -3,12 +3,9 @@ package pflag
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/csv"
|
||||
"fmt"
|
||||
"strings"
|
||||
)
|
||||
|
||||
var _ = fmt.Fprint
|
||||
|
||||
// -- stringSlice Value
|
||||
type stringSliceValue struct {
|
||||
value *[]string
|
||||
@ -39,7 +36,7 @@ func writeAsCSV(vals []string) (string, error) {
|
||||
return "", err
|
||||
}
|
||||
w.Flush()
|
||||
return strings.TrimSuffix(b.String(), fmt.Sprintln()), nil
|
||||
return strings.TrimSuffix(b.String(), "\n"), nil
|
||||
}
|
||||
|
||||
func (s *stringSliceValue) Set(val string) error {
|
||||
|
126
vendor/github.com/spf13/pflag/uint_slice.go
generated
vendored
Normal file
126
vendor/github.com/spf13/pflag/uint_slice.go
generated
vendored
Normal file
@ -0,0 +1,126 @@
|
||||
package pflag
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// -- uintSlice Value
|
||||
type uintSliceValue struct {
|
||||
value *[]uint
|
||||
changed bool
|
||||
}
|
||||
|
||||
func newUintSliceValue(val []uint, p *[]uint) *uintSliceValue {
|
||||
uisv := new(uintSliceValue)
|
||||
uisv.value = p
|
||||
*uisv.value = val
|
||||
return uisv
|
||||
}
|
||||
|
||||
func (s *uintSliceValue) Set(val string) error {
|
||||
ss := strings.Split(val, ",")
|
||||
out := make([]uint, len(ss))
|
||||
for i, d := range ss {
|
||||
u, err := strconv.ParseUint(d, 10, 0)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
out[i] = uint(u)
|
||||
}
|
||||
if !s.changed {
|
||||
*s.value = out
|
||||
} else {
|
||||
*s.value = append(*s.value, out...)
|
||||
}
|
||||
s.changed = true
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *uintSliceValue) Type() string {
|
||||
return "uintSlice"
|
||||
}
|
||||
|
||||
func (s *uintSliceValue) String() string {
|
||||
out := make([]string, len(*s.value))
|
||||
for i, d := range *s.value {
|
||||
out[i] = fmt.Sprintf("%d", d)
|
||||
}
|
||||
return "[" + strings.Join(out, ",") + "]"
|
||||
}
|
||||
|
||||
func uintSliceConv(val string) (interface{}, error) {
|
||||
val = strings.Trim(val, "[]")
|
||||
// Empty string would cause a slice with one (empty) entry
|
||||
if len(val) == 0 {
|
||||
return []uint{}, nil
|
||||
}
|
||||
ss := strings.Split(val, ",")
|
||||
out := make([]uint, len(ss))
|
||||
for i, d := range ss {
|
||||
u, err := strconv.ParseUint(d, 10, 0)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
out[i] = uint(u)
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// GetUintSlice returns the []uint value of a flag with the given name.
|
||||
func (f *FlagSet) GetUintSlice(name string) ([]uint, error) {
|
||||
val, err := f.getFlagType(name, "uintSlice", uintSliceConv)
|
||||
if err != nil {
|
||||
return []uint{}, err
|
||||
}
|
||||
return val.([]uint), nil
|
||||
}
|
||||
|
||||
// UintSliceVar defines a uintSlice flag with specified name, default value, and usage string.
|
||||
// The argument p points to a []uint variable in which to store the value of the flag.
|
||||
func (f *FlagSet) UintSliceVar(p *[]uint, name string, value []uint, usage string) {
|
||||
f.VarP(newUintSliceValue(value, p), name, "", usage)
|
||||
}
|
||||
|
||||
// UintSliceVarP is like UintSliceVar, but accepts a shorthand letter that can be used after a single dash.
|
||||
func (f *FlagSet) UintSliceVarP(p *[]uint, name, shorthand string, value []uint, usage string) {
|
||||
f.VarP(newUintSliceValue(value, p), name, shorthand, usage)
|
||||
}
|
||||
|
||||
// UintSliceVar defines a uint[] flag with specified name, default value, and usage string.
|
||||
// The argument p points to a uint[] variable in which to store the value of the flag.
|
||||
func UintSliceVar(p *[]uint, name string, value []uint, usage string) {
|
||||
CommandLine.VarP(newUintSliceValue(value, p), name, "", usage)
|
||||
}
|
||||
|
||||
// UintSliceVarP is like the UintSliceVar, but accepts a shorthand letter that can be used after a single dash.
|
||||
func UintSliceVarP(p *[]uint, name, shorthand string, value []uint, usage string) {
|
||||
CommandLine.VarP(newUintSliceValue(value, p), name, shorthand, usage)
|
||||
}
|
||||
|
||||
// UintSlice defines a []uint flag with specified name, default value, and usage string.
|
||||
// The return value is the address of a []uint variable that stores the value of the flag.
|
||||
func (f *FlagSet) UintSlice(name string, value []uint, usage string) *[]uint {
|
||||
p := []uint{}
|
||||
f.UintSliceVarP(&p, name, "", value, usage)
|
||||
return &p
|
||||
}
|
||||
|
||||
// UintSliceP is like UintSlice, but accepts a shorthand letter that can be used after a single dash.
|
||||
func (f *FlagSet) UintSliceP(name, shorthand string, value []uint, usage string) *[]uint {
|
||||
p := []uint{}
|
||||
f.UintSliceVarP(&p, name, shorthand, value, usage)
|
||||
return &p
|
||||
}
|
||||
|
||||
// UintSlice defines a []uint flag with specified name, default value, and usage string.
|
||||
// The return value is the address of a []uint variable that stores the value of the flag.
|
||||
func UintSlice(name string, value []uint, usage string) *[]uint {
|
||||
return CommandLine.UintSliceP(name, "", value, usage)
|
||||
}
|
||||
|
||||
// UintSliceP is like UintSlice, but accepts a shorthand letter that can be used after a single dash.
|
||||
func UintSliceP(name, shorthand string, value []uint, usage string) *[]uint {
|
||||
return CommandLine.UintSliceP(name, shorthand, value, usage)
|
||||
}
|
6
vendor/github.com/stretchr/testify/assert/assertions.go
generated
vendored
6
vendor/github.com/stretchr/testify/assert/assertions.go
generated
vendored
@ -1062,6 +1062,8 @@ func diff(expected interface{}, actual interface{}) string {
|
||||
}
|
||||
|
||||
var spewConfig = spew.ConfigState{
|
||||
Indent: " ",
|
||||
SortKeys: true,
|
||||
Indent: " ",
|
||||
DisablePointerAddresses: true,
|
||||
DisableCapacities: true,
|
||||
SortKeys: true,
|
||||
}
|
||||
|
8
vendor/golang.org/x/crypto/curve25519/const_amd64.h
generated
vendored
Normal file
8
vendor/golang.org/x/crypto/curve25519/const_amd64.h
generated
vendored
Normal file
@ -0,0 +1,8 @@
|
||||
// Copyright 2012 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// This code was translated into a form compatible with 6a from the public
|
||||
// domain sources in SUPERCOP: http://bench.cr.yp.to/supercop.html
|
||||
|
||||
#define REDMASK51 0x0007FFFFFFFFFFFF
|
4
vendor/golang.org/x/crypto/curve25519/const_amd64.s
generated
vendored
4
vendor/golang.org/x/crypto/curve25519/const_amd64.s
generated
vendored
@ -7,8 +7,8 @@
|
||||
|
||||
// +build amd64,!gccgo,!appengine
|
||||
|
||||
DATA ·REDMASK51(SB)/8, $0x0007FFFFFFFFFFFF
|
||||
GLOBL ·REDMASK51(SB), 8, $8
|
||||
// These constants cannot be encoded in non-MOVQ immediates.
|
||||
// We access them directly from memory instead.
|
||||
|
||||
DATA ·_121666_213(SB)/8, $996687872
|
||||
GLOBL ·_121666_213(SB), 8, $8
|
||||
|
29
vendor/golang.org/x/crypto/curve25519/curve25519_test.go
generated
vendored
29
vendor/golang.org/x/crypto/curve25519/curve25519_test.go
generated
vendored
@ -1,29 +0,0 @@
|
||||
// Copyright 2012 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package curve25519
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
)
|
||||
|
||||
const expectedHex = "89161fde887b2b53de549af483940106ecc114d6982daa98256de23bdf77661a"
|
||||
|
||||
func TestBaseScalarMult(t *testing.T) {
|
||||
var a, b [32]byte
|
||||
in := &a
|
||||
out := &b
|
||||
a[0] = 1
|
||||
|
||||
for i := 0; i < 200; i++ {
|
||||
ScalarBaseMult(out, in)
|
||||
in, out = out, in
|
||||
}
|
||||
|
||||
result := fmt.Sprintf("%x", in[:])
|
||||
if result != expectedHex {
|
||||
t.Errorf("incorrect result: got %s, want %s", result, expectedHex)
|
||||
}
|
||||
}
|
2
vendor/golang.org/x/crypto/curve25519/doc.go
generated
vendored
2
vendor/golang.org/x/crypto/curve25519/doc.go
generated
vendored
@ -4,7 +4,7 @@
|
||||
|
||||
// Package curve25519 provides an implementation of scalar multiplication on
|
||||
// the elliptic curve known as curve25519. See http://cr.yp.to/ecdh.html
|
||||
package curve25519 // import "golang.org/x/crypto/curve25519"
|
||||
package curve25519
|
||||
|
||||
// basePoint is the x coordinate of the generator of the curve.
|
||||
var basePoint = [32]byte{9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
|
||||
|
4
vendor/golang.org/x/crypto/curve25519/freeze_amd64.s
generated
vendored
4
vendor/golang.org/x/crypto/curve25519/freeze_amd64.s
generated
vendored
@ -7,6 +7,8 @@
|
||||
|
||||
// +build amd64,!gccgo,!appengine
|
||||
|
||||
#include "const_amd64.h"
|
||||
|
||||
// func freeze(inout *[5]uint64)
|
||||
TEXT ·freeze(SB),7,$0-8
|
||||
MOVQ inout+0(FP), DI
|
||||
@ -16,7 +18,7 @@ TEXT ·freeze(SB),7,$0-8
|
||||
MOVQ 16(DI),CX
|
||||
MOVQ 24(DI),R8
|
||||
MOVQ 32(DI),R9
|
||||
MOVQ ·REDMASK51(SB),AX
|
||||
MOVQ $REDMASK51,AX
|
||||
MOVQ AX,R10
|
||||
SUBQ $18,R10
|
||||
MOVQ $3,R11
|
||||
|
20
vendor/golang.org/x/crypto/curve25519/ladderstep_amd64.s
generated
vendored
20
vendor/golang.org/x/crypto/curve25519/ladderstep_amd64.s
generated
vendored
@ -7,6 +7,8 @@
|
||||
|
||||
// +build amd64,!gccgo,!appengine
|
||||
|
||||
#include "const_amd64.h"
|
||||
|
||||
// func ladderstep(inout *[5][5]uint64)
|
||||
TEXT ·ladderstep(SB),0,$296-8
|
||||
MOVQ inout+0(FP),DI
|
||||
@ -118,7 +120,7 @@ TEXT ·ladderstep(SB),0,$296-8
|
||||
MULQ 72(SP)
|
||||
ADDQ AX,R12
|
||||
ADCQ DX,R13
|
||||
MOVQ ·REDMASK51(SB),DX
|
||||
MOVQ $REDMASK51,DX
|
||||
SHLQ $13,CX:SI
|
||||
ANDQ DX,SI
|
||||
SHLQ $13,R9:R8
|
||||
@ -233,7 +235,7 @@ TEXT ·ladderstep(SB),0,$296-8
|
||||
MULQ 32(SP)
|
||||
ADDQ AX,R12
|
||||
ADCQ DX,R13
|
||||
MOVQ ·REDMASK51(SB),DX
|
||||
MOVQ $REDMASK51,DX
|
||||
SHLQ $13,CX:SI
|
||||
ANDQ DX,SI
|
||||
SHLQ $13,R9:R8
|
||||
@ -438,7 +440,7 @@ TEXT ·ladderstep(SB),0,$296-8
|
||||
MULQ 72(SP)
|
||||
ADDQ AX,R12
|
||||
ADCQ DX,R13
|
||||
MOVQ ·REDMASK51(SB),DX
|
||||
MOVQ $REDMASK51,DX
|
||||
SHLQ $13,CX:SI
|
||||
ANDQ DX,SI
|
||||
SHLQ $13,R9:R8
|
||||
@ -588,7 +590,7 @@ TEXT ·ladderstep(SB),0,$296-8
|
||||
MULQ 32(SP)
|
||||
ADDQ AX,R12
|
||||
ADCQ DX,R13
|
||||
MOVQ ·REDMASK51(SB),DX
|
||||
MOVQ $REDMASK51,DX
|
||||
SHLQ $13,CX:SI
|
||||
ANDQ DX,SI
|
||||
SHLQ $13,R9:R8
|
||||
@ -728,7 +730,7 @@ TEXT ·ladderstep(SB),0,$296-8
|
||||
MULQ 152(DI)
|
||||
ADDQ AX,R12
|
||||
ADCQ DX,R13
|
||||
MOVQ ·REDMASK51(SB),DX
|
||||
MOVQ $REDMASK51,DX
|
||||
SHLQ $13,CX:SI
|
||||
ANDQ DX,SI
|
||||
SHLQ $13,R9:R8
|
||||
@ -843,7 +845,7 @@ TEXT ·ladderstep(SB),0,$296-8
|
||||
MULQ 192(DI)
|
||||
ADDQ AX,R12
|
||||
ADCQ DX,R13
|
||||
MOVQ ·REDMASK51(SB),DX
|
||||
MOVQ $REDMASK51,DX
|
||||
SHLQ $13,CX:SI
|
||||
ANDQ DX,SI
|
||||
SHLQ $13,R9:R8
|
||||
@ -993,7 +995,7 @@ TEXT ·ladderstep(SB),0,$296-8
|
||||
MULQ 32(DI)
|
||||
ADDQ AX,R12
|
||||
ADCQ DX,R13
|
||||
MOVQ ·REDMASK51(SB),DX
|
||||
MOVQ $REDMASK51,DX
|
||||
SHLQ $13,CX:SI
|
||||
ANDQ DX,SI
|
||||
SHLQ $13,R9:R8
|
||||
@ -1143,7 +1145,7 @@ TEXT ·ladderstep(SB),0,$296-8
|
||||
MULQ 112(SP)
|
||||
ADDQ AX,R12
|
||||
ADCQ DX,R13
|
||||
MOVQ ·REDMASK51(SB),DX
|
||||
MOVQ $REDMASK51,DX
|
||||
SHLQ $13,CX:SI
|
||||
ANDQ DX,SI
|
||||
SHLQ $13,R9:R8
|
||||
@ -1329,7 +1331,7 @@ TEXT ·ladderstep(SB),0,$296-8
|
||||
MULQ 192(SP)
|
||||
ADDQ AX,R12
|
||||
ADCQ DX,R13
|
||||
MOVQ ·REDMASK51(SB),DX
|
||||
MOVQ $REDMASK51,DX
|
||||
SHLQ $13,CX:SI
|
||||
ANDQ DX,SI
|
||||
SHLQ $13,R9:R8
|
||||
|
4
vendor/golang.org/x/crypto/curve25519/mul_amd64.s
generated
vendored
4
vendor/golang.org/x/crypto/curve25519/mul_amd64.s
generated
vendored
@ -7,6 +7,8 @@
|
||||
|
||||
// +build amd64,!gccgo,!appengine
|
||||
|
||||
#include "const_amd64.h"
|
||||
|
||||
// func mul(dest, a, b *[5]uint64)
|
||||
TEXT ·mul(SB),0,$16-24
|
||||
MOVQ dest+0(FP), DI
|
||||
@ -121,7 +123,7 @@ TEXT ·mul(SB),0,$16-24
|
||||
MULQ 32(CX)
|
||||
ADDQ AX,R14
|
||||
ADCQ DX,R15
|
||||
MOVQ ·REDMASK51(SB),SI
|
||||
MOVQ $REDMASK51,SI
|
||||
SHLQ $13,R9:R8
|
||||
ANDQ SI,R8
|
||||
SHLQ $13,R11:R10
|
||||
|
4
vendor/golang.org/x/crypto/curve25519/square_amd64.s
generated
vendored
4
vendor/golang.org/x/crypto/curve25519/square_amd64.s
generated
vendored
@ -7,6 +7,8 @@
|
||||
|
||||
// +build amd64,!gccgo,!appengine
|
||||
|
||||
#include "const_amd64.h"
|
||||
|
||||
// func square(out, in *[5]uint64)
|
||||
TEXT ·square(SB),7,$0-16
|
||||
MOVQ out+0(FP), DI
|
||||
@ -84,7 +86,7 @@ TEXT ·square(SB),7,$0-16
|
||||
MULQ 32(SI)
|
||||
ADDQ AX,R13
|
||||
ADCQ DX,R14
|
||||
MOVQ ·REDMASK51(SB),SI
|
||||
MOVQ $REDMASK51,SI
|
||||
SHLQ $13,R8:CX
|
||||
ANDQ SI,CX
|
||||
SHLQ $13,R10:R9
|
||||
|
183
vendor/golang.org/x/crypto/ed25519/ed25519_test.go
generated
vendored
183
vendor/golang.org/x/crypto/ed25519/ed25519_test.go
generated
vendored
@ -1,183 +0,0 @@
|
||||
// Copyright 2016 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package ed25519
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"compress/gzip"
|
||||
"crypto"
|
||||
"crypto/rand"
|
||||
"encoding/hex"
|
||||
"os"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"golang.org/x/crypto/ed25519/internal/edwards25519"
|
||||
)
|
||||
|
||||
type zeroReader struct{}
|
||||
|
||||
func (zeroReader) Read(buf []byte) (int, error) {
|
||||
for i := range buf {
|
||||
buf[i] = 0
|
||||
}
|
||||
return len(buf), nil
|
||||
}
|
||||
|
||||
func TestUnmarshalMarshal(t *testing.T) {
|
||||
pub, _, _ := GenerateKey(rand.Reader)
|
||||
|
||||
var A edwards25519.ExtendedGroupElement
|
||||
var pubBytes [32]byte
|
||||
copy(pubBytes[:], pub)
|
||||
if !A.FromBytes(&pubBytes) {
|
||||
t.Fatalf("ExtendedGroupElement.FromBytes failed")
|
||||
}
|
||||
|
||||
var pub2 [32]byte
|
||||
A.ToBytes(&pub2)
|
||||
|
||||
if pubBytes != pub2 {
|
||||
t.Errorf("FromBytes(%v)->ToBytes does not round-trip, got %x\n", pubBytes, pub2)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSignVerify(t *testing.T) {
|
||||
var zero zeroReader
|
||||
public, private, _ := GenerateKey(zero)
|
||||
|
||||
message := []byte("test message")
|
||||
sig := Sign(private, message)
|
||||
if !Verify(public, message, sig) {
|
||||
t.Errorf("valid signature rejected")
|
||||
}
|
||||
|
||||
wrongMessage := []byte("wrong message")
|
||||
if Verify(public, wrongMessage, sig) {
|
||||
t.Errorf("signature of different message accepted")
|
||||
}
|
||||
}
|
||||
|
||||
func TestCryptoSigner(t *testing.T) {
|
||||
var zero zeroReader
|
||||
public, private, _ := GenerateKey(zero)
|
||||
|
||||
signer := crypto.Signer(private)
|
||||
|
||||
publicInterface := signer.Public()
|
||||
public2, ok := publicInterface.(PublicKey)
|
||||
if !ok {
|
||||
t.Fatalf("expected PublicKey from Public() but got %T", publicInterface)
|
||||
}
|
||||
|
||||
if !bytes.Equal(public, public2) {
|
||||
t.Errorf("public keys do not match: original:%x vs Public():%x", public, public2)
|
||||
}
|
||||
|
||||
message := []byte("message")
|
||||
var noHash crypto.Hash
|
||||
signature, err := signer.Sign(zero, message, noHash)
|
||||
if err != nil {
|
||||
t.Fatalf("error from Sign(): %s", err)
|
||||
}
|
||||
|
||||
if !Verify(public, message, signature) {
|
||||
t.Errorf("Verify failed on signature from Sign()")
|
||||
}
|
||||
}
|
||||
|
||||
func TestGolden(t *testing.T) {
|
||||
// sign.input.gz is a selection of test cases from
|
||||
// http://ed25519.cr.yp.to/python/sign.input
|
||||
testDataZ, err := os.Open("testdata/sign.input.gz")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer testDataZ.Close()
|
||||
testData, err := gzip.NewReader(testDataZ)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer testData.Close()
|
||||
|
||||
scanner := bufio.NewScanner(testData)
|
||||
lineNo := 0
|
||||
|
||||
for scanner.Scan() {
|
||||
lineNo++
|
||||
|
||||
line := scanner.Text()
|
||||
parts := strings.Split(line, ":")
|
||||
if len(parts) != 5 {
|
||||
t.Fatalf("bad number of parts on line %d", lineNo)
|
||||
}
|
||||
|
||||
privBytes, _ := hex.DecodeString(parts[0])
|
||||
pubKey, _ := hex.DecodeString(parts[1])
|
||||
msg, _ := hex.DecodeString(parts[2])
|
||||
sig, _ := hex.DecodeString(parts[3])
|
||||
// The signatures in the test vectors also include the message
|
||||
// at the end, but we just want R and S.
|
||||
sig = sig[:SignatureSize]
|
||||
|
||||
if l := len(pubKey); l != PublicKeySize {
|
||||
t.Fatalf("bad public key length on line %d: got %d bytes", lineNo, l)
|
||||
}
|
||||
|
||||
var priv [PrivateKeySize]byte
|
||||
copy(priv[:], privBytes)
|
||||
copy(priv[32:], pubKey)
|
||||
|
||||
sig2 := Sign(priv[:], msg)
|
||||
if !bytes.Equal(sig, sig2[:]) {
|
||||
t.Errorf("different signature result on line %d: %x vs %x", lineNo, sig, sig2)
|
||||
}
|
||||
|
||||
if !Verify(pubKey, msg, sig2) {
|
||||
t.Errorf("signature failed to verify on line %d", lineNo)
|
||||
}
|
||||
}
|
||||
|
||||
if err := scanner.Err(); err != nil {
|
||||
t.Fatalf("error reading test data: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkKeyGeneration(b *testing.B) {
|
||||
var zero zeroReader
|
||||
for i := 0; i < b.N; i++ {
|
||||
if _, _, err := GenerateKey(zero); err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkSigning(b *testing.B) {
|
||||
var zero zeroReader
|
||||
_, priv, err := GenerateKey(zero)
|
||||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
message := []byte("Hello, world!")
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
Sign(priv, message)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkVerification(b *testing.B) {
|
||||
var zero zeroReader
|
||||
pub, priv, err := GenerateKey(zero)
|
||||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
message := []byte("Hello, world!")
|
||||
signature := Sign(priv, message)
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
Verify(pub, message, signature)
|
||||
}
|
||||
}
|
BIN
vendor/golang.org/x/crypto/ed25519/testdata/sign.input.gz
generated
vendored
BIN
vendor/golang.org/x/crypto/ed25519/testdata/sign.input.gz
generated
vendored
Binary file not shown.
10
vendor/golang.org/x/crypto/poly1305/sum_amd64.s
generated
vendored
10
vendor/golang.org/x/crypto/poly1305/sum_amd64.s
generated
vendored
@ -54,9 +54,9 @@
|
||||
ADCQ t3, h1; \
|
||||
ADCQ $0, h2
|
||||
|
||||
DATA poly1305Mask<>+0x00(SB)/8, $0x0FFFFFFC0FFFFFFF
|
||||
DATA poly1305Mask<>+0x08(SB)/8, $0x0FFFFFFC0FFFFFFC
|
||||
GLOBL poly1305Mask<>(SB), RODATA, $16
|
||||
DATA ·poly1305Mask<>+0x00(SB)/8, $0x0FFFFFFC0FFFFFFF
|
||||
DATA ·poly1305Mask<>+0x08(SB)/8, $0x0FFFFFFC0FFFFFFC
|
||||
GLOBL ·poly1305Mask<>(SB), RODATA, $16
|
||||
|
||||
// func poly1305(out *[16]byte, m *byte, mlen uint64, key *[32]key)
|
||||
TEXT ·poly1305(SB), $0-32
|
||||
@ -67,8 +67,8 @@ TEXT ·poly1305(SB), $0-32
|
||||
|
||||
MOVQ 0(AX), R11
|
||||
MOVQ 8(AX), R12
|
||||
ANDQ poly1305Mask<>(SB), R11 // r0
|
||||
ANDQ poly1305Mask<>+8(SB), R12 // r1
|
||||
ANDQ ·poly1305Mask<>(SB), R11 // r0
|
||||
ANDQ ·poly1305Mask<>+8(SB), R12 // r1
|
||||
XORQ R8, R8 // h0
|
||||
XORQ R9, R9 // h1
|
||||
XORQ R10, R10 // h2
|
||||
|
14
vendor/golang.org/x/crypto/poly1305/sum_arm.s
generated
vendored
14
vendor/golang.org/x/crypto/poly1305/sum_arm.s
generated
vendored
@ -9,12 +9,12 @@
|
||||
// This code was translated into a form compatible with 5a from the public
|
||||
// domain source by Andrew Moon: github.com/floodyberry/poly1305-opt/blob/master/app/extensions/poly1305.
|
||||
|
||||
DATA poly1305_init_constants_armv6<>+0x00(SB)/4, $0x3ffffff
|
||||
DATA poly1305_init_constants_armv6<>+0x04(SB)/4, $0x3ffff03
|
||||
DATA poly1305_init_constants_armv6<>+0x08(SB)/4, $0x3ffc0ff
|
||||
DATA poly1305_init_constants_armv6<>+0x0c(SB)/4, $0x3f03fff
|
||||
DATA poly1305_init_constants_armv6<>+0x10(SB)/4, $0x00fffff
|
||||
GLOBL poly1305_init_constants_armv6<>(SB), 8, $20
|
||||
DATA ·poly1305_init_constants_armv6<>+0x00(SB)/4, $0x3ffffff
|
||||
DATA ·poly1305_init_constants_armv6<>+0x04(SB)/4, $0x3ffff03
|
||||
DATA ·poly1305_init_constants_armv6<>+0x08(SB)/4, $0x3ffc0ff
|
||||
DATA ·poly1305_init_constants_armv6<>+0x0c(SB)/4, $0x3f03fff
|
||||
DATA ·poly1305_init_constants_armv6<>+0x10(SB)/4, $0x00fffff
|
||||
GLOBL ·poly1305_init_constants_armv6<>(SB), 8, $20
|
||||
|
||||
// Warning: the linker may use R11 to synthesize certain instructions. Please
|
||||
// take care and verify that no synthetic instructions use it.
|
||||
@ -27,7 +27,7 @@ TEXT poly1305_init_ext_armv6<>(SB), NOSPLIT, $0
|
||||
ADD $4, R13, R8
|
||||
MOVM.IB [R4-R7], (R8)
|
||||
MOVM.IA.W (R1), [R2-R5]
|
||||
MOVW $poly1305_init_constants_armv6<>(SB), R7
|
||||
MOVW $·poly1305_init_constants_armv6<>(SB), R7
|
||||
MOVW R2, R8
|
||||
MOVW R2>>26, R9
|
||||
MOVW R3>>20, g
|
||||
|
1614
vendor/golang.org/x/crypto/poly1305/sum_ref.go
generated
vendored
1614
vendor/golang.org/x/crypto/poly1305/sum_ref.go
generated
vendored
File diff suppressed because it is too large
Load Diff
2
vendor/golang.org/x/crypto/ssh/agent/client.go
generated
vendored
2
vendor/golang.org/x/crypto/ssh/agent/client.go
generated
vendored
@ -9,7 +9,7 @@
|
||||
//
|
||||
// References:
|
||||
// [PROTOCOL.agent]: http://cvsweb.openbsd.org/cgi-bin/cvsweb/src/usr.bin/ssh/PROTOCOL.agent?rev=HEAD
|
||||
package agent // import "golang.org/x/crypto/ssh/agent"
|
||||
package agent
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
|
122
vendor/golang.org/x/crypto/ssh/benchmark_test.go
generated
vendored
122
vendor/golang.org/x/crypto/ssh/benchmark_test.go
generated
vendored
@ -1,122 +0,0 @@
|
||||
// Copyright 2013 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package ssh
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"io"
|
||||
"net"
|
||||
"testing"
|
||||
)
|
||||
|
||||
type server struct {
|
||||
*ServerConn
|
||||
chans <-chan NewChannel
|
||||
}
|
||||
|
||||
func newServer(c net.Conn, conf *ServerConfig) (*server, error) {
|
||||
sconn, chans, reqs, err := NewServerConn(c, conf)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
go DiscardRequests(reqs)
|
||||
return &server{sconn, chans}, nil
|
||||
}
|
||||
|
||||
func (s *server) Accept() (NewChannel, error) {
|
||||
n, ok := <-s.chans
|
||||
if !ok {
|
||||
return nil, io.EOF
|
||||
}
|
||||
return n, nil
|
||||
}
|
||||
|
||||
func sshPipe() (Conn, *server, error) {
|
||||
c1, c2, err := netPipe()
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
clientConf := ClientConfig{
|
||||
User: "user",
|
||||
}
|
||||
serverConf := ServerConfig{
|
||||
NoClientAuth: true,
|
||||
}
|
||||
serverConf.AddHostKey(testSigners["ecdsa"])
|
||||
done := make(chan *server, 1)
|
||||
go func() {
|
||||
server, err := newServer(c2, &serverConf)
|
||||
if err != nil {
|
||||
done <- nil
|
||||
}
|
||||
done <- server
|
||||
}()
|
||||
|
||||
client, _, reqs, err := NewClientConn(c1, "", &clientConf)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
server := <-done
|
||||
if server == nil {
|
||||
return nil, nil, errors.New("server handshake failed.")
|
||||
}
|
||||
go DiscardRequests(reqs)
|
||||
|
||||
return client, server, nil
|
||||
}
|
||||
|
||||
func BenchmarkEndToEnd(b *testing.B) {
|
||||
b.StopTimer()
|
||||
|
||||
client, server, err := sshPipe()
|
||||
if err != nil {
|
||||
b.Fatalf("sshPipe: %v", err)
|
||||
}
|
||||
|
||||
defer client.Close()
|
||||
defer server.Close()
|
||||
|
||||
size := (1 << 20)
|
||||
input := make([]byte, size)
|
||||
output := make([]byte, size)
|
||||
b.SetBytes(int64(size))
|
||||
done := make(chan int, 1)
|
||||
|
||||
go func() {
|
||||
newCh, err := server.Accept()
|
||||
if err != nil {
|
||||
b.Fatalf("Client: %v", err)
|
||||
}
|
||||
ch, incoming, err := newCh.Accept()
|
||||
go DiscardRequests(incoming)
|
||||
for i := 0; i < b.N; i++ {
|
||||
if _, err := io.ReadFull(ch, output); err != nil {
|
||||
b.Fatalf("ReadFull: %v", err)
|
||||
}
|
||||
}
|
||||
ch.Close()
|
||||
done <- 1
|
||||
}()
|
||||
|
||||
ch, in, err := client.OpenChannel("speed", nil)
|
||||
if err != nil {
|
||||
b.Fatalf("OpenChannel: %v", err)
|
||||
}
|
||||
go DiscardRequests(in)
|
||||
|
||||
b.ResetTimer()
|
||||
b.StartTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
if _, err := ch.Write(input); err != nil {
|
||||
b.Fatalf("WriteFull: %v", err)
|
||||
}
|
||||
}
|
||||
ch.Close()
|
||||
b.StopTimer()
|
||||
|
||||
<-done
|
||||
}
|
87
vendor/golang.org/x/crypto/ssh/buffer_test.go
generated
vendored
87
vendor/golang.org/x/crypto/ssh/buffer_test.go
generated
vendored
@ -1,87 +0,0 @@
|
||||
// Copyright 2011 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package ssh
|
||||
|
||||
import (
|
||||
"io"
|
||||
"testing"
|
||||
)
|
||||
|
||||
var alphabet = []byte("abcdefghijklmnopqrstuvwxyz")
|
||||
|
||||
func TestBufferReadwrite(t *testing.T) {
|
||||
b := newBuffer()
|
||||
b.write(alphabet[:10])
|
||||
r, _ := b.Read(make([]byte, 10))
|
||||
if r != 10 {
|
||||
t.Fatalf("Expected written == read == 10, written: 10, read %d", r)
|
||||
}
|
||||
|
||||
b = newBuffer()
|
||||
b.write(alphabet[:5])
|
||||
r, _ = b.Read(make([]byte, 10))
|
||||
if r != 5 {
|
||||
t.Fatalf("Expected written == read == 5, written: 5, read %d", r)
|
||||
}
|
||||
|
||||
b = newBuffer()
|
||||
b.write(alphabet[:10])
|
||||
r, _ = b.Read(make([]byte, 5))
|
||||
if r != 5 {
|
||||
t.Fatalf("Expected written == 10, read == 5, written: 10, read %d", r)
|
||||
}
|
||||
|
||||
b = newBuffer()
|
||||
b.write(alphabet[:5])
|
||||
b.write(alphabet[5:15])
|
||||
r, _ = b.Read(make([]byte, 10))
|
||||
r2, _ := b.Read(make([]byte, 10))
|
||||
if r != 10 || r2 != 5 || 15 != r+r2 {
|
||||
t.Fatal("Expected written == read == 15")
|
||||
}
|
||||
}
|
||||
|
||||
func TestBufferClose(t *testing.T) {
|
||||
b := newBuffer()
|
||||
b.write(alphabet[:10])
|
||||
b.eof()
|
||||
_, err := b.Read(make([]byte, 5))
|
||||
if err != nil {
|
||||
t.Fatal("expected read of 5 to not return EOF")
|
||||
}
|
||||
b = newBuffer()
|
||||
b.write(alphabet[:10])
|
||||
b.eof()
|
||||
r, err := b.Read(make([]byte, 5))
|
||||
r2, err2 := b.Read(make([]byte, 10))
|
||||
if r != 5 || r2 != 5 || err != nil || err2 != nil {
|
||||
t.Fatal("expected reads of 5 and 5")
|
||||
}
|
||||
|
||||
b = newBuffer()
|
||||
b.write(alphabet[:10])
|
||||
b.eof()
|
||||
r, err = b.Read(make([]byte, 5))
|
||||
r2, err2 = b.Read(make([]byte, 10))
|
||||
r3, err3 := b.Read(make([]byte, 10))
|
||||
if r != 5 || r2 != 5 || r3 != 0 || err != nil || err2 != nil || err3 != io.EOF {
|
||||
t.Fatal("expected reads of 5 and 5 and 0, with EOF")
|
||||
}
|
||||
|
||||
b = newBuffer()
|
||||
b.write(make([]byte, 5))
|
||||
b.write(make([]byte, 10))
|
||||
b.eof()
|
||||
r, err = b.Read(make([]byte, 9))
|
||||
r2, err2 = b.Read(make([]byte, 3))
|
||||
r3, err3 = b.Read(make([]byte, 3))
|
||||
r4, err4 := b.Read(make([]byte, 10))
|
||||
if err != nil || err2 != nil || err3 != nil || err4 != io.EOF {
|
||||
t.Fatalf("Expected EOF on forth read only, err=%v, err2=%v, err3=%v, err4=%v", err, err2, err3, err4)
|
||||
}
|
||||
if r != 9 || r2 != 3 || r3 != 3 || r4 != 0 {
|
||||
t.Fatal("Expected written == read == 15", r, r2, r3, r4)
|
||||
}
|
||||
}
|
216
vendor/golang.org/x/crypto/ssh/certs_test.go
generated
vendored
216
vendor/golang.org/x/crypto/ssh/certs_test.go
generated
vendored
@ -1,216 +0,0 @@
|
||||
// Copyright 2013 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package ssh
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/rand"
|
||||
"reflect"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
// Cert generated by ssh-keygen 6.0p1 Debian-4.
|
||||
// % ssh-keygen -s ca-key -I test user-key
|
||||
const exampleSSHCert = `ssh-rsa-cert-v01@openssh.com AAAAHHNzaC1yc2EtY2VydC12MDFAb3BlbnNzaC5jb20AAAAgb1srW/W3ZDjYAO45xLYAwzHBDLsJ4Ux6ICFIkTjb1LEAAAADAQABAAAAYQCkoR51poH0wE8w72cqSB8Sszx+vAhzcMdCO0wqHTj7UNENHWEXGrU0E0UQekD7U+yhkhtoyjbPOVIP7hNa6aRk/ezdh/iUnCIt4Jt1v3Z1h1P+hA4QuYFMHNB+rmjPwAcAAAAAAAAAAAAAAAEAAAAEdGVzdAAAAAAAAAAAAAAAAP//////////AAAAAAAAAIIAAAAVcGVybWl0LVgxMS1mb3J3YXJkaW5nAAAAAAAAABdwZXJtaXQtYWdlbnQtZm9yd2FyZGluZwAAAAAAAAAWcGVybWl0LXBvcnQtZm9yd2FyZGluZwAAAAAAAAAKcGVybWl0LXB0eQAAAAAAAAAOcGVybWl0LXVzZXItcmMAAAAAAAAAAAAAAHcAAAAHc3NoLXJzYQAAAAMBAAEAAABhANFS2kaktpSGc+CcmEKPyw9mJC4nZKxHKTgLVZeaGbFZOvJTNzBspQHdy7Q1uKSfktxpgjZnksiu/tFF9ngyY2KFoc+U88ya95IZUycBGCUbBQ8+bhDtw/icdDGQD5WnUwAAAG8AAAAHc3NoLXJzYQAAAGC8Y9Z2LQKhIhxf52773XaWrXdxP0t3GBVo4A10vUWiYoAGepr6rQIoGGXFxT4B9Gp+nEBJjOwKDXPrAevow0T9ca8gZN+0ykbhSrXLE5Ao48rqr3zP4O1/9P7e6gp0gw8=`
|
||||
|
||||
func TestParseCert(t *testing.T) {
|
||||
authKeyBytes := []byte(exampleSSHCert)
|
||||
|
||||
key, _, _, rest, err := ParseAuthorizedKey(authKeyBytes)
|
||||
if err != nil {
|
||||
t.Fatalf("ParseAuthorizedKey: %v", err)
|
||||
}
|
||||
if len(rest) > 0 {
|
||||
t.Errorf("rest: got %q, want empty", rest)
|
||||
}
|
||||
|
||||
if _, ok := key.(*Certificate); !ok {
|
||||
t.Fatalf("got %v (%T), want *Certificate", key, key)
|
||||
}
|
||||
|
||||
marshaled := MarshalAuthorizedKey(key)
|
||||
// Before comparison, remove the trailing newline that
|
||||
// MarshalAuthorizedKey adds.
|
||||
marshaled = marshaled[:len(marshaled)-1]
|
||||
if !bytes.Equal(authKeyBytes, marshaled) {
|
||||
t.Errorf("marshaled certificate does not match original: got %q, want %q", marshaled, authKeyBytes)
|
||||
}
|
||||
}
|
||||
|
||||
// Cert generated by ssh-keygen OpenSSH_6.8p1 OS X 10.10.3
|
||||
// % ssh-keygen -s ca -I testcert -O source-address=192.168.1.0/24 -O force-command=/bin/sleep user.pub
|
||||
// user.pub key: ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDACh1rt2DXfV3hk6fszSQcQ/rueMId0kVD9U7nl8cfEnFxqOCrNT92g4laQIGl2mn8lsGZfTLg8ksHq3gkvgO3oo/0wHy4v32JeBOHTsN5AL4gfHNEhWeWb50ev47hnTsRIt9P4dxogeUo/hTu7j9+s9lLpEQXCvq6xocXQt0j8MV9qZBBXFLXVT3cWIkSqOdwt/5ZBg+1GSrc7WfCXVWgTk4a20uPMuJPxU4RQwZW6X3+O8Pqo8C3cW0OzZRFP6gUYUKUsTI5WntlS+LAxgw1mZNsozFGdbiOPRnEryE3SRldh9vjDR3tin1fGpA5P7+CEB/bqaXtG3V+F2OkqaMN
|
||||
// Critical Options:
|
||||
// force-command /bin/sleep
|
||||
// source-address 192.168.1.0/24
|
||||
// Extensions:
|
||||
// permit-X11-forwarding
|
||||
// permit-agent-forwarding
|
||||
// permit-port-forwarding
|
||||
// permit-pty
|
||||
// permit-user-rc
|
||||
const exampleSSHCertWithOptions = `ssh-rsa-cert-v01@openssh.com AAAAHHNzaC1yc2EtY2VydC12MDFAb3BlbnNzaC5jb20AAAAgDyysCJY0XrO1n03EeRRoITnTPdjENFmWDs9X58PP3VUAAAADAQABAAABAQDACh1rt2DXfV3hk6fszSQcQ/rueMId0kVD9U7nl8cfEnFxqOCrNT92g4laQIGl2mn8lsGZfTLg8ksHq3gkvgO3oo/0wHy4v32JeBOHTsN5AL4gfHNEhWeWb50ev47hnTsRIt9P4dxogeUo/hTu7j9+s9lLpEQXCvq6xocXQt0j8MV9qZBBXFLXVT3cWIkSqOdwt/5ZBg+1GSrc7WfCXVWgTk4a20uPMuJPxU4RQwZW6X3+O8Pqo8C3cW0OzZRFP6gUYUKUsTI5WntlS+LAxgw1mZNsozFGdbiOPRnEryE3SRldh9vjDR3tin1fGpA5P7+CEB/bqaXtG3V+F2OkqaMNAAAAAAAAAAAAAAABAAAACHRlc3RjZXJ0AAAAAAAAAAAAAAAA//////////8AAABLAAAADWZvcmNlLWNvbW1hbmQAAAAOAAAACi9iaW4vc2xlZXAAAAAOc291cmNlLWFkZHJlc3MAAAASAAAADjE5Mi4xNjguMS4wLzI0AAAAggAAABVwZXJtaXQtWDExLWZvcndhcmRpbmcAAAAAAAAAF3Blcm1pdC1hZ2VudC1mb3J3YXJkaW5nAAAAAAAAABZwZXJtaXQtcG9ydC1mb3J3YXJkaW5nAAAAAAAAAApwZXJtaXQtcHR5AAAAAAAAAA5wZXJtaXQtdXNlci1yYwAAAAAAAAAAAAABFwAAAAdzc2gtcnNhAAAAAwEAAQAAAQEAwU+c5ui5A8+J/CFpjW8wCa52bEODA808WWQDCSuTG/eMXNf59v9Y8Pk0F1E9dGCosSNyVcB/hacUrc6He+i97+HJCyKavBsE6GDxrjRyxYqAlfcOXi/IVmaUGiO8OQ39d4GHrjToInKvExSUeleQyH4Y4/e27T/pILAqPFL3fyrvMLT5qU9QyIt6zIpa7GBP5+urouNavMprV3zsfIqNBbWypinOQAw823a5wN+zwXnhZrgQiHZ/USG09Y6k98y1dTVz8YHlQVR4D3lpTAsKDKJ5hCH9WU4fdf+lU8OyNGaJ/vz0XNqxcToe1l4numLTnaoSuH89pHryjqurB7lJKwAAAQ8AAAAHc3NoLXJzYQAAAQCaHvUIoPL1zWUHIXLvu96/HU1s/i4CAW2IIEuGgxCUCiFj6vyTyYtgxQxcmbfZf6eaITlS6XJZa7Qq4iaFZh75C1DXTX8labXhRSD4E2t//AIP9MC1rtQC5xo6FmbQ+BoKcDskr+mNACcbRSxs3IL3bwCfWDnIw2WbVox9ZdcthJKk4UoCW4ix4QwdHw7zlddlz++fGEEVhmTbll1SUkycGApPFBsAYRTMupUJcYPIeReBI/m8XfkoMk99bV8ZJQTAd7OekHY2/48Ff53jLmyDjP7kNw1F8OaPtkFs6dGJXta4krmaekPy87j+35In5hFj7yoOqvSbmYUkeX70/GGQ`
|
||||
|
||||
func TestParseCertWithOptions(t *testing.T) {
|
||||
opts := map[string]string{
|
||||
"source-address": "192.168.1.0/24",
|
||||
"force-command": "/bin/sleep",
|
||||
}
|
||||
exts := map[string]string{
|
||||
"permit-X11-forwarding": "",
|
||||
"permit-agent-forwarding": "",
|
||||
"permit-port-forwarding": "",
|
||||
"permit-pty": "",
|
||||
"permit-user-rc": "",
|
||||
}
|
||||
authKeyBytes := []byte(exampleSSHCertWithOptions)
|
||||
|
||||
key, _, _, rest, err := ParseAuthorizedKey(authKeyBytes)
|
||||
if err != nil {
|
||||
t.Fatalf("ParseAuthorizedKey: %v", err)
|
||||
}
|
||||
if len(rest) > 0 {
|
||||
t.Errorf("rest: got %q, want empty", rest)
|
||||
}
|
||||
cert, ok := key.(*Certificate)
|
||||
if !ok {
|
||||
t.Fatalf("got %v (%T), want *Certificate", key, key)
|
||||
}
|
||||
if !reflect.DeepEqual(cert.CriticalOptions, opts) {
|
||||
t.Errorf("unexpected critical options - got %v, want %v", cert.CriticalOptions, opts)
|
||||
}
|
||||
if !reflect.DeepEqual(cert.Extensions, exts) {
|
||||
t.Errorf("unexpected Extensions - got %v, want %v", cert.Extensions, exts)
|
||||
}
|
||||
marshaled := MarshalAuthorizedKey(key)
|
||||
// Before comparison, remove the trailing newline that
|
||||
// MarshalAuthorizedKey adds.
|
||||
marshaled = marshaled[:len(marshaled)-1]
|
||||
if !bytes.Equal(authKeyBytes, marshaled) {
|
||||
t.Errorf("marshaled certificate does not match original: got %q, want %q", marshaled, authKeyBytes)
|
||||
}
|
||||
}
|
||||
|
||||
func TestValidateCert(t *testing.T) {
|
||||
key, _, _, _, err := ParseAuthorizedKey([]byte(exampleSSHCert))
|
||||
if err != nil {
|
||||
t.Fatalf("ParseAuthorizedKey: %v", err)
|
||||
}
|
||||
validCert, ok := key.(*Certificate)
|
||||
if !ok {
|
||||
t.Fatalf("got %v (%T), want *Certificate", key, key)
|
||||
}
|
||||
checker := CertChecker{}
|
||||
checker.IsAuthority = func(k PublicKey) bool {
|
||||
return bytes.Equal(k.Marshal(), validCert.SignatureKey.Marshal())
|
||||
}
|
||||
|
||||
if err := checker.CheckCert("user", validCert); err != nil {
|
||||
t.Errorf("Unable to validate certificate: %v", err)
|
||||
}
|
||||
invalidCert := &Certificate{
|
||||
Key: testPublicKeys["rsa"],
|
||||
SignatureKey: testPublicKeys["ecdsa"],
|
||||
ValidBefore: CertTimeInfinity,
|
||||
Signature: &Signature{},
|
||||
}
|
||||
if err := checker.CheckCert("user", invalidCert); err == nil {
|
||||
t.Error("Invalid cert signature passed validation")
|
||||
}
|
||||
}
|
||||
|
||||
func TestValidateCertTime(t *testing.T) {
|
||||
cert := Certificate{
|
||||
ValidPrincipals: []string{"user"},
|
||||
Key: testPublicKeys["rsa"],
|
||||
ValidAfter: 50,
|
||||
ValidBefore: 100,
|
||||
}
|
||||
|
||||
cert.SignCert(rand.Reader, testSigners["ecdsa"])
|
||||
|
||||
for ts, ok := range map[int64]bool{
|
||||
25: false,
|
||||
50: true,
|
||||
99: true,
|
||||
100: false,
|
||||
125: false,
|
||||
} {
|
||||
checker := CertChecker{
|
||||
Clock: func() time.Time { return time.Unix(ts, 0) },
|
||||
}
|
||||
checker.IsAuthority = func(k PublicKey) bool {
|
||||
return bytes.Equal(k.Marshal(),
|
||||
testPublicKeys["ecdsa"].Marshal())
|
||||
}
|
||||
|
||||
if v := checker.CheckCert("user", &cert); (v == nil) != ok {
|
||||
t.Errorf("Authenticate(%d): %v", ts, v)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO(hanwen): tests for
|
||||
//
|
||||
// host keys:
|
||||
// * fallbacks
|
||||
|
||||
func TestHostKeyCert(t *testing.T) {
|
||||
cert := &Certificate{
|
||||
ValidPrincipals: []string{"hostname", "hostname.domain"},
|
||||
Key: testPublicKeys["rsa"],
|
||||
ValidBefore: CertTimeInfinity,
|
||||
CertType: HostCert,
|
||||
}
|
||||
cert.SignCert(rand.Reader, testSigners["ecdsa"])
|
||||
|
||||
checker := &CertChecker{
|
||||
IsAuthority: func(p PublicKey) bool {
|
||||
return bytes.Equal(testPublicKeys["ecdsa"].Marshal(), p.Marshal())
|
||||
},
|
||||
}
|
||||
|
||||
certSigner, err := NewCertSigner(cert, testSigners["rsa"])
|
||||
if err != nil {
|
||||
t.Errorf("NewCertSigner: %v", err)
|
||||
}
|
||||
|
||||
for _, name := range []string{"hostname", "otherhost"} {
|
||||
c1, c2, err := netPipe()
|
||||
if err != nil {
|
||||
t.Fatalf("netPipe: %v", err)
|
||||
}
|
||||
defer c1.Close()
|
||||
defer c2.Close()
|
||||
|
||||
errc := make(chan error)
|
||||
|
||||
go func() {
|
||||
conf := ServerConfig{
|
||||
NoClientAuth: true,
|
||||
}
|
||||
conf.AddHostKey(certSigner)
|
||||
_, _, _, err := NewServerConn(c1, &conf)
|
||||
errc <- err
|
||||
}()
|
||||
|
||||
config := &ClientConfig{
|
||||
User: "user",
|
||||
HostKeyCallback: checker.CheckHostKey,
|
||||
}
|
||||
_, _, _, err = NewClientConn(c2, name, config)
|
||||
|
||||
succeed := name == "hostname"
|
||||
if (err == nil) != succeed {
|
||||
t.Fatalf("NewClientConn(%q): %v", name, err)
|
||||
}
|
||||
|
||||
err = <-errc
|
||||
if (err == nil) != succeed {
|
||||
t.Fatalf("NewServerConn(%q): %v", name, err)
|
||||
}
|
||||
}
|
||||
}
|
4
vendor/golang.org/x/crypto/ssh/channel.go
generated
vendored
4
vendor/golang.org/x/crypto/ssh/channel.go
generated
vendored
@ -461,8 +461,8 @@ func (m *mux) newChannel(chanType string, direction channelDirection, extraData
|
||||
pending: newBuffer(),
|
||||
extPending: newBuffer(),
|
||||
direction: direction,
|
||||
incomingRequests: make(chan *Request, 16),
|
||||
msg: make(chan interface{}, 16),
|
||||
incomingRequests: make(chan *Request, chanSize),
|
||||
msg: make(chan interface{}, chanSize),
|
||||
chanType: chanType,
|
||||
extraData: extraData,
|
||||
mux: m,
|
||||
|
64
vendor/golang.org/x/crypto/ssh/cipher.go
generated
vendored
64
vendor/golang.org/x/crypto/ssh/cipher.go
generated
vendored
@ -135,6 +135,7 @@ const prefixLen = 5
|
||||
type streamPacketCipher struct {
|
||||
mac hash.Hash
|
||||
cipher cipher.Stream
|
||||
etm bool
|
||||
|
||||
// The following members are to avoid per-packet allocations.
|
||||
prefix [prefixLen]byte
|
||||
@ -150,7 +151,14 @@ func (s *streamPacketCipher) readPacket(seqNum uint32, r io.Reader) ([]byte, err
|
||||
return nil, err
|
||||
}
|
||||
|
||||
s.cipher.XORKeyStream(s.prefix[:], s.prefix[:])
|
||||
var encryptedPaddingLength [1]byte
|
||||
if s.mac != nil && s.etm {
|
||||
copy(encryptedPaddingLength[:], s.prefix[4:5])
|
||||
s.cipher.XORKeyStream(s.prefix[4:5], s.prefix[4:5])
|
||||
} else {
|
||||
s.cipher.XORKeyStream(s.prefix[:], s.prefix[:])
|
||||
}
|
||||
|
||||
length := binary.BigEndian.Uint32(s.prefix[0:4])
|
||||
paddingLength := uint32(s.prefix[4])
|
||||
|
||||
@ -159,7 +167,12 @@ func (s *streamPacketCipher) readPacket(seqNum uint32, r io.Reader) ([]byte, err
|
||||
s.mac.Reset()
|
||||
binary.BigEndian.PutUint32(s.seqNumBytes[:], seqNum)
|
||||
s.mac.Write(s.seqNumBytes[:])
|
||||
s.mac.Write(s.prefix[:])
|
||||
if s.etm {
|
||||
s.mac.Write(s.prefix[:4])
|
||||
s.mac.Write(encryptedPaddingLength[:])
|
||||
} else {
|
||||
s.mac.Write(s.prefix[:])
|
||||
}
|
||||
macSize = uint32(s.mac.Size())
|
||||
}
|
||||
|
||||
@ -184,10 +197,17 @@ func (s *streamPacketCipher) readPacket(seqNum uint32, r io.Reader) ([]byte, err
|
||||
}
|
||||
mac := s.packetData[length-1:]
|
||||
data := s.packetData[:length-1]
|
||||
|
||||
if s.mac != nil && s.etm {
|
||||
s.mac.Write(data)
|
||||
}
|
||||
|
||||
s.cipher.XORKeyStream(data, data)
|
||||
|
||||
if s.mac != nil {
|
||||
s.mac.Write(data)
|
||||
if !s.etm {
|
||||
s.mac.Write(data)
|
||||
}
|
||||
s.macResult = s.mac.Sum(s.macResult[:0])
|
||||
if subtle.ConstantTimeCompare(s.macResult, mac) != 1 {
|
||||
return nil, errors.New("ssh: MAC failure")
|
||||
@ -203,7 +223,13 @@ func (s *streamPacketCipher) writePacket(seqNum uint32, w io.Writer, rand io.Rea
|
||||
return errors.New("ssh: packet too large")
|
||||
}
|
||||
|
||||
paddingLength := packetSizeMultiple - (prefixLen+len(packet))%packetSizeMultiple
|
||||
aadlen := 0
|
||||
if s.mac != nil && s.etm {
|
||||
// packet length is not encrypted for EtM modes
|
||||
aadlen = 4
|
||||
}
|
||||
|
||||
paddingLength := packetSizeMultiple - (prefixLen+len(packet)-aadlen)%packetSizeMultiple
|
||||
if paddingLength < 4 {
|
||||
paddingLength += packetSizeMultiple
|
||||
}
|
||||
@ -220,15 +246,37 @@ func (s *streamPacketCipher) writePacket(seqNum uint32, w io.Writer, rand io.Rea
|
||||
s.mac.Reset()
|
||||
binary.BigEndian.PutUint32(s.seqNumBytes[:], seqNum)
|
||||
s.mac.Write(s.seqNumBytes[:])
|
||||
|
||||
if s.etm {
|
||||
// For EtM algorithms, the packet length must stay unencrypted,
|
||||
// but the following data (padding length) must be encrypted
|
||||
s.cipher.XORKeyStream(s.prefix[4:5], s.prefix[4:5])
|
||||
}
|
||||
|
||||
s.mac.Write(s.prefix[:])
|
||||
|
||||
if !s.etm {
|
||||
// For non-EtM algorithms, the algorithm is applied on unencrypted data
|
||||
s.mac.Write(packet)
|
||||
s.mac.Write(padding)
|
||||
}
|
||||
}
|
||||
|
||||
if !(s.mac != nil && s.etm) {
|
||||
// For EtM algorithms, the padding length has already been encrypted
|
||||
// and the packet length must remain unencrypted
|
||||
s.cipher.XORKeyStream(s.prefix[:], s.prefix[:])
|
||||
}
|
||||
|
||||
s.cipher.XORKeyStream(packet, packet)
|
||||
s.cipher.XORKeyStream(padding, padding)
|
||||
|
||||
if s.mac != nil && s.etm {
|
||||
// For EtM algorithms, packet and padding must be encrypted
|
||||
s.mac.Write(packet)
|
||||
s.mac.Write(padding)
|
||||
}
|
||||
|
||||
s.cipher.XORKeyStream(s.prefix[:], s.prefix[:])
|
||||
s.cipher.XORKeyStream(packet, packet)
|
||||
s.cipher.XORKeyStream(padding, padding)
|
||||
|
||||
if _, err := w.Write(s.prefix[:]); err != nil {
|
||||
return err
|
||||
}
|
||||
|
127
vendor/golang.org/x/crypto/ssh/cipher_test.go
generated
vendored
127
vendor/golang.org/x/crypto/ssh/cipher_test.go
generated
vendored
@ -1,127 +0,0 @@
|
||||
// Copyright 2011 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package ssh
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto"
|
||||
"crypto/aes"
|
||||
"crypto/rand"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestDefaultCiphersExist(t *testing.T) {
|
||||
for _, cipherAlgo := range supportedCiphers {
|
||||
if _, ok := cipherModes[cipherAlgo]; !ok {
|
||||
t.Errorf("default cipher %q is unknown", cipherAlgo)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestPacketCiphers(t *testing.T) {
|
||||
// Still test aes128cbc cipher although it's commented out.
|
||||
cipherModes[aes128cbcID] = &streamCipherMode{16, aes.BlockSize, 0, nil}
|
||||
defer delete(cipherModes, aes128cbcID)
|
||||
|
||||
for cipher := range cipherModes {
|
||||
kr := &kexResult{Hash: crypto.SHA1}
|
||||
algs := directionAlgorithms{
|
||||
Cipher: cipher,
|
||||
MAC: "hmac-sha1",
|
||||
Compression: "none",
|
||||
}
|
||||
client, err := newPacketCipher(clientKeys, algs, kr)
|
||||
if err != nil {
|
||||
t.Errorf("newPacketCipher(client, %q): %v", cipher, err)
|
||||
continue
|
||||
}
|
||||
server, err := newPacketCipher(clientKeys, algs, kr)
|
||||
if err != nil {
|
||||
t.Errorf("newPacketCipher(client, %q): %v", cipher, err)
|
||||
continue
|
||||
}
|
||||
|
||||
want := "bla bla"
|
||||
input := []byte(want)
|
||||
buf := &bytes.Buffer{}
|
||||
if err := client.writePacket(0, buf, rand.Reader, input); err != nil {
|
||||
t.Errorf("writePacket(%q): %v", cipher, err)
|
||||
continue
|
||||
}
|
||||
|
||||
packet, err := server.readPacket(0, buf)
|
||||
if err != nil {
|
||||
t.Errorf("readPacket(%q): %v", cipher, err)
|
||||
continue
|
||||
}
|
||||
|
||||
if string(packet) != want {
|
||||
t.Errorf("roundtrip(%q): got %q, want %q", cipher, packet, want)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestCBCOracleCounterMeasure(t *testing.T) {
|
||||
cipherModes[aes128cbcID] = &streamCipherMode{16, aes.BlockSize, 0, nil}
|
||||
defer delete(cipherModes, aes128cbcID)
|
||||
|
||||
kr := &kexResult{Hash: crypto.SHA1}
|
||||
algs := directionAlgorithms{
|
||||
Cipher: aes128cbcID,
|
||||
MAC: "hmac-sha1",
|
||||
Compression: "none",
|
||||
}
|
||||
client, err := newPacketCipher(clientKeys, algs, kr)
|
||||
if err != nil {
|
||||
t.Fatalf("newPacketCipher(client): %v", err)
|
||||
}
|
||||
|
||||
want := "bla bla"
|
||||
input := []byte(want)
|
||||
buf := &bytes.Buffer{}
|
||||
if err := client.writePacket(0, buf, rand.Reader, input); err != nil {
|
||||
t.Errorf("writePacket: %v", err)
|
||||
}
|
||||
|
||||
packetSize := buf.Len()
|
||||
buf.Write(make([]byte, 2*maxPacket))
|
||||
|
||||
// We corrupt each byte, but this usually will only test the
|
||||
// 'packet too large' or 'MAC failure' cases.
|
||||
lastRead := -1
|
||||
for i := 0; i < packetSize; i++ {
|
||||
server, err := newPacketCipher(clientKeys, algs, kr)
|
||||
if err != nil {
|
||||
t.Fatalf("newPacketCipher(client): %v", err)
|
||||
}
|
||||
|
||||
fresh := &bytes.Buffer{}
|
||||
fresh.Write(buf.Bytes())
|
||||
fresh.Bytes()[i] ^= 0x01
|
||||
|
||||
before := fresh.Len()
|
||||
_, err = server.readPacket(0, fresh)
|
||||
if err == nil {
|
||||
t.Errorf("corrupt byte %d: readPacket succeeded ", i)
|
||||
continue
|
||||
}
|
||||
if _, ok := err.(cbcError); !ok {
|
||||
t.Errorf("corrupt byte %d: got %v (%T), want cbcError", i, err, err)
|
||||
continue
|
||||
}
|
||||
|
||||
after := fresh.Len()
|
||||
bytesRead := before - after
|
||||
if bytesRead < maxPacket {
|
||||
t.Errorf("corrupt byte %d: read %d bytes, want more than %d", i, bytesRead, maxPacket)
|
||||
continue
|
||||
}
|
||||
|
||||
if i > 0 && bytesRead != lastRead {
|
||||
t.Errorf("corrupt byte %d: read %d bytes, want %d bytes read", i, bytesRead, lastRead)
|
||||
}
|
||||
lastRead = bytesRead
|
||||
}
|
||||
}
|
6
vendor/golang.org/x/crypto/ssh/client.go
generated
vendored
6
vendor/golang.org/x/crypto/ssh/client.go
generated
vendored
@ -40,7 +40,7 @@ func (c *Client) HandleChannelOpen(channelType string) <-chan NewChannel {
|
||||
return nil
|
||||
}
|
||||
|
||||
ch = make(chan NewChannel, 16)
|
||||
ch = make(chan NewChannel, chanSize)
|
||||
c.channelHandlers[channelType] = ch
|
||||
return ch
|
||||
}
|
||||
@ -97,13 +97,11 @@ func (c *connection) clientHandshake(dialAddress string, config *ClientConfig) e
|
||||
c.transport = newClientTransport(
|
||||
newTransport(c.sshConn.conn, config.Rand, true /* is client */),
|
||||
c.clientVersion, c.serverVersion, config, dialAddress, c.sshConn.RemoteAddr())
|
||||
if err := c.transport.requestInitialKeyChange(); err != nil {
|
||||
if err := c.transport.waitSession(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// We just did the key change, so the session ID is established.
|
||||
c.sessionID = c.transport.getSessionID()
|
||||
|
||||
return c.clientAuthenticate(config)
|
||||
}
|
||||
|
||||
|
4
vendor/golang.org/x/crypto/ssh/client_auth.go
generated
vendored
4
vendor/golang.org/x/crypto/ssh/client_auth.go
generated
vendored
@ -30,8 +30,10 @@ func (c *connection) clientAuthenticate(config *ClientConfig) error {
|
||||
// then any untried methods suggested by the server.
|
||||
tried := make(map[string]bool)
|
||||
var lastMethods []string
|
||||
|
||||
sessionID := c.transport.getSessionID()
|
||||
for auth := AuthMethod(new(noneAuth)); auth != nil; {
|
||||
ok, methods, err := auth.auth(c.transport.getSessionID(), config.User, c.transport, config.Rand)
|
||||
ok, methods, err := auth.auth(sessionID, config.User, c.transport, config.Rand)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
472
vendor/golang.org/x/crypto/ssh/client_auth_test.go
generated
vendored
472
vendor/golang.org/x/crypto/ssh/client_auth_test.go
generated
vendored
@ -1,472 +0,0 @@
|
||||
// Copyright 2011 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package ssh
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/rand"
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
type keyboardInteractive map[string]string
|
||||
|
||||
func (cr keyboardInteractive) Challenge(user string, instruction string, questions []string, echos []bool) ([]string, error) {
|
||||
var answers []string
|
||||
for _, q := range questions {
|
||||
answers = append(answers, cr[q])
|
||||
}
|
||||
return answers, nil
|
||||
}
|
||||
|
||||
// reused internally by tests
|
||||
var clientPassword = "tiger"
|
||||
|
||||
// tryAuth runs a handshake with a given config against an SSH server
|
||||
// with config serverConfig
|
||||
func tryAuth(t *testing.T, config *ClientConfig) error {
|
||||
c1, c2, err := netPipe()
|
||||
if err != nil {
|
||||
t.Fatalf("netPipe: %v", err)
|
||||
}
|
||||
defer c1.Close()
|
||||
defer c2.Close()
|
||||
|
||||
certChecker := CertChecker{
|
||||
IsAuthority: func(k PublicKey) bool {
|
||||
return bytes.Equal(k.Marshal(), testPublicKeys["ecdsa"].Marshal())
|
||||
},
|
||||
UserKeyFallback: func(conn ConnMetadata, key PublicKey) (*Permissions, error) {
|
||||
if conn.User() == "testuser" && bytes.Equal(key.Marshal(), testPublicKeys["rsa"].Marshal()) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
return nil, fmt.Errorf("pubkey for %q not acceptable", conn.User())
|
||||
},
|
||||
IsRevoked: func(c *Certificate) bool {
|
||||
return c.Serial == 666
|
||||
},
|
||||
}
|
||||
|
||||
serverConfig := &ServerConfig{
|
||||
PasswordCallback: func(conn ConnMetadata, pass []byte) (*Permissions, error) {
|
||||
if conn.User() == "testuser" && string(pass) == clientPassword {
|
||||
return nil, nil
|
||||
}
|
||||
return nil, errors.New("password auth failed")
|
||||
},
|
||||
PublicKeyCallback: certChecker.Authenticate,
|
||||
KeyboardInteractiveCallback: func(conn ConnMetadata, challenge KeyboardInteractiveChallenge) (*Permissions, error) {
|
||||
ans, err := challenge("user",
|
||||
"instruction",
|
||||
[]string{"question1", "question2"},
|
||||
[]bool{true, true})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ok := conn.User() == "testuser" && ans[0] == "answer1" && ans[1] == "answer2"
|
||||
if ok {
|
||||
challenge("user", "motd", nil, nil)
|
||||
return nil, nil
|
||||
}
|
||||
return nil, errors.New("keyboard-interactive failed")
|
||||
},
|
||||
AuthLogCallback: func(conn ConnMetadata, method string, err error) {
|
||||
t.Logf("user %q, method %q: %v", conn.User(), method, err)
|
||||
},
|
||||
}
|
||||
serverConfig.AddHostKey(testSigners["rsa"])
|
||||
|
||||
go newServer(c1, serverConfig)
|
||||
_, _, _, err = NewClientConn(c2, "", config)
|
||||
return err
|
||||
}
|
||||
|
||||
func TestClientAuthPublicKey(t *testing.T) {
|
||||
config := &ClientConfig{
|
||||
User: "testuser",
|
||||
Auth: []AuthMethod{
|
||||
PublicKeys(testSigners["rsa"]),
|
||||
},
|
||||
}
|
||||
if err := tryAuth(t, config); err != nil {
|
||||
t.Fatalf("unable to dial remote side: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestAuthMethodPassword(t *testing.T) {
|
||||
config := &ClientConfig{
|
||||
User: "testuser",
|
||||
Auth: []AuthMethod{
|
||||
Password(clientPassword),
|
||||
},
|
||||
}
|
||||
|
||||
if err := tryAuth(t, config); err != nil {
|
||||
t.Fatalf("unable to dial remote side: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestAuthMethodFallback(t *testing.T) {
|
||||
var passwordCalled bool
|
||||
config := &ClientConfig{
|
||||
User: "testuser",
|
||||
Auth: []AuthMethod{
|
||||
PublicKeys(testSigners["rsa"]),
|
||||
PasswordCallback(
|
||||
func() (string, error) {
|
||||
passwordCalled = true
|
||||
return "WRONG", nil
|
||||
}),
|
||||
},
|
||||
}
|
||||
|
||||
if err := tryAuth(t, config); err != nil {
|
||||
t.Fatalf("unable to dial remote side: %s", err)
|
||||
}
|
||||
|
||||
if passwordCalled {
|
||||
t.Errorf("password auth tried before public-key auth.")
|
||||
}
|
||||
}
|
||||
|
||||
func TestAuthMethodWrongPassword(t *testing.T) {
|
||||
config := &ClientConfig{
|
||||
User: "testuser",
|
||||
Auth: []AuthMethod{
|
||||
Password("wrong"),
|
||||
PublicKeys(testSigners["rsa"]),
|
||||
},
|
||||
}
|
||||
|
||||
if err := tryAuth(t, config); err != nil {
|
||||
t.Fatalf("unable to dial remote side: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestAuthMethodKeyboardInteractive(t *testing.T) {
|
||||
answers := keyboardInteractive(map[string]string{
|
||||
"question1": "answer1",
|
||||
"question2": "answer2",
|
||||
})
|
||||
config := &ClientConfig{
|
||||
User: "testuser",
|
||||
Auth: []AuthMethod{
|
||||
KeyboardInteractive(answers.Challenge),
|
||||
},
|
||||
}
|
||||
|
||||
if err := tryAuth(t, config); err != nil {
|
||||
t.Fatalf("unable to dial remote side: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestAuthMethodWrongKeyboardInteractive(t *testing.T) {
|
||||
answers := keyboardInteractive(map[string]string{
|
||||
"question1": "answer1",
|
||||
"question2": "WRONG",
|
||||
})
|
||||
config := &ClientConfig{
|
||||
User: "testuser",
|
||||
Auth: []AuthMethod{
|
||||
KeyboardInteractive(answers.Challenge),
|
||||
},
|
||||
}
|
||||
|
||||
if err := tryAuth(t, config); err == nil {
|
||||
t.Fatalf("wrong answers should not have authenticated with KeyboardInteractive")
|
||||
}
|
||||
}
|
||||
|
||||
// the mock server will only authenticate ssh-rsa keys
|
||||
func TestAuthMethodInvalidPublicKey(t *testing.T) {
|
||||
config := &ClientConfig{
|
||||
User: "testuser",
|
||||
Auth: []AuthMethod{
|
||||
PublicKeys(testSigners["dsa"]),
|
||||
},
|
||||
}
|
||||
|
||||
if err := tryAuth(t, config); err == nil {
|
||||
t.Fatalf("dsa private key should not have authenticated with rsa public key")
|
||||
}
|
||||
}
|
||||
|
||||
// the client should authenticate with the second key
|
||||
func TestAuthMethodRSAandDSA(t *testing.T) {
|
||||
config := &ClientConfig{
|
||||
User: "testuser",
|
||||
Auth: []AuthMethod{
|
||||
PublicKeys(testSigners["dsa"], testSigners["rsa"]),
|
||||
},
|
||||
}
|
||||
if err := tryAuth(t, config); err != nil {
|
||||
t.Fatalf("client could not authenticate with rsa key: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestClientHMAC(t *testing.T) {
|
||||
for _, mac := range supportedMACs {
|
||||
config := &ClientConfig{
|
||||
User: "testuser",
|
||||
Auth: []AuthMethod{
|
||||
PublicKeys(testSigners["rsa"]),
|
||||
},
|
||||
Config: Config{
|
||||
MACs: []string{mac},
|
||||
},
|
||||
}
|
||||
if err := tryAuth(t, config); err != nil {
|
||||
t.Fatalf("client could not authenticate with mac algo %s: %v", mac, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// issue 4285.
|
||||
func TestClientUnsupportedCipher(t *testing.T) {
|
||||
config := &ClientConfig{
|
||||
User: "testuser",
|
||||
Auth: []AuthMethod{
|
||||
PublicKeys(),
|
||||
},
|
||||
Config: Config{
|
||||
Ciphers: []string{"aes128-cbc"}, // not currently supported
|
||||
},
|
||||
}
|
||||
if err := tryAuth(t, config); err == nil {
|
||||
t.Errorf("expected no ciphers in common")
|
||||
}
|
||||
}
|
||||
|
||||
func TestClientUnsupportedKex(t *testing.T) {
|
||||
if os.Getenv("GO_BUILDER_NAME") != "" {
|
||||
t.Skip("skipping known-flaky test on the Go build dashboard; see golang.org/issue/15198")
|
||||
}
|
||||
config := &ClientConfig{
|
||||
User: "testuser",
|
||||
Auth: []AuthMethod{
|
||||
PublicKeys(),
|
||||
},
|
||||
Config: Config{
|
||||
KeyExchanges: []string{"diffie-hellman-group-exchange-sha256"}, // not currently supported
|
||||
},
|
||||
}
|
||||
if err := tryAuth(t, config); err == nil || !strings.Contains(err.Error(), "common algorithm") {
|
||||
t.Errorf("got %v, expected 'common algorithm'", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestClientLoginCert(t *testing.T) {
|
||||
cert := &Certificate{
|
||||
Key: testPublicKeys["rsa"],
|
||||
ValidBefore: CertTimeInfinity,
|
||||
CertType: UserCert,
|
||||
}
|
||||
cert.SignCert(rand.Reader, testSigners["ecdsa"])
|
||||
certSigner, err := NewCertSigner(cert, testSigners["rsa"])
|
||||
if err != nil {
|
||||
t.Fatalf("NewCertSigner: %v", err)
|
||||
}
|
||||
|
||||
clientConfig := &ClientConfig{
|
||||
User: "user",
|
||||
}
|
||||
clientConfig.Auth = append(clientConfig.Auth, PublicKeys(certSigner))
|
||||
|
||||
t.Log("should succeed")
|
||||
if err := tryAuth(t, clientConfig); err != nil {
|
||||
t.Errorf("cert login failed: %v", err)
|
||||
}
|
||||
|
||||
t.Log("corrupted signature")
|
||||
cert.Signature.Blob[0]++
|
||||
if err := tryAuth(t, clientConfig); err == nil {
|
||||
t.Errorf("cert login passed with corrupted sig")
|
||||
}
|
||||
|
||||
t.Log("revoked")
|
||||
cert.Serial = 666
|
||||
cert.SignCert(rand.Reader, testSigners["ecdsa"])
|
||||
if err := tryAuth(t, clientConfig); err == nil {
|
||||
t.Errorf("revoked cert login succeeded")
|
||||
}
|
||||
cert.Serial = 1
|
||||
|
||||
t.Log("sign with wrong key")
|
||||
cert.SignCert(rand.Reader, testSigners["dsa"])
|
||||
if err := tryAuth(t, clientConfig); err == nil {
|
||||
t.Errorf("cert login passed with non-authoritative key")
|
||||
}
|
||||
|
||||
t.Log("host cert")
|
||||
cert.CertType = HostCert
|
||||
cert.SignCert(rand.Reader, testSigners["ecdsa"])
|
||||
if err := tryAuth(t, clientConfig); err == nil {
|
||||
t.Errorf("cert login passed with wrong type")
|
||||
}
|
||||
cert.CertType = UserCert
|
||||
|
||||
t.Log("principal specified")
|
||||
cert.ValidPrincipals = []string{"user"}
|
||||
cert.SignCert(rand.Reader, testSigners["ecdsa"])
|
||||
if err := tryAuth(t, clientConfig); err != nil {
|
||||
t.Errorf("cert login failed: %v", err)
|
||||
}
|
||||
|
||||
t.Log("wrong principal specified")
|
||||
cert.ValidPrincipals = []string{"fred"}
|
||||
cert.SignCert(rand.Reader, testSigners["ecdsa"])
|
||||
if err := tryAuth(t, clientConfig); err == nil {
|
||||
t.Errorf("cert login passed with wrong principal")
|
||||
}
|
||||
cert.ValidPrincipals = nil
|
||||
|
||||
t.Log("added critical option")
|
||||
cert.CriticalOptions = map[string]string{"root-access": "yes"}
|
||||
cert.SignCert(rand.Reader, testSigners["ecdsa"])
|
||||
if err := tryAuth(t, clientConfig); err == nil {
|
||||
t.Errorf("cert login passed with unrecognized critical option")
|
||||
}
|
||||
|
||||
t.Log("allowed source address")
|
||||
cert.CriticalOptions = map[string]string{"source-address": "127.0.0.42/24"}
|
||||
cert.SignCert(rand.Reader, testSigners["ecdsa"])
|
||||
if err := tryAuth(t, clientConfig); err != nil {
|
||||
t.Errorf("cert login with source-address failed: %v", err)
|
||||
}
|
||||
|
||||
t.Log("disallowed source address")
|
||||
cert.CriticalOptions = map[string]string{"source-address": "127.0.0.42"}
|
||||
cert.SignCert(rand.Reader, testSigners["ecdsa"])
|
||||
if err := tryAuth(t, clientConfig); err == nil {
|
||||
t.Errorf("cert login with source-address succeeded")
|
||||
}
|
||||
}
|
||||
|
||||
func testPermissionsPassing(withPermissions bool, t *testing.T) {
|
||||
serverConfig := &ServerConfig{
|
||||
PublicKeyCallback: func(conn ConnMetadata, key PublicKey) (*Permissions, error) {
|
||||
if conn.User() == "nopermissions" {
|
||||
return nil, nil
|
||||
} else {
|
||||
return &Permissions{}, nil
|
||||
}
|
||||
},
|
||||
}
|
||||
serverConfig.AddHostKey(testSigners["rsa"])
|
||||
|
||||
clientConfig := &ClientConfig{
|
||||
Auth: []AuthMethod{
|
||||
PublicKeys(testSigners["rsa"]),
|
||||
},
|
||||
}
|
||||
if withPermissions {
|
||||
clientConfig.User = "permissions"
|
||||
} else {
|
||||
clientConfig.User = "nopermissions"
|
||||
}
|
||||
|
||||
c1, c2, err := netPipe()
|
||||
if err != nil {
|
||||
t.Fatalf("netPipe: %v", err)
|
||||
}
|
||||
defer c1.Close()
|
||||
defer c2.Close()
|
||||
|
||||
go NewClientConn(c2, "", clientConfig)
|
||||
serverConn, err := newServer(c1, serverConfig)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if p := serverConn.Permissions; (p != nil) != withPermissions {
|
||||
t.Fatalf("withPermissions is %t, but Permissions object is %#v", withPermissions, p)
|
||||
}
|
||||
}
|
||||
|
||||
func TestPermissionsPassing(t *testing.T) {
|
||||
testPermissionsPassing(true, t)
|
||||
}
|
||||
|
||||
func TestNoPermissionsPassing(t *testing.T) {
|
||||
testPermissionsPassing(false, t)
|
||||
}
|
||||
|
||||
func TestRetryableAuth(t *testing.T) {
|
||||
n := 0
|
||||
passwords := []string{"WRONG1", "WRONG2"}
|
||||
|
||||
config := &ClientConfig{
|
||||
User: "testuser",
|
||||
Auth: []AuthMethod{
|
||||
RetryableAuthMethod(PasswordCallback(func() (string, error) {
|
||||
p := passwords[n]
|
||||
n++
|
||||
return p, nil
|
||||
}), 2),
|
||||
PublicKeys(testSigners["rsa"]),
|
||||
},
|
||||
}
|
||||
|
||||
if err := tryAuth(t, config); err != nil {
|
||||
t.Fatalf("unable to dial remote side: %s", err)
|
||||
}
|
||||
if n != 2 {
|
||||
t.Fatalf("Did not try all passwords")
|
||||
}
|
||||
}
|
||||
|
||||
func ExampleRetryableAuthMethod(t *testing.T) {
|
||||
user := "testuser"
|
||||
NumberOfPrompts := 3
|
||||
|
||||
// Normally this would be a callback that prompts the user to answer the
|
||||
// provided questions
|
||||
Cb := func(user, instruction string, questions []string, echos []bool) (answers []string, err error) {
|
||||
return []string{"answer1", "answer2"}, nil
|
||||
}
|
||||
|
||||
config := &ClientConfig{
|
||||
User: user,
|
||||
Auth: []AuthMethod{
|
||||
RetryableAuthMethod(KeyboardInteractiveChallenge(Cb), NumberOfPrompts),
|
||||
},
|
||||
}
|
||||
|
||||
if err := tryAuth(t, config); err != nil {
|
||||
t.Fatalf("unable to dial remote side: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
// Test if username is received on server side when NoClientAuth is used
|
||||
func TestClientAuthNone(t *testing.T) {
|
||||
user := "testuser"
|
||||
serverConfig := &ServerConfig{
|
||||
NoClientAuth: true,
|
||||
}
|
||||
serverConfig.AddHostKey(testSigners["rsa"])
|
||||
|
||||
clientConfig := &ClientConfig{
|
||||
User: user,
|
||||
}
|
||||
|
||||
c1, c2, err := netPipe()
|
||||
if err != nil {
|
||||
t.Fatalf("netPipe: %v", err)
|
||||
}
|
||||
defer c1.Close()
|
||||
defer c2.Close()
|
||||
|
||||
go NewClientConn(c2, "", clientConfig)
|
||||
serverConn, err := newServer(c1, serverConfig)
|
||||
if err != nil {
|
||||
t.Fatalf("newServer: %v", err)
|
||||
}
|
||||
if serverConn.User() != user {
|
||||
t.Fatalf("server: got %q, want %q", serverConn.User(), user)
|
||||
}
|
||||
}
|
39
vendor/golang.org/x/crypto/ssh/client_test.go
generated
vendored
39
vendor/golang.org/x/crypto/ssh/client_test.go
generated
vendored
@ -1,39 +0,0 @@
|
||||
// Copyright 2014 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package ssh
|
||||
|
||||
import (
|
||||
"net"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func testClientVersion(t *testing.T, config *ClientConfig, expected string) {
|
||||
clientConn, serverConn := net.Pipe()
|
||||
defer clientConn.Close()
|
||||
receivedVersion := make(chan string, 1)
|
||||
go func() {
|
||||
version, err := readVersion(serverConn)
|
||||
if err != nil {
|
||||
receivedVersion <- ""
|
||||
} else {
|
||||
receivedVersion <- string(version)
|
||||
}
|
||||
serverConn.Close()
|
||||
}()
|
||||
NewClientConn(clientConn, "", config)
|
||||
actual := <-receivedVersion
|
||||
if actual != expected {
|
||||
t.Fatalf("got %s; want %s", actual, expected)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCustomClientVersion(t *testing.T) {
|
||||
version := "Test-Client-Version-0.0"
|
||||
testClientVersion(t, &ClientConfig{ClientVersion: version}, version)
|
||||
}
|
||||
|
||||
func TestDefaultClientVersion(t *testing.T) {
|
||||
testClientVersion(t, &ClientConfig{}, packageVersion)
|
||||
}
|
17
vendor/golang.org/x/crypto/ssh/common.go
generated
vendored
17
vendor/golang.org/x/crypto/ssh/common.go
generated
vendored
@ -56,7 +56,7 @@ var supportedHostKeyAlgos = []string{
|
||||
// This is based on RFC 4253, section 6.4, but with hmac-md5 variants removed
|
||||
// because they have reached the end of their useful life.
|
||||
var supportedMACs = []string{
|
||||
"hmac-sha2-256", "hmac-sha1", "hmac-sha1-96",
|
||||
"hmac-sha2-256-etm@openssh.com", "hmac-sha2-256", "hmac-sha1", "hmac-sha1-96",
|
||||
}
|
||||
|
||||
var supportedCompressions = []string{compressionNone}
|
||||
@ -104,6 +104,21 @@ type directionAlgorithms struct {
|
||||
Compression string
|
||||
}
|
||||
|
||||
// rekeyBytes returns a rekeying intervals in bytes.
|
||||
func (a *directionAlgorithms) rekeyBytes() int64 {
|
||||
// According to RFC4344 block ciphers should rekey after
|
||||
// 2^(BLOCKSIZE/4) blocks. For all AES flavors BLOCKSIZE is
|
||||
// 128.
|
||||
switch a.Cipher {
|
||||
case "aes128-ctr", "aes192-ctr", "aes256-ctr", gcmCipherID, aes128cbcID:
|
||||
return 16 * (1 << 32)
|
||||
|
||||
}
|
||||
|
||||
// For others, stick with RFC4253 recommendation to rekey after 1 Gb of data.
|
||||
return 1 << 30
|
||||
}
|
||||
|
||||
type algorithms struct {
|
||||
kex string
|
||||
hostKey string
|
||||
|
2
vendor/golang.org/x/crypto/ssh/doc.go
generated
vendored
2
vendor/golang.org/x/crypto/ssh/doc.go
generated
vendored
@ -15,4 +15,4 @@ References:
|
||||
[PROTOCOL.certkeys]: http://cvsweb.openbsd.org/cgi-bin/cvsweb/src/usr.bin/ssh/PROTOCOL.certkeys?rev=HEAD
|
||||
[SSH-PARAMETERS]: http://www.iana.org/assignments/ssh-parameters/ssh-parameters.xml#ssh-parameters-1
|
||||
*/
|
||||
package ssh // import "golang.org/x/crypto/ssh"
|
||||
package ssh
|
||||
|
262
vendor/golang.org/x/crypto/ssh/example_test.go
generated
vendored
262
vendor/golang.org/x/crypto/ssh/example_test.go
generated
vendored
@ -1,262 +0,0 @@
|
||||
// Copyright 2011 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package ssh_test
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"net"
|
||||
"net/http"
|
||||
|
||||
"golang.org/x/crypto/ssh"
|
||||
"golang.org/x/crypto/ssh/terminal"
|
||||
)
|
||||
|
||||
func ExampleNewServerConn() {
|
||||
// Public key authentication is done by comparing
|
||||
// the public key of a received connection
|
||||
// with the entries in the authorized_keys file.
|
||||
authorizedKeysBytes, err := ioutil.ReadFile("authorized_keys")
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to load authorized_keys, err: %v", err)
|
||||
}
|
||||
|
||||
authorizedKeysMap := map[string]bool{}
|
||||
for len(authorizedKeysBytes) > 0 {
|
||||
pubKey, _, _, rest, err := ssh.ParseAuthorizedKey(authorizedKeysBytes)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
authorizedKeysMap[string(pubKey.Marshal())] = true
|
||||
authorizedKeysBytes = rest
|
||||
}
|
||||
|
||||
// An SSH server is represented by a ServerConfig, which holds
|
||||
// certificate details and handles authentication of ServerConns.
|
||||
config := &ssh.ServerConfig{
|
||||
// Remove to disable password auth.
|
||||
PasswordCallback: func(c ssh.ConnMetadata, pass []byte) (*ssh.Permissions, error) {
|
||||
// Should use constant-time compare (or better, salt+hash) in
|
||||
// a production setting.
|
||||
if c.User() == "testuser" && string(pass) == "tiger" {
|
||||
return nil, nil
|
||||
}
|
||||
return nil, fmt.Errorf("password rejected for %q", c.User())
|
||||
},
|
||||
|
||||
// Remove to disable public key auth.
|
||||
PublicKeyCallback: func(c ssh.ConnMetadata, pubKey ssh.PublicKey) (*ssh.Permissions, error) {
|
||||
if authorizedKeysMap[string(pubKey.Marshal())] {
|
||||
return nil, nil
|
||||
}
|
||||
return nil, fmt.Errorf("unknown public key for %q", c.User())
|
||||
},
|
||||
}
|
||||
|
||||
privateBytes, err := ioutil.ReadFile("id_rsa")
|
||||
if err != nil {
|
||||
log.Fatal("Failed to load private key: ", err)
|
||||
}
|
||||
|
||||
private, err := ssh.ParsePrivateKey(privateBytes)
|
||||
if err != nil {
|
||||
log.Fatal("Failed to parse private key: ", err)
|
||||
}
|
||||
|
||||
config.AddHostKey(private)
|
||||
|
||||
// Once a ServerConfig has been configured, connections can be
|
||||
// accepted.
|
||||
listener, err := net.Listen("tcp", "0.0.0.0:2022")
|
||||
if err != nil {
|
||||
log.Fatal("failed to listen for connection: ", err)
|
||||
}
|
||||
nConn, err := listener.Accept()
|
||||
if err != nil {
|
||||
log.Fatal("failed to accept incoming connection: ", err)
|
||||
}
|
||||
|
||||
// Before use, a handshake must be performed on the incoming
|
||||
// net.Conn.
|
||||
_, chans, reqs, err := ssh.NewServerConn(nConn, config)
|
||||
if err != nil {
|
||||
log.Fatal("failed to handshake: ", err)
|
||||
}
|
||||
// The incoming Request channel must be serviced.
|
||||
go ssh.DiscardRequests(reqs)
|
||||
|
||||
// Service the incoming Channel channel.
|
||||
|
||||
// Service the incoming Channel channel.
|
||||
for newChannel := range chans {
|
||||
// Channels have a type, depending on the application level
|
||||
// protocol intended. In the case of a shell, the type is
|
||||
// "session" and ServerShell may be used to present a simple
|
||||
// terminal interface.
|
||||
if newChannel.ChannelType() != "session" {
|
||||
newChannel.Reject(ssh.UnknownChannelType, "unknown channel type")
|
||||
continue
|
||||
}
|
||||
channel, requests, err := newChannel.Accept()
|
||||
if err != nil {
|
||||
log.Fatalf("Could not accept channel: %v", err)
|
||||
}
|
||||
|
||||
// Sessions have out-of-band requests such as "shell",
|
||||
// "pty-req" and "env". Here we handle only the
|
||||
// "shell" request.
|
||||
go func(in <-chan *ssh.Request) {
|
||||
for req := range in {
|
||||
req.Reply(req.Type == "shell", nil)
|
||||
}
|
||||
}(requests)
|
||||
|
||||
term := terminal.NewTerminal(channel, "> ")
|
||||
|
||||
go func() {
|
||||
defer channel.Close()
|
||||
for {
|
||||
line, err := term.ReadLine()
|
||||
if err != nil {
|
||||
break
|
||||
}
|
||||
fmt.Println(line)
|
||||
}
|
||||
}()
|
||||
}
|
||||
}
|
||||
|
||||
func ExampleDial() {
|
||||
// An SSH client is represented with a ClientConn.
|
||||
//
|
||||
// To authenticate with the remote server you must pass at least one
|
||||
// implementation of AuthMethod via the Auth field in ClientConfig.
|
||||
config := &ssh.ClientConfig{
|
||||
User: "username",
|
||||
Auth: []ssh.AuthMethod{
|
||||
ssh.Password("yourpassword"),
|
||||
},
|
||||
}
|
||||
client, err := ssh.Dial("tcp", "yourserver.com:22", config)
|
||||
if err != nil {
|
||||
log.Fatal("Failed to dial: ", err)
|
||||
}
|
||||
|
||||
// Each ClientConn can support multiple interactive sessions,
|
||||
// represented by a Session.
|
||||
session, err := client.NewSession()
|
||||
if err != nil {
|
||||
log.Fatal("Failed to create session: ", err)
|
||||
}
|
||||
defer session.Close()
|
||||
|
||||
// Once a Session is created, you can execute a single command on
|
||||
// the remote side using the Run method.
|
||||
var b bytes.Buffer
|
||||
session.Stdout = &b
|
||||
if err := session.Run("/usr/bin/whoami"); err != nil {
|
||||
log.Fatal("Failed to run: " + err.Error())
|
||||
}
|
||||
fmt.Println(b.String())
|
||||
}
|
||||
|
||||
func ExamplePublicKeys() {
|
||||
// A public key may be used to authenticate against the remote
|
||||
// server by using an unencrypted PEM-encoded private key file.
|
||||
//
|
||||
// If you have an encrypted private key, the crypto/x509 package
|
||||
// can be used to decrypt it.
|
||||
key, err := ioutil.ReadFile("/home/user/.ssh/id_rsa")
|
||||
if err != nil {
|
||||
log.Fatalf("unable to read private key: %v", err)
|
||||
}
|
||||
|
||||
// Create the Signer for this private key.
|
||||
signer, err := ssh.ParsePrivateKey(key)
|
||||
if err != nil {
|
||||
log.Fatalf("unable to parse private key: %v", err)
|
||||
}
|
||||
|
||||
config := &ssh.ClientConfig{
|
||||
User: "user",
|
||||
Auth: []ssh.AuthMethod{
|
||||
// Use the PublicKeys method for remote authentication.
|
||||
ssh.PublicKeys(signer),
|
||||
},
|
||||
}
|
||||
|
||||
// Connect to the remote server and perform the SSH handshake.
|
||||
client, err := ssh.Dial("tcp", "host.com:22", config)
|
||||
if err != nil {
|
||||
log.Fatalf("unable to connect: %v", err)
|
||||
}
|
||||
defer client.Close()
|
||||
}
|
||||
|
||||
func ExampleClient_Listen() {
|
||||
config := &ssh.ClientConfig{
|
||||
User: "username",
|
||||
Auth: []ssh.AuthMethod{
|
||||
ssh.Password("password"),
|
||||
},
|
||||
}
|
||||
// Dial your ssh server.
|
||||
conn, err := ssh.Dial("tcp", "localhost:22", config)
|
||||
if err != nil {
|
||||
log.Fatal("unable to connect: ", err)
|
||||
}
|
||||
defer conn.Close()
|
||||
|
||||
// Request the remote side to open port 8080 on all interfaces.
|
||||
l, err := conn.Listen("tcp", "0.0.0.0:8080")
|
||||
if err != nil {
|
||||
log.Fatal("unable to register tcp forward: ", err)
|
||||
}
|
||||
defer l.Close()
|
||||
|
||||
// Serve HTTP with your SSH server acting as a reverse proxy.
|
||||
http.Serve(l, http.HandlerFunc(func(resp http.ResponseWriter, req *http.Request) {
|
||||
fmt.Fprintf(resp, "Hello world!\n")
|
||||
}))
|
||||
}
|
||||
|
||||
func ExampleSession_RequestPty() {
|
||||
// Create client config
|
||||
config := &ssh.ClientConfig{
|
||||
User: "username",
|
||||
Auth: []ssh.AuthMethod{
|
||||
ssh.Password("password"),
|
||||
},
|
||||
}
|
||||
// Connect to ssh server
|
||||
conn, err := ssh.Dial("tcp", "localhost:22", config)
|
||||
if err != nil {
|
||||
log.Fatal("unable to connect: ", err)
|
||||
}
|
||||
defer conn.Close()
|
||||
// Create a session
|
||||
session, err := conn.NewSession()
|
||||
if err != nil {
|
||||
log.Fatal("unable to create session: ", err)
|
||||
}
|
||||
defer session.Close()
|
||||
// Set up terminal modes
|
||||
modes := ssh.TerminalModes{
|
||||
ssh.ECHO: 0, // disable echoing
|
||||
ssh.TTY_OP_ISPEED: 14400, // input speed = 14.4kbaud
|
||||
ssh.TTY_OP_OSPEED: 14400, // output speed = 14.4kbaud
|
||||
}
|
||||
// Request pseudo terminal
|
||||
if err := session.RequestPty("xterm", 40, 80, modes); err != nil {
|
||||
log.Fatal("request for pseudo terminal failed: ", err)
|
||||
}
|
||||
// Start remote shell
|
||||
if err := session.Shell(); err != nil {
|
||||
log.Fatal("failed to start shell: ", err)
|
||||
}
|
||||
}
|
435
vendor/golang.org/x/crypto/ssh/handshake.go
generated
vendored
435
vendor/golang.org/x/crypto/ssh/handshake.go
generated
vendored
@ -19,6 +19,11 @@ import (
|
||||
// messages are wrong when using ECDH.
|
||||
const debugHandshake = false
|
||||
|
||||
// chanSize sets the amount of buffering SSH connections. This is
|
||||
// primarily for testing: setting chanSize=0 uncovers deadlocks more
|
||||
// quickly.
|
||||
const chanSize = 16
|
||||
|
||||
// keyingTransport is a packet based transport that supports key
|
||||
// changes. It need not be thread-safe. It should pass through
|
||||
// msgNewKeys in both directions.
|
||||
@ -53,34 +58,58 @@ type handshakeTransport struct {
|
||||
incoming chan []byte
|
||||
readError error
|
||||
|
||||
mu sync.Mutex
|
||||
writeError error
|
||||
sentInitPacket []byte
|
||||
sentInitMsg *kexInitMsg
|
||||
pendingPackets [][]byte // Used when a key exchange is in progress.
|
||||
|
||||
// If the read loop wants to schedule a kex, it pings this
|
||||
// channel, and the write loop will send out a kex
|
||||
// message.
|
||||
requestKex chan struct{}
|
||||
|
||||
// If the other side requests or confirms a kex, its kexInit
|
||||
// packet is sent here for the write loop to find it.
|
||||
startKex chan *pendingKex
|
||||
|
||||
// data for host key checking
|
||||
hostKeyCallback func(hostname string, remote net.Addr, key PublicKey) error
|
||||
dialAddress string
|
||||
remoteAddr net.Addr
|
||||
|
||||
readSinceKex uint64
|
||||
// Algorithms agreed in the last key exchange.
|
||||
algorithms *algorithms
|
||||
|
||||
// Protects the writing side of the connection
|
||||
mu sync.Mutex
|
||||
cond *sync.Cond
|
||||
sentInitPacket []byte
|
||||
sentInitMsg *kexInitMsg
|
||||
writtenSinceKex uint64
|
||||
writeError error
|
||||
readPacketsLeft uint32
|
||||
readBytesLeft int64
|
||||
|
||||
writePacketsLeft uint32
|
||||
writeBytesLeft int64
|
||||
|
||||
// The session ID or nil if first kex did not complete yet.
|
||||
sessionID []byte
|
||||
}
|
||||
|
||||
type pendingKex struct {
|
||||
otherInit []byte
|
||||
done chan error
|
||||
}
|
||||
|
||||
func newHandshakeTransport(conn keyingTransport, config *Config, clientVersion, serverVersion []byte) *handshakeTransport {
|
||||
t := &handshakeTransport{
|
||||
conn: conn,
|
||||
serverVersion: serverVersion,
|
||||
clientVersion: clientVersion,
|
||||
incoming: make(chan []byte, 16),
|
||||
config: config,
|
||||
incoming: make(chan []byte, chanSize),
|
||||
requestKex: make(chan struct{}, 1),
|
||||
startKex: make(chan *pendingKex, 1),
|
||||
|
||||
config: config,
|
||||
}
|
||||
t.cond = sync.NewCond(&t.mu)
|
||||
|
||||
// We always start with a mandatory key exchange.
|
||||
t.requestKex <- struct{}{}
|
||||
return t
|
||||
}
|
||||
|
||||
@ -95,6 +124,7 @@ func newClientTransport(conn keyingTransport, clientVersion, serverVersion []byt
|
||||
t.hostKeyAlgorithms = supportedHostKeyAlgos
|
||||
}
|
||||
go t.readLoop()
|
||||
go t.kexLoop()
|
||||
return t
|
||||
}
|
||||
|
||||
@ -102,6 +132,7 @@ func newServerTransport(conn keyingTransport, clientVersion, serverVersion []byt
|
||||
t := newHandshakeTransport(conn, &config.Config, clientVersion, serverVersion)
|
||||
t.hostKeys = config.hostKeys
|
||||
go t.readLoop()
|
||||
go t.kexLoop()
|
||||
return t
|
||||
}
|
||||
|
||||
@ -109,6 +140,20 @@ func (t *handshakeTransport) getSessionID() []byte {
|
||||
return t.sessionID
|
||||
}
|
||||
|
||||
// waitSession waits for the session to be established. This should be
|
||||
// the first thing to call after instantiating handshakeTransport.
|
||||
func (t *handshakeTransport) waitSession() error {
|
||||
p, err := t.readPacket()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if p[0] != msgNewKeys {
|
||||
return fmt.Errorf("ssh: first packet should be msgNewKeys")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (t *handshakeTransport) id() string {
|
||||
if len(t.hostKeys) > 0 {
|
||||
return "server"
|
||||
@ -116,6 +161,20 @@ func (t *handshakeTransport) id() string {
|
||||
return "client"
|
||||
}
|
||||
|
||||
func (t *handshakeTransport) printPacket(p []byte, write bool) {
|
||||
action := "got"
|
||||
if write {
|
||||
action = "sent"
|
||||
}
|
||||
|
||||
if p[0] == msgChannelData || p[0] == msgChannelExtendedData {
|
||||
log.Printf("%s %s data (packet %d bytes)", t.id(), action, len(p))
|
||||
} else {
|
||||
msg, err := decode(p)
|
||||
log.Printf("%s %s %T %v (%v)", t.id(), action, msg, msg, err)
|
||||
}
|
||||
}
|
||||
|
||||
func (t *handshakeTransport) readPacket() ([]byte, error) {
|
||||
p, ok := <-t.incoming
|
||||
if !ok {
|
||||
@ -125,8 +184,10 @@ func (t *handshakeTransport) readPacket() ([]byte, error) {
|
||||
}
|
||||
|
||||
func (t *handshakeTransport) readLoop() {
|
||||
first := true
|
||||
for {
|
||||
p, err := t.readOnePacket()
|
||||
p, err := t.readOnePacket(first)
|
||||
first = false
|
||||
if err != nil {
|
||||
t.readError = err
|
||||
close(t.incoming)
|
||||
@ -138,67 +199,204 @@ func (t *handshakeTransport) readLoop() {
|
||||
t.incoming <- p
|
||||
}
|
||||
|
||||
// If we can't read, declare the writing part dead too.
|
||||
t.mu.Lock()
|
||||
defer t.mu.Unlock()
|
||||
if t.writeError == nil {
|
||||
t.writeError = t.readError
|
||||
}
|
||||
t.cond.Broadcast()
|
||||
// Stop writers too.
|
||||
t.recordWriteError(t.readError)
|
||||
|
||||
// Unblock the writer should it wait for this.
|
||||
close(t.startKex)
|
||||
|
||||
// Don't close t.requestKex; it's also written to from writePacket.
|
||||
}
|
||||
|
||||
func (t *handshakeTransport) readOnePacket() ([]byte, error) {
|
||||
if t.readSinceKex > t.config.RekeyThreshold {
|
||||
if err := t.requestKeyChange(); err != nil {
|
||||
return nil, err
|
||||
func (t *handshakeTransport) pushPacket(p []byte) error {
|
||||
if debugHandshake {
|
||||
t.printPacket(p, true)
|
||||
}
|
||||
return t.conn.writePacket(p)
|
||||
}
|
||||
|
||||
func (t *handshakeTransport) getWriteError() error {
|
||||
t.mu.Lock()
|
||||
defer t.mu.Unlock()
|
||||
return t.writeError
|
||||
}
|
||||
|
||||
func (t *handshakeTransport) recordWriteError(err error) {
|
||||
t.mu.Lock()
|
||||
defer t.mu.Unlock()
|
||||
if t.writeError == nil && err != nil {
|
||||
t.writeError = err
|
||||
}
|
||||
}
|
||||
|
||||
func (t *handshakeTransport) requestKeyExchange() {
|
||||
select {
|
||||
case t.requestKex <- struct{}{}:
|
||||
default:
|
||||
// something already requested a kex, so do nothing.
|
||||
}
|
||||
}
|
||||
|
||||
func (t *handshakeTransport) kexLoop() {
|
||||
|
||||
write:
|
||||
for t.getWriteError() == nil {
|
||||
var request *pendingKex
|
||||
var sent bool
|
||||
|
||||
for request == nil || !sent {
|
||||
var ok bool
|
||||
select {
|
||||
case request, ok = <-t.startKex:
|
||||
if !ok {
|
||||
break write
|
||||
}
|
||||
case <-t.requestKex:
|
||||
break
|
||||
}
|
||||
|
||||
if !sent {
|
||||
if err := t.sendKexInit(); err != nil {
|
||||
t.recordWriteError(err)
|
||||
break
|
||||
}
|
||||
sent = true
|
||||
}
|
||||
}
|
||||
|
||||
if err := t.getWriteError(); err != nil {
|
||||
if request != nil {
|
||||
request.done <- err
|
||||
}
|
||||
break
|
||||
}
|
||||
|
||||
// We're not servicing t.requestKex, but that is OK:
|
||||
// we never block on sending to t.requestKex.
|
||||
|
||||
// We're not servicing t.startKex, but the remote end
|
||||
// has just sent us a kexInitMsg, so it can't send
|
||||
// another key change request, until we close the done
|
||||
// channel on the pendingKex request.
|
||||
|
||||
err := t.enterKeyExchange(request.otherInit)
|
||||
|
||||
t.mu.Lock()
|
||||
t.writeError = err
|
||||
t.sentInitPacket = nil
|
||||
t.sentInitMsg = nil
|
||||
t.writePacketsLeft = packetRekeyThreshold
|
||||
if t.config.RekeyThreshold > 0 {
|
||||
t.writeBytesLeft = int64(t.config.RekeyThreshold)
|
||||
} else if t.algorithms != nil {
|
||||
t.writeBytesLeft = t.algorithms.w.rekeyBytes()
|
||||
}
|
||||
|
||||
// we have completed the key exchange. Since the
|
||||
// reader is still blocked, it is safe to clear out
|
||||
// the requestKex channel. This avoids the situation
|
||||
// where: 1) we consumed our own request for the
|
||||
// initial kex, and 2) the kex from the remote side
|
||||
// caused another send on the requestKex channel,
|
||||
clear:
|
||||
for {
|
||||
select {
|
||||
case <-t.requestKex:
|
||||
//
|
||||
default:
|
||||
break clear
|
||||
}
|
||||
}
|
||||
|
||||
request.done <- t.writeError
|
||||
|
||||
// kex finished. Push packets that we received while
|
||||
// the kex was in progress. Don't look at t.startKex
|
||||
// and don't increment writtenSinceKex: if we trigger
|
||||
// another kex while we are still busy with the last
|
||||
// one, things will become very confusing.
|
||||
for _, p := range t.pendingPackets {
|
||||
t.writeError = t.pushPacket(p)
|
||||
if t.writeError != nil {
|
||||
break
|
||||
}
|
||||
}
|
||||
t.pendingPackets = t.pendingPackets[:0]
|
||||
t.mu.Unlock()
|
||||
}
|
||||
|
||||
// drain startKex channel. We don't service t.requestKex
|
||||
// because nobody does blocking sends there.
|
||||
go func() {
|
||||
for init := range t.startKex {
|
||||
init.done <- t.writeError
|
||||
}
|
||||
}()
|
||||
|
||||
// Unblock reader.
|
||||
t.conn.Close()
|
||||
}
|
||||
|
||||
// The protocol uses uint32 for packet counters, so we can't let them
|
||||
// reach 1<<32. We will actually read and write more packets than
|
||||
// this, though: the other side may send more packets, and after we
|
||||
// hit this limit on writing we will send a few more packets for the
|
||||
// key exchange itself.
|
||||
const packetRekeyThreshold = (1 << 31)
|
||||
|
||||
func (t *handshakeTransport) readOnePacket(first bool) ([]byte, error) {
|
||||
p, err := t.conn.readPacket()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
t.readSinceKex += uint64(len(p))
|
||||
if debugHandshake {
|
||||
if p[0] == msgChannelData || p[0] == msgChannelExtendedData {
|
||||
log.Printf("%s got data (packet %d bytes)", t.id(), len(p))
|
||||
} else {
|
||||
msg, err := decode(p)
|
||||
log.Printf("%s got %T %v (%v)", t.id(), msg, msg, err)
|
||||
}
|
||||
if t.readPacketsLeft > 0 {
|
||||
t.readPacketsLeft--
|
||||
} else {
|
||||
t.requestKeyExchange()
|
||||
}
|
||||
|
||||
if t.readBytesLeft > 0 {
|
||||
t.readBytesLeft -= int64(len(p))
|
||||
} else {
|
||||
t.requestKeyExchange()
|
||||
}
|
||||
|
||||
if debugHandshake {
|
||||
t.printPacket(p, false)
|
||||
}
|
||||
|
||||
if first && p[0] != msgKexInit {
|
||||
return nil, fmt.Errorf("ssh: first packet should be msgKexInit")
|
||||
}
|
||||
|
||||
if p[0] != msgKexInit {
|
||||
return p, nil
|
||||
}
|
||||
|
||||
t.mu.Lock()
|
||||
|
||||
firstKex := t.sessionID == nil
|
||||
|
||||
err = t.enterKeyExchangeLocked(p)
|
||||
if err != nil {
|
||||
// drop connection
|
||||
t.conn.Close()
|
||||
t.writeError = err
|
||||
kex := pendingKex{
|
||||
done: make(chan error, 1),
|
||||
otherInit: p,
|
||||
}
|
||||
t.startKex <- &kex
|
||||
err = <-kex.done
|
||||
|
||||
if debugHandshake {
|
||||
log.Printf("%s exited key exchange (first %v), err %v", t.id(), firstKex, err)
|
||||
}
|
||||
|
||||
// Unblock writers.
|
||||
t.sentInitMsg = nil
|
||||
t.sentInitPacket = nil
|
||||
t.cond.Broadcast()
|
||||
t.writtenSinceKex = 0
|
||||
t.mu.Unlock()
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
t.readSinceKex = 0
|
||||
t.readPacketsLeft = packetRekeyThreshold
|
||||
if t.config.RekeyThreshold > 0 {
|
||||
t.readBytesLeft = int64(t.config.RekeyThreshold)
|
||||
} else {
|
||||
t.readBytesLeft = t.algorithms.r.rekeyBytes()
|
||||
}
|
||||
|
||||
// By default, a key exchange is hidden from higher layers by
|
||||
// translating it into msgIgnore.
|
||||
@ -213,61 +411,16 @@ func (t *handshakeTransport) readOnePacket() ([]byte, error) {
|
||||
return successPacket, nil
|
||||
}
|
||||
|
||||
// keyChangeCategory describes whether a key exchange is the first on a
|
||||
// connection, or a subsequent one.
|
||||
type keyChangeCategory bool
|
||||
|
||||
const (
|
||||
firstKeyExchange keyChangeCategory = true
|
||||
subsequentKeyExchange keyChangeCategory = false
|
||||
)
|
||||
|
||||
// sendKexInit sends a key change message, and returns the message
|
||||
// that was sent. After initiating the key change, all writes will be
|
||||
// blocked until the change is done, and a failed key change will
|
||||
// close the underlying transport. This function is safe for
|
||||
// concurrent use by multiple goroutines.
|
||||
func (t *handshakeTransport) sendKexInit(isFirst keyChangeCategory) error {
|
||||
var err error
|
||||
|
||||
// sendKexInit sends a key change message.
|
||||
func (t *handshakeTransport) sendKexInit() error {
|
||||
t.mu.Lock()
|
||||
// If this is the initial key change, but we already have a sessionID,
|
||||
// then do nothing because the key exchange has already completed
|
||||
// asynchronously.
|
||||
if !isFirst || t.sessionID == nil {
|
||||
_, _, err = t.sendKexInitLocked(isFirst)
|
||||
}
|
||||
t.mu.Unlock()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if isFirst {
|
||||
if packet, err := t.readPacket(); err != nil {
|
||||
return err
|
||||
} else if packet[0] != msgNewKeys {
|
||||
return unexpectedMessageError(msgNewKeys, packet[0])
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (t *handshakeTransport) requestInitialKeyChange() error {
|
||||
return t.sendKexInit(firstKeyExchange)
|
||||
}
|
||||
|
||||
func (t *handshakeTransport) requestKeyChange() error {
|
||||
return t.sendKexInit(subsequentKeyExchange)
|
||||
}
|
||||
|
||||
// sendKexInitLocked sends a key change message. t.mu must be locked
|
||||
// while this happens.
|
||||
func (t *handshakeTransport) sendKexInitLocked(isFirst keyChangeCategory) (*kexInitMsg, []byte, error) {
|
||||
// kexInits may be sent either in response to the other side,
|
||||
// or because our side wants to initiate a key change, so we
|
||||
// may have already sent a kexInit. In that case, don't send a
|
||||
// second kexInit.
|
||||
defer t.mu.Unlock()
|
||||
if t.sentInitMsg != nil {
|
||||
return t.sentInitMsg, t.sentInitPacket, nil
|
||||
// kexInits may be sent either in response to the other side,
|
||||
// or because our side wants to initiate a key change, so we
|
||||
// may have already sent a kexInit. In that case, don't send a
|
||||
// second kexInit.
|
||||
return nil
|
||||
}
|
||||
|
||||
msg := &kexInitMsg{
|
||||
@ -295,53 +448,65 @@ func (t *handshakeTransport) sendKexInitLocked(isFirst keyChangeCategory) (*kexI
|
||||
packetCopy := make([]byte, len(packet))
|
||||
copy(packetCopy, packet)
|
||||
|
||||
if err := t.conn.writePacket(packetCopy); err != nil {
|
||||
return nil, nil, err
|
||||
if err := t.pushPacket(packetCopy); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
t.sentInitMsg = msg
|
||||
t.sentInitPacket = packet
|
||||
return msg, packet, nil
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (t *handshakeTransport) writePacket(p []byte) error {
|
||||
t.mu.Lock()
|
||||
defer t.mu.Unlock()
|
||||
|
||||
if t.writtenSinceKex > t.config.RekeyThreshold {
|
||||
t.sendKexInitLocked(subsequentKeyExchange)
|
||||
}
|
||||
for t.sentInitMsg != nil && t.writeError == nil {
|
||||
t.cond.Wait()
|
||||
}
|
||||
if t.writeError != nil {
|
||||
return t.writeError
|
||||
}
|
||||
t.writtenSinceKex += uint64(len(p))
|
||||
|
||||
switch p[0] {
|
||||
case msgKexInit:
|
||||
return errors.New("ssh: only handshakeTransport can send kexInit")
|
||||
case msgNewKeys:
|
||||
return errors.New("ssh: only handshakeTransport can send newKeys")
|
||||
default:
|
||||
return t.conn.writePacket(p)
|
||||
}
|
||||
|
||||
t.mu.Lock()
|
||||
defer t.mu.Unlock()
|
||||
if t.writeError != nil {
|
||||
return t.writeError
|
||||
}
|
||||
|
||||
if t.sentInitMsg != nil {
|
||||
// Copy the packet so the writer can reuse the buffer.
|
||||
cp := make([]byte, len(p))
|
||||
copy(cp, p)
|
||||
t.pendingPackets = append(t.pendingPackets, cp)
|
||||
return nil
|
||||
}
|
||||
|
||||
if t.writeBytesLeft > 0 {
|
||||
t.writeBytesLeft -= int64(len(p))
|
||||
} else {
|
||||
t.requestKeyExchange()
|
||||
}
|
||||
|
||||
if t.writePacketsLeft > 0 {
|
||||
t.writePacketsLeft--
|
||||
} else {
|
||||
t.requestKeyExchange()
|
||||
}
|
||||
|
||||
if err := t.pushPacket(p); err != nil {
|
||||
t.writeError = err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (t *handshakeTransport) Close() error {
|
||||
return t.conn.Close()
|
||||
}
|
||||
|
||||
// enterKeyExchange runs the key exchange. t.mu must be held while running this.
|
||||
func (t *handshakeTransport) enterKeyExchangeLocked(otherInitPacket []byte) error {
|
||||
func (t *handshakeTransport) enterKeyExchange(otherInitPacket []byte) error {
|
||||
if debugHandshake {
|
||||
log.Printf("%s entered key exchange", t.id())
|
||||
}
|
||||
myInit, myInitPacket, err := t.sendKexInitLocked(subsequentKeyExchange)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
otherInit := &kexInitMsg{}
|
||||
if err := Unmarshal(otherInitPacket, otherInit); err != nil {
|
||||
@ -352,20 +517,20 @@ func (t *handshakeTransport) enterKeyExchangeLocked(otherInitPacket []byte) erro
|
||||
clientVersion: t.clientVersion,
|
||||
serverVersion: t.serverVersion,
|
||||
clientKexInit: otherInitPacket,
|
||||
serverKexInit: myInitPacket,
|
||||
serverKexInit: t.sentInitPacket,
|
||||
}
|
||||
|
||||
clientInit := otherInit
|
||||
serverInit := myInit
|
||||
serverInit := t.sentInitMsg
|
||||
if len(t.hostKeys) == 0 {
|
||||
clientInit = myInit
|
||||
serverInit = otherInit
|
||||
clientInit, serverInit = serverInit, clientInit
|
||||
|
||||
magics.clientKexInit = myInitPacket
|
||||
magics.clientKexInit = t.sentInitPacket
|
||||
magics.serverKexInit = otherInitPacket
|
||||
}
|
||||
|
||||
algs, err := findAgreedAlgorithms(clientInit, serverInit)
|
||||
var err error
|
||||
t.algorithms, err = findAgreedAlgorithms(clientInit, serverInit)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -388,16 +553,16 @@ func (t *handshakeTransport) enterKeyExchangeLocked(otherInitPacket []byte) erro
|
||||
}
|
||||
}
|
||||
|
||||
kex, ok := kexAlgoMap[algs.kex]
|
||||
kex, ok := kexAlgoMap[t.algorithms.kex]
|
||||
if !ok {
|
||||
return fmt.Errorf("ssh: unexpected key exchange algorithm %v", algs.kex)
|
||||
return fmt.Errorf("ssh: unexpected key exchange algorithm %v", t.algorithms.kex)
|
||||
}
|
||||
|
||||
var result *kexResult
|
||||
if len(t.hostKeys) > 0 {
|
||||
result, err = t.server(kex, algs, &magics)
|
||||
result, err = t.server(kex, t.algorithms, &magics)
|
||||
} else {
|
||||
result, err = t.client(kex, algs, &magics)
|
||||
result, err = t.client(kex, t.algorithms, &magics)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
@ -409,7 +574,7 @@ func (t *handshakeTransport) enterKeyExchangeLocked(otherInitPacket []byte) erro
|
||||
}
|
||||
result.SessionID = t.sessionID
|
||||
|
||||
t.conn.prepareKeyChange(algs, result)
|
||||
t.conn.prepareKeyChange(t.algorithms, result)
|
||||
if err = t.conn.writePacket([]byte{msgNewKeys}); err != nil {
|
||||
return err
|
||||
}
|
||||
|
486
vendor/golang.org/x/crypto/ssh/handshake_test.go
generated
vendored
486
vendor/golang.org/x/crypto/ssh/handshake_test.go
generated
vendored
@ -1,486 +0,0 @@
|
||||
// Copyright 2013 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package ssh
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/rand"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net"
|
||||
"reflect"
|
||||
"runtime"
|
||||
"strings"
|
||||
"sync"
|
||||
"testing"
|
||||
)
|
||||
|
||||
type testChecker struct {
|
||||
calls []string
|
||||
}
|
||||
|
||||
func (t *testChecker) Check(dialAddr string, addr net.Addr, key PublicKey) error {
|
||||
if dialAddr == "bad" {
|
||||
return fmt.Errorf("dialAddr is bad")
|
||||
}
|
||||
|
||||
if tcpAddr, ok := addr.(*net.TCPAddr); !ok || tcpAddr == nil {
|
||||
return fmt.Errorf("testChecker: got %T want *net.TCPAddr", addr)
|
||||
}
|
||||
|
||||
t.calls = append(t.calls, fmt.Sprintf("%s %v %s %x", dialAddr, addr, key.Type(), key.Marshal()))
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// netPipe is analogous to net.Pipe, but it uses a real net.Conn, and
|
||||
// therefore is buffered (net.Pipe deadlocks if both sides start with
|
||||
// a write.)
|
||||
func netPipe() (net.Conn, net.Conn, error) {
|
||||
listener, err := net.Listen("tcp", "127.0.0.1:0")
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
defer listener.Close()
|
||||
c1, err := net.Dial("tcp", listener.Addr().String())
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
c2, err := listener.Accept()
|
||||
if err != nil {
|
||||
c1.Close()
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
return c1, c2, nil
|
||||
}
|
||||
|
||||
func handshakePair(clientConf *ClientConfig, addr string) (client *handshakeTransport, server *handshakeTransport, err error) {
|
||||
a, b, err := netPipe()
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
trC := newTransport(a, rand.Reader, true)
|
||||
trS := newTransport(b, rand.Reader, false)
|
||||
clientConf.SetDefaults()
|
||||
|
||||
v := []byte("version")
|
||||
client = newClientTransport(trC, v, v, clientConf, addr, a.RemoteAddr())
|
||||
|
||||
serverConf := &ServerConfig{}
|
||||
serverConf.AddHostKey(testSigners["ecdsa"])
|
||||
serverConf.AddHostKey(testSigners["rsa"])
|
||||
serverConf.SetDefaults()
|
||||
server = newServerTransport(trS, v, v, serverConf)
|
||||
|
||||
return client, server, nil
|
||||
}
|
||||
|
||||
func TestHandshakeBasic(t *testing.T) {
|
||||
if runtime.GOOS == "plan9" {
|
||||
t.Skip("see golang.org/issue/7237")
|
||||
}
|
||||
checker := &testChecker{}
|
||||
trC, trS, err := handshakePair(&ClientConfig{HostKeyCallback: checker.Check}, "addr")
|
||||
if err != nil {
|
||||
t.Fatalf("handshakePair: %v", err)
|
||||
}
|
||||
|
||||
defer trC.Close()
|
||||
defer trS.Close()
|
||||
|
||||
go func() {
|
||||
// Client writes a bunch of stuff, and does a key
|
||||
// change in the middle. This should not confuse the
|
||||
// handshake in progress
|
||||
for i := 0; i < 10; i++ {
|
||||
p := []byte{msgRequestSuccess, byte(i)}
|
||||
if err := trC.writePacket(p); err != nil {
|
||||
t.Fatalf("sendPacket: %v", err)
|
||||
}
|
||||
if i == 5 {
|
||||
// halfway through, we request a key change.
|
||||
err := trC.sendKexInit(subsequentKeyExchange)
|
||||
if err != nil {
|
||||
t.Fatalf("sendKexInit: %v", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
trC.Close()
|
||||
}()
|
||||
|
||||
// Server checks that client messages come in cleanly
|
||||
i := 0
|
||||
for {
|
||||
p, err := trS.readPacket()
|
||||
if err != nil {
|
||||
break
|
||||
}
|
||||
if p[0] == msgNewKeys {
|
||||
continue
|
||||
}
|
||||
want := []byte{msgRequestSuccess, byte(i)}
|
||||
if bytes.Compare(p, want) != 0 {
|
||||
t.Errorf("message %d: got %q, want %q", i, p, want)
|
||||
}
|
||||
i++
|
||||
}
|
||||
if i != 10 {
|
||||
t.Errorf("received %d messages, want 10.", i)
|
||||
}
|
||||
|
||||
// If all went well, we registered exactly 1 key change.
|
||||
if len(checker.calls) != 1 {
|
||||
t.Fatalf("got %d host key checks, want 1", len(checker.calls))
|
||||
}
|
||||
|
||||
pub := testSigners["ecdsa"].PublicKey()
|
||||
want := fmt.Sprintf("%s %v %s %x", "addr", trC.remoteAddr, pub.Type(), pub.Marshal())
|
||||
if want != checker.calls[0] {
|
||||
t.Errorf("got %q want %q for host key check", checker.calls[0], want)
|
||||
}
|
||||
}
|
||||
|
||||
func TestHandshakeError(t *testing.T) {
|
||||
checker := &testChecker{}
|
||||
trC, trS, err := handshakePair(&ClientConfig{HostKeyCallback: checker.Check}, "bad")
|
||||
if err != nil {
|
||||
t.Fatalf("handshakePair: %v", err)
|
||||
}
|
||||
defer trC.Close()
|
||||
defer trS.Close()
|
||||
|
||||
// send a packet
|
||||
packet := []byte{msgRequestSuccess, 42}
|
||||
if err := trC.writePacket(packet); err != nil {
|
||||
t.Errorf("writePacket: %v", err)
|
||||
}
|
||||
|
||||
// Now request a key change.
|
||||
err = trC.sendKexInit(subsequentKeyExchange)
|
||||
if err != nil {
|
||||
t.Errorf("sendKexInit: %v", err)
|
||||
}
|
||||
|
||||
// the key change will fail, and afterwards we can't write.
|
||||
if err := trC.writePacket([]byte{msgRequestSuccess, 43}); err == nil {
|
||||
t.Errorf("writePacket after botched rekey succeeded.")
|
||||
}
|
||||
|
||||
readback, err := trS.readPacket()
|
||||
if err != nil {
|
||||
t.Fatalf("server closed too soon: %v", err)
|
||||
}
|
||||
if bytes.Compare(readback, packet) != 0 {
|
||||
t.Errorf("got %q want %q", readback, packet)
|
||||
}
|
||||
readback, err = trS.readPacket()
|
||||
if err == nil {
|
||||
t.Errorf("got a message %q after failed key change", readback)
|
||||
}
|
||||
}
|
||||
|
||||
func TestForceFirstKex(t *testing.T) {
|
||||
checker := &testChecker{}
|
||||
trC, trS, err := handshakePair(&ClientConfig{HostKeyCallback: checker.Check}, "addr")
|
||||
if err != nil {
|
||||
t.Fatalf("handshakePair: %v", err)
|
||||
}
|
||||
|
||||
defer trC.Close()
|
||||
defer trS.Close()
|
||||
|
||||
trC.writePacket(Marshal(&serviceRequestMsg{serviceUserAuth}))
|
||||
|
||||
// We setup the initial key exchange, but the remote side
|
||||
// tries to send serviceRequestMsg in cleartext, which is
|
||||
// disallowed.
|
||||
|
||||
err = trS.sendKexInit(firstKeyExchange)
|
||||
if err == nil {
|
||||
t.Errorf("server first kex init should reject unexpected packet")
|
||||
}
|
||||
}
|
||||
|
||||
func TestHandshakeTwice(t *testing.T) {
|
||||
checker := &testChecker{}
|
||||
trC, trS, err := handshakePair(&ClientConfig{HostKeyCallback: checker.Check}, "addr")
|
||||
if err != nil {
|
||||
t.Fatalf("handshakePair: %v", err)
|
||||
}
|
||||
|
||||
defer trC.Close()
|
||||
defer trS.Close()
|
||||
|
||||
// Both sides should ask for the first key exchange first.
|
||||
err = trS.sendKexInit(firstKeyExchange)
|
||||
if err != nil {
|
||||
t.Errorf("server sendKexInit: %v", err)
|
||||
}
|
||||
|
||||
err = trC.sendKexInit(firstKeyExchange)
|
||||
if err != nil {
|
||||
t.Errorf("client sendKexInit: %v", err)
|
||||
}
|
||||
|
||||
sent := 0
|
||||
// send a packet
|
||||
packet := make([]byte, 5)
|
||||
packet[0] = msgRequestSuccess
|
||||
if err := trC.writePacket(packet); err != nil {
|
||||
t.Errorf("writePacket: %v", err)
|
||||
}
|
||||
sent++
|
||||
|
||||
// Send another packet. Use a fresh one, since writePacket destroys.
|
||||
packet = make([]byte, 5)
|
||||
packet[0] = msgRequestSuccess
|
||||
if err := trC.writePacket(packet); err != nil {
|
||||
t.Errorf("writePacket: %v", err)
|
||||
}
|
||||
sent++
|
||||
|
||||
// 2nd key change.
|
||||
err = trC.sendKexInit(subsequentKeyExchange)
|
||||
if err != nil {
|
||||
t.Errorf("sendKexInit: %v", err)
|
||||
}
|
||||
|
||||
packet = make([]byte, 5)
|
||||
packet[0] = msgRequestSuccess
|
||||
if err := trC.writePacket(packet); err != nil {
|
||||
t.Errorf("writePacket: %v", err)
|
||||
}
|
||||
sent++
|
||||
|
||||
packet = make([]byte, 5)
|
||||
packet[0] = msgRequestSuccess
|
||||
for i := 0; i < sent; i++ {
|
||||
msg, err := trS.readPacket()
|
||||
if err != nil {
|
||||
t.Fatalf("server closed too soon: %v", err)
|
||||
}
|
||||
|
||||
if bytes.Compare(msg, packet) != 0 {
|
||||
t.Errorf("packet %d: got %q want %q", i, msg, packet)
|
||||
}
|
||||
}
|
||||
if len(checker.calls) != 2 {
|
||||
t.Errorf("got %d key changes, want 2", len(checker.calls))
|
||||
}
|
||||
}
|
||||
|
||||
func TestHandshakeAutoRekeyWrite(t *testing.T) {
|
||||
checker := &testChecker{}
|
||||
clientConf := &ClientConfig{HostKeyCallback: checker.Check}
|
||||
clientConf.RekeyThreshold = 500
|
||||
trC, trS, err := handshakePair(clientConf, "addr")
|
||||
if err != nil {
|
||||
t.Fatalf("handshakePair: %v", err)
|
||||
}
|
||||
defer trC.Close()
|
||||
defer trS.Close()
|
||||
|
||||
for i := 0; i < 5; i++ {
|
||||
packet := make([]byte, 251)
|
||||
packet[0] = msgRequestSuccess
|
||||
if err := trC.writePacket(packet); err != nil {
|
||||
t.Errorf("writePacket: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
j := 0
|
||||
for ; j < 5; j++ {
|
||||
_, err := trS.readPacket()
|
||||
if err != nil {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if j != 5 {
|
||||
t.Errorf("got %d, want 5 messages", j)
|
||||
}
|
||||
|
||||
if len(checker.calls) != 2 {
|
||||
t.Errorf("got %d key changes, wanted 2", len(checker.calls))
|
||||
}
|
||||
}
|
||||
|
||||
type syncChecker struct {
|
||||
called chan int
|
||||
}
|
||||
|
||||
func (t *syncChecker) Check(dialAddr string, addr net.Addr, key PublicKey) error {
|
||||
t.called <- 1
|
||||
return nil
|
||||
}
|
||||
|
||||
func TestHandshakeAutoRekeyRead(t *testing.T) {
|
||||
sync := &syncChecker{make(chan int, 2)}
|
||||
clientConf := &ClientConfig{
|
||||
HostKeyCallback: sync.Check,
|
||||
}
|
||||
clientConf.RekeyThreshold = 500
|
||||
|
||||
trC, trS, err := handshakePair(clientConf, "addr")
|
||||
if err != nil {
|
||||
t.Fatalf("handshakePair: %v", err)
|
||||
}
|
||||
defer trC.Close()
|
||||
defer trS.Close()
|
||||
|
||||
packet := make([]byte, 501)
|
||||
packet[0] = msgRequestSuccess
|
||||
if err := trS.writePacket(packet); err != nil {
|
||||
t.Fatalf("writePacket: %v", err)
|
||||
}
|
||||
// While we read out the packet, a key change will be
|
||||
// initiated.
|
||||
if _, err := trC.readPacket(); err != nil {
|
||||
t.Fatalf("readPacket(client): %v", err)
|
||||
}
|
||||
|
||||
<-sync.called
|
||||
}
|
||||
|
||||
// errorKeyingTransport generates errors after a given number of
|
||||
// read/write operations.
|
||||
type errorKeyingTransport struct {
|
||||
packetConn
|
||||
readLeft, writeLeft int
|
||||
}
|
||||
|
||||
func (n *errorKeyingTransport) prepareKeyChange(*algorithms, *kexResult) error {
|
||||
return nil
|
||||
}
|
||||
func (n *errorKeyingTransport) getSessionID() []byte {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (n *errorKeyingTransport) writePacket(packet []byte) error {
|
||||
if n.writeLeft == 0 {
|
||||
n.Close()
|
||||
return errors.New("barf")
|
||||
}
|
||||
|
||||
n.writeLeft--
|
||||
return n.packetConn.writePacket(packet)
|
||||
}
|
||||
|
||||
func (n *errorKeyingTransport) readPacket() ([]byte, error) {
|
||||
if n.readLeft == 0 {
|
||||
n.Close()
|
||||
return nil, errors.New("barf")
|
||||
}
|
||||
|
||||
n.readLeft--
|
||||
return n.packetConn.readPacket()
|
||||
}
|
||||
|
||||
func TestHandshakeErrorHandlingRead(t *testing.T) {
|
||||
for i := 0; i < 20; i++ {
|
||||
testHandshakeErrorHandlingN(t, i, -1)
|
||||
}
|
||||
}
|
||||
|
||||
func TestHandshakeErrorHandlingWrite(t *testing.T) {
|
||||
for i := 0; i < 20; i++ {
|
||||
testHandshakeErrorHandlingN(t, -1, i)
|
||||
}
|
||||
}
|
||||
|
||||
// testHandshakeErrorHandlingN runs handshakes, injecting errors. If
|
||||
// handshakeTransport deadlocks, the go runtime will detect it and
|
||||
// panic.
|
||||
func testHandshakeErrorHandlingN(t *testing.T, readLimit, writeLimit int) {
|
||||
msg := Marshal(&serviceRequestMsg{strings.Repeat("x", int(minRekeyThreshold)/4)})
|
||||
|
||||
a, b := memPipe()
|
||||
defer a.Close()
|
||||
defer b.Close()
|
||||
|
||||
key := testSigners["ecdsa"]
|
||||
serverConf := Config{RekeyThreshold: minRekeyThreshold}
|
||||
serverConf.SetDefaults()
|
||||
serverConn := newHandshakeTransport(&errorKeyingTransport{a, readLimit, writeLimit}, &serverConf, []byte{'a'}, []byte{'b'})
|
||||
serverConn.hostKeys = []Signer{key}
|
||||
go serverConn.readLoop()
|
||||
|
||||
clientConf := Config{RekeyThreshold: 10 * minRekeyThreshold}
|
||||
clientConf.SetDefaults()
|
||||
clientConn := newHandshakeTransport(&errorKeyingTransport{b, -1, -1}, &clientConf, []byte{'a'}, []byte{'b'})
|
||||
clientConn.hostKeyAlgorithms = []string{key.PublicKey().Type()}
|
||||
go clientConn.readLoop()
|
||||
|
||||
var wg sync.WaitGroup
|
||||
wg.Add(4)
|
||||
|
||||
for _, hs := range []packetConn{serverConn, clientConn} {
|
||||
go func(c packetConn) {
|
||||
for {
|
||||
err := c.writePacket(msg)
|
||||
if err != nil {
|
||||
break
|
||||
}
|
||||
}
|
||||
wg.Done()
|
||||
}(hs)
|
||||
go func(c packetConn) {
|
||||
for {
|
||||
_, err := c.readPacket()
|
||||
if err != nil {
|
||||
break
|
||||
}
|
||||
}
|
||||
wg.Done()
|
||||
}(hs)
|
||||
}
|
||||
|
||||
wg.Wait()
|
||||
}
|
||||
|
||||
func TestDisconnect(t *testing.T) {
|
||||
if runtime.GOOS == "plan9" {
|
||||
t.Skip("see golang.org/issue/7237")
|
||||
}
|
||||
checker := &testChecker{}
|
||||
trC, trS, err := handshakePair(&ClientConfig{HostKeyCallback: checker.Check}, "addr")
|
||||
if err != nil {
|
||||
t.Fatalf("handshakePair: %v", err)
|
||||
}
|
||||
|
||||
defer trC.Close()
|
||||
defer trS.Close()
|
||||
|
||||
trC.writePacket([]byte{msgRequestSuccess, 0, 0})
|
||||
errMsg := &disconnectMsg{
|
||||
Reason: 42,
|
||||
Message: "such is life",
|
||||
}
|
||||
trC.writePacket(Marshal(errMsg))
|
||||
trC.writePacket([]byte{msgRequestSuccess, 0, 0})
|
||||
|
||||
packet, err := trS.readPacket()
|
||||
if err != nil {
|
||||
t.Fatalf("readPacket 1: %v", err)
|
||||
}
|
||||
if packet[0] != msgRequestSuccess {
|
||||
t.Errorf("got packet %v, want packet type %d", packet, msgRequestSuccess)
|
||||
}
|
||||
|
||||
_, err = trS.readPacket()
|
||||
if err == nil {
|
||||
t.Errorf("readPacket 2 succeeded")
|
||||
} else if !reflect.DeepEqual(err, errMsg) {
|
||||
t.Errorf("got error %#v, want %#v", err, errMsg)
|
||||
}
|
||||
|
||||
_, err = trS.readPacket()
|
||||
if err == nil {
|
||||
t.Errorf("readPacket 3 succeeded")
|
||||
}
|
||||
}
|
50
vendor/golang.org/x/crypto/ssh/kex_test.go
generated
vendored
50
vendor/golang.org/x/crypto/ssh/kex_test.go
generated
vendored
@ -1,50 +0,0 @@
|
||||
// Copyright 2013 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package ssh
|
||||
|
||||
// Key exchange tests.
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"reflect"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestKexes(t *testing.T) {
|
||||
type kexResultErr struct {
|
||||
result *kexResult
|
||||
err error
|
||||
}
|
||||
|
||||
for name, kex := range kexAlgoMap {
|
||||
a, b := memPipe()
|
||||
|
||||
s := make(chan kexResultErr, 1)
|
||||
c := make(chan kexResultErr, 1)
|
||||
var magics handshakeMagics
|
||||
go func() {
|
||||
r, e := kex.Client(a, rand.Reader, &magics)
|
||||
a.Close()
|
||||
c <- kexResultErr{r, e}
|
||||
}()
|
||||
go func() {
|
||||
r, e := kex.Server(b, rand.Reader, &magics, testSigners["ecdsa"])
|
||||
b.Close()
|
||||
s <- kexResultErr{r, e}
|
||||
}()
|
||||
|
||||
clientRes := <-c
|
||||
serverRes := <-s
|
||||
if clientRes.err != nil {
|
||||
t.Errorf("client: %v", clientRes.err)
|
||||
}
|
||||
if serverRes.err != nil {
|
||||
t.Errorf("server: %v", serverRes.err)
|
||||
}
|
||||
if !reflect.DeepEqual(clientRes.result, serverRes.result) {
|
||||
t.Errorf("kex %q: mismatch %#v, %#v", name, clientRes.result, serverRes.result)
|
||||
}
|
||||
}
|
||||
}
|
31
vendor/golang.org/x/crypto/ssh/keys.go
generated
vendored
31
vendor/golang.org/x/crypto/ssh/keys.go
generated
vendored
@ -10,10 +10,13 @@ import (
|
||||
"crypto/dsa"
|
||||
"crypto/ecdsa"
|
||||
"crypto/elliptic"
|
||||
"crypto/md5"
|
||||
"crypto/rsa"
|
||||
"crypto/sha256"
|
||||
"crypto/x509"
|
||||
"encoding/asn1"
|
||||
"encoding/base64"
|
||||
"encoding/hex"
|
||||
"encoding/pem"
|
||||
"errors"
|
||||
"fmt"
|
||||
@ -795,8 +798,8 @@ func ParseDSAPrivateKey(der []byte) (*dsa.PrivateKey, error) {
|
||||
P *big.Int
|
||||
Q *big.Int
|
||||
G *big.Int
|
||||
Priv *big.Int
|
||||
Pub *big.Int
|
||||
Priv *big.Int
|
||||
}
|
||||
rest, err := asn1.Unmarshal(der, &k)
|
||||
if err != nil {
|
||||
@ -813,9 +816,9 @@ func ParseDSAPrivateKey(der []byte) (*dsa.PrivateKey, error) {
|
||||
Q: k.Q,
|
||||
G: k.G,
|
||||
},
|
||||
Y: k.Priv,
|
||||
Y: k.Pub,
|
||||
},
|
||||
X: k.Pub,
|
||||
X: k.Priv,
|
||||
}, nil
|
||||
}
|
||||
|
||||
@ -878,3 +881,25 @@ func parseOpenSSHPrivateKey(key []byte) (*ed25519.PrivateKey, error) {
|
||||
copy(pk, pk1.Priv)
|
||||
return &pk, nil
|
||||
}
|
||||
|
||||
// FingerprintLegacyMD5 returns the user presentation of the key's
|
||||
// fingerprint as described by RFC 4716 section 4.
|
||||
func FingerprintLegacyMD5(pubKey PublicKey) string {
|
||||
md5sum := md5.Sum(pubKey.Marshal())
|
||||
hexarray := make([]string, len(md5sum))
|
||||
for i, c := range md5sum {
|
||||
hexarray[i] = hex.EncodeToString([]byte{c})
|
||||
}
|
||||
return strings.Join(hexarray, ":")
|
||||
}
|
||||
|
||||
// FingerprintSHA256 returns the user presentation of the key's
|
||||
// fingerprint as unpadded base64 encoded sha256 hash.
|
||||
// This format was introduced from OpenSSH 6.8.
|
||||
// https://www.openssh.com/txt/release-6.8
|
||||
// https://tools.ietf.org/html/rfc4648#section-3.2 (unpadded base64 encoding)
|
||||
func FingerprintSHA256(pubKey PublicKey) string {
|
||||
sha256sum := sha256.Sum256(pubKey.Marshal())
|
||||
hash := base64.RawStdEncoding.EncodeToString(sha256sum[:])
|
||||
return "SHA256:" + hash
|
||||
}
|
||||
|
456
vendor/golang.org/x/crypto/ssh/keys_test.go
generated
vendored
456
vendor/golang.org/x/crypto/ssh/keys_test.go
generated
vendored
@ -1,456 +0,0 @@
|
||||
// Copyright 2014 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package ssh
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/dsa"
|
||||
"crypto/ecdsa"
|
||||
"crypto/elliptic"
|
||||
"crypto/rand"
|
||||
"crypto/rsa"
|
||||
"encoding/base64"
|
||||
"fmt"
|
||||
"reflect"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"golang.org/x/crypto/ed25519"
|
||||
"golang.org/x/crypto/ssh/testdata"
|
||||
)
|
||||
|
||||
func rawKey(pub PublicKey) interface{} {
|
||||
switch k := pub.(type) {
|
||||
case *rsaPublicKey:
|
||||
return (*rsa.PublicKey)(k)
|
||||
case *dsaPublicKey:
|
||||
return (*dsa.PublicKey)(k)
|
||||
case *ecdsaPublicKey:
|
||||
return (*ecdsa.PublicKey)(k)
|
||||
case ed25519PublicKey:
|
||||
return (ed25519.PublicKey)(k)
|
||||
case *Certificate:
|
||||
return k
|
||||
}
|
||||
panic("unknown key type")
|
||||
}
|
||||
|
||||
func TestKeyMarshalParse(t *testing.T) {
|
||||
for _, priv := range testSigners {
|
||||
pub := priv.PublicKey()
|
||||
roundtrip, err := ParsePublicKey(pub.Marshal())
|
||||
if err != nil {
|
||||
t.Errorf("ParsePublicKey(%T): %v", pub, err)
|
||||
}
|
||||
|
||||
k1 := rawKey(pub)
|
||||
k2 := rawKey(roundtrip)
|
||||
|
||||
if !reflect.DeepEqual(k1, k2) {
|
||||
t.Errorf("got %#v in roundtrip, want %#v", k2, k1)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestUnsupportedCurves(t *testing.T) {
|
||||
raw, err := ecdsa.GenerateKey(elliptic.P224(), rand.Reader)
|
||||
if err != nil {
|
||||
t.Fatalf("GenerateKey: %v", err)
|
||||
}
|
||||
|
||||
if _, err = NewSignerFromKey(raw); err == nil || !strings.Contains(err.Error(), "only P-256") {
|
||||
t.Fatalf("NewPrivateKey should not succeed with P-224, got: %v", err)
|
||||
}
|
||||
|
||||
if _, err = NewPublicKey(&raw.PublicKey); err == nil || !strings.Contains(err.Error(), "only P-256") {
|
||||
t.Fatalf("NewPublicKey should not succeed with P-224, got: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestNewPublicKey(t *testing.T) {
|
||||
for _, k := range testSigners {
|
||||
raw := rawKey(k.PublicKey())
|
||||
// Skip certificates, as NewPublicKey does not support them.
|
||||
if _, ok := raw.(*Certificate); ok {
|
||||
continue
|
||||
}
|
||||
pub, err := NewPublicKey(raw)
|
||||
if err != nil {
|
||||
t.Errorf("NewPublicKey(%#v): %v", raw, err)
|
||||
}
|
||||
if !reflect.DeepEqual(k.PublicKey(), pub) {
|
||||
t.Errorf("NewPublicKey(%#v) = %#v, want %#v", raw, pub, k.PublicKey())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestKeySignVerify(t *testing.T) {
|
||||
for _, priv := range testSigners {
|
||||
pub := priv.PublicKey()
|
||||
|
||||
data := []byte("sign me")
|
||||
sig, err := priv.Sign(rand.Reader, data)
|
||||
if err != nil {
|
||||
t.Fatalf("Sign(%T): %v", priv, err)
|
||||
}
|
||||
|
||||
if err := pub.Verify(data, sig); err != nil {
|
||||
t.Errorf("publicKey.Verify(%T): %v", priv, err)
|
||||
}
|
||||
sig.Blob[5]++
|
||||
if err := pub.Verify(data, sig); err == nil {
|
||||
t.Errorf("publicKey.Verify on broken sig did not fail")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestParseRSAPrivateKey(t *testing.T) {
|
||||
key := testPrivateKeys["rsa"]
|
||||
|
||||
rsa, ok := key.(*rsa.PrivateKey)
|
||||
if !ok {
|
||||
t.Fatalf("got %T, want *rsa.PrivateKey", rsa)
|
||||
}
|
||||
|
||||
if err := rsa.Validate(); err != nil {
|
||||
t.Errorf("Validate: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestParseECPrivateKey(t *testing.T) {
|
||||
key := testPrivateKeys["ecdsa"]
|
||||
|
||||
ecKey, ok := key.(*ecdsa.PrivateKey)
|
||||
if !ok {
|
||||
t.Fatalf("got %T, want *ecdsa.PrivateKey", ecKey)
|
||||
}
|
||||
|
||||
if !validateECPublicKey(ecKey.Curve, ecKey.X, ecKey.Y) {
|
||||
t.Fatalf("public key does not validate.")
|
||||
}
|
||||
}
|
||||
|
||||
// See Issue https://github.com/golang/go/issues/6650.
|
||||
func TestParseEncryptedPrivateKeysFails(t *testing.T) {
|
||||
const wantSubstring = "encrypted"
|
||||
for i, tt := range testdata.PEMEncryptedKeys {
|
||||
_, err := ParsePrivateKey(tt.PEMBytes)
|
||||
if err == nil {
|
||||
t.Errorf("#%d key %s: ParsePrivateKey successfully parsed, expected an error", i, tt.Name)
|
||||
continue
|
||||
}
|
||||
|
||||
if !strings.Contains(err.Error(), wantSubstring) {
|
||||
t.Errorf("#%d key %s: got error %q, want substring %q", i, tt.Name, err, wantSubstring)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestParseDSA(t *testing.T) {
|
||||
// We actually exercise the ParsePrivateKey codepath here, as opposed to
|
||||
// using the ParseRawPrivateKey+NewSignerFromKey path that testdata_test.go
|
||||
// uses.
|
||||
s, err := ParsePrivateKey(testdata.PEMBytes["dsa"])
|
||||
if err != nil {
|
||||
t.Fatalf("ParsePrivateKey returned error: %s", err)
|
||||
}
|
||||
|
||||
data := []byte("sign me")
|
||||
sig, err := s.Sign(rand.Reader, data)
|
||||
if err != nil {
|
||||
t.Fatalf("dsa.Sign: %v", err)
|
||||
}
|
||||
|
||||
if err := s.PublicKey().Verify(data, sig); err != nil {
|
||||
t.Errorf("Verify failed: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
// Tests for authorized_keys parsing.
|
||||
|
||||
// getTestKey returns a public key, and its base64 encoding.
|
||||
func getTestKey() (PublicKey, string) {
|
||||
k := testPublicKeys["rsa"]
|
||||
|
||||
b := &bytes.Buffer{}
|
||||
e := base64.NewEncoder(base64.StdEncoding, b)
|
||||
e.Write(k.Marshal())
|
||||
e.Close()
|
||||
|
||||
return k, b.String()
|
||||
}
|
||||
|
||||
func TestMarshalParsePublicKey(t *testing.T) {
|
||||
pub, pubSerialized := getTestKey()
|
||||
line := fmt.Sprintf("%s %s user@host", pub.Type(), pubSerialized)
|
||||
|
||||
authKeys := MarshalAuthorizedKey(pub)
|
||||
actualFields := strings.Fields(string(authKeys))
|
||||
if len(actualFields) == 0 {
|
||||
t.Fatalf("failed authKeys: %v", authKeys)
|
||||
}
|
||||
|
||||
// drop the comment
|
||||
expectedFields := strings.Fields(line)[0:2]
|
||||
|
||||
if !reflect.DeepEqual(actualFields, expectedFields) {
|
||||
t.Errorf("got %v, expected %v", actualFields, expectedFields)
|
||||
}
|
||||
|
||||
actPub, _, _, _, err := ParseAuthorizedKey([]byte(line))
|
||||
if err != nil {
|
||||
t.Fatalf("cannot parse %v: %v", line, err)
|
||||
}
|
||||
if !reflect.DeepEqual(actPub, pub) {
|
||||
t.Errorf("got %v, expected %v", actPub, pub)
|
||||
}
|
||||
}
|
||||
|
||||
type authResult struct {
|
||||
pubKey PublicKey
|
||||
options []string
|
||||
comments string
|
||||
rest string
|
||||
ok bool
|
||||
}
|
||||
|
||||
func testAuthorizedKeys(t *testing.T, authKeys []byte, expected []authResult) {
|
||||
rest := authKeys
|
||||
var values []authResult
|
||||
for len(rest) > 0 {
|
||||
var r authResult
|
||||
var err error
|
||||
r.pubKey, r.comments, r.options, rest, err = ParseAuthorizedKey(rest)
|
||||
r.ok = (err == nil)
|
||||
t.Log(err)
|
||||
r.rest = string(rest)
|
||||
values = append(values, r)
|
||||
}
|
||||
|
||||
if !reflect.DeepEqual(values, expected) {
|
||||
t.Errorf("got %#v, expected %#v", values, expected)
|
||||
}
|
||||
}
|
||||
|
||||
func TestAuthorizedKeyBasic(t *testing.T) {
|
||||
pub, pubSerialized := getTestKey()
|
||||
line := "ssh-rsa " + pubSerialized + " user@host"
|
||||
testAuthorizedKeys(t, []byte(line),
|
||||
[]authResult{
|
||||
{pub, nil, "user@host", "", true},
|
||||
})
|
||||
}
|
||||
|
||||
func TestAuth(t *testing.T) {
|
||||
pub, pubSerialized := getTestKey()
|
||||
authWithOptions := []string{
|
||||
`# comments to ignore before any keys...`,
|
||||
``,
|
||||
`env="HOME=/home/root",no-port-forwarding ssh-rsa ` + pubSerialized + ` user@host`,
|
||||
`# comments to ignore, along with a blank line`,
|
||||
``,
|
||||
`env="HOME=/home/root2" ssh-rsa ` + pubSerialized + ` user2@host2`,
|
||||
``,
|
||||
`# more comments, plus a invalid entry`,
|
||||
`ssh-rsa data-that-will-not-parse user@host3`,
|
||||
}
|
||||
for _, eol := range []string{"\n", "\r\n"} {
|
||||
authOptions := strings.Join(authWithOptions, eol)
|
||||
rest2 := strings.Join(authWithOptions[3:], eol)
|
||||
rest3 := strings.Join(authWithOptions[6:], eol)
|
||||
testAuthorizedKeys(t, []byte(authOptions), []authResult{
|
||||
{pub, []string{`env="HOME=/home/root"`, "no-port-forwarding"}, "user@host", rest2, true},
|
||||
{pub, []string{`env="HOME=/home/root2"`}, "user2@host2", rest3, true},
|
||||
{nil, nil, "", "", false},
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestAuthWithQuotedSpaceInEnv(t *testing.T) {
|
||||
pub, pubSerialized := getTestKey()
|
||||
authWithQuotedSpaceInEnv := []byte(`env="HOME=/home/root dir",no-port-forwarding ssh-rsa ` + pubSerialized + ` user@host`)
|
||||
testAuthorizedKeys(t, []byte(authWithQuotedSpaceInEnv), []authResult{
|
||||
{pub, []string{`env="HOME=/home/root dir"`, "no-port-forwarding"}, "user@host", "", true},
|
||||
})
|
||||
}
|
||||
|
||||
func TestAuthWithQuotedCommaInEnv(t *testing.T) {
|
||||
pub, pubSerialized := getTestKey()
|
||||
authWithQuotedCommaInEnv := []byte(`env="HOME=/home/root,dir",no-port-forwarding ssh-rsa ` + pubSerialized + ` user@host`)
|
||||
testAuthorizedKeys(t, []byte(authWithQuotedCommaInEnv), []authResult{
|
||||
{pub, []string{`env="HOME=/home/root,dir"`, "no-port-forwarding"}, "user@host", "", true},
|
||||
})
|
||||
}
|
||||
|
||||
func TestAuthWithQuotedQuoteInEnv(t *testing.T) {
|
||||
pub, pubSerialized := getTestKey()
|
||||
authWithQuotedQuoteInEnv := []byte(`env="HOME=/home/\"root dir",no-port-forwarding` + "\t" + `ssh-rsa` + "\t" + pubSerialized + ` user@host`)
|
||||
authWithDoubleQuotedQuote := []byte(`no-port-forwarding,env="HOME=/home/ \"root dir\"" ssh-rsa ` + pubSerialized + "\t" + `user@host`)
|
||||
testAuthorizedKeys(t, []byte(authWithQuotedQuoteInEnv), []authResult{
|
||||
{pub, []string{`env="HOME=/home/\"root dir"`, "no-port-forwarding"}, "user@host", "", true},
|
||||
})
|
||||
|
||||
testAuthorizedKeys(t, []byte(authWithDoubleQuotedQuote), []authResult{
|
||||
{pub, []string{"no-port-forwarding", `env="HOME=/home/ \"root dir\""`}, "user@host", "", true},
|
||||
})
|
||||
}
|
||||
|
||||
func TestAuthWithInvalidSpace(t *testing.T) {
|
||||
_, pubSerialized := getTestKey()
|
||||
authWithInvalidSpace := []byte(`env="HOME=/home/root dir", no-port-forwarding ssh-rsa ` + pubSerialized + ` user@host
|
||||
#more to follow but still no valid keys`)
|
||||
testAuthorizedKeys(t, []byte(authWithInvalidSpace), []authResult{
|
||||
{nil, nil, "", "", false},
|
||||
})
|
||||
}
|
||||
|
||||
func TestAuthWithMissingQuote(t *testing.T) {
|
||||
pub, pubSerialized := getTestKey()
|
||||
authWithMissingQuote := []byte(`env="HOME=/home/root,no-port-forwarding ssh-rsa ` + pubSerialized + ` user@host
|
||||
env="HOME=/home/root",shared-control ssh-rsa ` + pubSerialized + ` user@host`)
|
||||
|
||||
testAuthorizedKeys(t, []byte(authWithMissingQuote), []authResult{
|
||||
{pub, []string{`env="HOME=/home/root"`, `shared-control`}, "user@host", "", true},
|
||||
})
|
||||
}
|
||||
|
||||
func TestInvalidEntry(t *testing.T) {
|
||||
authInvalid := []byte(`ssh-rsa`)
|
||||
_, _, _, _, err := ParseAuthorizedKey(authInvalid)
|
||||
if err == nil {
|
||||
t.Errorf("got valid entry for %q", authInvalid)
|
||||
}
|
||||
}
|
||||
|
||||
var knownHostsParseTests = []struct {
|
||||
input string
|
||||
err string
|
||||
|
||||
marker string
|
||||
comment string
|
||||
hosts []string
|
||||
rest string
|
||||
}{
|
||||
{
|
||||
"",
|
||||
"EOF",
|
||||
|
||||
"", "", nil, "",
|
||||
},
|
||||
{
|
||||
"# Just a comment",
|
||||
"EOF",
|
||||
|
||||
"", "", nil, "",
|
||||
},
|
||||
{
|
||||
" \t ",
|
||||
"EOF",
|
||||
|
||||
"", "", nil, "",
|
||||
},
|
||||
{
|
||||
"localhost ssh-rsa {RSAPUB}",
|
||||
"",
|
||||
|
||||
"", "", []string{"localhost"}, "",
|
||||
},
|
||||
{
|
||||
"localhost\tssh-rsa {RSAPUB}",
|
||||
"",
|
||||
|
||||
"", "", []string{"localhost"}, "",
|
||||
},
|
||||
{
|
||||
"localhost\tssh-rsa {RSAPUB}\tcomment comment",
|
||||
"",
|
||||
|
||||
"", "comment comment", []string{"localhost"}, "",
|
||||
},
|
||||
{
|
||||
"localhost\tssh-rsa {RSAPUB}\tcomment comment\n",
|
||||
"",
|
||||
|
||||
"", "comment comment", []string{"localhost"}, "",
|
||||
},
|
||||
{
|
||||
"localhost\tssh-rsa {RSAPUB}\tcomment comment\r\n",
|
||||
"",
|
||||
|
||||
"", "comment comment", []string{"localhost"}, "",
|
||||
},
|
||||
{
|
||||
"localhost\tssh-rsa {RSAPUB}\tcomment comment\r\nnext line",
|
||||
"",
|
||||
|
||||
"", "comment comment", []string{"localhost"}, "next line",
|
||||
},
|
||||
{
|
||||
"localhost,[host2:123]\tssh-rsa {RSAPUB}\tcomment comment",
|
||||
"",
|
||||
|
||||
"", "comment comment", []string{"localhost", "[host2:123]"}, "",
|
||||
},
|
||||
{
|
||||
"@marker \tlocalhost,[host2:123]\tssh-rsa {RSAPUB}",
|
||||
"",
|
||||
|
||||
"marker", "", []string{"localhost", "[host2:123]"}, "",
|
||||
},
|
||||
{
|
||||
"@marker \tlocalhost,[host2:123]\tssh-rsa aabbccdd",
|
||||
"short read",
|
||||
|
||||
"", "", nil, "",
|
||||
},
|
||||
}
|
||||
|
||||
func TestKnownHostsParsing(t *testing.T) {
|
||||
rsaPub, rsaPubSerialized := getTestKey()
|
||||
|
||||
for i, test := range knownHostsParseTests {
|
||||
var expectedKey PublicKey
|
||||
const rsaKeyToken = "{RSAPUB}"
|
||||
|
||||
input := test.input
|
||||
if strings.Contains(input, rsaKeyToken) {
|
||||
expectedKey = rsaPub
|
||||
input = strings.Replace(test.input, rsaKeyToken, rsaPubSerialized, -1)
|
||||
}
|
||||
|
||||
marker, hosts, pubKey, comment, rest, err := ParseKnownHosts([]byte(input))
|
||||
if err != nil {
|
||||
if len(test.err) == 0 {
|
||||
t.Errorf("#%d: unexpectedly failed with %q", i, err)
|
||||
} else if !strings.Contains(err.Error(), test.err) {
|
||||
t.Errorf("#%d: expected error containing %q, but got %q", i, test.err, err)
|
||||
}
|
||||
continue
|
||||
} else if len(test.err) != 0 {
|
||||
t.Errorf("#%d: succeeded but expected error including %q", i, test.err)
|
||||
continue
|
||||
}
|
||||
|
||||
if !reflect.DeepEqual(expectedKey, pubKey) {
|
||||
t.Errorf("#%d: expected key %#v, but got %#v", i, expectedKey, pubKey)
|
||||
}
|
||||
|
||||
if marker != test.marker {
|
||||
t.Errorf("#%d: expected marker %q, but got %q", i, test.marker, marker)
|
||||
}
|
||||
|
||||
if comment != test.comment {
|
||||
t.Errorf("#%d: expected comment %q, but got %q", i, test.comment, comment)
|
||||
}
|
||||
|
||||
if !reflect.DeepEqual(test.hosts, hosts) {
|
||||
t.Errorf("#%d: expected hosts %#v, but got %#v", i, test.hosts, hosts)
|
||||
}
|
||||
|
||||
if rest := string(rest); rest != test.rest {
|
||||
t.Errorf("#%d: expected remaining input to be %q, but got %q", i, test.rest, rest)
|
||||
}
|
||||
}
|
||||
}
|
10
vendor/golang.org/x/crypto/ssh/mac.go
generated
vendored
10
vendor/golang.org/x/crypto/ssh/mac.go
generated
vendored
@ -15,6 +15,7 @@ import (
|
||||
|
||||
type macMode struct {
|
||||
keySize int
|
||||
etm bool
|
||||
new func(key []byte) hash.Hash
|
||||
}
|
||||
|
||||
@ -45,13 +46,16 @@ func (t truncatingMAC) Size() int {
|
||||
func (t truncatingMAC) BlockSize() int { return t.hmac.BlockSize() }
|
||||
|
||||
var macModes = map[string]*macMode{
|
||||
"hmac-sha2-256": {32, func(key []byte) hash.Hash {
|
||||
"hmac-sha2-256-etm@openssh.com": {32, true, func(key []byte) hash.Hash {
|
||||
return hmac.New(sha256.New, key)
|
||||
}},
|
||||
"hmac-sha1": {20, func(key []byte) hash.Hash {
|
||||
"hmac-sha2-256": {32, false, func(key []byte) hash.Hash {
|
||||
return hmac.New(sha256.New, key)
|
||||
}},
|
||||
"hmac-sha1": {20, false, func(key []byte) hash.Hash {
|
||||
return hmac.New(sha1.New, key)
|
||||
}},
|
||||
"hmac-sha1-96": {20, func(key []byte) hash.Hash {
|
||||
"hmac-sha1-96": {20, false, func(key []byte) hash.Hash {
|
||||
return truncatingMAC{12, hmac.New(sha1.New, key)}
|
||||
}},
|
||||
}
|
||||
|
110
vendor/golang.org/x/crypto/ssh/mempipe_test.go
generated
vendored
110
vendor/golang.org/x/crypto/ssh/mempipe_test.go
generated
vendored
@ -1,110 +0,0 @@
|
||||
// Copyright 2013 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package ssh
|
||||
|
||||
import (
|
||||
"io"
|
||||
"sync"
|
||||
"testing"
|
||||
)
|
||||
|
||||
// An in-memory packetConn. It is safe to call Close and writePacket
|
||||
// from different goroutines.
|
||||
type memTransport struct {
|
||||
eof bool
|
||||
pending [][]byte
|
||||
write *memTransport
|
||||
sync.Mutex
|
||||
*sync.Cond
|
||||
}
|
||||
|
||||
func (t *memTransport) readPacket() ([]byte, error) {
|
||||
t.Lock()
|
||||
defer t.Unlock()
|
||||
for {
|
||||
if len(t.pending) > 0 {
|
||||
r := t.pending[0]
|
||||
t.pending = t.pending[1:]
|
||||
return r, nil
|
||||
}
|
||||
if t.eof {
|
||||
return nil, io.EOF
|
||||
}
|
||||
t.Cond.Wait()
|
||||
}
|
||||
}
|
||||
|
||||
func (t *memTransport) closeSelf() error {
|
||||
t.Lock()
|
||||
defer t.Unlock()
|
||||
if t.eof {
|
||||
return io.EOF
|
||||
}
|
||||
t.eof = true
|
||||
t.Cond.Broadcast()
|
||||
return nil
|
||||
}
|
||||
|
||||
func (t *memTransport) Close() error {
|
||||
err := t.write.closeSelf()
|
||||
t.closeSelf()
|
||||
return err
|
||||
}
|
||||
|
||||
func (t *memTransport) writePacket(p []byte) error {
|
||||
t.write.Lock()
|
||||
defer t.write.Unlock()
|
||||
if t.write.eof {
|
||||
return io.EOF
|
||||
}
|
||||
c := make([]byte, len(p))
|
||||
copy(c, p)
|
||||
t.write.pending = append(t.write.pending, c)
|
||||
t.write.Cond.Signal()
|
||||
return nil
|
||||
}
|
||||
|
||||
func memPipe() (a, b packetConn) {
|
||||
t1 := memTransport{}
|
||||
t2 := memTransport{}
|
||||
t1.write = &t2
|
||||
t2.write = &t1
|
||||
t1.Cond = sync.NewCond(&t1.Mutex)
|
||||
t2.Cond = sync.NewCond(&t2.Mutex)
|
||||
return &t1, &t2
|
||||
}
|
||||
|
||||
func TestMemPipe(t *testing.T) {
|
||||
a, b := memPipe()
|
||||
if err := a.writePacket([]byte{42}); err != nil {
|
||||
t.Fatalf("writePacket: %v", err)
|
||||
}
|
||||
if err := a.Close(); err != nil {
|
||||
t.Fatal("Close: ", err)
|
||||
}
|
||||
p, err := b.readPacket()
|
||||
if err != nil {
|
||||
t.Fatal("readPacket: ", err)
|
||||
}
|
||||
if len(p) != 1 || p[0] != 42 {
|
||||
t.Fatalf("got %v, want {42}", p)
|
||||
}
|
||||
p, err = b.readPacket()
|
||||
if err != io.EOF {
|
||||
t.Fatalf("got %v, %v, want EOF", p, err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestDoubleClose(t *testing.T) {
|
||||
a, _ := memPipe()
|
||||
err := a.Close()
|
||||
if err != nil {
|
||||
t.Errorf("Close: %v", err)
|
||||
}
|
||||
err = a.Close()
|
||||
if err != io.EOF {
|
||||
t.Errorf("expect EOF on double close.")
|
||||
}
|
||||
}
|
288
vendor/golang.org/x/crypto/ssh/messages_test.go
generated
vendored
288
vendor/golang.org/x/crypto/ssh/messages_test.go
generated
vendored
@ -1,288 +0,0 @@
|
||||
// Copyright 2011 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package ssh
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"math/big"
|
||||
"math/rand"
|
||||
"reflect"
|
||||
"testing"
|
||||
"testing/quick"
|
||||
)
|
||||
|
||||
var intLengthTests = []struct {
|
||||
val, length int
|
||||
}{
|
||||
{0, 4 + 0},
|
||||
{1, 4 + 1},
|
||||
{127, 4 + 1},
|
||||
{128, 4 + 2},
|
||||
{-1, 4 + 1},
|
||||
}
|
||||
|
||||
func TestIntLength(t *testing.T) {
|
||||
for _, test := range intLengthTests {
|
||||
v := new(big.Int).SetInt64(int64(test.val))
|
||||
length := intLength(v)
|
||||
if length != test.length {
|
||||
t.Errorf("For %d, got length %d but expected %d", test.val, length, test.length)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
type msgAllTypes struct {
|
||||
Bool bool `sshtype:"21"`
|
||||
Array [16]byte
|
||||
Uint64 uint64
|
||||
Uint32 uint32
|
||||
Uint8 uint8
|
||||
String string
|
||||
Strings []string
|
||||
Bytes []byte
|
||||
Int *big.Int
|
||||
Rest []byte `ssh:"rest"`
|
||||
}
|
||||
|
||||
func (t *msgAllTypes) Generate(rand *rand.Rand, size int) reflect.Value {
|
||||
m := &msgAllTypes{}
|
||||
m.Bool = rand.Intn(2) == 1
|
||||
randomBytes(m.Array[:], rand)
|
||||
m.Uint64 = uint64(rand.Int63n(1<<63 - 1))
|
||||
m.Uint32 = uint32(rand.Intn((1 << 31) - 1))
|
||||
m.Uint8 = uint8(rand.Intn(1 << 8))
|
||||
m.String = string(m.Array[:])
|
||||
m.Strings = randomNameList(rand)
|
||||
m.Bytes = m.Array[:]
|
||||
m.Int = randomInt(rand)
|
||||
m.Rest = m.Array[:]
|
||||
return reflect.ValueOf(m)
|
||||
}
|
||||
|
||||
func TestMarshalUnmarshal(t *testing.T) {
|
||||
rand := rand.New(rand.NewSource(0))
|
||||
iface := &msgAllTypes{}
|
||||
ty := reflect.ValueOf(iface).Type()
|
||||
|
||||
n := 100
|
||||
if testing.Short() {
|
||||
n = 5
|
||||
}
|
||||
for j := 0; j < n; j++ {
|
||||
v, ok := quick.Value(ty, rand)
|
||||
if !ok {
|
||||
t.Errorf("failed to create value")
|
||||
break
|
||||
}
|
||||
|
||||
m1 := v.Elem().Interface()
|
||||
m2 := iface
|
||||
|
||||
marshaled := Marshal(m1)
|
||||
if err := Unmarshal(marshaled, m2); err != nil {
|
||||
t.Errorf("Unmarshal %#v: %s", m1, err)
|
||||
break
|
||||
}
|
||||
|
||||
if !reflect.DeepEqual(v.Interface(), m2) {
|
||||
t.Errorf("got: %#v\nwant:%#v\n%x", m2, m1, marshaled)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestUnmarshalEmptyPacket(t *testing.T) {
|
||||
var b []byte
|
||||
var m channelRequestSuccessMsg
|
||||
if err := Unmarshal(b, &m); err == nil {
|
||||
t.Fatalf("unmarshal of empty slice succeeded")
|
||||
}
|
||||
}
|
||||
|
||||
func TestUnmarshalUnexpectedPacket(t *testing.T) {
|
||||
type S struct {
|
||||
I uint32 `sshtype:"43"`
|
||||
S string
|
||||
B bool
|
||||
}
|
||||
|
||||
s := S{11, "hello", true}
|
||||
packet := Marshal(s)
|
||||
packet[0] = 42
|
||||
roundtrip := S{}
|
||||
err := Unmarshal(packet, &roundtrip)
|
||||
if err == nil {
|
||||
t.Fatal("expected error, not nil")
|
||||
}
|
||||
}
|
||||
|
||||
func TestMarshalPtr(t *testing.T) {
|
||||
s := struct {
|
||||
S string
|
||||
}{"hello"}
|
||||
|
||||
m1 := Marshal(s)
|
||||
m2 := Marshal(&s)
|
||||
if !bytes.Equal(m1, m2) {
|
||||
t.Errorf("got %q, want %q for marshaled pointer", m2, m1)
|
||||
}
|
||||
}
|
||||
|
||||
func TestBareMarshalUnmarshal(t *testing.T) {
|
||||
type S struct {
|
||||
I uint32
|
||||
S string
|
||||
B bool
|
||||
}
|
||||
|
||||
s := S{42, "hello", true}
|
||||
packet := Marshal(s)
|
||||
roundtrip := S{}
|
||||
Unmarshal(packet, &roundtrip)
|
||||
|
||||
if !reflect.DeepEqual(s, roundtrip) {
|
||||
t.Errorf("got %#v, want %#v", roundtrip, s)
|
||||
}
|
||||
}
|
||||
|
||||
func TestBareMarshal(t *testing.T) {
|
||||
type S2 struct {
|
||||
I uint32
|
||||
}
|
||||
s := S2{42}
|
||||
packet := Marshal(s)
|
||||
i, rest, ok := parseUint32(packet)
|
||||
if len(rest) > 0 || !ok {
|
||||
t.Errorf("parseInt(%q): parse error", packet)
|
||||
}
|
||||
if i != s.I {
|
||||
t.Errorf("got %d, want %d", i, s.I)
|
||||
}
|
||||
}
|
||||
|
||||
func TestUnmarshalShortKexInitPacket(t *testing.T) {
|
||||
// This used to panic.
|
||||
// Issue 11348
|
||||
packet := []byte{0x14, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0xff, 0xff, 0xff, 0xff}
|
||||
kim := &kexInitMsg{}
|
||||
if err := Unmarshal(packet, kim); err == nil {
|
||||
t.Error("truncated packet unmarshaled without error")
|
||||
}
|
||||
}
|
||||
|
||||
func TestMarshalMultiTag(t *testing.T) {
|
||||
var res struct {
|
||||
A uint32 `sshtype:"1|2"`
|
||||
}
|
||||
|
||||
good1 := struct {
|
||||
A uint32 `sshtype:"1"`
|
||||
}{
|
||||
1,
|
||||
}
|
||||
good2 := struct {
|
||||
A uint32 `sshtype:"2"`
|
||||
}{
|
||||
1,
|
||||
}
|
||||
|
||||
if e := Unmarshal(Marshal(good1), &res); e != nil {
|
||||
t.Errorf("error unmarshaling multipart tag: %v", e)
|
||||
}
|
||||
|
||||
if e := Unmarshal(Marshal(good2), &res); e != nil {
|
||||
t.Errorf("error unmarshaling multipart tag: %v", e)
|
||||
}
|
||||
|
||||
bad1 := struct {
|
||||
A uint32 `sshtype:"3"`
|
||||
}{
|
||||
1,
|
||||
}
|
||||
if e := Unmarshal(Marshal(bad1), &res); e == nil {
|
||||
t.Errorf("bad struct unmarshaled without error")
|
||||
}
|
||||
}
|
||||
|
||||
func randomBytes(out []byte, rand *rand.Rand) {
|
||||
for i := 0; i < len(out); i++ {
|
||||
out[i] = byte(rand.Int31())
|
||||
}
|
||||
}
|
||||
|
||||
func randomNameList(rand *rand.Rand) []string {
|
||||
ret := make([]string, rand.Int31()&15)
|
||||
for i := range ret {
|
||||
s := make([]byte, 1+(rand.Int31()&15))
|
||||
for j := range s {
|
||||
s[j] = 'a' + uint8(rand.Int31()&15)
|
||||
}
|
||||
ret[i] = string(s)
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
func randomInt(rand *rand.Rand) *big.Int {
|
||||
return new(big.Int).SetInt64(int64(int32(rand.Uint32())))
|
||||
}
|
||||
|
||||
func (*kexInitMsg) Generate(rand *rand.Rand, size int) reflect.Value {
|
||||
ki := &kexInitMsg{}
|
||||
randomBytes(ki.Cookie[:], rand)
|
||||
ki.KexAlgos = randomNameList(rand)
|
||||
ki.ServerHostKeyAlgos = randomNameList(rand)
|
||||
ki.CiphersClientServer = randomNameList(rand)
|
||||
ki.CiphersServerClient = randomNameList(rand)
|
||||
ki.MACsClientServer = randomNameList(rand)
|
||||
ki.MACsServerClient = randomNameList(rand)
|
||||
ki.CompressionClientServer = randomNameList(rand)
|
||||
ki.CompressionServerClient = randomNameList(rand)
|
||||
ki.LanguagesClientServer = randomNameList(rand)
|
||||
ki.LanguagesServerClient = randomNameList(rand)
|
||||
if rand.Int31()&1 == 1 {
|
||||
ki.FirstKexFollows = true
|
||||
}
|
||||
return reflect.ValueOf(ki)
|
||||
}
|
||||
|
||||
func (*kexDHInitMsg) Generate(rand *rand.Rand, size int) reflect.Value {
|
||||
dhi := &kexDHInitMsg{}
|
||||
dhi.X = randomInt(rand)
|
||||
return reflect.ValueOf(dhi)
|
||||
}
|
||||
|
||||
var (
|
||||
_kexInitMsg = new(kexInitMsg).Generate(rand.New(rand.NewSource(0)), 10).Elem().Interface()
|
||||
_kexDHInitMsg = new(kexDHInitMsg).Generate(rand.New(rand.NewSource(0)), 10).Elem().Interface()
|
||||
|
||||
_kexInit = Marshal(_kexInitMsg)
|
||||
_kexDHInit = Marshal(_kexDHInitMsg)
|
||||
)
|
||||
|
||||
func BenchmarkMarshalKexInitMsg(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
Marshal(_kexInitMsg)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkUnmarshalKexInitMsg(b *testing.B) {
|
||||
m := new(kexInitMsg)
|
||||
for i := 0; i < b.N; i++ {
|
||||
Unmarshal(_kexInit, m)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkMarshalKexDHInitMsg(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
Marshal(_kexDHInitMsg)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkUnmarshalKexDHInitMsg(b *testing.B) {
|
||||
m := new(kexDHInitMsg)
|
||||
for i := 0; i < b.N; i++ {
|
||||
Unmarshal(_kexDHInit, m)
|
||||
}
|
||||
}
|
4
vendor/golang.org/x/crypto/ssh/mux.go
generated
vendored
4
vendor/golang.org/x/crypto/ssh/mux.go
generated
vendored
@ -116,9 +116,9 @@ func (m *mux) Wait() error {
|
||||
func newMux(p packetConn) *mux {
|
||||
m := &mux{
|
||||
conn: p,
|
||||
incomingChannels: make(chan NewChannel, 16),
|
||||
incomingChannels: make(chan NewChannel, chanSize),
|
||||
globalResponses: make(chan interface{}, 1),
|
||||
incomingRequests: make(chan *Request, 16),
|
||||
incomingRequests: make(chan *Request, chanSize),
|
||||
errCond: newCond(),
|
||||
}
|
||||
if debugMux {
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user