mirror of
https://github.com/octoleo/restic.git
synced 2024-12-24 11:55:28 +00:00
Merge pull request #458 from restic/use-gb-vendor
Properly vendor dependencies with gb-vendor
This commit is contained in:
commit
933479047f
82
vendor/manifest
vendored
Normal file
82
vendor/manifest
vendored
Normal file
@ -0,0 +1,82 @@
|
||||
{
|
||||
"version": 0,
|
||||
"dependencies": [
|
||||
{
|
||||
"importpath": "bazil.org/fuse",
|
||||
"repository": "https://github.com/bazil/fuse",
|
||||
"revision": "18419ee53958df28fcfc9490fe6123bd59e237bb",
|
||||
"branch": "HEAD"
|
||||
},
|
||||
{
|
||||
"importpath": "github.com/jessevdk/go-flags",
|
||||
"repository": "https://github.com/jessevdk/go-flags",
|
||||
"revision": "1b89bf73cd2c3a911d7b2a279ab085c4a18cf539",
|
||||
"branch": "HEAD"
|
||||
},
|
||||
{
|
||||
"importpath": "github.com/juju/errors",
|
||||
"repository": "https://github.com/juju/errors",
|
||||
"revision": "4567a5e69fd3130ca0d89f69478e7ac025b67452",
|
||||
"branch": "HEAD"
|
||||
},
|
||||
{
|
||||
"importpath": "github.com/kr/fs",
|
||||
"repository": "https://github.com/kr/fs",
|
||||
"revision": "2788f0dbd16903de03cb8186e5c7d97b69ad387b",
|
||||
"branch": "HEAD"
|
||||
},
|
||||
{
|
||||
"importpath": "github.com/minio/minio-go",
|
||||
"repository": "https://github.com/minio/minio-go",
|
||||
"revision": "a4cd3caabd5f9c35ac100110eb60c2b80798f1af",
|
||||
"branch": "HEAD"
|
||||
},
|
||||
{
|
||||
"importpath": "github.com/pkg/sftp",
|
||||
"repository": "https://github.com/pkg/sftp",
|
||||
"revision": "e84cc8c755ca39b7b64f510fe1fffc1b51f210a5",
|
||||
"branch": "HEAD"
|
||||
},
|
||||
{
|
||||
"importpath": "github.com/restic/chunker",
|
||||
"repository": "https://github.com/restic/chunker",
|
||||
"revision": "fc45043175c38d59374024a38fb7123c40a64f20",
|
||||
"branch": "HEAD"
|
||||
},
|
||||
{
|
||||
"importpath": "golang.org/x/crypto/pbkdf2",
|
||||
"repository": "https://go.googlesource.com/crypto",
|
||||
"revision": "cc04154d65fb9296747569b107cfd05380b1ea3e",
|
||||
"branch": "HEAD",
|
||||
"path": "/pbkdf2"
|
||||
},
|
||||
{
|
||||
"importpath": "golang.org/x/crypto/poly1305",
|
||||
"repository": "https://go.googlesource.com/crypto",
|
||||
"revision": "cc04154d65fb9296747569b107cfd05380b1ea3e",
|
||||
"branch": "HEAD",
|
||||
"path": "/poly1305"
|
||||
},
|
||||
{
|
||||
"importpath": "golang.org/x/crypto/scrypt",
|
||||
"repository": "https://go.googlesource.com/crypto",
|
||||
"revision": "cc04154d65fb9296747569b107cfd05380b1ea3e",
|
||||
"branch": "HEAD",
|
||||
"path": "/scrypt"
|
||||
},
|
||||
{
|
||||
"importpath": "golang.org/x/crypto/ssh",
|
||||
"repository": "https://go.googlesource.com/crypto",
|
||||
"revision": "cc04154d65fb9296747569b107cfd05380b1ea3e",
|
||||
"branch": "HEAD",
|
||||
"path": "/ssh"
|
||||
},
|
||||
{
|
||||
"importpath": "golang.org/x/net/context",
|
||||
"repository": "https://go.googlesource.com/net",
|
||||
"revision": "7654728e381988afd88e58cabfd6363a5ea91810",
|
||||
"branch": "HEAD",
|
||||
"path": "/context"
|
||||
}
|
||||
]
|
||||
}
|
2
vendor/src/bazil.org/fuse/.gitattributes
vendored
2
vendor/src/bazil.org/fuse/.gitattributes
vendored
@ -1,2 +0,0 @@
|
||||
*.go filter=gofmt
|
||||
*.cgo filter=gofmt
|
11
vendor/src/bazil.org/fuse/.gitignore
vendored
11
vendor/src/bazil.org/fuse/.gitignore
vendored
@ -1,11 +0,0 @@
|
||||
*~
|
||||
.#*
|
||||
## the next line needs to start with a backslash to avoid looking like
|
||||
## a comment
|
||||
\#*#
|
||||
.*.swp
|
||||
|
||||
*.test
|
||||
|
||||
/clockfs
|
||||
/hellofs
|
4
vendor/src/bazil.org/fuse/doc/.gitignore
vendored
4
vendor/src/bazil.org/fuse/doc/.gitignore
vendored
@ -1,4 +0,0 @@
|
||||
/*.seq.svg
|
||||
|
||||
# not ignoring *.seq.png; we want those committed to the repo
|
||||
# for embedding on Github
|
@ -1 +1 @@
|
||||
package fstestutil
|
||||
package fstestutil // import "bazil.org/fuse/fs/fstestutil"
|
||||
|
@ -1,4 +1,4 @@
|
||||
package record
|
||||
package record // import "bazil.org/fuse/fs/fstestutil/record"
|
||||
|
||||
import (
|
||||
"sync"
|
||||
|
2
vendor/src/bazil.org/fuse/fs/serve.go
vendored
2
vendor/src/bazil.org/fuse/fs/serve.go
vendored
@ -1,6 +1,6 @@
|
||||
// FUSE service loop, for servers that wish to use it.
|
||||
|
||||
package fs
|
||||
package fs // import "bazil.org/fuse/fs"
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
|
2
vendor/src/bazil.org/fuse/fuse.go
vendored
2
vendor/src/bazil.org/fuse/fuse.go
vendored
@ -98,7 +98,7 @@
|
||||
// Behavior and metadata of the mounted file system can be changed by
|
||||
// passing MountOption values to Mount.
|
||||
//
|
||||
package fuse
|
||||
package fuse // import "bazil.org/fuse"
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
|
@ -1,4 +1,4 @@
|
||||
package fuseutil
|
||||
package fuseutil // import "bazil.org/fuse/fuseutil"
|
||||
|
||||
import (
|
||||
"bazil.org/fuse"
|
||||
|
2
vendor/src/bazil.org/fuse/syscallx/doc.go
vendored
2
vendor/src/bazil.org/fuse/syscallx/doc.go
vendored
@ -10,4 +10,4 @@
|
||||
//
|
||||
// Options can be implemented with separate wrappers, in the style of
|
||||
// Linux getxattr/lgetxattr/fgetxattr.
|
||||
package syscallx
|
||||
package syscallx // import "bazil.org/fuse/syscallx"
|
||||
|
@ -1,35 +0,0 @@
|
||||
language: go
|
||||
|
||||
install:
|
||||
# go-flags
|
||||
- go get -d -v ./...
|
||||
- go build -v ./...
|
||||
|
||||
# linting
|
||||
- go get golang.org/x/tools/cmd/vet
|
||||
- go get github.com/golang/lint
|
||||
- go install github.com/golang/lint/golint
|
||||
|
||||
# code coverage
|
||||
- go get golang.org/x/tools/cmd/cover
|
||||
- go get github.com/onsi/ginkgo/ginkgo
|
||||
- go get github.com/modocache/gover
|
||||
- if [ "$TRAVIS_SECURE_ENV_VARS" = "true" ]; then go get github.com/mattn/goveralls; fi
|
||||
|
||||
script:
|
||||
# go-flags
|
||||
- $(exit $(gofmt -l . | wc -l))
|
||||
- go test -v ./...
|
||||
|
||||
# linting
|
||||
- go tool vet -all=true -v=true . || true
|
||||
- $(go env GOPATH | awk 'BEGIN{FS=":"} {print $1}')/bin/golint ./...
|
||||
|
||||
# code coverage
|
||||
- $(go env GOPATH | awk 'BEGIN{FS=":"} {print $1}')/bin/ginkgo -r -cover
|
||||
- $(go env GOPATH | awk 'BEGIN{FS=":"} {print $1}')/bin/gover
|
||||
- if [ "$TRAVIS_SECURE_ENV_VARS" = "true" ]; then $(go env GOPATH | awk 'BEGIN{FS=":"} {print $1}')/bin/goveralls -coverprofile=gover.coverprofile -service=travis-ci -repotoken $COVERALLS_TOKEN; fi
|
||||
|
||||
env:
|
||||
# coveralls.io
|
||||
secure: "RCYbiB4P0RjQRIoUx/vG/AjP3mmYCbzOmr86DCww1Z88yNcy3hYr3Cq8rpPtYU5v0g7wTpu4adaKIcqRE9xknYGbqj3YWZiCoBP1/n4Z+9sHW3Dsd9D/GRGeHUus0laJUGARjWoCTvoEtOgTdGQDoX7mH+pUUY0FBltNYUdOiiU="
|
23
vendor/src/github.com/juju/errors/.gitignore
vendored
23
vendor/src/github.com/juju/errors/.gitignore
vendored
@ -1,23 +0,0 @@
|
||||
# Compiled Object files, Static and Dynamic libs (Shared Objects)
|
||||
*.o
|
||||
*.a
|
||||
*.so
|
||||
|
||||
# Folders
|
||||
_obj
|
||||
_test
|
||||
|
||||
# Architecture specific extensions/prefixes
|
||||
*.[568vq]
|
||||
[568vq].out
|
||||
|
||||
*.cgo1.go
|
||||
*.cgo2.c
|
||||
_cgo_defun.c
|
||||
_cgo_gotypes.go
|
||||
_cgo_export.*
|
||||
|
||||
_testmain.go
|
||||
|
||||
*.exe
|
||||
*.test
|
@ -1,2 +0,0 @@
|
||||
*~
|
||||
*.test
|
23
vendor/src/github.com/minio/minio-go/.travis.yml
vendored
23
vendor/src/github.com/minio/minio-go/.travis.yml
vendored
@ -1,23 +0,0 @@
|
||||
sudo: false
|
||||
language: go
|
||||
|
||||
os:
|
||||
- linux
|
||||
- osx
|
||||
|
||||
env:
|
||||
- ARCH=x86_64
|
||||
- ARCH=i686
|
||||
|
||||
go:
|
||||
- 1.5.2
|
||||
- 1.5.3
|
||||
|
||||
script:
|
||||
- diff -au <(gofmt -d .) <(printf "")
|
||||
- go vet ./...
|
||||
- go test -short -race -v ./...
|
||||
|
||||
notifications:
|
||||
slack:
|
||||
secure: HrOX2k6F/sEl6Rr4m5vHOdJCIwV42be0kz1Jy/WSMvrl/fQ8YkldKviLeWh4aWt1kclsYhNQ4FqGML+RIZYsdOqej4fAw9Vi5pZkI1MzPJq0UjrtMqkqzvD90eDGQYCKwaXjEIN8cohwJeb6X0B0HKAd9sqJW5GH5SwnhH5WWP8=
|
1043
vendor/src/github.com/minio/minio-go/api_functional_v2_test.go
vendored
Normal file
1043
vendor/src/github.com/minio/minio-go/api_functional_v2_test.go
vendored
Normal file
File diff suppressed because it is too large
Load Diff
1072
vendor/src/github.com/minio/minio-go/api_functional_v4_test.go
vendored
Normal file
1072
vendor/src/github.com/minio/minio-go/api_functional_v4_test.go
vendored
Normal file
File diff suppressed because it is too large
Load Diff
583
vendor/src/github.com/minio/minio-go/api_unit_test.go
vendored
Normal file
583
vendor/src/github.com/minio/minio-go/api_unit_test.go
vendored
Normal file
@ -0,0 +1,583 @@
|
||||
/*
|
||||
* Minio Go Library for Amazon S3 Compatible Cloud Storage (C) 2015 Minio, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package minio
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"os"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
type customReader struct{}
|
||||
|
||||
func (c *customReader) Read(p []byte) (n int, err error) {
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
func (c *customReader) Size() (n int64) {
|
||||
return 10
|
||||
}
|
||||
|
||||
// Tests getReaderSize() for various Reader types.
|
||||
func TestGetReaderSize(t *testing.T) {
|
||||
var reader io.Reader
|
||||
size, err := getReaderSize(reader)
|
||||
if err != nil {
|
||||
t.Fatal("Error:", err)
|
||||
}
|
||||
if size != -1 {
|
||||
t.Fatal("Reader shouldn't have any length.")
|
||||
}
|
||||
|
||||
bytesReader := bytes.NewReader([]byte("Hello World"))
|
||||
size, err = getReaderSize(bytesReader)
|
||||
if err != nil {
|
||||
t.Fatal("Error:", err)
|
||||
}
|
||||
if size != int64(len("Hello World")) {
|
||||
t.Fatalf("Reader length doesn't match got: %v, want: %v", size, len("Hello World"))
|
||||
}
|
||||
|
||||
size, err = getReaderSize(new(customReader))
|
||||
if err != nil {
|
||||
t.Fatal("Error:", err)
|
||||
}
|
||||
if size != int64(10) {
|
||||
t.Fatalf("Reader length doesn't match got: %v, want: %v", size, 10)
|
||||
}
|
||||
|
||||
stringsReader := strings.NewReader("Hello World")
|
||||
size, err = getReaderSize(stringsReader)
|
||||
if err != nil {
|
||||
t.Fatal("Error:", err)
|
||||
}
|
||||
if size != int64(len("Hello World")) {
|
||||
t.Fatalf("Reader length doesn't match got: %v, want: %v", size, len("Hello World"))
|
||||
}
|
||||
|
||||
// Create request channel.
|
||||
reqCh := make(chan readRequest)
|
||||
// Create response channel.
|
||||
resCh := make(chan readResponse)
|
||||
// Create done channel.
|
||||
doneCh := make(chan struct{})
|
||||
// objectInfo.
|
||||
objectInfo := ObjectInfo{Size: 10}
|
||||
objectReader := newObject(reqCh, resCh, doneCh, objectInfo)
|
||||
defer objectReader.Close()
|
||||
|
||||
size, err = getReaderSize(objectReader)
|
||||
if err != nil {
|
||||
t.Fatal("Error:", err)
|
||||
}
|
||||
if size != int64(10) {
|
||||
t.Fatalf("Reader length doesn't match got: %v, want: %v", size, 10)
|
||||
}
|
||||
|
||||
fileReader, err := ioutil.TempFile(os.TempDir(), "prefix")
|
||||
if err != nil {
|
||||
t.Fatal("Error:", err)
|
||||
}
|
||||
defer fileReader.Close()
|
||||
defer os.RemoveAll(fileReader.Name())
|
||||
|
||||
size, err = getReaderSize(fileReader)
|
||||
if err != nil {
|
||||
t.Fatal("Error:", err)
|
||||
}
|
||||
if size == -1 {
|
||||
t.Fatal("Reader length for file cannot be -1.")
|
||||
}
|
||||
|
||||
// Verify for standard input, output and error file descriptors.
|
||||
size, err = getReaderSize(os.Stdin)
|
||||
if err != nil {
|
||||
t.Fatal("Error:", err)
|
||||
}
|
||||
if size != -1 {
|
||||
t.Fatal("Stdin should have length of -1.")
|
||||
}
|
||||
size, err = getReaderSize(os.Stdout)
|
||||
if err != nil {
|
||||
t.Fatal("Error:", err)
|
||||
}
|
||||
if size != -1 {
|
||||
t.Fatal("Stdout should have length of -1.")
|
||||
}
|
||||
size, err = getReaderSize(os.Stderr)
|
||||
if err != nil {
|
||||
t.Fatal("Error:", err)
|
||||
}
|
||||
if size != -1 {
|
||||
t.Fatal("Stderr should have length of -1.")
|
||||
}
|
||||
file, err := os.Open(os.TempDir())
|
||||
if err != nil {
|
||||
t.Fatal("Error:", err)
|
||||
}
|
||||
defer file.Close()
|
||||
_, err = getReaderSize(file)
|
||||
if err == nil {
|
||||
t.Fatal("Input file as directory should throw an error.")
|
||||
}
|
||||
}
|
||||
|
||||
// Tests valid hosts for location.
|
||||
func TestValidBucketLocation(t *testing.T) {
|
||||
s3Hosts := []struct {
|
||||
bucketLocation string
|
||||
endpoint string
|
||||
}{
|
||||
{"us-east-1", "s3.amazonaws.com"},
|
||||
{"unknown", "s3.amazonaws.com"},
|
||||
{"ap-southeast-1", "s3-ap-southeast-1.amazonaws.com"},
|
||||
}
|
||||
for _, s3Host := range s3Hosts {
|
||||
endpoint := getS3Endpoint(s3Host.bucketLocation)
|
||||
if endpoint != s3Host.endpoint {
|
||||
t.Fatal("Error: invalid bucket location", endpoint)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Tests valid bucket names.
|
||||
func TestBucketNames(t *testing.T) {
|
||||
buckets := []struct {
|
||||
name string
|
||||
valid error
|
||||
}{
|
||||
{".mybucket", ErrInvalidBucketName("Bucket name cannot start or end with a '.' dot.")},
|
||||
{"mybucket.", ErrInvalidBucketName("Bucket name cannot start or end with a '.' dot.")},
|
||||
{"mybucket-", ErrInvalidBucketName("Bucket name contains invalid characters.")},
|
||||
{"my", ErrInvalidBucketName("Bucket name cannot be smaller than 3 characters.")},
|
||||
{"", ErrInvalidBucketName("Bucket name cannot be empty.")},
|
||||
{"my..bucket", ErrInvalidBucketName("Bucket name cannot have successive periods.")},
|
||||
{"my.bucket.com", nil},
|
||||
{"my-bucket", nil},
|
||||
{"123my-bucket", nil},
|
||||
}
|
||||
|
||||
for _, b := range buckets {
|
||||
err := isValidBucketName(b.name)
|
||||
if err != b.valid {
|
||||
t.Fatal("Error:", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Tests temp file.
|
||||
func TestTempFile(t *testing.T) {
|
||||
tmpFile, err := newTempFile("testing")
|
||||
if err != nil {
|
||||
t.Fatal("Error:", err)
|
||||
}
|
||||
fileName := tmpFile.Name()
|
||||
// Closing temporary file purges the file.
|
||||
err = tmpFile.Close()
|
||||
if err != nil {
|
||||
t.Fatal("Error:", err)
|
||||
}
|
||||
st, err := os.Stat(fileName)
|
||||
if err != nil && !os.IsNotExist(err) {
|
||||
t.Fatal("Error:", err)
|
||||
}
|
||||
if err == nil && st != nil {
|
||||
t.Fatal("Error: file should be deleted and should not exist.")
|
||||
}
|
||||
}
|
||||
|
||||
// Tests url encoding.
|
||||
func TestEncodeURL2Path(t *testing.T) {
|
||||
type urlStrings struct {
|
||||
objName string
|
||||
encodedObjName string
|
||||
}
|
||||
|
||||
bucketName := "bucketName"
|
||||
want := []urlStrings{
|
||||
{
|
||||
objName: "本語",
|
||||
encodedObjName: "%E6%9C%AC%E8%AA%9E",
|
||||
},
|
||||
{
|
||||
objName: "本語.1",
|
||||
encodedObjName: "%E6%9C%AC%E8%AA%9E.1",
|
||||
},
|
||||
{
|
||||
objName: ">123>3123123",
|
||||
encodedObjName: "%3E123%3E3123123",
|
||||
},
|
||||
{
|
||||
objName: "test 1 2.txt",
|
||||
encodedObjName: "test%201%202.txt",
|
||||
},
|
||||
{
|
||||
objName: "test++ 1.txt",
|
||||
encodedObjName: "test%2B%2B%201.txt",
|
||||
},
|
||||
}
|
||||
|
||||
for _, o := range want {
|
||||
u, err := url.Parse(fmt.Sprintf("https://%s.s3.amazonaws.com/%s", bucketName, o.objName))
|
||||
if err != nil {
|
||||
t.Fatal("Error:", err)
|
||||
}
|
||||
urlPath := "/" + bucketName + "/" + o.encodedObjName
|
||||
if urlPath != encodeURL2Path(u) {
|
||||
t.Fatal("Error")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Tests error response structure.
|
||||
func TestErrorResponse(t *testing.T) {
|
||||
var err error
|
||||
err = ErrorResponse{
|
||||
Code: "Testing",
|
||||
}
|
||||
errResp := ToErrorResponse(err)
|
||||
if errResp.Code != "Testing" {
|
||||
t.Fatal("Type conversion failed, we have an empty struct.")
|
||||
}
|
||||
|
||||
// Test http response decoding.
|
||||
var httpResponse *http.Response
|
||||
// Set empty variables
|
||||
httpResponse = nil
|
||||
var bucketName, objectName string
|
||||
|
||||
// Should fail with invalid argument.
|
||||
err = httpRespToErrorResponse(httpResponse, bucketName, objectName)
|
||||
errResp = ToErrorResponse(err)
|
||||
if errResp.Code != "InvalidArgument" {
|
||||
t.Fatal("Empty response input should return invalid argument.")
|
||||
}
|
||||
}
|
||||
|
||||
// Tests signature calculation.
|
||||
func TestSignatureCalculation(t *testing.T) {
|
||||
req, err := http.NewRequest("GET", "https://s3.amazonaws.com", nil)
|
||||
if err != nil {
|
||||
t.Fatal("Error:", err)
|
||||
}
|
||||
req = signV4(*req, "", "", "us-east-1")
|
||||
if req.Header.Get("Authorization") != "" {
|
||||
t.Fatal("Error: anonymous credentials should not have Authorization header.")
|
||||
}
|
||||
|
||||
req = preSignV4(*req, "", "", "us-east-1", 0)
|
||||
if strings.Contains(req.URL.RawQuery, "X-Amz-Signature") {
|
||||
t.Fatal("Error: anonymous credentials should not have Signature query resource.")
|
||||
}
|
||||
|
||||
req = signV2(*req, "", "")
|
||||
if req.Header.Get("Authorization") != "" {
|
||||
t.Fatal("Error: anonymous credentials should not have Authorization header.")
|
||||
}
|
||||
|
||||
req = preSignV2(*req, "", "", 0)
|
||||
if strings.Contains(req.URL.RawQuery, "Signature") {
|
||||
t.Fatal("Error: anonymous credentials should not have Signature query resource.")
|
||||
}
|
||||
|
||||
req = signV4(*req, "ACCESS-KEY", "SECRET-KEY", "us-east-1")
|
||||
if req.Header.Get("Authorization") == "" {
|
||||
t.Fatal("Error: normal credentials should have Authorization header.")
|
||||
}
|
||||
|
||||
req = preSignV4(*req, "ACCESS-KEY", "SECRET-KEY", "us-east-1", 0)
|
||||
if !strings.Contains(req.URL.RawQuery, "X-Amz-Signature") {
|
||||
t.Fatal("Error: normal credentials should have Signature query resource.")
|
||||
}
|
||||
|
||||
req = signV2(*req, "ACCESS-KEY", "SECRET-KEY")
|
||||
if req.Header.Get("Authorization") == "" {
|
||||
t.Fatal("Error: normal credentials should have Authorization header.")
|
||||
}
|
||||
|
||||
req = preSignV2(*req, "ACCESS-KEY", "SECRET-KEY", 0)
|
||||
if !strings.Contains(req.URL.RawQuery, "Signature") {
|
||||
t.Fatal("Error: normal credentials should not have Signature query resource.")
|
||||
}
|
||||
}
|
||||
|
||||
// Tests signature type.
|
||||
func TestSignatureType(t *testing.T) {
|
||||
clnt := Client{}
|
||||
if !clnt.signature.isV4() {
|
||||
t.Fatal("Error")
|
||||
}
|
||||
clnt.signature = SignatureV2
|
||||
if !clnt.signature.isV2() {
|
||||
t.Fatal("Error")
|
||||
}
|
||||
if clnt.signature.isV4() {
|
||||
t.Fatal("Error")
|
||||
}
|
||||
clnt.signature = SignatureV4
|
||||
if !clnt.signature.isV4() {
|
||||
t.Fatal("Error")
|
||||
}
|
||||
}
|
||||
|
||||
// Tests bucket acl types.
|
||||
func TestBucketACLTypes(t *testing.T) {
|
||||
want := map[string]bool{
|
||||
"private": true,
|
||||
"public-read": true,
|
||||
"public-read-write": true,
|
||||
"authenticated-read": true,
|
||||
"invalid": false,
|
||||
}
|
||||
for acl, ok := range want {
|
||||
if BucketACL(acl).isValidBucketACL() != ok {
|
||||
t.Fatal("Error")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Tests optimal part size.
|
||||
func TestPartSize(t *testing.T) {
|
||||
totalPartsCount, partSize, lastPartSize, err := optimalPartInfo(5000000000000000000)
|
||||
if err == nil {
|
||||
t.Fatal("Error: should fail")
|
||||
}
|
||||
totalPartsCount, partSize, lastPartSize, err = optimalPartInfo(5497558138880)
|
||||
if err != nil {
|
||||
t.Fatal("Error: ", err)
|
||||
}
|
||||
if totalPartsCount != 9987 {
|
||||
t.Fatalf("Error: expecting total parts count of 9987: got %v instead", totalPartsCount)
|
||||
}
|
||||
if partSize != 550502400 {
|
||||
t.Fatalf("Error: expecting part size of 550502400: got %v instead", partSize)
|
||||
}
|
||||
if lastPartSize != 241172480 {
|
||||
t.Fatalf("Error: expecting last part size of 241172480: got %v instead", lastPartSize)
|
||||
}
|
||||
totalPartsCount, partSize, lastPartSize, err = optimalPartInfo(5000000000)
|
||||
if err != nil {
|
||||
t.Fatal("Error:", err)
|
||||
}
|
||||
if partSize != minPartSize {
|
||||
t.Fatalf("Error: expecting part size of %v: got %v instead", minPartSize, partSize)
|
||||
}
|
||||
totalPartsCount, partSize, lastPartSize, err = optimalPartInfo(-1)
|
||||
if err != nil {
|
||||
t.Fatal("Error:", err)
|
||||
}
|
||||
if totalPartsCount != 9987 {
|
||||
t.Fatalf("Error: expecting total parts count of 9987: got %v instead", totalPartsCount)
|
||||
}
|
||||
if partSize != 550502400 {
|
||||
t.Fatalf("Error: expecting part size of 550502400: got %v instead", partSize)
|
||||
}
|
||||
if lastPartSize != 241172480 {
|
||||
t.Fatalf("Error: expecting last part size of 241172480: got %v instead", lastPartSize)
|
||||
}
|
||||
}
|
||||
|
||||
// Tests url encoding.
|
||||
func TestURLEncoding(t *testing.T) {
|
||||
type urlStrings struct {
|
||||
name string
|
||||
encodedName string
|
||||
}
|
||||
|
||||
want := []urlStrings{
|
||||
{
|
||||
name: "bigfile-1._%",
|
||||
encodedName: "bigfile-1._%25",
|
||||
},
|
||||
{
|
||||
name: "本語",
|
||||
encodedName: "%E6%9C%AC%E8%AA%9E",
|
||||
},
|
||||
{
|
||||
name: "本語.1",
|
||||
encodedName: "%E6%9C%AC%E8%AA%9E.1",
|
||||
},
|
||||
{
|
||||
name: ">123>3123123",
|
||||
encodedName: "%3E123%3E3123123",
|
||||
},
|
||||
{
|
||||
name: "test 1 2.txt",
|
||||
encodedName: "test%201%202.txt",
|
||||
},
|
||||
{
|
||||
name: "test++ 1.txt",
|
||||
encodedName: "test%2B%2B%201.txt",
|
||||
},
|
||||
}
|
||||
|
||||
for _, u := range want {
|
||||
if u.encodedName != urlEncodePath(u.name) {
|
||||
t.Fatal("Error")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Tests constructing valid endpoint url.
|
||||
func TestGetEndpointURL(t *testing.T) {
|
||||
if _, err := getEndpointURL("s3.amazonaws.com", false); err != nil {
|
||||
t.Fatal("Error:", err)
|
||||
}
|
||||
if _, err := getEndpointURL("192.168.1.1", false); err != nil {
|
||||
t.Fatal("Error:", err)
|
||||
}
|
||||
if _, err := getEndpointURL("13333.123123.-", false); err == nil {
|
||||
t.Fatal("Error")
|
||||
}
|
||||
if _, err := getEndpointURL("s3.aamzza.-", false); err == nil {
|
||||
t.Fatal("Error")
|
||||
}
|
||||
if _, err := getEndpointURL("s3.amazonaws.com:443", false); err == nil {
|
||||
t.Fatal("Error")
|
||||
}
|
||||
}
|
||||
|
||||
// Tests valid ip address.
|
||||
func TestValidIPAddr(t *testing.T) {
|
||||
type validIP struct {
|
||||
ip string
|
||||
valid bool
|
||||
}
|
||||
|
||||
want := []validIP{
|
||||
{
|
||||
ip: "192.168.1.1",
|
||||
valid: true,
|
||||
},
|
||||
{
|
||||
ip: "192.1.8",
|
||||
valid: false,
|
||||
},
|
||||
{
|
||||
ip: "..192.",
|
||||
valid: false,
|
||||
},
|
||||
{
|
||||
ip: "192.168.1.1.1",
|
||||
valid: false,
|
||||
},
|
||||
}
|
||||
for _, w := range want {
|
||||
valid := isValidIP(w.ip)
|
||||
if valid != w.valid {
|
||||
t.Fatal("Error")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Tests valid endpoint domain.
|
||||
func TestValidEndpointDomain(t *testing.T) {
|
||||
type validEndpoint struct {
|
||||
endpointDomain string
|
||||
valid bool
|
||||
}
|
||||
|
||||
want := []validEndpoint{
|
||||
{
|
||||
endpointDomain: "s3.amazonaws.com",
|
||||
valid: true,
|
||||
},
|
||||
{
|
||||
endpointDomain: "s3.amazonaws.com_",
|
||||
valid: false,
|
||||
},
|
||||
{
|
||||
endpointDomain: "%$$$",
|
||||
valid: false,
|
||||
},
|
||||
{
|
||||
endpointDomain: "s3.amz.test.com",
|
||||
valid: true,
|
||||
},
|
||||
{
|
||||
endpointDomain: "s3.%%",
|
||||
valid: false,
|
||||
},
|
||||
{
|
||||
endpointDomain: "localhost",
|
||||
valid: true,
|
||||
},
|
||||
{
|
||||
endpointDomain: "-localhost",
|
||||
valid: false,
|
||||
},
|
||||
{
|
||||
endpointDomain: "",
|
||||
valid: false,
|
||||
},
|
||||
{
|
||||
endpointDomain: "\n \t",
|
||||
valid: false,
|
||||
},
|
||||
{
|
||||
endpointDomain: " ",
|
||||
valid: false,
|
||||
},
|
||||
}
|
||||
for _, w := range want {
|
||||
valid := isValidDomain(w.endpointDomain)
|
||||
if valid != w.valid {
|
||||
t.Fatal("Error:", w.endpointDomain)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Tests valid endpoint url.
|
||||
func TestValidEndpointURL(t *testing.T) {
|
||||
type validURL struct {
|
||||
url string
|
||||
valid bool
|
||||
}
|
||||
want := []validURL{
|
||||
{
|
||||
url: "https://s3.amazonaws.com",
|
||||
valid: true,
|
||||
},
|
||||
{
|
||||
url: "https://s3.amazonaws.com/bucket/object",
|
||||
valid: false,
|
||||
},
|
||||
{
|
||||
url: "192.168.1.1",
|
||||
valid: false,
|
||||
},
|
||||
}
|
||||
for _, w := range want {
|
||||
u, err := url.Parse(w.url)
|
||||
if err != nil {
|
||||
t.Fatal("Error:", err)
|
||||
}
|
||||
valid := false
|
||||
if err := isValidEndpointURL(u); err == nil {
|
||||
valid = true
|
||||
}
|
||||
if valid != w.valid {
|
||||
t.Fatal("Error")
|
||||
}
|
||||
}
|
||||
}
|
8
vendor/src/github.com/pkg/sftp/.gitignore
vendored
8
vendor/src/github.com/pkg/sftp/.gitignore
vendored
@ -1,8 +0,0 @@
|
||||
.*.swo
|
||||
.*.swp
|
||||
|
||||
server_standalone/server_standalone
|
||||
|
||||
examples/sftp-server/id_rsa
|
||||
examples/sftp-server/id_rsa.pub
|
||||
examples/sftp-server/sftp-server
|
21
vendor/src/github.com/pkg/sftp/.travis.yml
vendored
21
vendor/src/github.com/pkg/sftp/.travis.yml
vendored
@ -1,21 +0,0 @@
|
||||
language: go
|
||||
go_import_path: github.com/pkg/sftp
|
||||
go:
|
||||
- 1.5.2
|
||||
- 1.4.3
|
||||
- tip
|
||||
|
||||
sudo: false
|
||||
|
||||
addons:
|
||||
ssh_known_hosts:
|
||||
- bitbucket.org
|
||||
|
||||
install:
|
||||
- go get -t -v ./...
|
||||
- ssh-keygen -t rsa -q -P "" -f /home/travis/.ssh/id_rsa
|
||||
|
||||
script:
|
||||
- go test -integration -v ./...
|
||||
- go test -testserver -v ./...
|
||||
- go test -integration -testserver -v ./...
|
45
vendor/src/github.com/pkg/sftp/attrs_test.go
vendored
Normal file
45
vendor/src/github.com/pkg/sftp/attrs_test.go
vendored
Normal file
@ -0,0 +1,45 @@
|
||||
package sftp
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"os"
|
||||
"reflect"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
// ensure that attrs implemenst os.FileInfo
|
||||
var _ os.FileInfo = new(fileInfo)
|
||||
|
||||
var unmarshalAttrsTests = []struct {
|
||||
b []byte
|
||||
want *fileInfo
|
||||
rest []byte
|
||||
}{
|
||||
{marshal(nil, struct{ Flags uint32 }{}), &fileInfo{mtime: time.Unix(int64(0), 0)}, nil},
|
||||
{marshal(nil, struct {
|
||||
Flags uint32
|
||||
Size uint64
|
||||
}{ssh_FILEXFER_ATTR_SIZE, 20}), &fileInfo{size: 20, mtime: time.Unix(int64(0), 0)}, nil},
|
||||
{marshal(nil, struct {
|
||||
Flags uint32
|
||||
Size uint64
|
||||
Permissions uint32
|
||||
}{ssh_FILEXFER_ATTR_SIZE | ssh_FILEXFER_ATTR_PERMISSIONS, 20, 0644}), &fileInfo{size: 20, mode: os.FileMode(0644), mtime: time.Unix(int64(0), 0)}, nil},
|
||||
{marshal(nil, struct {
|
||||
Flags uint32
|
||||
Size uint64
|
||||
UID, GID, Permissions uint32
|
||||
}{ssh_FILEXFER_ATTR_SIZE | ssh_FILEXFER_ATTR_UIDGID | ssh_FILEXFER_ATTR_UIDGID | ssh_FILEXFER_ATTR_PERMISSIONS, 20, 1000, 1000, 0644}), &fileInfo{size: 20, mode: os.FileMode(0644), mtime: time.Unix(int64(0), 0)}, nil},
|
||||
}
|
||||
|
||||
func TestUnmarshalAttrs(t *testing.T) {
|
||||
for _, tt := range unmarshalAttrsTests {
|
||||
stat, rest := unmarshalAttrs(tt.b)
|
||||
got := fileInfoFromStat(stat, "")
|
||||
tt.want.sys = got.Sys()
|
||||
if !reflect.DeepEqual(got, tt.want) || !bytes.Equal(tt.rest, rest) {
|
||||
t.Errorf("unmarshalAttrs(%#v): want %#v, %#v, got: %#v, %#v", tt.b, tt.want, tt.rest, got, rest)
|
||||
}
|
||||
}
|
||||
}
|
46
vendor/src/github.com/pkg/sftp/client_integration_darwin_test.go
vendored
Normal file
46
vendor/src/github.com/pkg/sftp/client_integration_darwin_test.go
vendored
Normal file
@ -0,0 +1,46 @@
|
||||
package sftp
|
||||
|
||||
import (
|
||||
"syscall"
|
||||
"testing"
|
||||
)
|
||||
|
||||
const sftpServer = "/usr/libexec/sftp-server"
|
||||
|
||||
func TestClientStatVFS(t *testing.T) {
|
||||
if *testServerImpl {
|
||||
t.Skipf("go server does not support FXP_EXTENDED")
|
||||
}
|
||||
sftp, cmd := testClient(t, READWRITE, NO_DELAY)
|
||||
defer cmd.Wait()
|
||||
defer sftp.Close()
|
||||
|
||||
vfs, err := sftp.StatVFS("/")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// get system stats
|
||||
s := syscall.Statfs_t{}
|
||||
err = syscall.Statfs("/", &s)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// check some stats
|
||||
if vfs.Files != uint64(s.Files) {
|
||||
t.Fatal("fr_size does not match")
|
||||
}
|
||||
|
||||
if vfs.Bfree != uint64(s.Bfree) {
|
||||
t.Fatal("f_bsize does not match")
|
||||
}
|
||||
|
||||
if vfs.Favail != uint64(s.Ffree) {
|
||||
t.Fatal("f_namemax does not match")
|
||||
}
|
||||
|
||||
if vfs.Bavail != s.Bavail {
|
||||
t.Fatal("f_bavail does not match")
|
||||
}
|
||||
}
|
46
vendor/src/github.com/pkg/sftp/client_integration_linux_test.go
vendored
Normal file
46
vendor/src/github.com/pkg/sftp/client_integration_linux_test.go
vendored
Normal file
@ -0,0 +1,46 @@
|
||||
package sftp
|
||||
|
||||
import (
|
||||
"syscall"
|
||||
"testing"
|
||||
)
|
||||
|
||||
const sftpServer = "/usr/lib/openssh/sftp-server"
|
||||
|
||||
func TestClientStatVFS(t *testing.T) {
|
||||
if *testServerImpl {
|
||||
t.Skipf("go server does not support FXP_EXTENDED")
|
||||
}
|
||||
sftp, cmd := testClient(t, READWRITE, NO_DELAY)
|
||||
defer cmd.Wait()
|
||||
defer sftp.Close()
|
||||
|
||||
vfs, err := sftp.StatVFS("/")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// get system stats
|
||||
s := syscall.Statfs_t{}
|
||||
err = syscall.Statfs("/", &s)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// check some stats
|
||||
if vfs.Frsize != uint64(s.Frsize) {
|
||||
t.Fatal("fr_size does not match")
|
||||
}
|
||||
|
||||
if vfs.Bsize != uint64(s.Bsize) {
|
||||
t.Fatal("f_bsize does not match")
|
||||
}
|
||||
|
||||
if vfs.Namemax != uint64(s.Namelen) {
|
||||
t.Fatal("f_namemax does not match")
|
||||
}
|
||||
|
||||
if vfs.Bavail != s.Bavail {
|
||||
t.Fatal("f_bavail does not match")
|
||||
}
|
||||
}
|
1616
vendor/src/github.com/pkg/sftp/client_integration_test.go
vendored
Normal file
1616
vendor/src/github.com/pkg/sftp/client_integration_test.go
vendored
Normal file
File diff suppressed because it is too large
Load Diff
99
vendor/src/github.com/pkg/sftp/client_test.go
vendored
Normal file
99
vendor/src/github.com/pkg/sftp/client_test.go
vendored
Normal file
@ -0,0 +1,99 @@
|
||||
package sftp
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"io"
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/kr/fs"
|
||||
)
|
||||
|
||||
// assert that *Client implements fs.FileSystem
|
||||
var _ fs.FileSystem = new(Client)
|
||||
|
||||
// assert that *File implements io.ReadWriteCloser
|
||||
var _ io.ReadWriteCloser = new(File)
|
||||
|
||||
func TestNormaliseError(t *testing.T) {
|
||||
var (
|
||||
ok = &StatusError{Code: ssh_FX_OK}
|
||||
eof = &StatusError{Code: ssh_FX_EOF}
|
||||
fail = &StatusError{Code: ssh_FX_FAILURE}
|
||||
noSuchFile = &StatusError{Code: ssh_FX_NO_SUCH_FILE}
|
||||
foo = errors.New("foo")
|
||||
)
|
||||
|
||||
var tests = []struct {
|
||||
desc string
|
||||
err error
|
||||
want error
|
||||
}{
|
||||
{
|
||||
desc: "nil error",
|
||||
},
|
||||
{
|
||||
desc: "not *StatusError",
|
||||
err: foo,
|
||||
want: foo,
|
||||
},
|
||||
{
|
||||
desc: "*StatusError with ssh_FX_EOF",
|
||||
err: eof,
|
||||
want: io.EOF,
|
||||
},
|
||||
{
|
||||
desc: "*StatusError with ssh_FX_NO_SUCH_FILE",
|
||||
err: noSuchFile,
|
||||
want: os.ErrNotExist,
|
||||
},
|
||||
{
|
||||
desc: "*StatusError with ssh_FX_OK",
|
||||
err: ok,
|
||||
},
|
||||
{
|
||||
desc: "*StatusError with ssh_FX_FAILURE",
|
||||
err: fail,
|
||||
want: fail,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
got := normaliseError(tt.err)
|
||||
if got != tt.want {
|
||||
t.Errorf("normaliseError(%#v), test %q\n- want: %#v\n- got: %#v",
|
||||
tt.err, tt.desc, tt.want, got)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var flagsTests = []struct {
|
||||
flags int
|
||||
want uint32
|
||||
}{
|
||||
{os.O_RDONLY, ssh_FXF_READ},
|
||||
{os.O_WRONLY, ssh_FXF_WRITE},
|
||||
{os.O_RDWR, ssh_FXF_READ | ssh_FXF_WRITE},
|
||||
{os.O_RDWR | os.O_CREATE | os.O_TRUNC, ssh_FXF_READ | ssh_FXF_WRITE | ssh_FXF_CREAT | ssh_FXF_TRUNC},
|
||||
{os.O_WRONLY | os.O_APPEND, ssh_FXF_WRITE | ssh_FXF_APPEND},
|
||||
}
|
||||
|
||||
func TestFlags(t *testing.T) {
|
||||
for i, tt := range flagsTests {
|
||||
got := flags(tt.flags)
|
||||
if got != tt.want {
|
||||
t.Errorf("test %v: flags(%x): want: %x, got: %x", i, tt.flags, tt.want, got)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestMissingLangTag(t *testing.T) {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
t.Fail()
|
||||
}
|
||||
}()
|
||||
buf := marshalUint32([]byte{}, 0)
|
||||
buf = marshalStatus(buf, StatusError{})
|
||||
_ = unmarshalStatus(0, buf[:len(buf)-4])
|
||||
}
|
90
vendor/src/github.com/pkg/sftp/example_test.go
vendored
Normal file
90
vendor/src/github.com/pkg/sftp/example_test.go
vendored
Normal file
@ -0,0 +1,90 @@
|
||||
package sftp_test
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"os/exec"
|
||||
|
||||
"github.com/pkg/sftp"
|
||||
"golang.org/x/crypto/ssh"
|
||||
)
|
||||
|
||||
func Example(conn *ssh.Client) {
|
||||
// open an SFTP session over an existing ssh connection.
|
||||
sftp, err := sftp.NewClient(conn)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
defer sftp.Close()
|
||||
|
||||
// walk a directory
|
||||
w := sftp.Walk("/home/user")
|
||||
for w.Step() {
|
||||
if w.Err() != nil {
|
||||
continue
|
||||
}
|
||||
log.Println(w.Path())
|
||||
}
|
||||
|
||||
// leave your mark
|
||||
f, err := sftp.Create("hello.txt")
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
if _, err := f.Write([]byte("Hello world!")); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
// check it's there
|
||||
fi, err := sftp.Lstat("hello.txt")
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
log.Println(fi)
|
||||
}
|
||||
|
||||
func ExampleNewClientPipe() {
|
||||
// Connect to a remote host and request the sftp subsystem via the 'ssh'
|
||||
// command. This assumes that passwordless login is correctly configured.
|
||||
cmd := exec.Command("ssh", "example.com", "-s", "sftp")
|
||||
|
||||
// send errors from ssh to stderr
|
||||
cmd.Stderr = os.Stderr
|
||||
|
||||
// get stdin and stdout
|
||||
wr, err := cmd.StdinPipe()
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
rd, err := cmd.StdoutPipe()
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
// start the process
|
||||
if err := cmd.Start(); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
defer cmd.Wait()
|
||||
|
||||
// open the SFTP session
|
||||
client, err := sftp.NewClientPipe(rd, wr)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
// read a directory
|
||||
list, err := client.ReadDir("/")
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
// print contents
|
||||
for _, item := range list {
|
||||
fmt.Println(item.Name())
|
||||
}
|
||||
|
||||
// close the connection
|
||||
client.Close()
|
||||
}
|
5
vendor/src/github.com/pkg/sftp/other_test.go
vendored
Normal file
5
vendor/src/github.com/pkg/sftp/other_test.go
vendored
Normal file
@ -0,0 +1,5 @@
|
||||
// +build !linux,!darwin
|
||||
|
||||
package sftp
|
||||
|
||||
const sftpServer = "/usr/bin/false" // unsupported
|
345
vendor/src/github.com/pkg/sftp/packet_test.go
vendored
Normal file
345
vendor/src/github.com/pkg/sftp/packet_test.go
vendored
Normal file
@ -0,0 +1,345 @@
|
||||
package sftp
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding"
|
||||
"os"
|
||||
"testing"
|
||||
)
|
||||
|
||||
var marshalUint32Tests = []struct {
|
||||
v uint32
|
||||
want []byte
|
||||
}{
|
||||
{1, []byte{0, 0, 0, 1}},
|
||||
{256, []byte{0, 0, 1, 0}},
|
||||
{^uint32(0), []byte{255, 255, 255, 255}},
|
||||
}
|
||||
|
||||
func TestMarshalUint32(t *testing.T) {
|
||||
for _, tt := range marshalUint32Tests {
|
||||
got := marshalUint32(nil, tt.v)
|
||||
if !bytes.Equal(tt.want, got) {
|
||||
t.Errorf("marshalUint32(%d): want %v, got %v", tt.v, tt.want, got)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var marshalUint64Tests = []struct {
|
||||
v uint64
|
||||
want []byte
|
||||
}{
|
||||
{1, []byte{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1}},
|
||||
{256, []byte{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0}},
|
||||
{^uint64(0), []byte{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}},
|
||||
{1 << 32, []byte{0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0}},
|
||||
}
|
||||
|
||||
func TestMarshalUint64(t *testing.T) {
|
||||
for _, tt := range marshalUint64Tests {
|
||||
got := marshalUint64(nil, tt.v)
|
||||
if !bytes.Equal(tt.want, got) {
|
||||
t.Errorf("marshalUint64(%d): want %#v, got %#v", tt.v, tt.want, got)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var marshalStringTests = []struct {
|
||||
v string
|
||||
want []byte
|
||||
}{
|
||||
{"", []byte{0, 0, 0, 0}},
|
||||
{"/foo", []byte{0x0, 0x0, 0x0, 0x4, 0x2f, 0x66, 0x6f, 0x6f}},
|
||||
}
|
||||
|
||||
func TestMarshalString(t *testing.T) {
|
||||
for _, tt := range marshalStringTests {
|
||||
got := marshalString(nil, tt.v)
|
||||
if !bytes.Equal(tt.want, got) {
|
||||
t.Errorf("marshalString(%q): want %#v, got %#v", tt.v, tt.want, got)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var marshalTests = []struct {
|
||||
v interface{}
|
||||
want []byte
|
||||
}{
|
||||
{uint8(1), []byte{1}},
|
||||
{byte(1), []byte{1}},
|
||||
{uint32(1), []byte{0, 0, 0, 1}},
|
||||
{uint64(1), []byte{0, 0, 0, 0, 0, 0, 0, 1}},
|
||||
{"foo", []byte{0x0, 0x0, 0x0, 0x3, 0x66, 0x6f, 0x6f}},
|
||||
{[]uint32{1, 2, 3, 4}, []byte{0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x2, 0x0, 0x0, 0x0, 0x3, 0x0, 0x0, 0x0, 0x4}},
|
||||
}
|
||||
|
||||
func TestMarshal(t *testing.T) {
|
||||
for _, tt := range marshalTests {
|
||||
got := marshal(nil, tt.v)
|
||||
if !bytes.Equal(tt.want, got) {
|
||||
t.Errorf("marshal(%v): want %#v, got %#v", tt.v, tt.want, got)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var unmarshalUint32Tests = []struct {
|
||||
b []byte
|
||||
want uint32
|
||||
rest []byte
|
||||
}{
|
||||
{[]byte{0, 0, 0, 0}, 0, nil},
|
||||
{[]byte{0, 0, 1, 0}, 256, nil},
|
||||
{[]byte{255, 0, 0, 255}, 4278190335, nil},
|
||||
}
|
||||
|
||||
func TestUnmarshalUint32(t *testing.T) {
|
||||
for _, tt := range unmarshalUint32Tests {
|
||||
got, rest := unmarshalUint32(tt.b)
|
||||
if got != tt.want || !bytes.Equal(rest, tt.rest) {
|
||||
t.Errorf("unmarshalUint32(%v): want %v, %#v, got %v, %#v", tt.b, tt.want, tt.rest, got, rest)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var unmarshalUint64Tests = []struct {
|
||||
b []byte
|
||||
want uint64
|
||||
rest []byte
|
||||
}{
|
||||
{[]byte{0, 0, 0, 0, 0, 0, 0, 0}, 0, nil},
|
||||
{[]byte{0, 0, 0, 0, 0, 0, 1, 0}, 256, nil},
|
||||
{[]byte{255, 0, 0, 0, 0, 0, 0, 255}, 18374686479671623935, nil},
|
||||
}
|
||||
|
||||
func TestUnmarshalUint64(t *testing.T) {
|
||||
for _, tt := range unmarshalUint64Tests {
|
||||
got, rest := unmarshalUint64(tt.b)
|
||||
if got != tt.want || !bytes.Equal(rest, tt.rest) {
|
||||
t.Errorf("unmarshalUint64(%v): want %v, %#v, got %v, %#v", tt.b, tt.want, tt.rest, got, rest)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var unmarshalStringTests = []struct {
|
||||
b []byte
|
||||
want string
|
||||
rest []byte
|
||||
}{
|
||||
{marshalString(nil, ""), "", nil},
|
||||
{marshalString(nil, "blah"), "blah", nil},
|
||||
}
|
||||
|
||||
func TestUnmarshalString(t *testing.T) {
|
||||
for _, tt := range unmarshalStringTests {
|
||||
got, rest := unmarshalString(tt.b)
|
||||
if got != tt.want || !bytes.Equal(rest, tt.rest) {
|
||||
t.Errorf("unmarshalUint64(%v): want %q, %#v, got %q, %#v", tt.b, tt.want, tt.rest, got, rest)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var sendPacketTests = []struct {
|
||||
p encoding.BinaryMarshaler
|
||||
want []byte
|
||||
}{
|
||||
{sshFxInitPacket{
|
||||
Version: 3,
|
||||
Extensions: []extensionPair{
|
||||
{"posix-rename@openssh.com", "1"},
|
||||
},
|
||||
}, []byte{0x0, 0x0, 0x0, 0x26, 0x1, 0x0, 0x0, 0x0, 0x3, 0x0, 0x0, 0x0, 0x18, 0x70, 0x6f, 0x73, 0x69, 0x78, 0x2d, 0x72, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x40, 0x6f, 0x70, 0x65, 0x6e, 0x73, 0x73, 0x68, 0x2e, 0x63, 0x6f, 0x6d, 0x0, 0x0, 0x0, 0x1, 0x31}},
|
||||
|
||||
{sshFxpOpenPacket{
|
||||
ID: 1,
|
||||
Path: "/foo",
|
||||
Pflags: flags(os.O_RDONLY),
|
||||
}, []byte{0x0, 0x0, 0x0, 0x15, 0x3, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x4, 0x2f, 0x66, 0x6f, 0x6f, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0}},
|
||||
|
||||
{sshFxpWritePacket{
|
||||
ID: 124,
|
||||
Handle: "foo",
|
||||
Offset: 13,
|
||||
Length: uint32(len([]byte("bar"))),
|
||||
Data: []byte("bar"),
|
||||
}, []byte{0x0, 0x0, 0x0, 0x1b, 0x6, 0x0, 0x0, 0x0, 0x7c, 0x0, 0x0, 0x0, 0x3, 0x66, 0x6f, 0x6f, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xd, 0x0, 0x0, 0x0, 0x3, 0x62, 0x61, 0x72}},
|
||||
|
||||
{sshFxpSetstatPacket{
|
||||
ID: 31,
|
||||
Path: "/bar",
|
||||
Flags: flags(os.O_WRONLY),
|
||||
Attrs: struct {
|
||||
UID uint32
|
||||
GID uint32
|
||||
}{1000, 100},
|
||||
}, []byte{0x0, 0x0, 0x0, 0x19, 0x9, 0x0, 0x0, 0x0, 0x1f, 0x0, 0x0, 0x0, 0x4, 0x2f, 0x62, 0x61, 0x72, 0x0, 0x0, 0x0, 0x2, 0x0, 0x0, 0x3, 0xe8, 0x0, 0x0, 0x0, 0x64}},
|
||||
}
|
||||
|
||||
func TestSendPacket(t *testing.T) {
|
||||
for _, tt := range sendPacketTests {
|
||||
var w bytes.Buffer
|
||||
sendPacket(&w, tt.p)
|
||||
if got := w.Bytes(); !bytes.Equal(tt.want, got) {
|
||||
t.Errorf("sendPacket(%v): want %#v, got %#v", tt.p, tt.want, got)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func sp(p encoding.BinaryMarshaler) []byte {
|
||||
var w bytes.Buffer
|
||||
sendPacket(&w, p)
|
||||
return w.Bytes()
|
||||
}
|
||||
|
||||
var recvPacketTests = []struct {
|
||||
b []byte
|
||||
want uint8
|
||||
rest []byte
|
||||
}{
|
||||
{sp(sshFxInitPacket{
|
||||
Version: 3,
|
||||
Extensions: []extensionPair{
|
||||
{"posix-rename@openssh.com", "1"},
|
||||
},
|
||||
}), ssh_FXP_INIT, []byte{0x0, 0x0, 0x0, 0x3, 0x0, 0x0, 0x0, 0x18, 0x70, 0x6f, 0x73, 0x69, 0x78, 0x2d, 0x72, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x40, 0x6f, 0x70, 0x65, 0x6e, 0x73, 0x73, 0x68, 0x2e, 0x63, 0x6f, 0x6d, 0x0, 0x0, 0x0, 0x1, 0x31}},
|
||||
}
|
||||
|
||||
func TestRecvPacket(t *testing.T) {
|
||||
for _, tt := range recvPacketTests {
|
||||
r := bytes.NewReader(tt.b)
|
||||
got, rest, _ := recvPacket(r)
|
||||
if got != tt.want || !bytes.Equal(rest, tt.rest) {
|
||||
t.Errorf("recvPacket(%#v): want %v, %#v, got %v, %#v", tt.b, tt.want, tt.rest, got, rest)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestSSHFxpOpenPacketreadonly(t *testing.T) {
|
||||
var tests = []struct {
|
||||
pflags uint32
|
||||
ok bool
|
||||
}{
|
||||
{
|
||||
pflags: ssh_FXF_READ,
|
||||
ok: true,
|
||||
},
|
||||
{
|
||||
pflags: ssh_FXF_WRITE,
|
||||
ok: false,
|
||||
},
|
||||
{
|
||||
pflags: ssh_FXF_READ | ssh_FXF_WRITE,
|
||||
ok: false,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
p := &sshFxpOpenPacket{
|
||||
Pflags: tt.pflags,
|
||||
}
|
||||
|
||||
if want, got := tt.ok, p.readonly(); want != got {
|
||||
t.Errorf("unexpected value for p.readonly(): want: %v, got: %v",
|
||||
want, got)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestSSHFxpOpenPackethasPflags(t *testing.T) {
|
||||
var tests = []struct {
|
||||
desc string
|
||||
haveFlags uint32
|
||||
testFlags []uint32
|
||||
ok bool
|
||||
}{
|
||||
{
|
||||
desc: "have read, test against write",
|
||||
haveFlags: ssh_FXF_READ,
|
||||
testFlags: []uint32{ssh_FXF_WRITE},
|
||||
ok: false,
|
||||
},
|
||||
{
|
||||
desc: "have write, test against read",
|
||||
haveFlags: ssh_FXF_WRITE,
|
||||
testFlags: []uint32{ssh_FXF_READ},
|
||||
ok: false,
|
||||
},
|
||||
{
|
||||
desc: "have read+write, test against read",
|
||||
haveFlags: ssh_FXF_READ | ssh_FXF_WRITE,
|
||||
testFlags: []uint32{ssh_FXF_READ},
|
||||
ok: true,
|
||||
},
|
||||
{
|
||||
desc: "have read+write, test against write",
|
||||
haveFlags: ssh_FXF_READ | ssh_FXF_WRITE,
|
||||
testFlags: []uint32{ssh_FXF_WRITE},
|
||||
ok: true,
|
||||
},
|
||||
{
|
||||
desc: "have read+write, test against read+write",
|
||||
haveFlags: ssh_FXF_READ | ssh_FXF_WRITE,
|
||||
testFlags: []uint32{ssh_FXF_READ, ssh_FXF_WRITE},
|
||||
ok: true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Log(tt.desc)
|
||||
|
||||
p := &sshFxpOpenPacket{
|
||||
Pflags: tt.haveFlags,
|
||||
}
|
||||
|
||||
if want, got := tt.ok, p.hasPflags(tt.testFlags...); want != got {
|
||||
t.Errorf("unexpected value for p.hasPflags(%#v): want: %v, got: %v",
|
||||
tt.testFlags, want, got)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkMarshalInit(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
sp(sshFxInitPacket{
|
||||
Version: 3,
|
||||
Extensions: []extensionPair{
|
||||
{"posix-rename@openssh.com", "1"},
|
||||
},
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkMarshalOpen(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
sp(sshFxpOpenPacket{
|
||||
ID: 1,
|
||||
Path: "/home/test/some/random/path",
|
||||
Pflags: flags(os.O_RDONLY),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkMarshalWriteWorstCase(b *testing.B) {
|
||||
data := make([]byte, 32*1024)
|
||||
for i := 0; i < b.N; i++ {
|
||||
sp(sshFxpWritePacket{
|
||||
ID: 1,
|
||||
Handle: "someopaquehandle",
|
||||
Offset: 0,
|
||||
Length: uint32(len(data)),
|
||||
Data: data,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkMarshalWrite1k(b *testing.B) {
|
||||
data := make([]byte, 1024)
|
||||
for i := 0; i < b.N; i++ {
|
||||
sp(sshFxpWritePacket{
|
||||
ID: 1,
|
||||
Handle: "someopaquehandle",
|
||||
Offset: 0,
|
||||
Length: uint32(len(data)),
|
||||
Data: data,
|
||||
})
|
||||
}
|
||||
}
|
672
vendor/src/github.com/pkg/sftp/server_integration_test.go
vendored
Normal file
672
vendor/src/github.com/pkg/sftp/server_integration_test.go
vendored
Normal file
@ -0,0 +1,672 @@
|
||||
package sftp
|
||||
|
||||
// sftp server integration tests
|
||||
// enable with -integration
|
||||
// example invokation (darwin): gofmt -w `find . -name \*.go` && (cd server_standalone/ ; go build -tags debug) && go test -tags debug github.com/pkg/sftp -integration -v -sftp /usr/libexec/sftp-server -run ServerCompareSubsystems
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/hex"
|
||||
"flag"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"math/rand"
|
||||
"net"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/kr/fs"
|
||||
"golang.org/x/crypto/ssh"
|
||||
)
|
||||
|
||||
var testSftpClientBin = flag.String("sftp_client", "/usr/bin/sftp", "location of the sftp client binary")
|
||||
var sshServerDebugStream = ioutil.Discard
|
||||
var sftpServerDebugStream = ioutil.Discard
|
||||
var sftpClientDebugStream = ioutil.Discard
|
||||
|
||||
const (
|
||||
GOLANG_SFTP = true
|
||||
OPENSSH_SFTP = false
|
||||
)
|
||||
|
||||
var (
|
||||
hostPrivateKeySigner ssh.Signer
|
||||
privKey = []byte(`
|
||||
-----BEGIN RSA PRIVATE KEY-----
|
||||
MIIEowIBAAKCAQEArhp7SqFnXVZAgWREL9Ogs+miy4IU/m0vmdkoK6M97G9NX/Pj
|
||||
wf8I/3/ynxmcArbt8Rc4JgkjT2uxx/NqR0yN42N1PjO5Czu0dms1PSqcKIJdeUBV
|
||||
7gdrKSm9Co4d2vwfQp5mg47eG4w63pz7Drk9+VIyi9YiYH4bve7WnGDswn4ycvYZ
|
||||
slV5kKnjlfCdPig+g5P7yQYud0cDWVwyA0+kxvL6H3Ip+Fu8rLDZn4/P1WlFAIuc
|
||||
PAf4uEKDGGmC2URowi5eesYR7f6GN/HnBs2776laNlAVXZUmYTUfOGagwLsEkx8x
|
||||
XdNqntfbs2MOOoK+myJrNtcB9pCrM0H6um19uQIDAQABAoIBABkWr9WdVKvalgkP
|
||||
TdQmhu3mKRNyd1wCl+1voZ5IM9Ayac/98UAvZDiNU4Uhx52MhtVLJ0gz4Oa8+i16
|
||||
IkKMAZZW6ro/8dZwkBzQbieWUFJ2Fso2PyvB3etcnGU8/Yhk9IxBDzy+BbuqhYE2
|
||||
1ebVQtz+v1HvVZzaD11bYYm/Xd7Y28QREVfFen30Q/v3dv7dOteDE/RgDS8Czz7w
|
||||
jMW32Q8JL5grz7zPkMK39BLXsTcSYcaasT2ParROhGJZDmbgd3l33zKCVc1zcj9B
|
||||
SA47QljGd09Tys958WWHgtj2o7bp9v1Ufs4LnyKgzrB80WX1ovaSQKvd5THTLchO
|
||||
kLIhUAECgYEA2doGXy9wMBmTn/hjiVvggR1aKiBwUpnB87Hn5xCMgoECVhFZlT6l
|
||||
WmZe7R2klbtG1aYlw+y+uzHhoVDAJW9AUSV8qoDUwbRXvBVlp+In5wIqJ+VjfivK
|
||||
zgIfzomL5NvDz37cvPmzqIeySTowEfbQyq7CUQSoDtE9H97E2wWZhDkCgYEAzJdJ
|
||||
k+NSFoTkHhfD3L0xCDHpRV3gvaOeew8524fVtVUq53X8m91ng4AX1r74dCUYwwiF
|
||||
gqTtSSJfx2iH1xKnNq28M9uKg7wOrCKrRqNPnYUO3LehZEC7rwUr26z4iJDHjjoB
|
||||
uBcS7nw0LJ+0Zeg1IF+aIdZGV3MrAKnrzWPixYECgYBsffX6ZWebrMEmQ89eUtFF
|
||||
u9ZxcGI/4K8ErC7vlgBD5ffB4TYZ627xzFWuBLs4jmHCeNIJ9tct5rOVYN+wRO1k
|
||||
/CRPzYUnSqb+1jEgILL6istvvv+DkE+ZtNkeRMXUndWwel94BWsBnUKe0UmrSJ3G
|
||||
sq23J3iCmJW2T3z+DpXbkQKBgQCK+LUVDNPE0i42NsRnm+fDfkvLP7Kafpr3Umdl
|
||||
tMY474o+QYn+wg0/aPJIf9463rwMNyyhirBX/k57IIktUdFdtfPicd2MEGETElWv
|
||||
nN1GzYxD50Rs2f/jKisZhEwqT9YNyV9DkgDdGGdEbJNYqbv0qpwDIg8T9foe8E1p
|
||||
bdErgQKBgAt290I3L316cdxIQTkJh1DlScN/unFffITwu127WMr28Jt3mq3cZpuM
|
||||
Aecey/eEKCj+Rlas5NDYKsB18QIuAw+qqWyq0LAKLiAvP1965Rkc4PLScl3MgJtO
|
||||
QYa37FK0p8NcDeUuF86zXBVutwS5nJLchHhKfd590ks57OROtm29
|
||||
-----END RSA PRIVATE KEY-----
|
||||
`)
|
||||
)
|
||||
|
||||
func init() {
|
||||
var err error
|
||||
hostPrivateKeySigner, err = ssh.ParsePrivateKey(privKey)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
func keyAuth(conn ssh.ConnMetadata, key ssh.PublicKey) (*ssh.Permissions, error) {
|
||||
permissions := &ssh.Permissions{
|
||||
CriticalOptions: map[string]string{},
|
||||
Extensions: map[string]string{},
|
||||
}
|
||||
return permissions, nil
|
||||
}
|
||||
|
||||
func pwAuth(conn ssh.ConnMetadata, pw []byte) (*ssh.Permissions, error) {
|
||||
permissions := &ssh.Permissions{
|
||||
CriticalOptions: map[string]string{},
|
||||
Extensions: map[string]string{},
|
||||
}
|
||||
return permissions, nil
|
||||
}
|
||||
|
||||
func basicServerConfig() *ssh.ServerConfig {
|
||||
config := ssh.ServerConfig{
|
||||
Config: ssh.Config{
|
||||
MACs: []string{"hmac-sha1"},
|
||||
},
|
||||
PasswordCallback: pwAuth,
|
||||
PublicKeyCallback: keyAuth,
|
||||
}
|
||||
config.AddHostKey(hostPrivateKeySigner)
|
||||
return &config
|
||||
}
|
||||
|
||||
type sshServer struct {
|
||||
useSubsystem bool
|
||||
conn net.Conn
|
||||
config *ssh.ServerConfig
|
||||
sshConn *ssh.ServerConn
|
||||
newChans <-chan ssh.NewChannel
|
||||
newReqs <-chan *ssh.Request
|
||||
}
|
||||
|
||||
func sshServerFromConn(conn net.Conn, useSubsystem bool, config *ssh.ServerConfig) (*sshServer, error) {
|
||||
// From a standard TCP connection to an encrypted SSH connection
|
||||
sshConn, newChans, newReqs, err := ssh.NewServerConn(conn, config)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
svr := &sshServer{useSubsystem, conn, config, sshConn, newChans, newReqs}
|
||||
svr.listenChannels()
|
||||
return svr, nil
|
||||
}
|
||||
|
||||
func (svr *sshServer) Wait() error {
|
||||
return svr.sshConn.Wait()
|
||||
}
|
||||
|
||||
func (svr *sshServer) Close() error {
|
||||
return svr.sshConn.Close()
|
||||
}
|
||||
|
||||
func (svr *sshServer) listenChannels() {
|
||||
go func() {
|
||||
for chanReq := range svr.newChans {
|
||||
go svr.handleChanReq(chanReq)
|
||||
}
|
||||
}()
|
||||
go func() {
|
||||
for req := range svr.newReqs {
|
||||
go svr.handleReq(req)
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
func (svr *sshServer) handleReq(req *ssh.Request) {
|
||||
switch req.Type {
|
||||
default:
|
||||
rejectRequest(req)
|
||||
}
|
||||
}
|
||||
|
||||
type sshChannelServer struct {
|
||||
svr *sshServer
|
||||
chanReq ssh.NewChannel
|
||||
ch ssh.Channel
|
||||
newReqs <-chan *ssh.Request
|
||||
}
|
||||
|
||||
type sshSessionChannelServer struct {
|
||||
*sshChannelServer
|
||||
env []string
|
||||
}
|
||||
|
||||
func (svr *sshServer) handleChanReq(chanReq ssh.NewChannel) {
|
||||
fmt.Fprintf(sshServerDebugStream, "channel request: %v, extra: '%v'\n", chanReq.ChannelType(), hex.EncodeToString(chanReq.ExtraData()))
|
||||
switch chanReq.ChannelType() {
|
||||
case "session":
|
||||
if ch, reqs, err := chanReq.Accept(); err != nil {
|
||||
fmt.Fprintf(sshServerDebugStream, "fail to accept channel request: %v\n", err)
|
||||
chanReq.Reject(ssh.ResourceShortage, "channel accept failure")
|
||||
} else {
|
||||
chsvr := &sshSessionChannelServer{
|
||||
sshChannelServer: &sshChannelServer{svr, chanReq, ch, reqs},
|
||||
env: append([]string{}, os.Environ()...),
|
||||
}
|
||||
chsvr.handle()
|
||||
}
|
||||
default:
|
||||
chanReq.Reject(ssh.UnknownChannelType, "channel type is not a session")
|
||||
}
|
||||
}
|
||||
|
||||
func (chsvr *sshSessionChannelServer) handle() {
|
||||
// should maybe do something here...
|
||||
go chsvr.handleReqs()
|
||||
}
|
||||
|
||||
func (chsvr *sshSessionChannelServer) handleReqs() {
|
||||
for req := range chsvr.newReqs {
|
||||
chsvr.handleReq(req)
|
||||
}
|
||||
fmt.Fprintf(sshServerDebugStream, "ssh server session channel complete\n")
|
||||
}
|
||||
|
||||
func (chsvr *sshSessionChannelServer) handleReq(req *ssh.Request) {
|
||||
switch req.Type {
|
||||
case "env":
|
||||
chsvr.handleEnv(req)
|
||||
case "subsystem":
|
||||
chsvr.handleSubsystem(req)
|
||||
default:
|
||||
rejectRequest(req)
|
||||
}
|
||||
}
|
||||
|
||||
func rejectRequest(req *ssh.Request) error {
|
||||
fmt.Fprintf(sshServerDebugStream, "ssh rejecting request, type: %s\n", req.Type)
|
||||
err := req.Reply(false, []byte{})
|
||||
if err != nil {
|
||||
fmt.Fprintf(sshServerDebugStream, "ssh request reply had error: %v\n", err)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func rejectRequestUnmarshalError(req *ssh.Request, s interface{}, err error) error {
|
||||
fmt.Fprintf(sshServerDebugStream, "ssh request unmarshaling error, type '%T': %v\n", s, err)
|
||||
rejectRequest(req)
|
||||
return err
|
||||
}
|
||||
|
||||
// env request form:
|
||||
type sshEnvRequest struct {
|
||||
Envvar string
|
||||
Value string
|
||||
}
|
||||
|
||||
func (chsvr *sshSessionChannelServer) handleEnv(req *ssh.Request) error {
|
||||
envReq := &sshEnvRequest{}
|
||||
if err := ssh.Unmarshal(req.Payload, envReq); err != nil {
|
||||
return rejectRequestUnmarshalError(req, envReq, err)
|
||||
}
|
||||
req.Reply(true, nil)
|
||||
|
||||
found := false
|
||||
for i, envstr := range chsvr.env {
|
||||
if strings.HasPrefix(envstr, envReq.Envvar+"=") {
|
||||
found = true
|
||||
chsvr.env[i] = envReq.Envvar + "=" + envReq.Value
|
||||
}
|
||||
}
|
||||
if !found {
|
||||
chsvr.env = append(chsvr.env, envReq.Envvar+"="+envReq.Value)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Payload: int: command size, string: command
|
||||
type sshSubsystemRequest struct {
|
||||
Name string
|
||||
}
|
||||
|
||||
type sshSubsystemExitStatus struct {
|
||||
Status uint32
|
||||
}
|
||||
|
||||
func (chsvr *sshSessionChannelServer) handleSubsystem(req *ssh.Request) error {
|
||||
defer func() {
|
||||
err1 := chsvr.ch.CloseWrite()
|
||||
err2 := chsvr.ch.Close()
|
||||
fmt.Fprintf(sshServerDebugStream, "ssh server subsystem request complete, err: %v %v\n", err1, err2)
|
||||
}()
|
||||
|
||||
subsystemReq := &sshSubsystemRequest{}
|
||||
if err := ssh.Unmarshal(req.Payload, subsystemReq); err != nil {
|
||||
return rejectRequestUnmarshalError(req, subsystemReq, err)
|
||||
}
|
||||
|
||||
// reply to the ssh client
|
||||
|
||||
// no idea if this is actually correct spec-wise.
|
||||
// just enough for an sftp server to start.
|
||||
if subsystemReq.Name != "sftp" {
|
||||
return req.Reply(false, nil)
|
||||
}
|
||||
|
||||
req.Reply(true, nil)
|
||||
|
||||
if !chsvr.svr.useSubsystem {
|
||||
// use the openssh sftp server backend; this is to test the ssh code, not the sftp code,
|
||||
// or is used for comparison between our sftp subsystem and the openssh sftp subsystem
|
||||
cmd := exec.Command(*testSftp, "-e", "-l", "DEBUG") // log to stderr
|
||||
cmd.Stdin = chsvr.ch
|
||||
cmd.Stdout = chsvr.ch
|
||||
cmd.Stderr = sftpServerDebugStream
|
||||
if err := cmd.Start(); err != nil {
|
||||
return err
|
||||
}
|
||||
return cmd.Wait()
|
||||
}
|
||||
|
||||
sftpServer, err := NewServer(
|
||||
chsvr.ch,
|
||||
chsvr.ch,
|
||||
WithDebug(sftpServerDebugStream),
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// wait for the session to close
|
||||
runErr := sftpServer.Serve()
|
||||
exitStatus := uint32(1)
|
||||
if runErr == nil {
|
||||
exitStatus = uint32(0)
|
||||
}
|
||||
|
||||
_, exitStatusErr := chsvr.ch.SendRequest("exit-status", false, ssh.Marshal(sshSubsystemExitStatus{exitStatus}))
|
||||
return exitStatusErr
|
||||
}
|
||||
|
||||
// starts an ssh server to test. returns: host string and port
|
||||
func testServer(t *testing.T, useSubsystem bool, readonly bool) (net.Listener, string, int) {
|
||||
if !*testIntegration {
|
||||
t.Skip("skipping intergration test")
|
||||
}
|
||||
|
||||
listener, err := net.Listen("tcp", "127.0.0.1:0")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
host, portStr, err := net.SplitHostPort(listener.Addr().String())
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
port, err := strconv.Atoi(portStr)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
go func() {
|
||||
for {
|
||||
conn, err := listener.Accept()
|
||||
if err != nil {
|
||||
fmt.Fprintf(sshServerDebugStream, "ssh server socket closed: %v\n", err)
|
||||
break
|
||||
}
|
||||
|
||||
go func() {
|
||||
defer conn.Close()
|
||||
sshSvr, err := sshServerFromConn(conn, useSubsystem, basicServerConfig())
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
return
|
||||
}
|
||||
err = sshSvr.Wait()
|
||||
fmt.Fprintf(sshServerDebugStream, "ssh server finished, err: %v\n", err)
|
||||
}()
|
||||
}
|
||||
}()
|
||||
|
||||
return listener, host, port
|
||||
}
|
||||
|
||||
func runSftpClient(t *testing.T, script string, path string, host string, port int) (string, error) {
|
||||
// if sftp client binary is unavailable, skip test
|
||||
if _, err := os.Stat(*testSftpClientBin); err != nil {
|
||||
t.Skip("sftp client binary unavailable")
|
||||
}
|
||||
args := []string{
|
||||
// "-vvvv",
|
||||
"-b", "-",
|
||||
"-o", "StrictHostKeyChecking=no",
|
||||
"-o", "LogLevel=ERROR",
|
||||
"-o", "UserKnownHostsFile /dev/null",
|
||||
"-P", fmt.Sprintf("%d", port), fmt.Sprintf("%s:%s", host, path),
|
||||
}
|
||||
cmd := exec.Command(*testSftpClientBin, args...)
|
||||
var stdout bytes.Buffer
|
||||
cmd.Stdin = bytes.NewBufferString(script)
|
||||
cmd.Stdout = &stdout
|
||||
cmd.Stderr = sftpClientDebugStream
|
||||
if err := cmd.Start(); err != nil {
|
||||
return "", err
|
||||
}
|
||||
err := cmd.Wait()
|
||||
return string(stdout.Bytes()), err
|
||||
}
|
||||
|
||||
func TestServerCompareSubsystems(t *testing.T) {
|
||||
listenerGo, hostGo, portGo := testServer(t, GOLANG_SFTP, READONLY)
|
||||
listenerOp, hostOp, portOp := testServer(t, OPENSSH_SFTP, READONLY)
|
||||
defer listenerGo.Close()
|
||||
defer listenerOp.Close()
|
||||
|
||||
script := `
|
||||
ls /
|
||||
ls -l /
|
||||
ls /dev/
|
||||
ls -l /dev/
|
||||
ls -l /etc/
|
||||
ls -l /bin/
|
||||
ls -l /usr/bin/
|
||||
`
|
||||
outputGo, err := runSftpClient(t, script, "/", hostGo, portGo)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
outputOp, err := runSftpClient(t, script, "/", hostOp, portOp)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
newlineRegex := regexp.MustCompile(`\r*\n`)
|
||||
spaceRegex := regexp.MustCompile(`\s+`)
|
||||
outputGoLines := newlineRegex.Split(outputGo, -1)
|
||||
outputOpLines := newlineRegex.Split(outputOp, -1)
|
||||
|
||||
for i, goLine := range outputGoLines {
|
||||
if i > len(outputOpLines) {
|
||||
t.Fatalf("output line count differs")
|
||||
}
|
||||
opLine := outputOpLines[i]
|
||||
bad := false
|
||||
if goLine != opLine {
|
||||
goWords := spaceRegex.Split(goLine, -1)
|
||||
opWords := spaceRegex.Split(opLine, -1)
|
||||
// allow words[2] and [3] to be different as these are users & groups
|
||||
// also allow words[1] to differ as the link count for directories like
|
||||
// proc is unstable during testing as processes are created/destroyed.
|
||||
for j, goWord := range goWords {
|
||||
if j > len(opWords) {
|
||||
bad = true
|
||||
}
|
||||
opWord := opWords[j]
|
||||
if goWord != opWord && j != 1 && j != 2 && j != 3 {
|
||||
bad = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if bad {
|
||||
t.Errorf("outputs differ, go:\n%v\nopenssh:\n%v\n", goLine, opLine)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var rng = rand.New(rand.NewSource(time.Now().Unix()))
|
||||
|
||||
func randData(length int) []byte {
|
||||
data := make([]byte, length)
|
||||
for i := 0; i < length; i++ {
|
||||
data[i] = byte(rng.Uint32())
|
||||
}
|
||||
return data
|
||||
}
|
||||
|
||||
func randName() string {
|
||||
return "sftp." + hex.EncodeToString(randData(16))
|
||||
}
|
||||
|
||||
func TestServerMkdirRmdir(t *testing.T) {
|
||||
listenerGo, hostGo, portGo := testServer(t, GOLANG_SFTP, READONLY)
|
||||
defer listenerGo.Close()
|
||||
|
||||
tmpDir := "/tmp/" + randName()
|
||||
defer os.RemoveAll(tmpDir)
|
||||
|
||||
// mkdir remote
|
||||
if _, err := runSftpClient(t, "mkdir "+tmpDir, "/", hostGo, portGo); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// directory should now exist
|
||||
if _, err := os.Stat(tmpDir); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// now remove the directory
|
||||
if _, err := runSftpClient(t, "rmdir "+tmpDir, "/", hostGo, portGo); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if _, err := os.Stat(tmpDir); err == nil {
|
||||
t.Fatal("should have error after deleting the directory")
|
||||
}
|
||||
}
|
||||
|
||||
func TestServerSymlink(t *testing.T) {
|
||||
listenerGo, hostGo, portGo := testServer(t, GOLANG_SFTP, READONLY)
|
||||
defer listenerGo.Close()
|
||||
|
||||
link := "/tmp/" + randName()
|
||||
defer os.RemoveAll(link)
|
||||
|
||||
// now create a symbolic link within the new directory
|
||||
if output, err := runSftpClient(t, "symlink /bin/sh "+link, "/", hostGo, portGo); err != nil {
|
||||
t.Fatalf("failed: %v %v", err, string(output))
|
||||
}
|
||||
|
||||
// symlink should now exist
|
||||
if stat, err := os.Lstat(link); err != nil {
|
||||
t.Fatal(err)
|
||||
} else if (stat.Mode() & os.ModeSymlink) != os.ModeSymlink {
|
||||
t.Fatalf("is not a symlink: %v", stat.Mode())
|
||||
}
|
||||
}
|
||||
|
||||
func TestServerPut(t *testing.T) {
|
||||
listenerGo, hostGo, portGo := testServer(t, GOLANG_SFTP, READONLY)
|
||||
defer listenerGo.Close()
|
||||
|
||||
tmpFileLocal := "/tmp/" + randName()
|
||||
tmpFileRemote := "/tmp/" + randName()
|
||||
defer os.RemoveAll(tmpFileLocal)
|
||||
defer os.RemoveAll(tmpFileRemote)
|
||||
|
||||
t.Logf("put: local %v remote %v", tmpFileLocal, tmpFileRemote)
|
||||
|
||||
// create a file with random contents. This will be the local file pushed to the server
|
||||
tmpFileLocalData := randData(10 * 1024 * 1024)
|
||||
if err := ioutil.WriteFile(tmpFileLocal, tmpFileLocalData, 0644); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// sftp the file to the server
|
||||
if output, err := runSftpClient(t, "put "+tmpFileLocal+" "+tmpFileRemote, "/", hostGo, portGo); err != nil {
|
||||
t.Fatalf("runSftpClient failed: %v, output\n%v\n", err, output)
|
||||
}
|
||||
|
||||
// tmpFile2 should now exist, with the same contents
|
||||
if tmpFileRemoteData, err := ioutil.ReadFile(tmpFileRemote); err != nil {
|
||||
t.Fatal(err)
|
||||
} else if string(tmpFileLocalData) != string(tmpFileRemoteData) {
|
||||
t.Fatal("contents of file incorrect after put")
|
||||
}
|
||||
}
|
||||
|
||||
func TestServerGet(t *testing.T) {
|
||||
listenerGo, hostGo, portGo := testServer(t, GOLANG_SFTP, READONLY)
|
||||
defer listenerGo.Close()
|
||||
|
||||
tmpFileLocal := "/tmp/" + randName()
|
||||
tmpFileRemote := "/tmp/" + randName()
|
||||
defer os.RemoveAll(tmpFileLocal)
|
||||
defer os.RemoveAll(tmpFileRemote)
|
||||
|
||||
t.Logf("get: local %v remote %v", tmpFileLocal, tmpFileRemote)
|
||||
|
||||
// create a file with random contents. This will be the remote file pulled from the server
|
||||
tmpFileRemoteData := randData(10 * 1024 * 1024)
|
||||
if err := ioutil.WriteFile(tmpFileRemote, tmpFileRemoteData, 0644); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// sftp the file to the server
|
||||
if output, err := runSftpClient(t, "get "+tmpFileRemote+" "+tmpFileLocal, "/", hostGo, portGo); err != nil {
|
||||
t.Fatalf("runSftpClient failed: %v, output\n%v\n", err, output)
|
||||
}
|
||||
|
||||
// tmpFile2 should now exist, with the same contents
|
||||
if tmpFileLocalData, err := ioutil.ReadFile(tmpFileLocal); err != nil {
|
||||
t.Fatal(err)
|
||||
} else if string(tmpFileLocalData) != string(tmpFileRemoteData) {
|
||||
t.Fatal("contents of file incorrect after put")
|
||||
}
|
||||
}
|
||||
|
||||
func compareDirectoriesRecursive(t *testing.T, aroot, broot string) {
|
||||
walker := fs.Walk(aroot)
|
||||
for walker.Step() {
|
||||
if err := walker.Err(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
// find paths
|
||||
aPath := walker.Path()
|
||||
aRel, err := filepath.Rel(aroot, aPath)
|
||||
if err != nil {
|
||||
t.Fatalf("could not find relative path for %v: %v", aPath, err)
|
||||
}
|
||||
bPath := path.Join(broot, aRel)
|
||||
|
||||
if aRel == "." {
|
||||
continue
|
||||
}
|
||||
|
||||
//t.Logf("comparing: %v a: %v b %v", aRel, aPath, bPath)
|
||||
|
||||
// if a is a link, the sftp recursive copy won't have copied it. ignore
|
||||
aLink, err := os.Lstat(aPath)
|
||||
if err != nil {
|
||||
t.Fatalf("could not lstat %v: %v", aPath, err)
|
||||
}
|
||||
if aLink.Mode()&os.ModeSymlink != 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
// stat the files
|
||||
aFile, err := os.Stat(aPath)
|
||||
if err != nil {
|
||||
t.Fatalf("could not stat %v: %v", aPath, err)
|
||||
}
|
||||
bFile, err := os.Stat(bPath)
|
||||
if err != nil {
|
||||
t.Fatalf("could not stat %v: %v", bPath, err)
|
||||
}
|
||||
|
||||
// compare stats, with some leniency for the timestamp
|
||||
if aFile.Mode() != bFile.Mode() {
|
||||
t.Fatalf("modes different for %v: %v vs %v", aRel, aFile.Mode(), bFile.Mode())
|
||||
}
|
||||
if !aFile.IsDir() {
|
||||
if aFile.Size() != bFile.Size() {
|
||||
t.Fatalf("sizes different for %v: %v vs %v", aRel, aFile.Size(), bFile.Size())
|
||||
}
|
||||
}
|
||||
timeDiff := aFile.ModTime().Sub(bFile.ModTime())
|
||||
if timeDiff > time.Second || timeDiff < -time.Second {
|
||||
t.Fatalf("mtimes different for %v: %v vs %v", aRel, aFile.ModTime(), bFile.ModTime())
|
||||
}
|
||||
|
||||
// compare contents
|
||||
if !aFile.IsDir() {
|
||||
if aContents, err := ioutil.ReadFile(aPath); err != nil {
|
||||
t.Fatal(err)
|
||||
} else if bContents, err := ioutil.ReadFile(bPath); err != nil {
|
||||
t.Fatal(err)
|
||||
} else if string(aContents) != string(bContents) {
|
||||
t.Fatalf("contents different for %v", aRel)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestServerPutRecursive(t *testing.T) {
|
||||
listenerGo, hostGo, portGo := testServer(t, GOLANG_SFTP, READONLY)
|
||||
defer listenerGo.Close()
|
||||
|
||||
dirLocal, err := os.Getwd()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
tmpDirRemote := "/tmp/" + randName()
|
||||
defer os.RemoveAll(tmpDirRemote)
|
||||
|
||||
t.Logf("put recursive: local %v remote %v", dirLocal, tmpDirRemote)
|
||||
|
||||
// push this directory (source code etc) recursively to the server
|
||||
if output, err := runSftpClient(t, "mkdir "+tmpDirRemote+"\r\nput -r -P "+dirLocal+"/ "+tmpDirRemote+"/", "/", hostGo, portGo); err != nil {
|
||||
t.Fatalf("runSftpClient failed: %v, output\n%v\n", err, output)
|
||||
}
|
||||
|
||||
compareDirectoriesRecursive(t, dirLocal, path.Join(tmpDirRemote, path.Base(dirLocal)))
|
||||
}
|
||||
|
||||
func TestServerGetRecursive(t *testing.T) {
|
||||
listenerGo, hostGo, portGo := testServer(t, GOLANG_SFTP, READONLY)
|
||||
defer listenerGo.Close()
|
||||
|
||||
dirRemote, err := os.Getwd()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
tmpDirLocal := "/tmp/" + randName()
|
||||
defer os.RemoveAll(tmpDirLocal)
|
||||
|
||||
t.Logf("get recursive: local %v remote %v", tmpDirLocal, dirRemote)
|
||||
|
||||
// pull this directory (source code etc) recursively from the server
|
||||
if output, err := runSftpClient(t, "lmkdir "+tmpDirLocal+"\r\nget -r -P "+dirRemote+"/ "+tmpDirLocal+"/", "/", hostGo, portGo); err != nil {
|
||||
t.Fatalf("runSftpClient failed: %v, output\n%v\n", err, output)
|
||||
}
|
||||
|
||||
compareDirectoriesRecursive(t, dirRemote, path.Join(tmpDirLocal, path.Base(dirRemote)))
|
||||
}
|
11
vendor/src/github.com/restic/chunker/.travis.yml
vendored
11
vendor/src/github.com/restic/chunker/.travis.yml
vendored
@ -1,11 +0,0 @@
|
||||
language: go
|
||||
sudo: false
|
||||
|
||||
go:
|
||||
- 1.3.3
|
||||
- 1.4.2
|
||||
- 1.5.1
|
||||
|
||||
os:
|
||||
- linux
|
||||
- osx
|
@ -16,7 +16,7 @@ Hash Functions SHA-1, SHA-224, SHA-256, SHA-384 and SHA-512 for HMAC. To
|
||||
choose, you can pass the `New` functions from the different SHA packages to
|
||||
pbkdf2.Key.
|
||||
*/
|
||||
package pbkdf2
|
||||
package pbkdf2 // import "golang.org/x/crypto/pbkdf2"
|
||||
|
||||
import (
|
||||
"crypto/hmac"
|
||||
|
@ -16,7 +16,7 @@ used with a fixed key in order to generate one-time keys from an nonce.
|
||||
However, in this package AES isn't used and the one-time key is specified
|
||||
directly.
|
||||
*/
|
||||
package poly1305
|
||||
package poly1305 // import "golang.org/x/crypto/poly1305"
|
||||
|
||||
import "crypto/subtle"
|
||||
|
||||
|
@ -5,7 +5,7 @@
|
||||
// Package scrypt implements the scrypt key derivation function as defined in
|
||||
// Colin Percival's paper "Stronger Key Derivation via Sequential Memory-Hard
|
||||
// Functions" (http://www.tarsnap.com/scrypt/scrypt.pdf).
|
||||
package scrypt
|
||||
package scrypt // import "golang.org/x/crypto/scrypt"
|
||||
|
||||
import (
|
||||
"crypto/sha256"
|
||||
|
@ -8,7 +8,7 @@
|
||||
References:
|
||||
[PROTOCOL.agent]: http://cvsweb.openbsd.org/cgi-bin/cvsweb/src/usr.bin/ssh/PROTOCOL.agent?rev=HEAD
|
||||
*/
|
||||
package agent
|
||||
package agent // import "golang.org/x/crypto/ssh/agent"
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
|
2
vendor/src/golang.org/x/crypto/ssh/doc.go
vendored
2
vendor/src/golang.org/x/crypto/ssh/doc.go
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
|
||||
package ssh // import "golang.org/x/crypto/ssh"
|
||||
|
@ -14,7 +14,7 @@
|
||||
// panic(err)
|
||||
// }
|
||||
// defer terminal.Restore(0, oldState)
|
||||
package terminal
|
||||
package terminal // import "golang.org/x/crypto/ssh/terminal"
|
||||
|
||||
import (
|
||||
"io"
|
||||
|
@ -4,4 +4,4 @@
|
||||
|
||||
// This package contains integration tests for the
|
||||
// golang.org/x/crypto/ssh package.
|
||||
package test
|
||||
package test // import "golang.org/x/crypto/ssh/test"
|
||||
|
@ -5,4 +5,4 @@
|
||||
// This package contains test data shared between the various subpackages of
|
||||
// the golang.org/x/crypto/ssh package. Under no circumstance should
|
||||
// this data be used for production code.
|
||||
package testdata
|
||||
package testdata // import "golang.org/x/crypto/ssh/testdata"
|
||||
|
@ -34,7 +34,7 @@
|
||||
//
|
||||
// See http://blog.golang.org/context for example code for a server that uses
|
||||
// Contexts.
|
||||
package context
|
||||
package context // import "golang.org/x/net/context"
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
@ -3,7 +3,7 @@
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// Package ctxhttp provides helper functions for performing context-aware HTTP requests.
|
||||
package ctxhttp
|
||||
package ctxhttp // import "golang.org/x/net/context/ctxhttp"
|
||||
|
||||
import (
|
||||
"io"
|
||||
|
Loading…
Reference in New Issue
Block a user