forked from TrueCloudLab/restic
Update golang.org/x/*
This commit is contained in:
parent
faca9276e9
commit
9940b7f853
160 changed files with 20941 additions and 4329 deletions
16
vendor/manifest
vendored
16
vendor/manifest
vendored
|
@ -76,56 +76,56 @@
|
|||
{
|
||||
"importpath": "golang.org/x/crypto/curve25519",
|
||||
"repository": "https://go.googlesource.com/crypto",
|
||||
"revision": "81372b2fc2f10bef2a7f338da115c315a56b2726",
|
||||
"revision": "efac7f277b17c19894091e358c6130cb6bd51117",
|
||||
"branch": "master",
|
||||
"path": "/curve25519"
|
||||
},
|
||||
{
|
||||
"importpath": "golang.org/x/crypto/ed25519",
|
||||
"repository": "https://go.googlesource.com/crypto",
|
||||
"revision": "81372b2fc2f10bef2a7f338da115c315a56b2726",
|
||||
"revision": "efac7f277b17c19894091e358c6130cb6bd51117",
|
||||
"branch": "master",
|
||||
"path": "/ed25519"
|
||||
},
|
||||
{
|
||||
"importpath": "golang.org/x/crypto/pbkdf2",
|
||||
"repository": "https://go.googlesource.com/crypto",
|
||||
"revision": "81372b2fc2f10bef2a7f338da115c315a56b2726",
|
||||
"revision": "efac7f277b17c19894091e358c6130cb6bd51117",
|
||||
"branch": "master",
|
||||
"path": "/pbkdf2"
|
||||
},
|
||||
{
|
||||
"importpath": "golang.org/x/crypto/poly1305",
|
||||
"repository": "https://go.googlesource.com/crypto",
|
||||
"revision": "5f31782cfb2b6373211f8f9fbf31283fa234b570",
|
||||
"revision": "efac7f277b17c19894091e358c6130cb6bd51117",
|
||||
"branch": "master",
|
||||
"path": "/poly1305"
|
||||
},
|
||||
{
|
||||
"importpath": "golang.org/x/crypto/scrypt",
|
||||
"repository": "https://go.googlesource.com/crypto",
|
||||
"revision": "81372b2fc2f10bef2a7f338da115c315a56b2726",
|
||||
"revision": "efac7f277b17c19894091e358c6130cb6bd51117",
|
||||
"branch": "master",
|
||||
"path": "/scrypt"
|
||||
},
|
||||
{
|
||||
"importpath": "golang.org/x/crypto/ssh",
|
||||
"repository": "https://go.googlesource.com/crypto",
|
||||
"revision": "81372b2fc2f10bef2a7f338da115c315a56b2726",
|
||||
"revision": "efac7f277b17c19894091e358c6130cb6bd51117",
|
||||
"branch": "master",
|
||||
"path": "/ssh"
|
||||
},
|
||||
{
|
||||
"importpath": "golang.org/x/net/context",
|
||||
"repository": "https://go.googlesource.com/net",
|
||||
"revision": "de35ec43e7a9aabd6a9c54d2898220ea7e44de7d",
|
||||
"revision": "5602c733f70afc6dcec6766be0d5034d4c4f14de",
|
||||
"branch": "master",
|
||||
"path": "/context"
|
||||
},
|
||||
{
|
||||
"importpath": "golang.org/x/sys/unix",
|
||||
"repository": "https://go.googlesource.com/sys",
|
||||
"revision": "30de6d19a3bd89a5f38ae4028e23aaa5582648af",
|
||||
"revision": "f3918c30c5c2cb527c0b071a27c35120a6c0719a",
|
||||
"branch": "master",
|
||||
"path": "/unix"
|
||||
}
|
||||
|
|
8
vendor/src/golang.org/x/crypto/curve25519/const_amd64.h
vendored
Normal file
8
vendor/src/golang.org/x/crypto/curve25519/const_amd64.h
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
|
|
@ -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
|
||||
|
|
|
@ -2,87 +2,64 @@
|
|||
// 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
|
||||
|
||||
// +build amd64,!gccgo,!appengine
|
||||
|
||||
// func cswap(inout *[5]uint64, v uint64)
|
||||
// func cswap(inout *[4][5]uint64, v uint64)
|
||||
TEXT ·cswap(SB),7,$0
|
||||
MOVQ inout+0(FP),DI
|
||||
MOVQ v+8(FP),SI
|
||||
|
||||
CMPQ SI,$1
|
||||
MOVQ 0(DI),SI
|
||||
MOVQ 80(DI),DX
|
||||
MOVQ 8(DI),CX
|
||||
MOVQ 88(DI),R8
|
||||
MOVQ SI,R9
|
||||
CMOVQEQ DX,SI
|
||||
CMOVQEQ R9,DX
|
||||
MOVQ CX,R9
|
||||
CMOVQEQ R8,CX
|
||||
CMOVQEQ R9,R8
|
||||
MOVQ SI,0(DI)
|
||||
MOVQ DX,80(DI)
|
||||
MOVQ CX,8(DI)
|
||||
MOVQ R8,88(DI)
|
||||
MOVQ 16(DI),SI
|
||||
MOVQ 96(DI),DX
|
||||
MOVQ 24(DI),CX
|
||||
MOVQ 104(DI),R8
|
||||
MOVQ SI,R9
|
||||
CMOVQEQ DX,SI
|
||||
CMOVQEQ R9,DX
|
||||
MOVQ CX,R9
|
||||
CMOVQEQ R8,CX
|
||||
CMOVQEQ R9,R8
|
||||
MOVQ SI,16(DI)
|
||||
MOVQ DX,96(DI)
|
||||
MOVQ CX,24(DI)
|
||||
MOVQ R8,104(DI)
|
||||
MOVQ 32(DI),SI
|
||||
MOVQ 112(DI),DX
|
||||
MOVQ 40(DI),CX
|
||||
MOVQ 120(DI),R8
|
||||
MOVQ SI,R9
|
||||
CMOVQEQ DX,SI
|
||||
CMOVQEQ R9,DX
|
||||
MOVQ CX,R9
|
||||
CMOVQEQ R8,CX
|
||||
CMOVQEQ R9,R8
|
||||
MOVQ SI,32(DI)
|
||||
MOVQ DX,112(DI)
|
||||
MOVQ CX,40(DI)
|
||||
MOVQ R8,120(DI)
|
||||
MOVQ 48(DI),SI
|
||||
MOVQ 128(DI),DX
|
||||
MOVQ 56(DI),CX
|
||||
MOVQ 136(DI),R8
|
||||
MOVQ SI,R9
|
||||
CMOVQEQ DX,SI
|
||||
CMOVQEQ R9,DX
|
||||
MOVQ CX,R9
|
||||
CMOVQEQ R8,CX
|
||||
CMOVQEQ R9,R8
|
||||
MOVQ SI,48(DI)
|
||||
MOVQ DX,128(DI)
|
||||
MOVQ CX,56(DI)
|
||||
MOVQ R8,136(DI)
|
||||
MOVQ 64(DI),SI
|
||||
MOVQ 144(DI),DX
|
||||
MOVQ 72(DI),CX
|
||||
MOVQ 152(DI),R8
|
||||
MOVQ SI,R9
|
||||
CMOVQEQ DX,SI
|
||||
CMOVQEQ R9,DX
|
||||
MOVQ CX,R9
|
||||
CMOVQEQ R8,CX
|
||||
CMOVQEQ R9,R8
|
||||
MOVQ SI,64(DI)
|
||||
MOVQ DX,144(DI)
|
||||
MOVQ CX,72(DI)
|
||||
MOVQ R8,152(DI)
|
||||
MOVQ DI,AX
|
||||
MOVQ SI,DX
|
||||
SUBQ $1, SI
|
||||
NOTQ SI
|
||||
MOVQ SI, X15
|
||||
PSHUFD $0x44, X15, X15
|
||||
|
||||
MOVOU 0(DI), X0
|
||||
MOVOU 16(DI), X2
|
||||
MOVOU 32(DI), X4
|
||||
MOVOU 48(DI), X6
|
||||
MOVOU 64(DI), X8
|
||||
MOVOU 80(DI), X1
|
||||
MOVOU 96(DI), X3
|
||||
MOVOU 112(DI), X5
|
||||
MOVOU 128(DI), X7
|
||||
MOVOU 144(DI), X9
|
||||
|
||||
MOVO X1, X10
|
||||
MOVO X3, X11
|
||||
MOVO X5, X12
|
||||
MOVO X7, X13
|
||||
MOVO X9, X14
|
||||
|
||||
PXOR X0, X10
|
||||
PXOR X2, X11
|
||||
PXOR X4, X12
|
||||
PXOR X6, X13
|
||||
PXOR X8, X14
|
||||
PAND X15, X10
|
||||
PAND X15, X11
|
||||
PAND X15, X12
|
||||
PAND X15, X13
|
||||
PAND X15, X14
|
||||
PXOR X10, X0
|
||||
PXOR X10, X1
|
||||
PXOR X11, X2
|
||||
PXOR X11, X3
|
||||
PXOR X12, X4
|
||||
PXOR X12, X5
|
||||
PXOR X13, X6
|
||||
PXOR X13, X7
|
||||
PXOR X14, X8
|
||||
PXOR X14, X9
|
||||
|
||||
MOVOU X0, 0(DI)
|
||||
MOVOU X2, 16(DI)
|
||||
MOVOU X4, 32(DI)
|
||||
MOVOU X6, 48(DI)
|
||||
MOVOU X8, 64(DI)
|
||||
MOVOU X1, 80(DI)
|
||||
MOVOU X3, 96(DI)
|
||||
MOVOU X5, 112(DI)
|
||||
MOVOU X7, 128(DI)
|
||||
MOVOU X9, 144(DI)
|
||||
RET
|
||||
|
|
|
@ -8,6 +8,10 @@
|
|||
|
||||
package curve25519
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
)
|
||||
|
||||
// This code is a port of the public domain, "ref10" implementation of
|
||||
// curve25519 from SUPERCOP 20130419 by D. J. Bernstein.
|
||||
|
||||
|
@ -50,17 +54,11 @@ func feCopy(dst, src *fieldElement) {
|
|||
//
|
||||
// Preconditions: b in {0,1}.
|
||||
func feCSwap(f, g *fieldElement, b int32) {
|
||||
var x fieldElement
|
||||
b = -b
|
||||
for i := range x {
|
||||
x[i] = b & (f[i] ^ g[i])
|
||||
}
|
||||
|
||||
for i := range f {
|
||||
f[i] ^= x[i]
|
||||
}
|
||||
for i := range g {
|
||||
g[i] ^= x[i]
|
||||
t := b & (f[i] ^ g[i])
|
||||
f[i] ^= t
|
||||
g[i] ^= t
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -75,12 +73,7 @@ func load3(in []byte) int64 {
|
|||
|
||||
// load4 reads a 32-bit, little-endian value from in.
|
||||
func load4(in []byte) int64 {
|
||||
var r int64
|
||||
r = int64(in[0])
|
||||
r |= int64(in[1]) << 8
|
||||
r |= int64(in[2]) << 16
|
||||
r |= int64(in[3]) << 24
|
||||
return r
|
||||
return int64(binary.LittleEndian.Uint32(in))
|
||||
}
|
||||
|
||||
func feFromBytes(dst *fieldElement, src *[32]byte) {
|
||||
|
|
|
@ -27,3 +27,13 @@ func TestBaseScalarMult(t *testing.T) {
|
|||
t.Errorf("incorrect result: got %s, want %s", result, expectedHex)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkScalarBaseMult(b *testing.B) {
|
||||
var in, out [32]byte
|
||||
in[0] = 1
|
||||
|
||||
b.SetBytes(32)
|
||||
for i := 0; i < b.N; i++ {
|
||||
ScalarBaseMult(&out, &in)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,29 +7,18 @@
|
|||
|
||||
// +build amd64,!gccgo,!appengine
|
||||
|
||||
#include "const_amd64.h"
|
||||
|
||||
// func freeze(inout *[5]uint64)
|
||||
TEXT ·freeze(SB),7,$96-8
|
||||
TEXT ·freeze(SB),7,$0-8
|
||||
MOVQ inout+0(FP), DI
|
||||
|
||||
MOVQ SP,R11
|
||||
MOVQ $31,CX
|
||||
NOTQ CX
|
||||
ANDQ CX,SP
|
||||
ADDQ $32,SP
|
||||
|
||||
MOVQ R11,0(SP)
|
||||
MOVQ R12,8(SP)
|
||||
MOVQ R13,16(SP)
|
||||
MOVQ R14,24(SP)
|
||||
MOVQ R15,32(SP)
|
||||
MOVQ BX,40(SP)
|
||||
MOVQ BP,48(SP)
|
||||
MOVQ 0(DI),SI
|
||||
MOVQ 8(DI),DX
|
||||
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
|
||||
|
@ -81,14 +70,4 @@ REDUCELOOP:
|
|||
MOVQ CX,16(DI)
|
||||
MOVQ R8,24(DI)
|
||||
MOVQ R9,32(DI)
|
||||
MOVQ 0(SP),R11
|
||||
MOVQ 8(SP),R12
|
||||
MOVQ 16(SP),R13
|
||||
MOVQ 24(SP),R14
|
||||
MOVQ 32(SP),R15
|
||||
MOVQ 40(SP),BX
|
||||
MOVQ 48(SP),BP
|
||||
MOVQ R11,SP
|
||||
MOVQ DI,AX
|
||||
MOVQ SI,DX
|
||||
RET
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -7,36 +7,24 @@
|
|||
|
||||
// +build amd64,!gccgo,!appengine
|
||||
|
||||
#include "const_amd64.h"
|
||||
|
||||
// func mul(dest, a, b *[5]uint64)
|
||||
TEXT ·mul(SB),0,$128-24
|
||||
TEXT ·mul(SB),0,$16-24
|
||||
MOVQ dest+0(FP), DI
|
||||
MOVQ a+8(FP), SI
|
||||
MOVQ b+16(FP), DX
|
||||
|
||||
MOVQ SP,R11
|
||||
MOVQ $31,CX
|
||||
NOTQ CX
|
||||
ANDQ CX,SP
|
||||
ADDQ $32,SP
|
||||
|
||||
MOVQ R11,0(SP)
|
||||
MOVQ R12,8(SP)
|
||||
MOVQ R13,16(SP)
|
||||
MOVQ R14,24(SP)
|
||||
MOVQ R15,32(SP)
|
||||
MOVQ BX,40(SP)
|
||||
MOVQ BP,48(SP)
|
||||
MOVQ DI,56(SP)
|
||||
MOVQ DX,CX
|
||||
MOVQ 24(SI),DX
|
||||
IMUL3Q $19,DX,AX
|
||||
MOVQ AX,64(SP)
|
||||
MOVQ AX,0(SP)
|
||||
MULQ 16(CX)
|
||||
MOVQ AX,R8
|
||||
MOVQ DX,R9
|
||||
MOVQ 32(SI),DX
|
||||
IMUL3Q $19,DX,AX
|
||||
MOVQ AX,72(SP)
|
||||
MOVQ AX,8(SP)
|
||||
MULQ 8(CX)
|
||||
ADDQ AX,R8
|
||||
ADCQ DX,R9
|
||||
|
@ -111,11 +99,11 @@ TEXT ·mul(SB),0,$128-24
|
|||
MULQ 8(CX)
|
||||
ADDQ AX,BX
|
||||
ADCQ DX,BP
|
||||
MOVQ 64(SP),AX
|
||||
MOVQ 0(SP),AX
|
||||
MULQ 24(CX)
|
||||
ADDQ AX,R10
|
||||
ADCQ DX,R11
|
||||
MOVQ 64(SP),AX
|
||||
MOVQ 0(SP),AX
|
||||
MULQ 32(CX)
|
||||
ADDQ AX,R12
|
||||
ADCQ DX,R13
|
||||
|
@ -123,19 +111,19 @@ TEXT ·mul(SB),0,$128-24
|
|||
MULQ 0(CX)
|
||||
ADDQ AX,BX
|
||||
ADCQ DX,BP
|
||||
MOVQ 72(SP),AX
|
||||
MOVQ 8(SP),AX
|
||||
MULQ 16(CX)
|
||||
ADDQ AX,R10
|
||||
ADCQ DX,R11
|
||||
MOVQ 72(SP),AX
|
||||
MOVQ 8(SP),AX
|
||||
MULQ 24(CX)
|
||||
ADDQ AX,R12
|
||||
ADCQ DX,R13
|
||||
MOVQ 72(SP),AX
|
||||
MOVQ 8(SP),AX
|
||||
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
|
||||
|
@ -178,14 +166,4 @@ TEXT ·mul(SB),0,$128-24
|
|||
MOVQ R9,16(DI)
|
||||
MOVQ AX,24(DI)
|
||||
MOVQ R10,32(DI)
|
||||
MOVQ 0(SP),R11
|
||||
MOVQ 8(SP),R12
|
||||
MOVQ 16(SP),R13
|
||||
MOVQ 24(SP),R14
|
||||
MOVQ 32(SP),R15
|
||||
MOVQ 40(SP),BX
|
||||
MOVQ 48(SP),BP
|
||||
MOVQ R11,SP
|
||||
MOVQ DI,AX
|
||||
MOVQ SI,DX
|
||||
RET
|
||||
|
|
|
@ -7,24 +7,13 @@
|
|||
|
||||
// +build amd64,!gccgo,!appengine
|
||||
|
||||
#include "const_amd64.h"
|
||||
|
||||
// func square(out, in *[5]uint64)
|
||||
TEXT ·square(SB),7,$96-16
|
||||
TEXT ·square(SB),7,$0-16
|
||||
MOVQ out+0(FP), DI
|
||||
MOVQ in+8(FP), SI
|
||||
|
||||
MOVQ SP,R11
|
||||
MOVQ $31,CX
|
||||
NOTQ CX
|
||||
ANDQ CX,SP
|
||||
ADDQ $32, SP
|
||||
|
||||
MOVQ R11,0(SP)
|
||||
MOVQ R12,8(SP)
|
||||
MOVQ R13,16(SP)
|
||||
MOVQ R14,24(SP)
|
||||
MOVQ R15,32(SP)
|
||||
MOVQ BX,40(SP)
|
||||
MOVQ BP,48(SP)
|
||||
MOVQ 0(SI),AX
|
||||
MULQ 0(SI)
|
||||
MOVQ AX,CX
|
||||
|
@ -97,7 +86,7 @@ TEXT ·square(SB),7,$96-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
|
||||
|
@ -140,14 +129,4 @@ TEXT ·square(SB),7,$96-16
|
|||
MOVQ R9,16(DI)
|
||||
MOVQ AX,24(DI)
|
||||
MOVQ R10,32(DI)
|
||||
MOVQ 0(SP),R11
|
||||
MOVQ 8(SP),R12
|
||||
MOVQ 16(SP),R13
|
||||
MOVQ 24(SP),R14
|
||||
MOVQ 32(SP),R15
|
||||
MOVQ 40(SP),BX
|
||||
MOVQ 48(SP),BP
|
||||
MOVQ R11,SP
|
||||
MOVQ DI,AX
|
||||
MOVQ SI,DX
|
||||
RET
|
||||
|
|
|
@ -6,10 +6,14 @@ package poly1305
|
|||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/hex"
|
||||
"flag"
|
||||
"testing"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
var stressFlag = flag.Bool("stress", false, "run slow stress tests")
|
||||
|
||||
var testData = []struct {
|
||||
in, k, correct []byte
|
||||
}{
|
||||
|
@ -39,6 +43,36 @@ var testData = []struct {
|
|||
[]byte{0x3b, 0x3a, 0x29, 0xe9, 0x3b, 0x21, 0x3a, 0x5c, 0x5c, 0x3b, 0x3b, 0x05, 0x3a, 0x3a, 0x8c, 0x0d},
|
||||
[]byte{0x6d, 0xc1, 0x8b, 0x8c, 0x34, 0x4c, 0xd7, 0x99, 0x27, 0x11, 0x8b, 0xbe, 0x84, 0xb7, 0xf3, 0x14},
|
||||
},
|
||||
{
|
||||
// This test generates a result of (2^130-1) % (2^130-5).
|
||||
[]byte{
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
},
|
||||
[]byte{1, 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},
|
||||
[]byte{4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
|
||||
},
|
||||
{
|
||||
// This test generates a result of (2^130-6) % (2^130-5).
|
||||
[]byte{
|
||||
0xfa, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
},
|
||||
[]byte{1, 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},
|
||||
[]byte{0xfa, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
|
||||
},
|
||||
{
|
||||
// This test generates a result of (2^130-5) % (2^130-5).
|
||||
[]byte{
|
||||
0xfb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
},
|
||||
[]byte{1, 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},
|
||||
[]byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
|
||||
},
|
||||
}
|
||||
|
||||
func testSum(t *testing.T, unaligned bool) {
|
||||
|
@ -58,6 +92,39 @@ func testSum(t *testing.T, unaligned bool) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestBurnin(t *testing.T) {
|
||||
// This test can be used to sanity-check significant changes. It can
|
||||
// take about many minutes to run, even on fast machines. It's disabled
|
||||
// by default.
|
||||
if !*stressFlag {
|
||||
t.Skip("skipping without -stress")
|
||||
}
|
||||
|
||||
var key [32]byte
|
||||
var input [25]byte
|
||||
var output [16]byte
|
||||
|
||||
for i := range key {
|
||||
key[i] = 1
|
||||
}
|
||||
for i := range input {
|
||||
input[i] = 2
|
||||
}
|
||||
|
||||
for i := uint64(0); i < 1e10; i++ {
|
||||
Sum(&output, input[:], &key)
|
||||
copy(key[0:], output[:])
|
||||
copy(key[16:], output[:])
|
||||
copy(input[:], output[:])
|
||||
copy(input[16:], output[:])
|
||||
}
|
||||
|
||||
const expected = "5e3b866aea0b636d240c83c428f84bfa"
|
||||
if got := hex.EncodeToString(output[:]); got != expected {
|
||||
t.Errorf("expected %s, got %s", expected, got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSum(t *testing.T) { testSum(t, false) }
|
||||
func TestSumUnaligned(t *testing.T) { testSum(t, true) }
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build amd64,!gccgo,!appengine,go1.7
|
||||
// +build amd64,!gccgo,!appengine
|
||||
|
||||
package poly1305
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build amd64,!gccgo,!appengine,go1.7
|
||||
// +build amd64,!gccgo,!appengine
|
||||
|
||||
#include "textflag.h"
|
||||
|
||||
|
@ -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
|
||||
|
|
253
vendor/src/golang.org/x/crypto/poly1305/sum_arm.s
vendored
253
vendor/src/golang.org/x/crypto/poly1305/sum_arm.s
vendored
|
@ -2,27 +2,32 @@
|
|||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build arm,!gccgo,!appengine,!nacl
|
||||
|
||||
#include "textflag.h"
|
||||
|
||||
// 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.
|
||||
|
||||
// +build arm,!gccgo,!appengine,!nacl
|
||||
|
||||
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.
|
||||
|
||||
TEXT poly1305_init_ext_armv6<>(SB), NOSPLIT|NOFRAME, $0
|
||||
MOVM.DB.W [R4-R11], (R13)
|
||||
TEXT poly1305_init_ext_armv6<>(SB), NOSPLIT, $0
|
||||
// Needs 16 bytes of stack and 64 bytes of space pointed to by R0. (It
|
||||
// might look like it's only 60 bytes of space but the final four bytes
|
||||
// will be written by another function.) We need to skip over four
|
||||
// bytes of stack because that's saving the value of 'g'.
|
||||
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
|
||||
|
@ -46,7 +51,8 @@ TEXT poly1305_init_ext_armv6<>(SB), NOSPLIT|NOFRAME, $0
|
|||
MOVM.IA.W [R2-R6], (R0)
|
||||
MOVM.IA.W (R1), [R2-R5]
|
||||
MOVM.IA [R2-R6], (R0)
|
||||
MOVM.IA.W (R13), [R4-R11]
|
||||
ADD $20, R13, R0
|
||||
MOVM.DA (R0), [R4-R7]
|
||||
RET
|
||||
|
||||
#define MOVW_UNALIGNED(Rsrc, Rdst, Rtmp, offset) \
|
||||
|
@ -59,29 +65,35 @@ TEXT poly1305_init_ext_armv6<>(SB), NOSPLIT|NOFRAME, $0
|
|||
MOVBU (offset+3)(Rsrc), Rtmp; \
|
||||
MOVBU Rtmp, (offset+3)(Rdst)
|
||||
|
||||
TEXT poly1305_blocks_armv6<>(SB), NOSPLIT|NOFRAME, $0
|
||||
MOVM.DB.W [R4, R5, R6, R7, R8, R9, g, R11, R14], (R13)
|
||||
SUB $128, R13
|
||||
MOVW R0, 36(R13)
|
||||
MOVW R1, 40(R13)
|
||||
MOVW R2, 44(R13)
|
||||
MOVW R1, R14
|
||||
MOVW R2, R12
|
||||
MOVW 56(R0), R8
|
||||
WORD $0xe1180008 // TST R8, R8 not working see issue 5921
|
||||
EOR R6, R6, R6
|
||||
MOVW.EQ $(1<<24), R6
|
||||
MOVW R6, 32(R13)
|
||||
ADD $64, R13, g
|
||||
MOVM.IA (R0), [R0-R9]
|
||||
MOVM.IA [R0-R4], (g)
|
||||
CMP $16, R12
|
||||
BLO poly1305_blocks_armv6_done
|
||||
TEXT poly1305_blocks_armv6<>(SB), NOSPLIT, $0
|
||||
// Needs 24 bytes of stack for saved registers and then 88 bytes of
|
||||
// scratch space after that. We assume that 24 bytes at (R13) have
|
||||
// already been used: four bytes for the link register saved in the
|
||||
// prelude of poly1305_auth_armv6, four bytes for saving the value of g
|
||||
// in that function and 16 bytes of scratch space used around
|
||||
// poly1305_finish_ext_armv6_skip1.
|
||||
ADD $24, R13, R12
|
||||
MOVM.IB [R4-R8, R14], (R12)
|
||||
MOVW R0, 88(R13)
|
||||
MOVW R1, 92(R13)
|
||||
MOVW R2, 96(R13)
|
||||
MOVW R1, R14
|
||||
MOVW R2, R12
|
||||
MOVW 56(R0), R8
|
||||
WORD $0xe1180008 // TST R8, R8 not working see issue 5921
|
||||
EOR R6, R6, R6
|
||||
MOVW.EQ $(1<<24), R6
|
||||
MOVW R6, 84(R13)
|
||||
ADD $116, R13, g
|
||||
MOVM.IA (R0), [R0-R9]
|
||||
MOVM.IA [R0-R4], (g)
|
||||
CMP $16, R12
|
||||
BLO poly1305_blocks_armv6_done
|
||||
|
||||
poly1305_blocks_armv6_mainloop:
|
||||
WORD $0xe31e0003 // TST R14, #3 not working see issue 5921
|
||||
BEQ poly1305_blocks_armv6_mainloop_aligned
|
||||
ADD $48, R13, g
|
||||
ADD $100, R13, g
|
||||
MOVW_UNALIGNED(R14, g, R0, 0)
|
||||
MOVW_UNALIGNED(R14, g, R0, 4)
|
||||
MOVW_UNALIGNED(R14, g, R0, 8)
|
||||
|
@ -97,21 +109,21 @@ poly1305_blocks_armv6_mainloop_loaded:
|
|||
MOVW R0>>26, g
|
||||
MOVW R1>>20, R11
|
||||
MOVW R2>>14, R12
|
||||
MOVW R14, 40(R13)
|
||||
MOVW R14, 92(R13)
|
||||
MOVW R3>>8, R4
|
||||
ORR R1<<6, g, g
|
||||
ORR R2<<12, R11, R11
|
||||
ORR R3<<18, R12, R12
|
||||
BIC $0xfc000000, R0, R0
|
||||
BIC $0xfc000000, g, g
|
||||
MOVW 32(R13), R3
|
||||
MOVW 84(R13), R3
|
||||
BIC $0xfc000000, R11, R11
|
||||
BIC $0xfc000000, R12, R12
|
||||
ADD R0, R5, R5
|
||||
ADD g, R6, R6
|
||||
ORR R3, R4, R4
|
||||
ADD R11, R7, R7
|
||||
ADD $64, R13, R14
|
||||
ADD $116, R13, R14
|
||||
ADD R12, R8, R8
|
||||
ADD R4, R9, R9
|
||||
MOVM.IA (R14), [R0-R4]
|
||||
|
@ -127,10 +139,10 @@ poly1305_blocks_armv6_mainloop_loaded:
|
|||
MULALU R0, R8, (R14, R12)
|
||||
MULALU R0, R9, (R11, g)
|
||||
MULALU R4, R9, (R14, R12)
|
||||
MOVW g, 24(R13)
|
||||
MOVW R11, 28(R13)
|
||||
MOVW R12, 16(R13)
|
||||
MOVW R14, 20(R13)
|
||||
MOVW g, 76(R13)
|
||||
MOVW R11, 80(R13)
|
||||
MOVW R12, 68(R13)
|
||||
MOVW R14, 72(R13)
|
||||
MULLU R2, R5, (R11, g)
|
||||
MULLU R1, R5, (R14, R12)
|
||||
MULALU R1, R6, (R11, g)
|
||||
|
@ -143,16 +155,17 @@ poly1305_blocks_armv6_mainloop_loaded:
|
|||
MULALU R3, R8, (R14, R12)
|
||||
MULALU R3, R9, (R11, g)
|
||||
MULALU R2, R9, (R14, R12)
|
||||
MOVW g, 8(R13)
|
||||
MOVW R11, 12(R13)
|
||||
MOVW R12, 0(R13)
|
||||
MOVW R14, w+4(SP)
|
||||
MOVW g, 60(R13)
|
||||
MOVW R11, 64(R13)
|
||||
MOVW R12, 52(R13)
|
||||
MOVW R14, 56(R13)
|
||||
MULLU R0, R5, (R11, g)
|
||||
MULALU R4, R6, (R11, g)
|
||||
MULALU R3, R7, (R11, g)
|
||||
MULALU R2, R8, (R11, g)
|
||||
MULALU R1, R9, (R11, g)
|
||||
MOVM.IA (R13), [R0-R7]
|
||||
ADD $52, R13, R0
|
||||
MOVM.IA (R0), [R0-R7]
|
||||
MOVW g>>26, R12
|
||||
MOVW R4>>26, R14
|
||||
ORR R11<<6, R12, R12
|
||||
|
@ -183,23 +196,23 @@ poly1305_blocks_armv6_mainloop_loaded:
|
|||
MOVW R4>>26, R12
|
||||
BIC $0xfc000000, R4, R8
|
||||
ADD R12, R6, R9
|
||||
MOVW w+44(SP), R12
|
||||
MOVW w+40(SP), R14
|
||||
MOVW 96(R13), R12
|
||||
MOVW 92(R13), R14
|
||||
MOVW R0, R6
|
||||
CMP $32, R12
|
||||
SUB $16, R12, R12
|
||||
MOVW R12, 44(R13)
|
||||
MOVW R12, 96(R13)
|
||||
BHS poly1305_blocks_armv6_mainloop
|
||||
|
||||
poly1305_blocks_armv6_done:
|
||||
MOVW 36(R13), R12
|
||||
MOVW R5, 20(R12)
|
||||
MOVW R6, 24(R12)
|
||||
MOVW R7, 28(R12)
|
||||
MOVW R8, 32(R12)
|
||||
MOVW R9, 36(R12)
|
||||
ADD $128, R13, R13
|
||||
MOVM.IA.W (R13), [R4, R5, R6, R7, R8, R9, g, R11, R14]
|
||||
MOVW 88(R13), R12
|
||||
MOVW R5, 20(R12)
|
||||
MOVW R6, 24(R12)
|
||||
MOVW R7, 28(R12)
|
||||
MOVW R8, 32(R12)
|
||||
MOVW R9, 36(R12)
|
||||
ADD $48, R13, R0
|
||||
MOVM.DA (R0), [R4-R8, R14]
|
||||
RET
|
||||
|
||||
#define MOVHUP_UNALIGNED(Rsrc, Rdst, Rtmp) \
|
||||
|
@ -212,25 +225,76 @@ poly1305_blocks_armv6_done:
|
|||
MOVHUP_UNALIGNED(Rsrc, Rdst, Rtmp); \
|
||||
MOVHUP_UNALIGNED(Rsrc, Rdst, Rtmp)
|
||||
|
||||
TEXT poly1305_finish_ext_armv6<>(SB), NOSPLIT | NOFRAME, $0
|
||||
MOVM.DB.W [R4, R5, R6, R7, R8, R9, g, R11, R14], (R13)
|
||||
SUB $16, R13, R13
|
||||
MOVW R0, R5
|
||||
MOVW R1, R6
|
||||
MOVW R2, R7
|
||||
MOVW R3, R8
|
||||
AND.S R2, R2, R2
|
||||
BEQ poly1305_finish_ext_armv6_noremaining
|
||||
EOR R0, R0
|
||||
MOVW R13, R9
|
||||
MOVW R0, 0(R13)
|
||||
MOVW R0, 4(R13)
|
||||
MOVW R0, 8(R13)
|
||||
MOVW R0, 12(R13)
|
||||
WORD $0xe3110003 // TST R1, #3 not working see issue 5921
|
||||
BEQ poly1305_finish_ext_armv6_aligned
|
||||
WORD $0xe3120008 // TST R2, #8 not working see issue 5921
|
||||
BEQ poly1305_finish_ext_armv6_skip8
|
||||
// func poly1305_auth_armv6(out *[16]byte, m *byte, mlen uint32, key *[32]key)
|
||||
TEXT ·poly1305_auth_armv6(SB), $196-16
|
||||
// The value 196, just above, is the sum of 64 (the size of the context
|
||||
// structure) and 132 (the amount of stack needed).
|
||||
//
|
||||
// At this point, the stack pointer (R13) has been moved down. It
|
||||
// points to the saved link register and there's 196 bytes of free
|
||||
// space above it.
|
||||
//
|
||||
// The stack for this function looks like:
|
||||
//
|
||||
// +---------------------
|
||||
// |
|
||||
// | 64 bytes of context structure
|
||||
// |
|
||||
// +---------------------
|
||||
// |
|
||||
// | 112 bytes for poly1305_blocks_armv6
|
||||
// |
|
||||
// +---------------------
|
||||
// | 16 bytes of final block, constructed at
|
||||
// | poly1305_finish_ext_armv6_skip8
|
||||
// +---------------------
|
||||
// | four bytes of saved 'g'
|
||||
// +---------------------
|
||||
// | lr, saved by prelude <- R13 points here
|
||||
// +---------------------
|
||||
MOVW g, 4(R13)
|
||||
|
||||
MOVW out+0(FP), R4
|
||||
MOVW m+4(FP), R5
|
||||
MOVW mlen+8(FP), R6
|
||||
MOVW key+12(FP), R7
|
||||
|
||||
ADD $136, R13, R0 // 136 = 4 + 4 + 16 + 112
|
||||
MOVW R7, R1
|
||||
|
||||
// poly1305_init_ext_armv6 will write to the stack from R13+4, but
|
||||
// that's ok because none of the other values have been written yet.
|
||||
BL poly1305_init_ext_armv6<>(SB)
|
||||
BIC.S $15, R6, R2
|
||||
BEQ poly1305_auth_armv6_noblocks
|
||||
ADD $136, R13, R0
|
||||
MOVW R5, R1
|
||||
ADD R2, R5, R5
|
||||
SUB R2, R6, R6
|
||||
BL poly1305_blocks_armv6<>(SB)
|
||||
|
||||
poly1305_auth_armv6_noblocks:
|
||||
ADD $136, R13, R0
|
||||
MOVW R5, R1
|
||||
MOVW R6, R2
|
||||
MOVW R4, R3
|
||||
|
||||
MOVW R0, R5
|
||||
MOVW R1, R6
|
||||
MOVW R2, R7
|
||||
MOVW R3, R8
|
||||
AND.S R2, R2, R2
|
||||
BEQ poly1305_finish_ext_armv6_noremaining
|
||||
EOR R0, R0
|
||||
ADD $8, R13, R9 // 8 = offset to 16 byte scratch space
|
||||
MOVW R0, (R9)
|
||||
MOVW R0, 4(R9)
|
||||
MOVW R0, 8(R9)
|
||||
MOVW R0, 12(R9)
|
||||
WORD $0xe3110003 // TST R1, #3 not working see issue 5921
|
||||
BEQ poly1305_finish_ext_armv6_aligned
|
||||
WORD $0xe3120008 // TST R2, #8 not working see issue 5921
|
||||
BEQ poly1305_finish_ext_armv6_skip8
|
||||
MOVWP_UNALIGNED(R1, R9, g)
|
||||
MOVWP_UNALIGNED(R1, R9, g)
|
||||
|
||||
|
@ -274,7 +338,7 @@ poly1305_finish_ext_armv6_skip1:
|
|||
MOVBU R11, 0(R9)
|
||||
MOVW R11, 56(R5)
|
||||
MOVW R5, R0
|
||||
MOVW R13, R1
|
||||
ADD $8, R13, R1
|
||||
MOVW $16, R2
|
||||
BL poly1305_blocks_armv6<>(SB)
|
||||
|
||||
|
@ -313,14 +377,14 @@ poly1305_finish_ext_armv6_noremaining:
|
|||
MOVW $-(1<<26), R12
|
||||
ADD R11>>26, R12, R12
|
||||
BIC $0xfc000000, R11, R11
|
||||
ADD R12, R4, R14
|
||||
MOVW R14>>31, R12
|
||||
ADD R12, R4, R9
|
||||
MOVW R9>>31, R12
|
||||
SUB $1, R12
|
||||
AND R12, R6, R6
|
||||
AND R12, R7, R7
|
||||
AND R12, g, g
|
||||
AND R12, R11, R11
|
||||
AND R12, R14, R14
|
||||
AND R12, R9, R9
|
||||
MVN R12, R12
|
||||
AND R12, R0, R0
|
||||
AND R12, R1, R1
|
||||
|
@ -331,7 +395,7 @@ poly1305_finish_ext_armv6_noremaining:
|
|||
ORR R7, R1, R1
|
||||
ORR g, R2, R2
|
||||
ORR R11, R3, R3
|
||||
ORR R14, R4, R4
|
||||
ORR R9, R4, R4
|
||||
ORR R1<<26, R0, R0
|
||||
MOVW R1>>6, R1
|
||||
ORR R2<<20, R1, R1
|
||||
|
@ -359,36 +423,5 @@ poly1305_finish_ext_armv6_noremaining:
|
|||
EOR R7, R7, R7
|
||||
MOVM.IA.W [R0-R7], (R12)
|
||||
MOVM.IA [R0-R7], (R12)
|
||||
ADD $16, R13, R13
|
||||
MOVM.IA.W (R13), [R4, R5, R6, R7, R8, R9, g, R11, R14]
|
||||
RET
|
||||
|
||||
// func poly1305_auth_armv6(out *[16]byte, m *byte, mlen uint32, key *[32]key)
|
||||
TEXT ·poly1305_auth_armv6(SB), $280-16
|
||||
MOVW out+0(FP), R4
|
||||
MOVW m+4(FP), R5
|
||||
MOVW mlen+8(FP), R6
|
||||
MOVW key+12(FP), R7
|
||||
|
||||
MOVW R13, R8
|
||||
BIC $63, R13
|
||||
SUB $64, R13, R13
|
||||
MOVW R13, R0
|
||||
MOVW R7, R1
|
||||
BL poly1305_init_ext_armv6<>(SB)
|
||||
BIC.S $15, R6, R2
|
||||
BEQ poly1305_auth_armv6_noblocks
|
||||
MOVW R13, R0
|
||||
MOVW R5, R1
|
||||
ADD R2, R5, R5
|
||||
SUB R2, R6, R6
|
||||
BL poly1305_blocks_armv6<>(SB)
|
||||
|
||||
poly1305_auth_armv6_noblocks:
|
||||
MOVW R13, R0
|
||||
MOVW R5, R1
|
||||
MOVW R6, R2
|
||||
MOVW R4, R3
|
||||
BL poly1305_finish_ext_armv6<>(SB)
|
||||
MOVW R8, R13
|
||||
MOVW 4(R13), g
|
||||
RET
|
||||
|
|
1616
vendor/src/golang.org/x/crypto/poly1305/sum_ref.go
vendored
1616
vendor/src/golang.org/x/crypto/poly1305/sum_ref.go
vendored
File diff suppressed because it is too large
Load diff
|
@ -86,6 +86,11 @@ func testAgent(t *testing.T, key interface{}, cert *ssh.Certificate, lifetimeSec
|
|||
testAgentInterface(t, agent, key, cert, lifetimeSecs)
|
||||
}
|
||||
|
||||
func testKeyring(t *testing.T, key interface{}, cert *ssh.Certificate, lifetimeSecs uint32) {
|
||||
a := NewKeyring()
|
||||
testAgentInterface(t, a, key, cert, lifetimeSecs)
|
||||
}
|
||||
|
||||
func testAgentInterface(t *testing.T, agent Agent, key interface{}, cert *ssh.Certificate, lifetimeSecs uint32) {
|
||||
signer, err := ssh.NewSignerFromKey(key)
|
||||
if err != nil {
|
||||
|
@ -137,11 +142,25 @@ func testAgentInterface(t *testing.T, agent Agent, key interface{}, cert *ssh.Ce
|
|||
if err := pubKey.Verify(data, sig); err != nil {
|
||||
t.Fatalf("Verify(%s): %v", pubKey.Type(), err)
|
||||
}
|
||||
|
||||
// If the key has a lifetime, is it removed when it should be?
|
||||
if lifetimeSecs > 0 {
|
||||
time.Sleep(time.Second*time.Duration(lifetimeSecs) + 100*time.Millisecond)
|
||||
keys, err := agent.List()
|
||||
if err != nil {
|
||||
t.Fatalf("List: %v", err)
|
||||
}
|
||||
if len(keys) > 0 {
|
||||
t.Fatalf("key not expired")
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func TestAgent(t *testing.T) {
|
||||
for _, keyType := range []string{"rsa", "dsa", "ecdsa", "ed25519"} {
|
||||
testAgent(t, testPrivateKeys[keyType], nil, 0)
|
||||
testKeyring(t, testPrivateKeys[keyType], nil, 1)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -154,17 +173,14 @@ func TestCert(t *testing.T) {
|
|||
cert.SignCert(rand.Reader, testSigners["ecdsa"])
|
||||
|
||||
testAgent(t, testPrivateKeys["rsa"], cert, 0)
|
||||
}
|
||||
|
||||
func TestConstraints(t *testing.T) {
|
||||
testAgent(t, testPrivateKeys["rsa"], nil, 3600 /* lifetime in seconds */)
|
||||
testKeyring(t, testPrivateKeys["rsa"], cert, 1)
|
||||
}
|
||||
|
||||
// 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")
|
||||
listener, err := net.Listen("tcp", ":0")
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
@ -217,7 +233,9 @@ func TestAuth(t *testing.T) {
|
|||
conn.Close()
|
||||
}()
|
||||
|
||||
conf := ssh.ClientConfig{}
|
||||
conf := ssh.ClientConfig{
|
||||
HostKeyCallback: ssh.InsecureIgnoreHostKey(),
|
||||
}
|
||||
conf.Auth = append(conf.Auth, ssh.PublicKeysCallback(agent.Signers))
|
||||
conn, _, _, err := ssh.NewClientConn(b, "", &conf)
|
||||
if err != nil {
|
||||
|
|
|
@ -6,20 +6,20 @@ package agent_test
|
|||
|
||||
import (
|
||||
"log"
|
||||
"os"
|
||||
"net"
|
||||
"os"
|
||||
|
||||
"golang.org/x/crypto/ssh"
|
||||
"golang.org/x/crypto/ssh/agent"
|
||||
"golang.org/x/crypto/ssh"
|
||||
"golang.org/x/crypto/ssh/agent"
|
||||
)
|
||||
|
||||
func ExampleClientAgent() {
|
||||
// ssh-agent has a UNIX socket under $SSH_AUTH_SOCK
|
||||
socket := os.Getenv("SSH_AUTH_SOCK")
|
||||
conn, err := net.Dial("unix", socket)
|
||||
if err != nil {
|
||||
log.Fatalf("net.Dial: %v", err)
|
||||
}
|
||||
conn, err := net.Dial("unix", socket)
|
||||
if err != nil {
|
||||
log.Fatalf("net.Dial: %v", err)
|
||||
}
|
||||
agentClient := agent.NewClient(conn)
|
||||
config := &ssh.ClientConfig{
|
||||
User: "username",
|
||||
|
@ -29,6 +29,7 @@ func ExampleClientAgent() {
|
|||
// wants it.
|
||||
ssh.PublicKeysCallback(agentClient.Signers),
|
||||
},
|
||||
HostKeyCallback: ssh.InsecureIgnoreHostKey(),
|
||||
}
|
||||
|
||||
sshc, err := ssh.Dial("tcp", "localhost:22", config)
|
||||
|
|
|
@ -11,6 +11,7 @@ import (
|
|||
"errors"
|
||||
"fmt"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"golang.org/x/crypto/ssh"
|
||||
)
|
||||
|
@ -18,6 +19,7 @@ import (
|
|||
type privKey struct {
|
||||
signer ssh.Signer
|
||||
comment string
|
||||
expire *time.Time
|
||||
}
|
||||
|
||||
type keyring struct {
|
||||
|
@ -48,15 +50,9 @@ func (r *keyring) RemoveAll() error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// Remove removes all identities with the given public key.
|
||||
func (r *keyring) Remove(key ssh.PublicKey) error {
|
||||
r.mu.Lock()
|
||||
defer r.mu.Unlock()
|
||||
if r.locked {
|
||||
return errLocked
|
||||
}
|
||||
|
||||
want := key.Marshal()
|
||||
// removeLocked does the actual key removal. The caller must already be holding the
|
||||
// keyring mutex.
|
||||
func (r *keyring) removeLocked(want []byte) error {
|
||||
found := false
|
||||
for i := 0; i < len(r.keys); {
|
||||
if bytes.Equal(r.keys[i].signer.PublicKey().Marshal(), want) {
|
||||
|
@ -75,7 +71,18 @@ func (r *keyring) Remove(key ssh.PublicKey) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// Lock locks the agent. Sign and Remove will fail, and List will empty an empty list.
|
||||
// Remove removes all identities with the given public key.
|
||||
func (r *keyring) Remove(key ssh.PublicKey) error {
|
||||
r.mu.Lock()
|
||||
defer r.mu.Unlock()
|
||||
if r.locked {
|
||||
return errLocked
|
||||
}
|
||||
|
||||
return r.removeLocked(key.Marshal())
|
||||
}
|
||||
|
||||
// Lock locks the agent. Sign and Remove will fail, and List will return an empty list.
|
||||
func (r *keyring) Lock(passphrase []byte) error {
|
||||
r.mu.Lock()
|
||||
defer r.mu.Unlock()
|
||||
|
@ -104,6 +111,17 @@ func (r *keyring) Unlock(passphrase []byte) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// expireKeysLocked removes expired keys from the keyring. If a key was added
|
||||
// with a lifetimesecs contraint and seconds >= lifetimesecs seconds have
|
||||
// ellapsed, it is removed. The caller *must* be holding the keyring mutex.
|
||||
func (r *keyring) expireKeysLocked() {
|
||||
for _, k := range r.keys {
|
||||
if k.expire != nil && time.Now().After(*k.expire) {
|
||||
r.removeLocked(k.signer.PublicKey().Marshal())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// List returns the identities known to the agent.
|
||||
func (r *keyring) List() ([]*Key, error) {
|
||||
r.mu.Lock()
|
||||
|
@ -113,6 +131,7 @@ func (r *keyring) List() ([]*Key, error) {
|
|||
return nil, nil
|
||||
}
|
||||
|
||||
r.expireKeysLocked()
|
||||
var ids []*Key
|
||||
for _, k := range r.keys {
|
||||
pub := k.signer.PublicKey()
|
||||
|
@ -146,7 +165,17 @@ func (r *keyring) Add(key AddedKey) error {
|
|||
}
|
||||
}
|
||||
|
||||
r.keys = append(r.keys, privKey{signer, key.Comment})
|
||||
p := privKey{
|
||||
signer: signer,
|
||||
comment: key.Comment,
|
||||
}
|
||||
|
||||
if key.LifetimeSecs > 0 {
|
||||
t := time.Now().Add(time.Duration(key.LifetimeSecs) * time.Second)
|
||||
p.expire = &t
|
||||
}
|
||||
|
||||
r.keys = append(r.keys, p)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
@ -159,6 +188,7 @@ func (r *keyring) Sign(key ssh.PublicKey, data []byte) (*ssh.Signature, error) {
|
|||
return nil, errLocked
|
||||
}
|
||||
|
||||
r.expireKeysLocked()
|
||||
wanted := key.Marshal()
|
||||
for _, k := range r.keys {
|
||||
if bytes.Equal(k.signer.PublicKey().Marshal(), wanted) {
|
||||
|
@ -176,6 +206,7 @@ func (r *keyring) Signers() ([]ssh.Signer, error) {
|
|||
return nil, errLocked
|
||||
}
|
||||
|
||||
r.expireKeysLocked()
|
||||
s := make([]ssh.Signer, 0, len(r.keys))
|
||||
for _, k := range r.keys {
|
||||
s = append(s, k.signer)
|
||||
|
|
|
@ -4,9 +4,7 @@
|
|||
|
||||
package agent
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
import "testing"
|
||||
|
||||
func addTestKey(t *testing.T, a Agent, keyName string) {
|
||||
err := a.Add(AddedKey{
|
||||
|
|
|
@ -56,7 +56,9 @@ func TestSetupForwardAgent(t *testing.T) {
|
|||
incoming <- conn
|
||||
}()
|
||||
|
||||
conf := ssh.ClientConfig{}
|
||||
conf := ssh.ClientConfig{
|
||||
HostKeyCallback: ssh.InsecureIgnoreHostKey(),
|
||||
}
|
||||
conn, chans, reqs, err := ssh.NewClientConn(b, "", &conf)
|
||||
if err != nil {
|
||||
t.Fatalf("NewClientConn: %v", err)
|
||||
|
|
2
vendor/src/golang.org/x/crypto/ssh/certs.go
vendored
2
vendor/src/golang.org/x/crypto/ssh/certs.go
vendored
|
@ -268,7 +268,7 @@ type CertChecker struct {
|
|||
// HostKeyFallback is called when CertChecker.CheckHostKey encounters a
|
||||
// public key that is not a certificate. It must implement host key
|
||||
// validation or else, if nil, all such keys are rejected.
|
||||
HostKeyFallback func(addr string, remote net.Addr, key PublicKey) error
|
||||
HostKeyFallback HostKeyCallback
|
||||
|
||||
// IsRevoked is called for each certificate so that revocation checking
|
||||
// can be implemented. It should return true if the given certificate
|
||||
|
|
|
@ -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/src/golang.org/x/crypto/ssh/cipher.go
vendored
64
vendor/src/golang.org/x/crypto/ssh/cipher.go
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
|
||||
}
|
||||
|
|
|
@ -26,39 +26,41 @@ func TestPacketCiphers(t *testing.T) {
|
|||
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
|
||||
}
|
||||
for mac := range macModes {
|
||||
kr := &kexResult{Hash: crypto.SHA1}
|
||||
algs := directionAlgorithms{
|
||||
Cipher: cipher,
|
||||
MAC: mac,
|
||||
Compression: "none",
|
||||
}
|
||||
client, err := newPacketCipher(clientKeys, algs, kr)
|
||||
if err != nil {
|
||||
t.Errorf("newPacketCipher(client, %q, %q): %v", cipher, mac, err)
|
||||
continue
|
||||
}
|
||||
server, err := newPacketCipher(clientKeys, algs, kr)
|
||||
if err != nil {
|
||||
t.Errorf("newPacketCipher(client, %q, %q): %v", cipher, mac, 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
|
||||
}
|
||||
want := "bla bla"
|
||||
input := []byte(want)
|
||||
buf := &bytes.Buffer{}
|
||||
if err := client.writePacket(0, buf, rand.Reader, input); err != nil {
|
||||
t.Errorf("writePacket(%q, %q): %v", cipher, mac, err)
|
||||
continue
|
||||
}
|
||||
|
||||
packet, err := server.readPacket(0, buf)
|
||||
if err != nil {
|
||||
t.Errorf("readPacket(%q): %v", cipher, err)
|
||||
continue
|
||||
}
|
||||
packet, err := server.readPacket(0, buf)
|
||||
if err != nil {
|
||||
t.Errorf("readPacket(%q, %q): %v", cipher, mac, err)
|
||||
continue
|
||||
}
|
||||
|
||||
if string(packet) != want {
|
||||
t.Errorf("roundtrip(%q): got %q, want %q", cipher, packet, want)
|
||||
if string(packet) != want {
|
||||
t.Errorf("roundtrip(%q, %q): got %q, want %q", cipher, mac, packet, want)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
62
vendor/src/golang.org/x/crypto/ssh/client.go
vendored
62
vendor/src/golang.org/x/crypto/ssh/client.go
vendored
|
@ -5,6 +5,7 @@
|
|||
package ssh
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net"
|
||||
|
@ -13,7 +14,7 @@ import (
|
|||
)
|
||||
|
||||
// Client implements a traditional SSH client that supports shells,
|
||||
// subprocesses, port forwarding and tunneled dialing.
|
||||
// subprocesses, TCP port/streamlocal forwarding and tunneled dialing.
|
||||
type Client struct {
|
||||
Conn
|
||||
|
||||
|
@ -40,7 +41,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
|
||||
}
|
||||
|
@ -59,6 +60,7 @@ func NewClient(c Conn, chans <-chan NewChannel, reqs <-chan *Request) *Client {
|
|||
conn.forwards.closeAll()
|
||||
}()
|
||||
go conn.forwards.handleChannels(conn.HandleChannelOpen("forwarded-tcpip"))
|
||||
go conn.forwards.handleChannels(conn.HandleChannelOpen("forwarded-streamlocal@openssh.com"))
|
||||
return conn
|
||||
}
|
||||
|
||||
|
@ -68,6 +70,11 @@ func NewClient(c Conn, chans <-chan NewChannel, reqs <-chan *Request) *Client {
|
|||
func NewClientConn(c net.Conn, addr string, config *ClientConfig) (Conn, <-chan NewChannel, <-chan *Request, error) {
|
||||
fullConf := *config
|
||||
fullConf.SetDefaults()
|
||||
if fullConf.HostKeyCallback == nil {
|
||||
c.Close()
|
||||
return nil, nil, nil, errors.New("ssh: must specify HostKeyCallback")
|
||||
}
|
||||
|
||||
conn := &connection{
|
||||
sshConn: sshConn{conn: c},
|
||||
}
|
||||
|
@ -97,13 +104,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)
|
||||
}
|
||||
|
||||
|
@ -175,6 +180,13 @@ func Dial(network, addr string, config *ClientConfig) (*Client, error) {
|
|||
return NewClient(c, chans, reqs), nil
|
||||
}
|
||||
|
||||
// HostKeyCallback is the function type used for verifying server
|
||||
// keys. A HostKeyCallback must return nil if the host key is OK, or
|
||||
// an error to reject it. It receives the hostname as passed to Dial
|
||||
// or NewClientConn. The remote address is the RemoteAddr of the
|
||||
// net.Conn underlying the the SSH connection.
|
||||
type HostKeyCallback func(hostname string, remote net.Addr, key PublicKey) error
|
||||
|
||||
// A ClientConfig structure is used to configure a Client. It must not be
|
||||
// modified after having been passed to an SSH function.
|
||||
type ClientConfig struct {
|
||||
|
@ -190,10 +202,12 @@ type ClientConfig struct {
|
|||
// be used during authentication.
|
||||
Auth []AuthMethod
|
||||
|
||||
// HostKeyCallback, if not nil, is called during the cryptographic
|
||||
// handshake to validate the server's host key. A nil HostKeyCallback
|
||||
// implies that all host keys are accepted.
|
||||
HostKeyCallback func(hostname string, remote net.Addr, key PublicKey) error
|
||||
// HostKeyCallback is called during the cryptographic
|
||||
// handshake to validate the server's host key. The client
|
||||
// configuration must supply this callback for the connection
|
||||
// to succeed. The functions InsecureIgnoreHostKey or
|
||||
// FixedHostKey can be used for simplistic host key checks.
|
||||
HostKeyCallback HostKeyCallback
|
||||
|
||||
// ClientVersion contains the version identification string that will
|
||||
// be used for the connection. If empty, a reasonable default is used.
|
||||
|
@ -211,3 +225,33 @@ type ClientConfig struct {
|
|||
// A Timeout of zero means no timeout.
|
||||
Timeout time.Duration
|
||||
}
|
||||
|
||||
// InsecureIgnoreHostKey returns a function that can be used for
|
||||
// ClientConfig.HostKeyCallback to accept any host key. It should
|
||||
// not be used for production code.
|
||||
func InsecureIgnoreHostKey() HostKeyCallback {
|
||||
return func(hostname string, remote net.Addr, key PublicKey) error {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
type fixedHostKey struct {
|
||||
key PublicKey
|
||||
}
|
||||
|
||||
func (f *fixedHostKey) check(hostname string, remote net.Addr, key PublicKey) error {
|
||||
if f.key == nil {
|
||||
return fmt.Errorf("ssh: required host key was nil")
|
||||
}
|
||||
if !bytes.Equal(key.Marshal(), f.key.Marshal()) {
|
||||
return fmt.Errorf("ssh: host key mismatch")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// FixedHostKey returns a function for use in
|
||||
// ClientConfig.HostKeyCallback to accept only a specific host key.
|
||||
func FixedHostKey(key PublicKey) HostKeyCallback {
|
||||
hk := &fixedHostKey{key}
|
||||
return hk.check
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
@ -177,31 +179,26 @@ func (cb publicKeyCallback) method() string {
|
|||
}
|
||||
|
||||
func (cb publicKeyCallback) auth(session []byte, user string, c packetConn, rand io.Reader) (bool, []string, error) {
|
||||
// Authentication is performed in two stages. The first stage sends an
|
||||
// enquiry to test if each key is acceptable to the remote. The second
|
||||
// stage attempts to authenticate with the valid keys obtained in the
|
||||
// first stage.
|
||||
// Authentication is performed by sending an enquiry to test if a key is
|
||||
// acceptable to the remote. If the key is acceptable, the client will
|
||||
// attempt to authenticate with the valid key. If not the client will repeat
|
||||
// the process with the remaining keys.
|
||||
|
||||
signers, err := cb()
|
||||
if err != nil {
|
||||
return false, nil, err
|
||||
}
|
||||
var validKeys []Signer
|
||||
for _, signer := range signers {
|
||||
if ok, err := validateKey(signer.PublicKey(), user, c); ok {
|
||||
validKeys = append(validKeys, signer)
|
||||
} else {
|
||||
if err != nil {
|
||||
return false, nil, err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// methods that may continue if this auth is not successful.
|
||||
var methods []string
|
||||
for _, signer := range validKeys {
|
||||
pub := signer.PublicKey()
|
||||
for _, signer := range signers {
|
||||
ok, err := validateKey(signer.PublicKey(), user, c)
|
||||
if err != nil {
|
||||
return false, nil, err
|
||||
}
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
|
||||
pub := signer.PublicKey()
|
||||
pubKey := pub.Marshal()
|
||||
sign, err := signer.Sign(rand, buildDataSignedForAuth(session, userAuthRequestMsg{
|
||||
User: user,
|
||||
|
@ -234,13 +231,29 @@ func (cb publicKeyCallback) auth(session []byte, user string, c packetConn, rand
|
|||
if err != nil {
|
||||
return false, nil, err
|
||||
}
|
||||
if success {
|
||||
|
||||
// If authentication succeeds or the list of available methods does not
|
||||
// contain the "publickey" method, do not attempt to authenticate with any
|
||||
// other keys. According to RFC 4252 Section 7, the latter can occur when
|
||||
// additional authentication methods are required.
|
||||
if success || !containsMethod(methods, cb.method()) {
|
||||
return success, methods, err
|
||||
}
|
||||
}
|
||||
|
||||
return false, methods, nil
|
||||
}
|
||||
|
||||
func containsMethod(methods []string, method string) bool {
|
||||
for _, m := range methods {
|
||||
if m == method {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
// validateKey validates the key provided is acceptable to the server.
|
||||
func validateKey(key PublicKey, user string, c packetConn) (bool, error) {
|
||||
pubKey := key.Marshal()
|
||||
|
|
|
@ -76,9 +76,6 @@ func tryAuth(t *testing.T, config *ClientConfig) error {
|
|||
}
|
||||
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"])
|
||||
|
||||
|
@ -93,6 +90,7 @@ func TestClientAuthPublicKey(t *testing.T) {
|
|||
Auth: []AuthMethod{
|
||||
PublicKeys(testSigners["rsa"]),
|
||||
},
|
||||
HostKeyCallback: InsecureIgnoreHostKey(),
|
||||
}
|
||||
if err := tryAuth(t, config); err != nil {
|
||||
t.Fatalf("unable to dial remote side: %s", err)
|
||||
|
@ -105,6 +103,7 @@ func TestAuthMethodPassword(t *testing.T) {
|
|||
Auth: []AuthMethod{
|
||||
Password(clientPassword),
|
||||
},
|
||||
HostKeyCallback: InsecureIgnoreHostKey(),
|
||||
}
|
||||
|
||||
if err := tryAuth(t, config); err != nil {
|
||||
|
@ -124,6 +123,7 @@ func TestAuthMethodFallback(t *testing.T) {
|
|||
return "WRONG", nil
|
||||
}),
|
||||
},
|
||||
HostKeyCallback: InsecureIgnoreHostKey(),
|
||||
}
|
||||
|
||||
if err := tryAuth(t, config); err != nil {
|
||||
|
@ -142,6 +142,7 @@ func TestAuthMethodWrongPassword(t *testing.T) {
|
|||
Password("wrong"),
|
||||
PublicKeys(testSigners["rsa"]),
|
||||
},
|
||||
HostKeyCallback: InsecureIgnoreHostKey(),
|
||||
}
|
||||
|
||||
if err := tryAuth(t, config); err != nil {
|
||||
|
@ -159,6 +160,7 @@ func TestAuthMethodKeyboardInteractive(t *testing.T) {
|
|||
Auth: []AuthMethod{
|
||||
KeyboardInteractive(answers.Challenge),
|
||||
},
|
||||
HostKeyCallback: InsecureIgnoreHostKey(),
|
||||
}
|
||||
|
||||
if err := tryAuth(t, config); err != nil {
|
||||
|
@ -204,6 +206,7 @@ func TestAuthMethodRSAandDSA(t *testing.T) {
|
|||
Auth: []AuthMethod{
|
||||
PublicKeys(testSigners["dsa"], testSigners["rsa"]),
|
||||
},
|
||||
HostKeyCallback: InsecureIgnoreHostKey(),
|
||||
}
|
||||
if err := tryAuth(t, config); err != nil {
|
||||
t.Fatalf("client could not authenticate with rsa key: %v", err)
|
||||
|
@ -220,6 +223,7 @@ func TestClientHMAC(t *testing.T) {
|
|||
Config: Config{
|
||||
MACs: []string{mac},
|
||||
},
|
||||
HostKeyCallback: InsecureIgnoreHostKey(),
|
||||
}
|
||||
if err := tryAuth(t, config); err != nil {
|
||||
t.Fatalf("client could not authenticate with mac algo %s: %v", mac, err)
|
||||
|
@ -255,6 +259,7 @@ func TestClientUnsupportedKex(t *testing.T) {
|
|||
Config: Config{
|
||||
KeyExchanges: []string{"diffie-hellman-group-exchange-sha256"}, // not currently supported
|
||||
},
|
||||
HostKeyCallback: InsecureIgnoreHostKey(),
|
||||
}
|
||||
if err := tryAuth(t, config); err == nil || !strings.Contains(err.Error(), "common algorithm") {
|
||||
t.Errorf("got %v, expected 'common algorithm'", err)
|
||||
|
@ -274,22 +279,23 @@ func TestClientLoginCert(t *testing.T) {
|
|||
}
|
||||
|
||||
clientConfig := &ClientConfig{
|
||||
User: "user",
|
||||
User: "user",
|
||||
HostKeyCallback: InsecureIgnoreHostKey(),
|
||||
}
|
||||
clientConfig.Auth = append(clientConfig.Auth, PublicKeys(certSigner))
|
||||
|
||||
t.Log("should succeed")
|
||||
// should succeed
|
||||
if err := tryAuth(t, clientConfig); err != nil {
|
||||
t.Errorf("cert login failed: %v", err)
|
||||
}
|
||||
|
||||
t.Log("corrupted signature")
|
||||
// corrupted signature
|
||||
cert.Signature.Blob[0]++
|
||||
if err := tryAuth(t, clientConfig); err == nil {
|
||||
t.Errorf("cert login passed with corrupted sig")
|
||||
}
|
||||
|
||||
t.Log("revoked")
|
||||
// revoked
|
||||
cert.Serial = 666
|
||||
cert.SignCert(rand.Reader, testSigners["ecdsa"])
|
||||
if err := tryAuth(t, clientConfig); err == nil {
|
||||
|
@ -297,13 +303,13 @@ func TestClientLoginCert(t *testing.T) {
|
|||
}
|
||||
cert.Serial = 1
|
||||
|
||||
t.Log("sign with wrong key")
|
||||
// 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")
|
||||
// host cert
|
||||
cert.CertType = HostCert
|
||||
cert.SignCert(rand.Reader, testSigners["ecdsa"])
|
||||
if err := tryAuth(t, clientConfig); err == nil {
|
||||
|
@ -311,14 +317,14 @@ func TestClientLoginCert(t *testing.T) {
|
|||
}
|
||||
cert.CertType = UserCert
|
||||
|
||||
t.Log("principal specified")
|
||||
// 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")
|
||||
// wrong principal specified
|
||||
cert.ValidPrincipals = []string{"fred"}
|
||||
cert.SignCert(rand.Reader, testSigners["ecdsa"])
|
||||
if err := tryAuth(t, clientConfig); err == nil {
|
||||
|
@ -326,22 +332,22 @@ func TestClientLoginCert(t *testing.T) {
|
|||
}
|
||||
cert.ValidPrincipals = nil
|
||||
|
||||
t.Log("added critical option")
|
||||
// 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"}
|
||||
// allowed source address
|
||||
cert.CriticalOptions = map[string]string{"source-address": "127.0.0.42/24,::42/120"}
|
||||
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"}
|
||||
// disallowed source address
|
||||
cert.CriticalOptions = map[string]string{"source-address": "127.0.0.42,::42"}
|
||||
cert.SignCert(rand.Reader, testSigners["ecdsa"])
|
||||
if err := tryAuth(t, clientConfig); err == nil {
|
||||
t.Errorf("cert login with source-address succeeded")
|
||||
|
@ -364,6 +370,7 @@ func testPermissionsPassing(withPermissions bool, t *testing.T) {
|
|||
Auth: []AuthMethod{
|
||||
PublicKeys(testSigners["rsa"]),
|
||||
},
|
||||
HostKeyCallback: InsecureIgnoreHostKey(),
|
||||
}
|
||||
if withPermissions {
|
||||
clientConfig.User = "permissions"
|
||||
|
@ -410,6 +417,7 @@ func TestRetryableAuth(t *testing.T) {
|
|||
}), 2),
|
||||
PublicKeys(testSigners["rsa"]),
|
||||
},
|
||||
HostKeyCallback: InsecureIgnoreHostKey(),
|
||||
}
|
||||
|
||||
if err := tryAuth(t, config); err != nil {
|
||||
|
@ -431,7 +439,8 @@ func ExampleRetryableAuthMethod(t *testing.T) {
|
|||
}
|
||||
|
||||
config := &ClientConfig{
|
||||
User: user,
|
||||
HostKeyCallback: InsecureIgnoreHostKey(),
|
||||
User: user,
|
||||
Auth: []AuthMethod{
|
||||
RetryableAuthMethod(KeyboardInteractiveChallenge(Cb), NumberOfPrompts),
|
||||
},
|
||||
|
@ -451,7 +460,8 @@ func TestClientAuthNone(t *testing.T) {
|
|||
serverConfig.AddHostKey(testSigners["rsa"])
|
||||
|
||||
clientConfig := &ClientConfig{
|
||||
User: user,
|
||||
User: user,
|
||||
HostKeyCallback: InsecureIgnoreHostKey(),
|
||||
}
|
||||
|
||||
c1, c2, err := netPipe()
|
||||
|
@ -464,9 +474,106 @@ func TestClientAuthNone(t *testing.T) {
|
|||
go NewClientConn(c2, "", clientConfig)
|
||||
serverConn, err := newServer(c1, serverConfig)
|
||||
if err != nil {
|
||||
t.Fatal("newServer: %v", err)
|
||||
t.Fatalf("newServer: %v", err)
|
||||
}
|
||||
if serverConn.User() != user {
|
||||
t.Fatalf("server: got %q, want %q", serverConn.User(), user)
|
||||
}
|
||||
}
|
||||
|
||||
// Test if authentication attempts are limited on server when MaxAuthTries is set
|
||||
func TestClientAuthMaxAuthTries(t *testing.T) {
|
||||
user := "testuser"
|
||||
|
||||
serverConfig := &ServerConfig{
|
||||
MaxAuthTries: 2,
|
||||
PasswordCallback: func(conn ConnMetadata, pass []byte) (*Permissions, error) {
|
||||
if conn.User() == "testuser" && string(pass) == "right" {
|
||||
return nil, nil
|
||||
}
|
||||
return nil, errors.New("password auth failed")
|
||||
},
|
||||
}
|
||||
serverConfig.AddHostKey(testSigners["rsa"])
|
||||
|
||||
expectedErr := fmt.Errorf("ssh: handshake failed: %v", &disconnectMsg{
|
||||
Reason: 2,
|
||||
Message: "too many authentication failures",
|
||||
})
|
||||
|
||||
for tries := 2; tries < 4; tries++ {
|
||||
n := tries
|
||||
clientConfig := &ClientConfig{
|
||||
User: user,
|
||||
Auth: []AuthMethod{
|
||||
RetryableAuthMethod(PasswordCallback(func() (string, error) {
|
||||
n--
|
||||
if n == 0 {
|
||||
return "right", nil
|
||||
} else {
|
||||
return "wrong", nil
|
||||
}
|
||||
}), tries),
|
||||
},
|
||||
HostKeyCallback: InsecureIgnoreHostKey(),
|
||||
}
|
||||
|
||||
c1, c2, err := netPipe()
|
||||
if err != nil {
|
||||
t.Fatalf("netPipe: %v", err)
|
||||
}
|
||||
defer c1.Close()
|
||||
defer c2.Close()
|
||||
|
||||
go newServer(c1, serverConfig)
|
||||
_, _, _, err = NewClientConn(c2, "", clientConfig)
|
||||
if tries > 2 {
|
||||
if err == nil {
|
||||
t.Fatalf("client: got no error, want %s", expectedErr)
|
||||
} else if err.Error() != expectedErr.Error() {
|
||||
t.Fatalf("client: got %s, want %s", err, expectedErr)
|
||||
}
|
||||
} else {
|
||||
if err != nil {
|
||||
t.Fatalf("client: got %s, want no error", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Test if authentication attempts are correctly limited on server
|
||||
// when more public keys are provided then MaxAuthTries
|
||||
func TestClientAuthMaxAuthTriesPublicKey(t *testing.T) {
|
||||
signers := []Signer{}
|
||||
for i := 0; i < 6; i++ {
|
||||
signers = append(signers, testSigners["dsa"])
|
||||
}
|
||||
|
||||
validConfig := &ClientConfig{
|
||||
User: "testuser",
|
||||
Auth: []AuthMethod{
|
||||
PublicKeys(append([]Signer{testSigners["rsa"]}, signers...)...),
|
||||
},
|
||||
HostKeyCallback: InsecureIgnoreHostKey(),
|
||||
}
|
||||
if err := tryAuth(t, validConfig); err != nil {
|
||||
t.Fatalf("unable to dial remote side: %s", err)
|
||||
}
|
||||
|
||||
expectedErr := fmt.Errorf("ssh: handshake failed: %v", &disconnectMsg{
|
||||
Reason: 2,
|
||||
Message: "too many authentication failures",
|
||||
})
|
||||
invalidConfig := &ClientConfig{
|
||||
User: "testuser",
|
||||
Auth: []AuthMethod{
|
||||
PublicKeys(append(signers, testSigners["rsa"])...),
|
||||
},
|
||||
HostKeyCallback: InsecureIgnoreHostKey(),
|
||||
}
|
||||
if err := tryAuth(t, invalidConfig); err == nil {
|
||||
t.Fatalf("client: got no error, want %s", expectedErr)
|
||||
} else if err.Error() != expectedErr.Error() {
|
||||
t.Fatalf("client: got %s, want %s", err, expectedErr)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@ package ssh
|
|||
|
||||
import (
|
||||
"net"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
|
@ -13,6 +14,7 @@ func testClientVersion(t *testing.T, config *ClientConfig, expected string) {
|
|||
clientConn, serverConn := net.Pipe()
|
||||
defer clientConn.Close()
|
||||
receivedVersion := make(chan string, 1)
|
||||
config.HostKeyCallback = InsecureIgnoreHostKey()
|
||||
go func() {
|
||||
version, err := readVersion(serverConn)
|
||||
if err != nil {
|
||||
|
@ -37,3 +39,43 @@ func TestCustomClientVersion(t *testing.T) {
|
|||
func TestDefaultClientVersion(t *testing.T) {
|
||||
testClientVersion(t, &ClientConfig{}, packageVersion)
|
||||
}
|
||||
|
||||
func TestHostKeyCheck(t *testing.T) {
|
||||
for _, tt := range []struct {
|
||||
name string
|
||||
wantError string
|
||||
key PublicKey
|
||||
}{
|
||||
{"no callback", "must specify HostKeyCallback", nil},
|
||||
{"correct key", "", testSigners["rsa"].PublicKey()},
|
||||
{"mismatch", "mismatch", testSigners["ecdsa"].PublicKey()},
|
||||
} {
|
||||
c1, c2, err := netPipe()
|
||||
if err != nil {
|
||||
t.Fatalf("netPipe: %v", err)
|
||||
}
|
||||
defer c1.Close()
|
||||
defer c2.Close()
|
||||
serverConf := &ServerConfig{
|
||||
NoClientAuth: true,
|
||||
}
|
||||
serverConf.AddHostKey(testSigners["rsa"])
|
||||
|
||||
go NewServerConn(c1, serverConf)
|
||||
clientConf := ClientConfig{
|
||||
User: "user",
|
||||
}
|
||||
if tt.key != nil {
|
||||
clientConf.HostKeyCallback = FixedHostKey(tt.key)
|
||||
}
|
||||
|
||||
_, _, _, err = NewClientConn(c2, "", &clientConf)
|
||||
if err != nil {
|
||||
if tt.wantError == "" || !strings.Contains(err.Error(), tt.wantError) {
|
||||
t.Errorf("%s: got error %q, missing %q", tt.name, err.Error(), tt.wantError)
|
||||
}
|
||||
} else if tt.wantError != "" {
|
||||
t.Errorf("%s: succeeded, but want error string %q", tt.name, tt.wantError)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
31
vendor/src/golang.org/x/crypto/ssh/common.go
vendored
31
vendor/src/golang.org/x/crypto/ssh/common.go
vendored
|
@ -9,6 +9,7 @@ import (
|
|||
"crypto/rand"
|
||||
"fmt"
|
||||
"io"
|
||||
"math"
|
||||
"sync"
|
||||
|
||||
_ "crypto/sha1"
|
||||
|
@ -40,7 +41,7 @@ var supportedKexAlgos = []string{
|
|||
kexAlgoDH14SHA1, kexAlgoDH1SHA1,
|
||||
}
|
||||
|
||||
// supportedKexAlgos specifies the supported host-key algorithms (i.e. methods
|
||||
// supportedHostKeyAlgos specifies the supported host-key algorithms (i.e. methods
|
||||
// of authenticating servers) in preference order.
|
||||
var supportedHostKeyAlgos = []string{
|
||||
CertAlgoRSAv01, CertAlgoDSAv01, CertAlgoECDSA256v01,
|
||||
|
@ -56,7 +57,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 +105,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
|
||||
|
@ -171,7 +187,7 @@ type Config struct {
|
|||
|
||||
// The maximum number of bytes sent or received after which a
|
||||
// new key is negotiated. It must be at least 256. If
|
||||
// unspecified, 1 gigabyte is used.
|
||||
// unspecified, a size suitable for the chosen cipher is used.
|
||||
RekeyThreshold uint64
|
||||
|
||||
// The allowed key exchanges algorithms. If unspecified then a
|
||||
|
@ -215,11 +231,12 @@ func (c *Config) SetDefaults() {
|
|||
}
|
||||
|
||||
if c.RekeyThreshold == 0 {
|
||||
// RFC 4253, section 9 suggests rekeying after 1G.
|
||||
c.RekeyThreshold = 1 << 30
|
||||
}
|
||||
if c.RekeyThreshold < minRekeyThreshold {
|
||||
// cipher specific default
|
||||
} else if c.RekeyThreshold < minRekeyThreshold {
|
||||
c.RekeyThreshold = minRekeyThreshold
|
||||
} else if c.RekeyThreshold >= math.MaxInt64 {
|
||||
// Avoid weirdness if somebody uses -1 as a threshold.
|
||||
c.RekeyThreshold = math.MaxInt64
|
||||
}
|
||||
}
|
||||
|
||||
|
|
3
vendor/src/golang.org/x/crypto/ssh/doc.go
vendored
3
vendor/src/golang.org/x/crypto/ssh/doc.go
vendored
|
@ -14,5 +14,8 @@ others.
|
|||
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
|
||||
|
||||
This package does not fall under the stability promise of the Go language itself,
|
||||
so its API may be changed when pressing needs arise.
|
||||
*/
|
||||
package ssh // import "golang.org/x/crypto/ssh"
|
||||
|
|
128
vendor/src/golang.org/x/crypto/ssh/example_test.go
vendored
128
vendor/src/golang.org/x/crypto/ssh/example_test.go
vendored
|
@ -5,21 +5,45 @@
|
|||
package ssh_test
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"net"
|
||||
"net/http"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"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.
|
||||
|
@ -28,16 +52,24 @@ func ExampleNewServerConn() {
|
|||
}
|
||||
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 {
|
||||
panic("Failed to load private key")
|
||||
log.Fatal("Failed to load private key: ", err)
|
||||
}
|
||||
|
||||
private, err := ssh.ParsePrivateKey(privateBytes)
|
||||
if err != nil {
|
||||
panic("Failed to parse private key")
|
||||
log.Fatal("Failed to parse private key: ", err)
|
||||
}
|
||||
|
||||
config.AddHostKey(private)
|
||||
|
@ -46,18 +78,18 @@ func ExampleNewServerConn() {
|
|||
// accepted.
|
||||
listener, err := net.Listen("tcp", "0.0.0.0:2022")
|
||||
if err != nil {
|
||||
panic("failed to listen for connection")
|
||||
log.Fatal("failed to listen for connection: ", err)
|
||||
}
|
||||
nConn, err := listener.Accept()
|
||||
if err != nil {
|
||||
panic("failed to accept incoming connection")
|
||||
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 {
|
||||
panic("failed to handshake")
|
||||
log.Fatal("failed to handshake: ", err)
|
||||
}
|
||||
// The incoming Request channel must be serviced.
|
||||
go ssh.DiscardRequests(reqs)
|
||||
|
@ -74,7 +106,7 @@ func ExampleNewServerConn() {
|
|||
}
|
||||
channel, requests, err := newChannel.Accept()
|
||||
if err != nil {
|
||||
panic("could not accept channel.")
|
||||
log.Fatalf("Could not accept channel: %v", err)
|
||||
}
|
||||
|
||||
// Sessions have out-of-band requests such as "shell",
|
||||
|
@ -82,18 +114,7 @@ func ExampleNewServerConn() {
|
|||
// "shell" request.
|
||||
go func(in <-chan *ssh.Request) {
|
||||
for req := range in {
|
||||
ok := false
|
||||
switch req.Type {
|
||||
case "shell":
|
||||
ok = true
|
||||
if len(req.Payload) > 0 {
|
||||
// We don't accept any
|
||||
// commands, only the
|
||||
// default shell.
|
||||
ok = false
|
||||
}
|
||||
}
|
||||
req.Reply(ok, nil)
|
||||
req.Reply(req.Type == "shell", nil)
|
||||
}
|
||||
}(requests)
|
||||
|
||||
|
@ -112,27 +133,70 @@ func ExampleNewServerConn() {
|
|||
}
|
||||
}
|
||||
|
||||
func ExampleHostKeyCheck() {
|
||||
// Every client must provide a host key check. Here is a
|
||||
// simple-minded parse of OpenSSH's known_hosts file
|
||||
host := "hostname"
|
||||
file, err := os.Open(filepath.Join(os.Getenv("HOME"), ".ssh", "known_hosts"))
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
scanner := bufio.NewScanner(file)
|
||||
var hostKey ssh.PublicKey
|
||||
for scanner.Scan() {
|
||||
fields := strings.Split(scanner.Text(), " ")
|
||||
if len(fields) != 3 {
|
||||
continue
|
||||
}
|
||||
if strings.Contains(fields[0], host) {
|
||||
var err error
|
||||
hostKey, _, _, _, err = ssh.ParseAuthorizedKey(scanner.Bytes())
|
||||
if err != nil {
|
||||
log.Fatalf("error parsing %q: %v", fields[2], err)
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if hostKey == nil {
|
||||
log.Fatalf("no hostkey for %s", host)
|
||||
}
|
||||
|
||||
config := ssh.ClientConfig{
|
||||
User: os.Getenv("USER"),
|
||||
HostKeyCallback: ssh.FixedHostKey(hostKey),
|
||||
}
|
||||
|
||||
_, err = ssh.Dial("tcp", host+":22", &config)
|
||||
log.Println(err)
|
||||
}
|
||||
|
||||
func ExampleDial() {
|
||||
var hostKey ssh.PublicKey
|
||||
// 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.
|
||||
// implementation of AuthMethod via the Auth field in ClientConfig,
|
||||
// and provide a HostKeyCallback.
|
||||
config := &ssh.ClientConfig{
|
||||
User: "username",
|
||||
Auth: []ssh.AuthMethod{
|
||||
ssh.Password("yourpassword"),
|
||||
},
|
||||
HostKeyCallback: ssh.FixedHostKey(hostKey),
|
||||
}
|
||||
client, err := ssh.Dial("tcp", "yourserver.com:22", config)
|
||||
if err != nil {
|
||||
panic("Failed to dial: " + err.Error())
|
||||
log.Fatal("Failed to dial: ", err)
|
||||
}
|
||||
|
||||
// Each ClientConn can support multiple interactive sessions,
|
||||
// represented by a Session.
|
||||
session, err := client.NewSession()
|
||||
if err != nil {
|
||||
panic("Failed to create session: " + err.Error())
|
||||
log.Fatal("Failed to create session: ", err)
|
||||
}
|
||||
defer session.Close()
|
||||
|
||||
|
@ -141,12 +205,13 @@ func ExampleDial() {
|
|||
var b bytes.Buffer
|
||||
session.Stdout = &b
|
||||
if err := session.Run("/usr/bin/whoami"); err != nil {
|
||||
panic("Failed to run: " + err.Error())
|
||||
log.Fatal("Failed to run: " + err.Error())
|
||||
}
|
||||
fmt.Println(b.String())
|
||||
}
|
||||
|
||||
func ExamplePublicKeys() {
|
||||
var hostKey ssh.PublicKey
|
||||
// A public key may be used to authenticate against the remote
|
||||
// server by using an unencrypted PEM-encoded private key file.
|
||||
//
|
||||
|
@ -169,6 +234,7 @@ func ExamplePublicKeys() {
|
|||
// Use the PublicKeys method for remote authentication.
|
||||
ssh.PublicKeys(signer),
|
||||
},
|
||||
HostKeyCallback: ssh.FixedHostKey(hostKey),
|
||||
}
|
||||
|
||||
// Connect to the remote server and perform the SSH handshake.
|
||||
|
@ -180,23 +246,25 @@ func ExamplePublicKeys() {
|
|||
}
|
||||
|
||||
func ExampleClient_Listen() {
|
||||
var hostKey ssh.PublicKey
|
||||
config := &ssh.ClientConfig{
|
||||
User: "username",
|
||||
Auth: []ssh.AuthMethod{
|
||||
ssh.Password("password"),
|
||||
},
|
||||
HostKeyCallback: ssh.FixedHostKey(hostKey),
|
||||
}
|
||||
// Dial your ssh server.
|
||||
conn, err := ssh.Dial("tcp", "localhost:22", config)
|
||||
if err != nil {
|
||||
log.Fatalf("unable to connect: %s", err)
|
||||
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.Fatalf("unable to register tcp forward: %v", err)
|
||||
log.Fatal("unable to register tcp forward: ", err)
|
||||
}
|
||||
defer l.Close()
|
||||
|
||||
|
@ -207,23 +275,25 @@ func ExampleClient_Listen() {
|
|||
}
|
||||
|
||||
func ExampleSession_RequestPty() {
|
||||
var hostKey ssh.PublicKey
|
||||
// Create client config
|
||||
config := &ssh.ClientConfig{
|
||||
User: "username",
|
||||
Auth: []ssh.AuthMethod{
|
||||
ssh.Password("password"),
|
||||
},
|
||||
HostKeyCallback: ssh.FixedHostKey(hostKey),
|
||||
}
|
||||
// Connect to ssh server
|
||||
conn, err := ssh.Dial("tcp", "localhost:22", config)
|
||||
if err != nil {
|
||||
log.Fatalf("unable to connect: %s", err)
|
||||
log.Fatal("unable to connect: ", err)
|
||||
}
|
||||
defer conn.Close()
|
||||
// Create a session
|
||||
session, err := conn.NewSession()
|
||||
if err != nil {
|
||||
log.Fatalf("unable to create session: %s", err)
|
||||
log.Fatal("unable to create session: ", err)
|
||||
}
|
||||
defer session.Close()
|
||||
// Set up terminal modes
|
||||
|
@ -233,11 +303,11 @@ func ExampleSession_RequestPty() {
|
|||
ssh.TTY_OP_OSPEED: 14400, // output speed = 14.4kbaud
|
||||
}
|
||||
// Request pseudo terminal
|
||||
if err := session.RequestPty("xterm", 80, 40, modes); err != nil {
|
||||
log.Fatalf("request for pseudo terminal failed: %s", err)
|
||||
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.Fatalf("failed to start shell: %s", err)
|
||||
log.Fatal("failed to start shell: ", err)
|
||||
}
|
||||
}
|
||||
|
|
473
vendor/src/golang.org/x/crypto/ssh/handshake.go
vendored
473
vendor/src/golang.org/x/crypto/ssh/handshake.go
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,60 @@ 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
|
||||
hostKeyCallback HostKeyCallback
|
||||
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)
|
||||
t.resetReadThresholds()
|
||||
t.resetWriteThresholds()
|
||||
|
||||
// We always start with a mandatory key exchange.
|
||||
t.requestKex <- struct{}{}
|
||||
return t
|
||||
}
|
||||
|
||||
|
@ -95,6 +126,7 @@ func newClientTransport(conn keyingTransport, clientVersion, serverVersion []byt
|
|||
t.hostKeyAlgorithms = supportedHostKeyAlgos
|
||||
}
|
||||
go t.readLoop()
|
||||
go t.kexLoop()
|
||||
return t
|
||||
}
|
||||
|
||||
|
@ -102,6 +134,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 +142,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 +163,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 +186,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 +201,217 @@ 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) resetWriteThresholds() {
|
||||
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()
|
||||
} else {
|
||||
t.writeBytesLeft = 1 << 30
|
||||
}
|
||||
}
|
||||
|
||||
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.resetWriteThresholds()
|
||||
|
||||
// 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) resetReadThresholds() {
|
||||
t.readPacketsLeft = packetRekeyThreshold
|
||||
if t.config.RekeyThreshold > 0 {
|
||||
t.readBytesLeft = int64(t.config.RekeyThreshold)
|
||||
} else if t.algorithms != nil {
|
||||
t.readBytesLeft = t.algorithms.r.rekeyBytes()
|
||||
} else {
|
||||
t.readBytesLeft = 1 << 30
|
||||
}
|
||||
}
|
||||
|
||||
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.resetReadThresholds()
|
||||
|
||||
// By default, a key exchange is hidden from higher layers by
|
||||
// translating it into msgIgnore.
|
||||
|
@ -213,61 +426,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 +463,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,26 +532,35 @@ 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
|
||||
}
|
||||
|
||||
// We don't send FirstKexFollows, but we handle receiving it.
|
||||
if otherInit.FirstKexFollows && algs.kex != otherInit.KexAlgos[0] {
|
||||
//
|
||||
// RFC 4253 section 7 defines the kex and the agreement method for
|
||||
// first_kex_packet_follows. It states that the guessed packet
|
||||
// should be ignored if the "kex algorithm and/or the host
|
||||
// key algorithm is guessed wrong (server and client have
|
||||
// different preferred algorithm), or if any of the other
|
||||
// algorithms cannot be agreed upon". The other algorithms have
|
||||
// already been checked above so the kex algorithm and host key
|
||||
// algorithm are checked here.
|
||||
if otherInit.FirstKexFollows && (clientInit.KexAlgos[0] != serverInit.KexAlgos[0] || clientInit.ServerHostKeyAlgos[0] != serverInit.ServerHostKeyAlgos[0]) {
|
||||
// other side sent a kex message for the wrong algorithm,
|
||||
// which we have to ignore.
|
||||
if _, err := t.conn.readPacket(); err != nil {
|
||||
|
@ -379,16 +568,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 {
|
||||
|
@ -400,7 +589,9 @@ func (t *handshakeTransport) enterKeyExchangeLocked(otherInitPacket []byte) erro
|
|||
}
|
||||
result.SessionID = t.sessionID
|
||||
|
||||
t.conn.prepareKeyChange(algs, result)
|
||||
if err := t.conn.prepareKeyChange(t.algorithms, result); err != nil {
|
||||
return err
|
||||
}
|
||||
if err = t.conn.writePacket([]byte{msgNewKeys}); err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -440,11 +631,9 @@ func (t *handshakeTransport) client(kex kexAlgorithm, algs *algorithms, magics *
|
|||
return nil, err
|
||||
}
|
||||
|
||||
if t.hostKeyCallback != nil {
|
||||
err = t.hostKeyCallback(t.dialAddress, t.remoteAddr, hostKey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = t.hostKeyCallback(t.dialAddress, t.remoteAddr, hostKey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return result, nil
|
||||
|
|
456
vendor/src/golang.org/x/crypto/ssh/handshake_test.go
vendored
456
vendor/src/golang.org/x/crypto/ssh/handshake_test.go
vendored
|
@ -9,6 +9,7 @@ import (
|
|||
"crypto/rand"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"net"
|
||||
"reflect"
|
||||
"runtime"
|
||||
|
@ -39,7 +40,7 @@ func (t *testChecker) Check(dialAddr string, addr net.Addr, key PublicKey) error
|
|||
// 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")
|
||||
listener, err := net.Listen("tcp", ":0")
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
@ -58,14 +59,46 @@ func netPipe() (net.Conn, net.Conn, error) {
|
|||
return c1, c2, nil
|
||||
}
|
||||
|
||||
func handshakePair(clientConf *ClientConfig, addr string) (client *handshakeTransport, server *handshakeTransport, err error) {
|
||||
// noiseTransport inserts ignore messages to check that the read loop
|
||||
// and the key exchange filters out these messages.
|
||||
type noiseTransport struct {
|
||||
keyingTransport
|
||||
}
|
||||
|
||||
func (t *noiseTransport) writePacket(p []byte) error {
|
||||
ignore := []byte{msgIgnore}
|
||||
if err := t.keyingTransport.writePacket(ignore); err != nil {
|
||||
return err
|
||||
}
|
||||
debug := []byte{msgDebug, 1, 2, 3}
|
||||
if err := t.keyingTransport.writePacket(debug); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return t.keyingTransport.writePacket(p)
|
||||
}
|
||||
|
||||
func addNoiseTransport(t keyingTransport) keyingTransport {
|
||||
return &noiseTransport{t}
|
||||
}
|
||||
|
||||
// handshakePair creates two handshakeTransports connected with each
|
||||
// other. If the noise argument is true, both transports will try to
|
||||
// confuse the other side by sending ignore and debug messages.
|
||||
func handshakePair(clientConf *ClientConfig, addr string, noise bool) (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)
|
||||
var trC, trS keyingTransport
|
||||
|
||||
trC = newTransport(a, rand.Reader, true)
|
||||
trS = newTransport(b, rand.Reader, false)
|
||||
if noise {
|
||||
trC = addNoiseTransport(trC)
|
||||
trS = addNoiseTransport(trS)
|
||||
}
|
||||
clientConf.SetDefaults()
|
||||
|
||||
v := []byte("version")
|
||||
|
@ -77,6 +110,13 @@ func handshakePair(clientConf *ClientConfig, addr string) (client *handshakeTran
|
|||
serverConf.SetDefaults()
|
||||
server = newServerTransport(trS, v, v, serverConf)
|
||||
|
||||
if err := server.waitSession(); err != nil {
|
||||
return nil, nil, fmt.Errorf("server.waitSession: %v", err)
|
||||
}
|
||||
if err := client.waitSession(); err != nil {
|
||||
return nil, nil, fmt.Errorf("client.waitSession: %v", err)
|
||||
}
|
||||
|
||||
return client, server, nil
|
||||
}
|
||||
|
||||
|
@ -84,8 +124,14 @@ 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")
|
||||
|
||||
checker := &syncChecker{
|
||||
waitCall: make(chan int, 10),
|
||||
called: make(chan int, 10),
|
||||
}
|
||||
|
||||
checker.waitCall <- 1
|
||||
trC, trS, err := handshakePair(&ClientConfig{HostKeyCallback: checker.Check}, "addr", false)
|
||||
if err != nil {
|
||||
t.Fatalf("handshakePair: %v", err)
|
||||
}
|
||||
|
@ -93,240 +139,195 @@ func TestHandshakeBasic(t *testing.T) {
|
|||
defer trC.Close()
|
||||
defer trS.Close()
|
||||
|
||||
// Let first kex complete normally.
|
||||
<-checker.called
|
||||
|
||||
clientDone := make(chan int, 0)
|
||||
gotHalf := make(chan int, 0)
|
||||
const N = 20
|
||||
|
||||
go func() {
|
||||
defer close(clientDone)
|
||||
// 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++ {
|
||||
// handshake in progress. We do this twice, so we test
|
||||
// that the packet buffer is reset correctly.
|
||||
for i := 0; i < N; i++ {
|
||||
p := []byte{msgRequestSuccess, byte(i)}
|
||||
if err := trC.writePacket(p); err != nil {
|
||||
t.Fatalf("sendPacket: %v", err)
|
||||
}
|
||||
if i == 5 {
|
||||
if (i % 10) == 5 {
|
||||
<-gotHalf
|
||||
// halfway through, we request a key change.
|
||||
err := trC.sendKexInit(subsequentKeyExchange)
|
||||
if err != nil {
|
||||
t.Fatalf("sendKexInit: %v", err)
|
||||
}
|
||||
trC.requestKeyExchange()
|
||||
|
||||
// Wait until we can be sure the key
|
||||
// change has really started before we
|
||||
// write more.
|
||||
<-checker.called
|
||||
}
|
||||
if (i % 10) == 7 {
|
||||
// write some packets until the kex
|
||||
// completes, to test buffering of
|
||||
// packets.
|
||||
checker.waitCall <- 1
|
||||
}
|
||||
}
|
||||
trC.Close()
|
||||
}()
|
||||
|
||||
// Server checks that client messages come in cleanly
|
||||
i := 0
|
||||
for {
|
||||
p, err := trS.readPacket()
|
||||
err = nil
|
||||
for ; i < N; i++ {
|
||||
var p []byte
|
||||
p, err = trS.readPacket()
|
||||
if err != nil {
|
||||
break
|
||||
}
|
||||
if p[0] == msgNewKeys {
|
||||
continue
|
||||
if (i % 10) == 5 {
|
||||
gotHalf <- 1
|
||||
}
|
||||
|
||||
want := []byte{msgRequestSuccess, byte(i)}
|
||||
if bytes.Compare(p, want) != 0 {
|
||||
t.Errorf("message %d: got %q, want %q", i, p, want)
|
||||
t.Errorf("message %d: got %v, want %v", i, p, want)
|
||||
}
|
||||
i++
|
||||
}
|
||||
if i != 10 {
|
||||
<-clientDone
|
||||
if err != nil && err != io.EOF {
|
||||
t.Fatalf("server error: %v", err)
|
||||
}
|
||||
if i != N {
|
||||
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)
|
||||
close(checker.called)
|
||||
if _, ok := <-checker.called; ok {
|
||||
// If all went well, we registered exactly 2 key changes: one
|
||||
// that establishes the session, and one that we requested
|
||||
// additionally.
|
||||
t.Fatalf("got another host key checks after 2 handshakes")
|
||||
}
|
||||
}
|
||||
|
||||
func TestForceFirstKex(t *testing.T) {
|
||||
// like handshakePair, but must access the keyingTransport.
|
||||
checker := &testChecker{}
|
||||
trC, trS, err := handshakePair(&ClientConfig{HostKeyCallback: checker.Check}, "addr")
|
||||
clientConf := &ClientConfig{HostKeyCallback: checker.Check}
|
||||
a, b, err := netPipe()
|
||||
if err != nil {
|
||||
t.Fatalf("handshakePair: %v", err)
|
||||
t.Fatalf("netPipe: %v", err)
|
||||
}
|
||||
|
||||
defer trC.Close()
|
||||
defer trS.Close()
|
||||
var trC, trS keyingTransport
|
||||
|
||||
trC = newTransport(a, rand.Reader, true)
|
||||
|
||||
// This is the disallowed packet:
|
||||
trC.writePacket(Marshal(&serviceRequestMsg{serviceUserAuth}))
|
||||
|
||||
// Rest of the setup.
|
||||
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)
|
||||
|
||||
defer client.Close()
|
||||
defer server.Close()
|
||||
|
||||
// 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 {
|
||||
if err := server.waitSession(); 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{}
|
||||
checker := &syncChecker{
|
||||
called: make(chan int, 10),
|
||||
waitCall: nil,
|
||||
}
|
||||
clientConf := &ClientConfig{HostKeyCallback: checker.Check}
|
||||
clientConf.RekeyThreshold = 500
|
||||
trC, trS, err := handshakePair(clientConf, "addr")
|
||||
trC, trS, err := handshakePair(clientConf, "addr", false)
|
||||
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 {
|
||||
input := make([]byte, 251)
|
||||
input[0] = msgRequestSuccess
|
||||
|
||||
done := make(chan int, 1)
|
||||
const numPacket = 5
|
||||
go func() {
|
||||
defer close(done)
|
||||
j := 0
|
||||
for ; j < numPacket; j++ {
|
||||
if p, err := trS.readPacket(); err != nil {
|
||||
break
|
||||
} else if !bytes.Equal(input, p) {
|
||||
t.Errorf("got packet type %d, want %d", p[0], input[0])
|
||||
}
|
||||
}
|
||||
|
||||
if j != numPacket {
|
||||
t.Errorf("got %d, want 5 messages", j)
|
||||
}
|
||||
}()
|
||||
|
||||
<-checker.called
|
||||
|
||||
for i := 0; i < numPacket; i++ {
|
||||
p := make([]byte, len(input))
|
||||
copy(p, input)
|
||||
if err := trC.writePacket(p); err != nil {
|
||||
t.Errorf("writePacket: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
j := 0
|
||||
for ; j < 5; j++ {
|
||||
_, err := trS.readPacket()
|
||||
if err != nil {
|
||||
break
|
||||
if i == 2 {
|
||||
// Make sure the kex is in progress.
|
||||
<-checker.called
|
||||
}
|
||||
}
|
||||
|
||||
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))
|
||||
}
|
||||
<-done
|
||||
}
|
||||
|
||||
type syncChecker struct {
|
||||
called chan int
|
||||
waitCall chan int
|
||||
called chan int
|
||||
}
|
||||
|
||||
func (t *syncChecker) Check(dialAddr string, addr net.Addr, key PublicKey) error {
|
||||
t.called <- 1
|
||||
func (c *syncChecker) Check(dialAddr string, addr net.Addr, key PublicKey) error {
|
||||
c.called <- 1
|
||||
if c.waitCall != nil {
|
||||
<-c.waitCall
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func TestHandshakeAutoRekeyRead(t *testing.T) {
|
||||
sync := &syncChecker{make(chan int, 2)}
|
||||
sync := &syncChecker{
|
||||
called: make(chan int, 2),
|
||||
waitCall: nil,
|
||||
}
|
||||
clientConf := &ClientConfig{
|
||||
HostKeyCallback: sync.Check,
|
||||
}
|
||||
clientConf.RekeyThreshold = 500
|
||||
|
||||
trC, trS, err := handshakePair(clientConf, "addr")
|
||||
trC, trS, err := handshakePair(clientConf, "addr", false)
|
||||
if err != nil {
|
||||
t.Fatalf("handshakePair: %v", err)
|
||||
}
|
||||
|
@ -338,12 +339,19 @@ func TestHandshakeAutoRekeyRead(t *testing.T) {
|
|||
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)
|
||||
}
|
||||
done := make(chan int, 1)
|
||||
go func() {
|
||||
defer close(done)
|
||||
if _, err := trC.readPacket(); err != nil {
|
||||
t.Fatalf("readPacket(client): %v", err)
|
||||
}
|
||||
|
||||
}()
|
||||
|
||||
<-done
|
||||
<-sync.called
|
||||
}
|
||||
|
||||
|
@ -357,6 +365,7 @@ type errorKeyingTransport struct {
|
|||
func (n *errorKeyingTransport) prepareKeyChange(*algorithms, *kexResult) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (n *errorKeyingTransport) getSessionID() []byte {
|
||||
return nil
|
||||
}
|
||||
|
@ -383,20 +392,32 @@ func (n *errorKeyingTransport) readPacket() ([]byte, error) {
|
|||
|
||||
func TestHandshakeErrorHandlingRead(t *testing.T) {
|
||||
for i := 0; i < 20; i++ {
|
||||
testHandshakeErrorHandlingN(t, i, -1)
|
||||
testHandshakeErrorHandlingN(t, i, -1, false)
|
||||
}
|
||||
}
|
||||
|
||||
func TestHandshakeErrorHandlingWrite(t *testing.T) {
|
||||
for i := 0; i < 20; i++ {
|
||||
testHandshakeErrorHandlingN(t, -1, i)
|
||||
testHandshakeErrorHandlingN(t, -1, i, false)
|
||||
}
|
||||
}
|
||||
|
||||
func TestHandshakeErrorHandlingReadCoupled(t *testing.T) {
|
||||
for i := 0; i < 20; i++ {
|
||||
testHandshakeErrorHandlingN(t, i, -1, true)
|
||||
}
|
||||
}
|
||||
|
||||
func TestHandshakeErrorHandlingWriteCoupled(t *testing.T) {
|
||||
for i := 0; i < 20; i++ {
|
||||
testHandshakeErrorHandlingN(t, -1, i, true)
|
||||
}
|
||||
}
|
||||
|
||||
// testHandshakeErrorHandlingN runs handshakes, injecting errors. If
|
||||
// handshakeTransport deadlocks, the go runtime will detect it and
|
||||
// panic.
|
||||
func testHandshakeErrorHandlingN(t *testing.T, readLimit, writeLimit int) {
|
||||
func testHandshakeErrorHandlingN(t *testing.T, readLimit, writeLimit int, coupled bool) {
|
||||
msg := Marshal(&serviceRequestMsg{strings.Repeat("x", int(minRekeyThreshold)/4)})
|
||||
|
||||
a, b := memPipe()
|
||||
|
@ -409,37 +430,58 @@ func testHandshakeErrorHandlingN(t *testing.T, readLimit, writeLimit int) {
|
|||
serverConn := newHandshakeTransport(&errorKeyingTransport{a, readLimit, writeLimit}, &serverConf, []byte{'a'}, []byte{'b'})
|
||||
serverConn.hostKeys = []Signer{key}
|
||||
go serverConn.readLoop()
|
||||
go serverConn.kexLoop()
|
||||
|
||||
clientConf := Config{RekeyThreshold: 10 * minRekeyThreshold}
|
||||
clientConf.SetDefaults()
|
||||
clientConn := newHandshakeTransport(&errorKeyingTransport{b, -1, -1}, &clientConf, []byte{'a'}, []byte{'b'})
|
||||
clientConn.hostKeyAlgorithms = []string{key.PublicKey().Type()}
|
||||
clientConn.hostKeyCallback = InsecureIgnoreHostKey()
|
||||
go clientConn.readLoop()
|
||||
go clientConn.kexLoop()
|
||||
|
||||
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
|
||||
if !coupled {
|
||||
wg.Add(2)
|
||||
go func(c packetConn) {
|
||||
for i := 0; ; i++ {
|
||||
str := fmt.Sprintf("%08x", i) + strings.Repeat("x", int(minRekeyThreshold)/4-8)
|
||||
err := c.writePacket(Marshal(&serviceRequestMsg{str}))
|
||||
if err != nil {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
wg.Done()
|
||||
}(hs)
|
||||
go func(c packetConn) {
|
||||
for {
|
||||
_, err := c.readPacket()
|
||||
if err != nil {
|
||||
break
|
||||
wg.Done()
|
||||
c.Close()
|
||||
}(hs)
|
||||
go func(c packetConn) {
|
||||
for {
|
||||
_, err := c.readPacket()
|
||||
if err != nil {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
wg.Done()
|
||||
}(hs)
|
||||
}
|
||||
wg.Done()
|
||||
}(hs)
|
||||
} else {
|
||||
wg.Add(1)
|
||||
go func(c packetConn) {
|
||||
for {
|
||||
_, err := c.readPacket()
|
||||
if err != nil {
|
||||
break
|
||||
}
|
||||
if err := c.writePacket(msg); err != nil {
|
||||
break
|
||||
}
|
||||
|
||||
}
|
||||
wg.Done()
|
||||
}(hs)
|
||||
}
|
||||
}
|
||||
wg.Wait()
|
||||
}
|
||||
|
||||
|
@ -448,7 +490,7 @@ func TestDisconnect(t *testing.T) {
|
|||
t.Skip("see golang.org/issue/7237")
|
||||
}
|
||||
checker := &testChecker{}
|
||||
trC, trS, err := handshakePair(&ClientConfig{HostKeyCallback: checker.Check}, "addr")
|
||||
trC, trS, err := handshakePair(&ClientConfig{HostKeyCallback: checker.Check}, "addr", false)
|
||||
if err != nil {
|
||||
t.Fatalf("handshakePair: %v", err)
|
||||
}
|
||||
|
@ -484,3 +526,31 @@ func TestDisconnect(t *testing.T) {
|
|||
t.Errorf("readPacket 3 succeeded")
|
||||
}
|
||||
}
|
||||
|
||||
func TestHandshakeRekeyDefault(t *testing.T) {
|
||||
clientConf := &ClientConfig{
|
||||
Config: Config{
|
||||
Ciphers: []string{"aes128-ctr"},
|
||||
},
|
||||
HostKeyCallback: InsecureIgnoreHostKey(),
|
||||
}
|
||||
trC, trS, err := handshakePair(clientConf, "addr", false)
|
||||
if err != nil {
|
||||
t.Fatalf("handshakePair: %v", err)
|
||||
}
|
||||
defer trC.Close()
|
||||
defer trS.Close()
|
||||
|
||||
trC.writePacket([]byte{msgRequestSuccess, 0, 0})
|
||||
trC.Close()
|
||||
|
||||
rgb := (1024 + trC.readBytesLeft) >> 30
|
||||
wgb := (1024 + trC.writeBytesLeft) >> 30
|
||||
|
||||
if rgb != 64 {
|
||||
t.Errorf("got rekey after %dG read, want 64G", rgb)
|
||||
}
|
||||
if wgb != 64 {
|
||||
t.Errorf("got rekey after %dG write, want 64G", wgb)
|
||||
}
|
||||
}
|
||||
|
|
30
vendor/src/golang.org/x/crypto/ssh/kex.go
vendored
30
vendor/src/golang.org/x/crypto/ssh/kex.go
vendored
|
@ -77,11 +77,11 @@ type kexAlgorithm interface {
|
|||
|
||||
// dhGroup is a multiplicative group suitable for implementing Diffie-Hellman key agreement.
|
||||
type dhGroup struct {
|
||||
g, p *big.Int
|
||||
g, p, pMinus1 *big.Int
|
||||
}
|
||||
|
||||
func (group *dhGroup) diffieHellman(theirPublic, myPrivate *big.Int) (*big.Int, error) {
|
||||
if theirPublic.Sign() <= 0 || theirPublic.Cmp(group.p) >= 0 {
|
||||
if theirPublic.Cmp(bigOne) <= 0 || theirPublic.Cmp(group.pMinus1) >= 0 {
|
||||
return nil, errors.New("ssh: DH parameter out of bounds")
|
||||
}
|
||||
return new(big.Int).Exp(theirPublic, myPrivate, group.p), nil
|
||||
|
@ -90,10 +90,17 @@ func (group *dhGroup) diffieHellman(theirPublic, myPrivate *big.Int) (*big.Int,
|
|||
func (group *dhGroup) Client(c packetConn, randSource io.Reader, magics *handshakeMagics) (*kexResult, error) {
|
||||
hashFunc := crypto.SHA1
|
||||
|
||||
x, err := rand.Int(randSource, group.p)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
var x *big.Int
|
||||
for {
|
||||
var err error
|
||||
if x, err = rand.Int(randSource, group.pMinus1); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if x.Sign() > 0 {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
X := new(big.Int).Exp(group.g, x, group.p)
|
||||
kexDHInit := kexDHInitMsg{
|
||||
X: X,
|
||||
|
@ -146,9 +153,14 @@ func (group *dhGroup) Server(c packetConn, randSource io.Reader, magics *handsha
|
|||
return
|
||||
}
|
||||
|
||||
y, err := rand.Int(randSource, group.p)
|
||||
if err != nil {
|
||||
return
|
||||
var y *big.Int
|
||||
for {
|
||||
if y, err = rand.Int(randSource, group.pMinus1); err != nil {
|
||||
return
|
||||
}
|
||||
if y.Sign() > 0 {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
Y := new(big.Int).Exp(group.g, y, group.p)
|
||||
|
@ -373,6 +385,7 @@ func init() {
|
|||
kexAlgoMap[kexAlgoDH1SHA1] = &dhGroup{
|
||||
g: new(big.Int).SetInt64(2),
|
||||
p: p,
|
||||
pMinus1: new(big.Int).Sub(p, bigOne),
|
||||
}
|
||||
|
||||
// This is the group called diffie-hellman-group14-sha1 in RFC
|
||||
|
@ -382,6 +395,7 @@ func init() {
|
|||
kexAlgoMap[kexAlgoDH14SHA1] = &dhGroup{
|
||||
g: new(big.Int).SetInt64(2),
|
||||
p: p,
|
||||
pMinus1: new(big.Int).Sub(p, bigOne),
|
||||
}
|
||||
|
||||
kexAlgoMap[kexAlgoECDH521] = &ecdh{elliptic.P521()}
|
||||
|
|
163
vendor/src/golang.org/x/crypto/ssh/keys.go
vendored
163
vendor/src/golang.org/x/crypto/ssh/keys.go
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"
|
||||
|
@ -281,6 +284,12 @@ type PublicKey interface {
|
|||
Verify(data []byte, sig *Signature) error
|
||||
}
|
||||
|
||||
// CryptoPublicKey, if implemented by a PublicKey,
|
||||
// returns the underlying crypto.PublicKey form of the key.
|
||||
type CryptoPublicKey interface {
|
||||
CryptoPublicKey() crypto.PublicKey
|
||||
}
|
||||
|
||||
// A Signer can create signatures that verify against a public key.
|
||||
type Signer interface {
|
||||
// PublicKey returns an associated PublicKey instance.
|
||||
|
@ -348,6 +357,10 @@ func (r *rsaPublicKey) Verify(data []byte, sig *Signature) error {
|
|||
return rsa.VerifyPKCS1v15((*rsa.PublicKey)(r), crypto.SHA1, digest, sig.Blob)
|
||||
}
|
||||
|
||||
func (r *rsaPublicKey) CryptoPublicKey() crypto.PublicKey {
|
||||
return (*rsa.PublicKey)(r)
|
||||
}
|
||||
|
||||
type dsaPublicKey dsa.PublicKey
|
||||
|
||||
func (r *dsaPublicKey) Type() string {
|
||||
|
@ -416,6 +429,10 @@ func (k *dsaPublicKey) Verify(data []byte, sig *Signature) error {
|
|||
return errors.New("ssh: signature did not verify")
|
||||
}
|
||||
|
||||
func (k *dsaPublicKey) CryptoPublicKey() crypto.PublicKey {
|
||||
return (*dsa.PublicKey)(k)
|
||||
}
|
||||
|
||||
type dsaPrivateKey struct {
|
||||
*dsa.PrivateKey
|
||||
}
|
||||
|
@ -509,6 +526,10 @@ func (key ed25519PublicKey) Verify(b []byte, sig *Signature) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (k ed25519PublicKey) CryptoPublicKey() crypto.PublicKey {
|
||||
return ed25519.PublicKey(k)
|
||||
}
|
||||
|
||||
func supportedEllipticCurve(curve elliptic.Curve) bool {
|
||||
return curve == elliptic.P256() || curve == elliptic.P384() || curve == elliptic.P521()
|
||||
}
|
||||
|
@ -604,6 +625,10 @@ func (key *ecdsaPublicKey) Verify(data []byte, sig *Signature) error {
|
|||
return errors.New("ssh: signature did not verify")
|
||||
}
|
||||
|
||||
func (k *ecdsaPublicKey) CryptoPublicKey() crypto.PublicKey {
|
||||
return (*ecdsa.PublicKey)(k)
|
||||
}
|
||||
|
||||
// NewSignerFromKey takes an *rsa.PrivateKey, *dsa.PrivateKey,
|
||||
// *ecdsa.PrivateKey or any other crypto.Signer and returns a corresponding
|
||||
// Signer instance. ECDSA keys must use P-256, P-384 or P-521.
|
||||
|
@ -700,8 +725,8 @@ func (s *wrappedSigner) Sign(rand io.Reader, data []byte) (*Signature, error) {
|
|||
}
|
||||
|
||||
// NewPublicKey takes an *rsa.PublicKey, *dsa.PublicKey, *ecdsa.PublicKey,
|
||||
// ed25519.PublicKey, or any other crypto.Signer and returns a corresponding
|
||||
// Signer instance. ECDSA keys must use P-256, P-384 or P-521.
|
||||
// or ed25519.PublicKey returns a corresponding PublicKey instance.
|
||||
// ECDSA keys must use P-256, P-384 or P-521.
|
||||
func NewPublicKey(key interface{}) (PublicKey, error) {
|
||||
switch key := key.(type) {
|
||||
case *rsa.PublicKey:
|
||||
|
@ -731,6 +756,14 @@ func ParsePrivateKey(pemBytes []byte) (Signer, error) {
|
|||
return NewSignerFromKey(key)
|
||||
}
|
||||
|
||||
// encryptedBlock tells whether a private key is
|
||||
// encrypted by examining its Proc-Type header
|
||||
// for a mention of ENCRYPTED
|
||||
// according to RFC 1421 Section 4.6.1.1.
|
||||
func encryptedBlock(block *pem.Block) bool {
|
||||
return strings.Contains(block.Headers["Proc-Type"], "ENCRYPTED")
|
||||
}
|
||||
|
||||
// ParseRawPrivateKey returns a private key from a PEM encoded private key. It
|
||||
// supports RSA (PKCS#1), DSA (OpenSSL), and ECDSA private keys.
|
||||
func ParseRawPrivateKey(pemBytes []byte) (interface{}, error) {
|
||||
|
@ -739,6 +772,10 @@ func ParseRawPrivateKey(pemBytes []byte) (interface{}, error) {
|
|||
return nil, errors.New("ssh: no key found")
|
||||
}
|
||||
|
||||
if encryptedBlock(block) {
|
||||
return nil, errors.New("ssh: cannot decode encrypted private keys")
|
||||
}
|
||||
|
||||
switch block.Type {
|
||||
case "RSA PRIVATE KEY":
|
||||
return x509.ParsePKCS1PrivateKey(block.Bytes)
|
||||
|
@ -761,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 {
|
||||
|
@ -779,15 +816,15 @@ 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
|
||||
}
|
||||
|
||||
// Implemented based on the documentation at
|
||||
// https://github.com/openssh/openssh-portable/blob/master/PROTOCOL.key
|
||||
func parseOpenSSHPrivateKey(key []byte) (*ed25519.PrivateKey, error) {
|
||||
func parseOpenSSHPrivateKey(key []byte) (crypto.PrivateKey, error) {
|
||||
magic := append([]byte("openssh-key-v1"), 0)
|
||||
if !bytes.Equal(magic, key[0:len(magic)]) {
|
||||
return nil, errors.New("ssh: invalid openssh private key format")
|
||||
|
@ -807,14 +844,15 @@ func parseOpenSSHPrivateKey(key []byte) (*ed25519.PrivateKey, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
if w.KdfName != "none" || w.CipherName != "none" {
|
||||
return nil, errors.New("ssh: cannot decode encrypted private keys")
|
||||
}
|
||||
|
||||
pk1 := struct {
|
||||
Check1 uint32
|
||||
Check2 uint32
|
||||
Keytype string
|
||||
Pub []byte
|
||||
Priv []byte
|
||||
Comment string
|
||||
Pad []byte `ssh:"rest"`
|
||||
Rest []byte `ssh:"rest"`
|
||||
}{}
|
||||
|
||||
if err := Unmarshal(w.PrivKeyBlock, &pk1); err != nil {
|
||||
|
@ -825,22 +863,95 @@ func parseOpenSSHPrivateKey(key []byte) (*ed25519.PrivateKey, error) {
|
|||
return nil, errors.New("ssh: checkint mismatch")
|
||||
}
|
||||
|
||||
// we only handle ed25519 keys currently
|
||||
if pk1.Keytype != KeyAlgoED25519 {
|
||||
// we only handle ed25519 and rsa keys currently
|
||||
switch pk1.Keytype {
|
||||
case KeyAlgoRSA:
|
||||
// https://github.com/openssh/openssh-portable/blob/master/sshkey.c#L2760-L2773
|
||||
key := struct {
|
||||
N *big.Int
|
||||
E *big.Int
|
||||
D *big.Int
|
||||
Iqmp *big.Int
|
||||
P *big.Int
|
||||
Q *big.Int
|
||||
Comment string
|
||||
Pad []byte `ssh:"rest"`
|
||||
}{}
|
||||
|
||||
if err := Unmarshal(pk1.Rest, &key); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for i, b := range key.Pad {
|
||||
if int(b) != i+1 {
|
||||
return nil, errors.New("ssh: padding not as expected")
|
||||
}
|
||||
}
|
||||
|
||||
pk := &rsa.PrivateKey{
|
||||
PublicKey: rsa.PublicKey{
|
||||
N: key.N,
|
||||
E: int(key.E.Int64()),
|
||||
},
|
||||
D: key.D,
|
||||
Primes: []*big.Int{key.P, key.Q},
|
||||
}
|
||||
|
||||
if err := pk.Validate(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
pk.Precompute()
|
||||
|
||||
return pk, nil
|
||||
case KeyAlgoED25519:
|
||||
key := struct {
|
||||
Pub []byte
|
||||
Priv []byte
|
||||
Comment string
|
||||
Pad []byte `ssh:"rest"`
|
||||
}{}
|
||||
|
||||
if err := Unmarshal(pk1.Rest, &key); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if len(key.Priv) != ed25519.PrivateKeySize {
|
||||
return nil, errors.New("ssh: private key unexpected length")
|
||||
}
|
||||
|
||||
for i, b := range key.Pad {
|
||||
if int(b) != i+1 {
|
||||
return nil, errors.New("ssh: padding not as expected")
|
||||
}
|
||||
}
|
||||
|
||||
pk := ed25519.PrivateKey(make([]byte, ed25519.PrivateKeySize))
|
||||
copy(pk, key.Priv)
|
||||
return &pk, nil
|
||||
default:
|
||||
return nil, errors.New("ssh: unhandled key type")
|
||||
}
|
||||
|
||||
for i, b := range pk1.Pad {
|
||||
if int(b) != i+1 {
|
||||
return nil, errors.New("ssh: padding not as expected")
|
||||
}
|
||||
}
|
||||
|
||||
if len(pk1.Priv) != ed25519.PrivateKeySize {
|
||||
return nil, errors.New("ssh: private key unexpected length")
|
||||
}
|
||||
|
||||
pk := ed25519.PrivateKey(make([]byte, ed25519.PrivateKeySize))
|
||||
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
|
||||
}
|
||||
|
|
52
vendor/src/golang.org/x/crypto/ssh/keys_test.go
vendored
52
vendor/src/golang.org/x/crypto/ssh/keys_test.go
vendored
|
@ -132,6 +132,22 @@ func TestParseECPrivateKey(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
// 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
|
||||
|
@ -309,14 +325,14 @@ func TestInvalidEntry(t *testing.T) {
|
|||
}
|
||||
|
||||
var knownHostsParseTests = []struct {
|
||||
input string
|
||||
err string
|
||||
input string
|
||||
err string
|
||||
|
||||
marker string
|
||||
comment string
|
||||
hosts []string
|
||||
rest string
|
||||
} {
|
||||
marker string
|
||||
comment string
|
||||
hosts []string
|
||||
rest string
|
||||
}{
|
||||
{
|
||||
"",
|
||||
"EOF",
|
||||
|
@ -375,13 +391,13 @@ var knownHostsParseTests = []struct {
|
|||
"localhost,[host2:123]\tssh-rsa {RSAPUB}\tcomment comment",
|
||||
"",
|
||||
|
||||
"", "comment comment", []string{"localhost","[host2:123]"}, "",
|
||||
"", "comment comment", []string{"localhost", "[host2:123]"}, "",
|
||||
},
|
||||
{
|
||||
"@marker \tlocalhost,[host2:123]\tssh-rsa {RSAPUB}",
|
||||
"",
|
||||
|
||||
"marker", "", []string{"localhost","[host2:123]"}, "",
|
||||
"marker", "", []string{"localhost", "[host2:123]"}, "",
|
||||
},
|
||||
{
|
||||
"@marker \tlocalhost,[host2:123]\tssh-rsa aabbccdd",
|
||||
|
@ -438,3 +454,21 @@ func TestKnownHostsParsing(t *testing.T) {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestFingerprintLegacyMD5(t *testing.T) {
|
||||
pub, _ := getTestKey()
|
||||
fingerprint := FingerprintLegacyMD5(pub)
|
||||
want := "fb:61:6d:1a:e3:f0:95:45:3c:a0:79:be:4a:93:63:66" // ssh-keygen -lf -E md5 rsa
|
||||
if fingerprint != want {
|
||||
t.Errorf("got fingerprint %q want %q", fingerprint, want)
|
||||
}
|
||||
}
|
||||
|
||||
func TestFingerprintSHA256(t *testing.T) {
|
||||
pub, _ := getTestKey()
|
||||
fingerprint := FingerprintSHA256(pub)
|
||||
want := "SHA256:Anr3LjZK8YVpjrxu79myrW9Hrb/wpcMNpVvTq/RcBm8" // ssh-keygen -lf rsa
|
||||
if fingerprint != want {
|
||||
t.Errorf("got fingerprint %q want %q", fingerprint, want)
|
||||
}
|
||||
}
|
||||
|
|
469
vendor/src/golang.org/x/crypto/ssh/knownhosts/knownhosts.go
vendored
Normal file
469
vendor/src/golang.org/x/crypto/ssh/knownhosts/knownhosts.go
vendored
Normal file
|
@ -0,0 +1,469 @@
|
|||
// Copyright 2017 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 knownhosts implements a parser for the OpenSSH
|
||||
// known_hosts host key database.
|
||||
package knownhosts
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"encoding/base64"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"net"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"golang.org/x/crypto/ssh"
|
||||
)
|
||||
|
||||
// See the sshd manpage
|
||||
// (http://man.openbsd.org/sshd#SSH_KNOWN_HOSTS_FILE_FORMAT) for
|
||||
// background.
|
||||
|
||||
type addr struct{ host, port string }
|
||||
|
||||
func (a *addr) String() string {
|
||||
return a.host + ":" + a.port
|
||||
}
|
||||
|
||||
func (a *addr) eq(b addr) bool {
|
||||
return a.host == b.host && a.port == b.port
|
||||
}
|
||||
|
||||
type hostPattern struct {
|
||||
negate bool
|
||||
addr addr
|
||||
}
|
||||
|
||||
func (p *hostPattern) String() string {
|
||||
n := ""
|
||||
if p.negate {
|
||||
n = "!"
|
||||
}
|
||||
|
||||
return n + p.addr.String()
|
||||
}
|
||||
|
||||
// See
|
||||
// https://android.googlesource.com/platform/external/openssh/+/ab28f5495c85297e7a597c1ba62e996416da7c7e/addrmatch.c
|
||||
// The matching of * has no regard for separators, unlike filesystem globs
|
||||
func wildcardMatch(pat []byte, str []byte) bool {
|
||||
for {
|
||||
if len(pat) == 0 {
|
||||
return len(str) == 0
|
||||
}
|
||||
if len(str) == 0 {
|
||||
return false
|
||||
}
|
||||
|
||||
if pat[0] == '*' {
|
||||
if len(pat) == 1 {
|
||||
return true
|
||||
}
|
||||
|
||||
for j := range str {
|
||||
if wildcardMatch(pat[1:], str[j:]) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
if pat[0] == '?' || pat[0] == str[0] {
|
||||
pat = pat[1:]
|
||||
str = str[1:]
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (l *hostPattern) match(a addr) bool {
|
||||
return wildcardMatch([]byte(l.addr.host), []byte(a.host)) && l.addr.port == a.port
|
||||
}
|
||||
|
||||
type keyDBLine struct {
|
||||
cert bool
|
||||
patterns []*hostPattern
|
||||
knownKey KnownKey
|
||||
}
|
||||
|
||||
func (l *keyDBLine) String() string {
|
||||
c := ""
|
||||
if l.cert {
|
||||
c = markerCert + " "
|
||||
}
|
||||
|
||||
var ss []string
|
||||
for _, p := range l.patterns {
|
||||
ss = append(ss, p.String())
|
||||
}
|
||||
|
||||
return c + strings.Join(ss, ",") + " " + serialize(l.knownKey.Key)
|
||||
}
|
||||
|
||||
func serialize(k ssh.PublicKey) string {
|
||||
return k.Type() + " " + base64.StdEncoding.EncodeToString(k.Marshal())
|
||||
}
|
||||
|
||||
func (l *keyDBLine) match(addrs []addr) bool {
|
||||
matched := false
|
||||
for _, p := range l.patterns {
|
||||
for _, a := range addrs {
|
||||
m := p.match(a)
|
||||
if p.negate {
|
||||
if m {
|
||||
return false
|
||||
} else {
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
if m {
|
||||
matched = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return matched
|
||||
}
|
||||
|
||||
type hostKeyDB struct {
|
||||
// Serialized version of revoked keys
|
||||
revoked map[string]*KnownKey
|
||||
lines []keyDBLine
|
||||
}
|
||||
|
||||
func (db *hostKeyDB) String() string {
|
||||
var ls []string
|
||||
for _, k := range db.revoked {
|
||||
ls = append(ls, markerRevoked+" * "+serialize(k.Key))
|
||||
}
|
||||
for _, l := range db.lines {
|
||||
ls = append(ls, l.String())
|
||||
}
|
||||
return strings.Join(ls, "\n")
|
||||
}
|
||||
|
||||
func newHostKeyDB() *hostKeyDB {
|
||||
db := &hostKeyDB{
|
||||
revoked: make(map[string]*KnownKey),
|
||||
}
|
||||
|
||||
return db
|
||||
}
|
||||
|
||||
func keyEq(a, b ssh.PublicKey) bool {
|
||||
return bytes.Equal(a.Marshal(), b.Marshal())
|
||||
}
|
||||
|
||||
// IsAuthority can be used as a callback in ssh.CertChecker
|
||||
func (db *hostKeyDB) IsAuthority(remote ssh.PublicKey) bool {
|
||||
for _, l := range db.lines {
|
||||
// TODO(hanwen): should we check the hostname against host pattern?
|
||||
if l.cert && keyEq(l.knownKey.Key, remote) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// IsRevoked can be used as a callback in ssh.CertChecker
|
||||
func (db *hostKeyDB) IsRevoked(key *ssh.Certificate) bool {
|
||||
_, ok := db.revoked[string(key.Marshal())]
|
||||
return ok
|
||||
}
|
||||
|
||||
const markerCert = "@cert-authority"
|
||||
const markerRevoked = "@revoked"
|
||||
|
||||
func nextWord(line []byte) (string, []byte) {
|
||||
i := bytes.IndexAny(line, "\t ")
|
||||
if i == -1 {
|
||||
return string(line), nil
|
||||
}
|
||||
|
||||
return string(line[:i]), bytes.TrimSpace(line[i:])
|
||||
}
|
||||
|
||||
func parseLine(line []byte) (marker string, pattern []string, key ssh.PublicKey, err error) {
|
||||
if w, next := nextWord(line); w == markerCert || w == markerRevoked {
|
||||
marker = w
|
||||
line = next
|
||||
}
|
||||
|
||||
hostPart, line := nextWord(line)
|
||||
if len(line) == 0 {
|
||||
return "", nil, nil, errors.New("knownhosts: missing host pattern")
|
||||
}
|
||||
|
||||
if len(hostPart) > 0 && hostPart[0] == '|' {
|
||||
return "", nil, nil, errors.New("knownhosts: hashed hostnames not implemented")
|
||||
}
|
||||
|
||||
pattern = strings.Split(hostPart, ",")
|
||||
|
||||
// ignore the keytype as it's in the key blob anyway.
|
||||
_, line = nextWord(line)
|
||||
if len(line) == 0 {
|
||||
return "", nil, nil, errors.New("knownhosts: missing key type pattern")
|
||||
}
|
||||
|
||||
keyBlob, _ := nextWord(line)
|
||||
|
||||
keyBytes, err := base64.StdEncoding.DecodeString(keyBlob)
|
||||
if err != nil {
|
||||
return "", nil, nil, err
|
||||
}
|
||||
key, err = ssh.ParsePublicKey(keyBytes)
|
||||
if err != nil {
|
||||
return "", nil, nil, err
|
||||
}
|
||||
|
||||
return marker, pattern, key, nil
|
||||
}
|
||||
|
||||
func (db *hostKeyDB) parseLine(line []byte, filename string, linenum int) error {
|
||||
marker, patterns, key, err := parseLine(line)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if marker == markerRevoked {
|
||||
db.revoked[string(key.Marshal())] = &KnownKey{
|
||||
Key: key,
|
||||
Filename: filename,
|
||||
Line: linenum,
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
entry := keyDBLine{
|
||||
cert: marker == markerCert,
|
||||
knownKey: KnownKey{
|
||||
Filename: filename,
|
||||
Line: linenum,
|
||||
Key: key,
|
||||
},
|
||||
}
|
||||
|
||||
for _, p := range patterns {
|
||||
if len(p) == 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
var a addr
|
||||
var negate bool
|
||||
if p[0] == '!' {
|
||||
negate = true
|
||||
p = p[1:]
|
||||
}
|
||||
|
||||
if len(p) == 0 {
|
||||
return errors.New("knownhosts: negation without following hostname")
|
||||
}
|
||||
|
||||
if p[0] == '[' {
|
||||
a.host, a.port, err = net.SplitHostPort(p)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
a.host, a.port, err = net.SplitHostPort(p)
|
||||
if err != nil {
|
||||
a.host = p
|
||||
a.port = "22"
|
||||
}
|
||||
}
|
||||
|
||||
entry.patterns = append(entry.patterns, &hostPattern{
|
||||
negate: negate,
|
||||
addr: a,
|
||||
})
|
||||
}
|
||||
|
||||
db.lines = append(db.lines, entry)
|
||||
return nil
|
||||
}
|
||||
|
||||
// KnownKey represents a key declared in a known_hosts file.
|
||||
type KnownKey struct {
|
||||
Key ssh.PublicKey
|
||||
Filename string
|
||||
Line int
|
||||
}
|
||||
|
||||
func (k *KnownKey) String() string {
|
||||
return fmt.Sprintf("%s:%d: %s", k.Filename, k.Line, serialize(k.Key))
|
||||
}
|
||||
|
||||
// KeyError is returned if we did not find the key in the host key
|
||||
// database, or there was a mismatch. Typically, in batch
|
||||
// applications, this should be interpreted as failure. Interactive
|
||||
// applications can offer an interactive prompt to the user.
|
||||
type KeyError struct {
|
||||
// Want holds the accepted host keys. For each key algorithm,
|
||||
// there can be one hostkey. If Want is empty, the host is
|
||||
// unknown. If Want is non-empty, there was a mismatch, which
|
||||
// can signify a MITM attack.
|
||||
Want []KnownKey
|
||||
}
|
||||
|
||||
func (u *KeyError) Error() string {
|
||||
if len(u.Want) == 0 {
|
||||
return "knownhosts: key is unknown"
|
||||
}
|
||||
return "knownhosts: key mismatch"
|
||||
}
|
||||
|
||||
// RevokedError is returned if we found a key that was revoked.
|
||||
type RevokedError struct {
|
||||
Revoked KnownKey
|
||||
}
|
||||
|
||||
func (r *RevokedError) Error() string {
|
||||
return "knownhosts: key is revoked"
|
||||
}
|
||||
|
||||
// check checks a key against the host database. This should not be
|
||||
// used for verifying certificates.
|
||||
func (db *hostKeyDB) check(address string, remote net.Addr, remoteKey ssh.PublicKey) error {
|
||||
if revoked := db.revoked[string(remoteKey.Marshal())]; revoked != nil {
|
||||
return &RevokedError{Revoked: *revoked}
|
||||
}
|
||||
|
||||
host, port, err := net.SplitHostPort(remote.String())
|
||||
if err != nil {
|
||||
return fmt.Errorf("knownhosts: SplitHostPort(%s): %v", remote, err)
|
||||
}
|
||||
|
||||
addrs := []addr{
|
||||
{host, port},
|
||||
}
|
||||
|
||||
if address != "" {
|
||||
host, port, err := net.SplitHostPort(address)
|
||||
if err != nil {
|
||||
return fmt.Errorf("knownhosts: SplitHostPort(%s): %v", address, err)
|
||||
}
|
||||
|
||||
addrs = append(addrs, addr{host, port})
|
||||
}
|
||||
|
||||
return db.checkAddrs(addrs, remoteKey)
|
||||
}
|
||||
|
||||
// checkAddrs checks if we can find the given public key for any of
|
||||
// the given addresses. If we only find an entry for the IP address,
|
||||
// or only the hostname, then this still succeeds.
|
||||
func (db *hostKeyDB) checkAddrs(addrs []addr, remoteKey ssh.PublicKey) error {
|
||||
// TODO(hanwen): are these the right semantics? What if there
|
||||
// is just a key for the IP address, but not for the
|
||||
// hostname?
|
||||
|
||||
// Algorithm => key.
|
||||
knownKeys := map[string]KnownKey{}
|
||||
for _, l := range db.lines {
|
||||
if l.match(addrs) {
|
||||
typ := l.knownKey.Key.Type()
|
||||
if _, ok := knownKeys[typ]; !ok {
|
||||
knownKeys[typ] = l.knownKey
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
keyErr := &KeyError{}
|
||||
for _, v := range knownKeys {
|
||||
keyErr.Want = append(keyErr.Want, v)
|
||||
}
|
||||
|
||||
// Unknown remote host.
|
||||
if len(knownKeys) == 0 {
|
||||
return keyErr
|
||||
}
|
||||
|
||||
// If the remote host starts using a different, unknown key type, we
|
||||
// also interpret that as a mismatch.
|
||||
if known, ok := knownKeys[remoteKey.Type()]; !ok || !keyEq(known.Key, remoteKey) {
|
||||
return keyErr
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// The Read function parses file contents.
|
||||
func (db *hostKeyDB) Read(r io.Reader, filename string) error {
|
||||
scanner := bufio.NewScanner(r)
|
||||
|
||||
lineNum := 0
|
||||
for scanner.Scan() {
|
||||
lineNum++
|
||||
line := scanner.Bytes()
|
||||
line = bytes.TrimSpace(line)
|
||||
if len(line) == 0 || line[0] == '#' {
|
||||
continue
|
||||
}
|
||||
|
||||
if err := db.parseLine(line, filename, lineNum); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return scanner.Err()
|
||||
}
|
||||
|
||||
// New creates a host key callback from the given OpenSSH host key
|
||||
// files. The returned callback is for use in
|
||||
// ssh.ClientConfig.HostKeyCallback. Hostnames are ignored for
|
||||
// certificates, ie. any certificate authority is assumed to be valid
|
||||
// for all remote hosts. Hashed hostnames are not supported.
|
||||
func New(files ...string) (ssh.HostKeyCallback, error) {
|
||||
db := newHostKeyDB()
|
||||
for _, fn := range files {
|
||||
f, err := os.Open(fn)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer f.Close()
|
||||
if err := db.Read(f, fn); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
// TODO(hanwen): properly supporting certificates requires an
|
||||
// API change in the SSH library: IsAuthority should provide
|
||||
// the address too?
|
||||
|
||||
var certChecker ssh.CertChecker
|
||||
certChecker.IsAuthority = db.IsAuthority
|
||||
certChecker.IsRevoked = db.IsRevoked
|
||||
certChecker.HostKeyFallback = db.check
|
||||
|
||||
return certChecker.CheckHostKey, nil
|
||||
}
|
||||
|
||||
// Line returns a line to add append to the known_hosts files.
|
||||
func Line(addresses []string, key ssh.PublicKey) string {
|
||||
var trimmed []string
|
||||
for _, a := range addresses {
|
||||
host, port, err := net.SplitHostPort(a)
|
||||
if err != nil {
|
||||
host = a
|
||||
port = "22"
|
||||
}
|
||||
entry := host
|
||||
if port != "22" {
|
||||
entry = "[" + entry + "]:" + port
|
||||
} else if strings.Contains(host, ":") {
|
||||
entry = "[" + entry + "]"
|
||||
}
|
||||
|
||||
trimmed = append(trimmed, entry)
|
||||
}
|
||||
|
||||
return strings.Join(trimmed, ",") + " " + serialize(key)
|
||||
}
|
237
vendor/src/golang.org/x/crypto/ssh/knownhosts/knownhosts_test.go
vendored
Normal file
237
vendor/src/golang.org/x/crypto/ssh/knownhosts/knownhosts_test.go
vendored
Normal file
|
@ -0,0 +1,237 @@
|
|||
// Copyright 2017 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 knownhosts
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"net"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"golang.org/x/crypto/ssh"
|
||||
)
|
||||
|
||||
const edKeyStr = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIGBAarftlLeoyf+v+nVchEZII/vna2PCV8FaX4vsF5BX"
|
||||
const alternateEdKeyStr = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIXffBYeYL+WVzVru8npl5JHt2cjlr4ornFTWzoij9sx"
|
||||
const ecKeyStr = "ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBNLCu01+wpXe3xB5olXCN4SqU2rQu0qjSRKJO4Bg+JRCPU+ENcgdA5srTU8xYDz/GEa4dzK5ldPw4J/gZgSXCMs="
|
||||
|
||||
var ecKey, alternateEdKey, edKey ssh.PublicKey
|
||||
var testAddr = &net.TCPAddr{
|
||||
IP: net.IP{198, 41, 30, 196},
|
||||
Port: 22,
|
||||
}
|
||||
|
||||
var testAddr6 = &net.TCPAddr{
|
||||
IP: net.IP{198, 41, 30, 196,
|
||||
1, 2, 3, 4,
|
||||
1, 2, 3, 4,
|
||||
1, 2, 3, 4,
|
||||
},
|
||||
Port: 22,
|
||||
}
|
||||
|
||||
func init() {
|
||||
var err error
|
||||
ecKey, _, _, _, err = ssh.ParseAuthorizedKey([]byte(ecKeyStr))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
edKey, _, _, _, err = ssh.ParseAuthorizedKey([]byte(edKeyStr))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
alternateEdKey, _, _, _, err = ssh.ParseAuthorizedKey([]byte(alternateEdKeyStr))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
func testDB(t *testing.T, s string) *hostKeyDB {
|
||||
db := newHostKeyDB()
|
||||
if err := db.Read(bytes.NewBufferString(s), "testdb"); err != nil {
|
||||
t.Fatalf("Read: %v", err)
|
||||
}
|
||||
|
||||
return db
|
||||
}
|
||||
|
||||
func TestRevoked(t *testing.T) {
|
||||
db := testDB(t, "\n\n@revoked * "+edKeyStr+"\n")
|
||||
want := &RevokedError{
|
||||
Revoked: KnownKey{
|
||||
Key: edKey,
|
||||
Filename: "testdb",
|
||||
Line: 3,
|
||||
},
|
||||
}
|
||||
if err := db.check("", &net.TCPAddr{
|
||||
Port: 42,
|
||||
}, edKey); err == nil {
|
||||
t.Fatal("no error for revoked key")
|
||||
} else if !reflect.DeepEqual(want, err) {
|
||||
t.Fatalf("got %#v, want %#v", want, err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestBracket(t *testing.T) {
|
||||
db := testDB(t, `[git.eclipse.org]:29418,[198.41.30.196]:29418 `+edKeyStr)
|
||||
|
||||
if err := db.check("git.eclipse.org:29418", &net.TCPAddr{
|
||||
IP: net.IP{198, 41, 30, 196},
|
||||
Port: 29418,
|
||||
}, edKey); err != nil {
|
||||
t.Errorf("got error %v, want none", err)
|
||||
}
|
||||
|
||||
if err := db.check("git.eclipse.org:29419", &net.TCPAddr{
|
||||
Port: 42,
|
||||
}, edKey); err == nil {
|
||||
t.Fatalf("no error for unknown address")
|
||||
} else if ke, ok := err.(*KeyError); !ok {
|
||||
t.Fatalf("got type %T, want *KeyError", err)
|
||||
} else if len(ke.Want) > 0 {
|
||||
t.Fatalf("got Want %v, want []", ke.Want)
|
||||
}
|
||||
}
|
||||
|
||||
func TestNewKeyType(t *testing.T) {
|
||||
str := fmt.Sprintf("%s %s", testAddr, edKeyStr)
|
||||
db := testDB(t, str)
|
||||
if err := db.check("", testAddr, ecKey); err == nil {
|
||||
t.Fatalf("no error for unknown address")
|
||||
} else if ke, ok := err.(*KeyError); !ok {
|
||||
t.Fatalf("got type %T, want *KeyError", err)
|
||||
} else if len(ke.Want) == 0 {
|
||||
t.Fatalf("got empty KeyError.Want")
|
||||
}
|
||||
}
|
||||
|
||||
func TestSameKeyType(t *testing.T) {
|
||||
str := fmt.Sprintf("%s %s", testAddr, edKeyStr)
|
||||
db := testDB(t, str)
|
||||
if err := db.check("", testAddr, alternateEdKey); err == nil {
|
||||
t.Fatalf("no error for unknown address")
|
||||
} else if ke, ok := err.(*KeyError); !ok {
|
||||
t.Fatalf("got type %T, want *KeyError", err)
|
||||
} else if len(ke.Want) == 0 {
|
||||
t.Fatalf("got empty KeyError.Want")
|
||||
} else if got, want := ke.Want[0].Key.Marshal(), edKey.Marshal(); !bytes.Equal(got, want) {
|
||||
t.Fatalf("got key %q, want %q", got, want)
|
||||
}
|
||||
}
|
||||
|
||||
func TestIPAddress(t *testing.T) {
|
||||
str := fmt.Sprintf("%s %s", testAddr, edKeyStr)
|
||||
db := testDB(t, str)
|
||||
if err := db.check("", testAddr, edKey); err != nil {
|
||||
t.Errorf("got error %q, want none", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestIPv6Address(t *testing.T) {
|
||||
str := fmt.Sprintf("%s %s", testAddr6, edKeyStr)
|
||||
db := testDB(t, str)
|
||||
|
||||
if err := db.check("", testAddr6, edKey); err != nil {
|
||||
t.Errorf("got error %q, want none", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestBasic(t *testing.T) {
|
||||
str := fmt.Sprintf("#comment\n\nserver.org,%s %s\notherhost %s", testAddr, edKeyStr, ecKeyStr)
|
||||
db := testDB(t, str)
|
||||
if err := db.check("server.org:22", testAddr, edKey); err != nil {
|
||||
t.Errorf("got error %q, want none", err)
|
||||
}
|
||||
|
||||
want := KnownKey{
|
||||
Key: edKey,
|
||||
Filename: "testdb",
|
||||
Line: 3,
|
||||
}
|
||||
if err := db.check("server.org:22", testAddr, ecKey); err == nil {
|
||||
t.Errorf("succeeded, want KeyError")
|
||||
} else if ke, ok := err.(*KeyError); !ok {
|
||||
t.Errorf("got %T, want *KeyError", err)
|
||||
} else if len(ke.Want) != 1 {
|
||||
t.Errorf("got %v, want 1 entry", ke)
|
||||
} else if !reflect.DeepEqual(ke.Want[0], want) {
|
||||
t.Errorf("got %v, want %v", ke.Want[0], want)
|
||||
}
|
||||
}
|
||||
|
||||
func TestNegate(t *testing.T) {
|
||||
str := fmt.Sprintf("%s,!server.org %s", testAddr, edKeyStr)
|
||||
db := testDB(t, str)
|
||||
if err := db.check("server.org:22", testAddr, ecKey); err == nil {
|
||||
t.Errorf("succeeded")
|
||||
} else if ke, ok := err.(*KeyError); !ok {
|
||||
t.Errorf("got error type %T, want *KeyError", err)
|
||||
} else if len(ke.Want) != 0 {
|
||||
t.Errorf("got expected keys %d (first of type %s), want []", len(ke.Want), ke.Want[0].Key.Type())
|
||||
}
|
||||
}
|
||||
|
||||
func TestWildcard(t *testing.T) {
|
||||
str := fmt.Sprintf("server*.domain %s", edKeyStr)
|
||||
db := testDB(t, str)
|
||||
|
||||
want := &KeyError{
|
||||
Want: []KnownKey{{
|
||||
Filename: "testdb",
|
||||
Line: 1,
|
||||
Key: edKey,
|
||||
}},
|
||||
}
|
||||
|
||||
got := db.check("server.domain:22", &net.TCPAddr{}, ecKey)
|
||||
if !reflect.DeepEqual(got, want) {
|
||||
t.Errorf("got %s, want %s", got, want)
|
||||
}
|
||||
}
|
||||
|
||||
func TestLine(t *testing.T) {
|
||||
for in, want := range map[string]string{
|
||||
"server.org": "server.org " + edKeyStr,
|
||||
"server.org:22": "server.org " + edKeyStr,
|
||||
"server.org:23": "[server.org]:23 " + edKeyStr,
|
||||
"[c629:1ec4:102:304:102:304:102:304]:22": "[c629:1ec4:102:304:102:304:102:304] " + edKeyStr,
|
||||
"[c629:1ec4:102:304:102:304:102:304]:23": "[c629:1ec4:102:304:102:304:102:304]:23 " + edKeyStr,
|
||||
} {
|
||||
if got := Line([]string{in}, edKey); got != want {
|
||||
t.Errorf("Line(%q) = %q, want %q", in, got, want)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestWildcardMatch(t *testing.T) {
|
||||
for _, c := range []struct {
|
||||
pat, str string
|
||||
want bool
|
||||
}{
|
||||
{"a?b", "abb", true},
|
||||
{"ab", "abc", false},
|
||||
{"abc", "ab", false},
|
||||
{"a*b", "axxxb", true},
|
||||
{"a*b", "axbxb", true},
|
||||
{"a*b", "axbxbc", false},
|
||||
{"a*?", "axbxc", true},
|
||||
{"a*b*", "axxbxxxxxx", true},
|
||||
{"a*b*c", "axxbxxxxxxc", true},
|
||||
{"a*b*?", "axxbxxxxxxc", true},
|
||||
{"a*b*z", "axxbxxbxxxz", true},
|
||||
{"a*b*z", "axxbxxzxxxz", true},
|
||||
{"a*b*z", "axxbxxzxxx", false},
|
||||
} {
|
||||
got := wildcardMatch([]byte(c.pat), []byte(c.str))
|
||||
if got != c.want {
|
||||
t.Errorf("wildcardMatch(%q, %q) = %v, want %v", c.pat, c.str, got, c.want)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// TODO(hanwen): test coverage for certificates.
|
10
vendor/src/golang.org/x/crypto/ssh/mac.go
vendored
10
vendor/src/golang.org/x/crypto/ssh/mac.go
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)}
|
||||
}},
|
||||
}
|
||||
|
|
4
vendor/src/golang.org/x/crypto/ssh/mux.go
vendored
4
vendor/src/golang.org/x/crypto/ssh/mux.go
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 {
|
||||
|
|
|
@ -499,4 +499,7 @@ func TestDebug(t *testing.T) {
|
|||
if debugHandshake {
|
||||
t.Error("handshake debug switched on")
|
||||
}
|
||||
if debugTransport {
|
||||
t.Error("transport debug switched on")
|
||||
}
|
||||
}
|
||||
|
|
70
vendor/src/golang.org/x/crypto/ssh/server.go
vendored
70
vendor/src/golang.org/x/crypto/ssh/server.go
vendored
|
@ -10,6 +10,7 @@ import (
|
|||
"fmt"
|
||||
"io"
|
||||
"net"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// The Permissions type holds fine-grained permissions that are
|
||||
|
@ -44,6 +45,12 @@ type ServerConfig struct {
|
|||
// authenticating.
|
||||
NoClientAuth bool
|
||||
|
||||
// MaxAuthTries specifies the maximum number of authentication attempts
|
||||
// permitted per connection. If set to a negative number, the number of
|
||||
// attempts are unlimited. If set to zero, the number of attempts are limited
|
||||
// to 6.
|
||||
MaxAuthTries int
|
||||
|
||||
// PasswordCallback, if non-nil, is called when a user
|
||||
// attempts to authenticate using a password.
|
||||
PasswordCallback func(conn ConnMetadata, password []byte) (*Permissions, error)
|
||||
|
@ -140,6 +147,10 @@ type ServerConn struct {
|
|||
// Request and NewChannel channels must be serviced, or the connection
|
||||
// will hang.
|
||||
func NewServerConn(c net.Conn, config *ServerConfig) (*ServerConn, <-chan NewChannel, <-chan *Request, error) {
|
||||
if config.MaxAuthTries == 0 {
|
||||
config.MaxAuthTries = 6
|
||||
}
|
||||
|
||||
fullConf := *config
|
||||
fullConf.SetDefaults()
|
||||
s := &connection{
|
||||
|
@ -188,7 +199,7 @@ func (s *connection) serverHandshake(config *ServerConfig) (*Permissions, error)
|
|||
tr := newTransport(s.sshConn.conn, config.Rand, false /* not client */)
|
||||
s.transport = newServerTransport(tr, s.clientVersion, s.serverVersion, config)
|
||||
|
||||
if err := s.transport.requestInitialKeyChange(); err != nil {
|
||||
if err := s.transport.waitSession(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
|
@ -231,7 +242,7 @@ func isAcceptableAlgo(algo string) bool {
|
|||
return false
|
||||
}
|
||||
|
||||
func checkSourceAddress(addr net.Addr, sourceAddr string) error {
|
||||
func checkSourceAddress(addr net.Addr, sourceAddrs string) error {
|
||||
if addr == nil {
|
||||
return errors.New("ssh: no address known for client, but source-address match required")
|
||||
}
|
||||
|
@ -241,18 +252,20 @@ func checkSourceAddress(addr net.Addr, sourceAddr string) error {
|
|||
return fmt.Errorf("ssh: remote address %v is not an TCP address when checking source-address match", addr)
|
||||
}
|
||||
|
||||
if allowedIP := net.ParseIP(sourceAddr); allowedIP != nil {
|
||||
if bytes.Equal(allowedIP, tcpAddr.IP) {
|
||||
return nil
|
||||
}
|
||||
} else {
|
||||
_, ipNet, err := net.ParseCIDR(sourceAddr)
|
||||
if err != nil {
|
||||
return fmt.Errorf("ssh: error parsing source-address restriction %q: %v", sourceAddr, err)
|
||||
}
|
||||
for _, sourceAddr := range strings.Split(sourceAddrs, ",") {
|
||||
if allowedIP := net.ParseIP(sourceAddr); allowedIP != nil {
|
||||
if allowedIP.Equal(tcpAddr.IP) {
|
||||
return nil
|
||||
}
|
||||
} else {
|
||||
_, ipNet, err := net.ParseCIDR(sourceAddr)
|
||||
if err != nil {
|
||||
return fmt.Errorf("ssh: error parsing source-address restriction %q: %v", sourceAddr, err)
|
||||
}
|
||||
|
||||
if ipNet.Contains(tcpAddr.IP) {
|
||||
return nil
|
||||
if ipNet.Contains(tcpAddr.IP) {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -260,12 +273,27 @@ func checkSourceAddress(addr net.Addr, sourceAddr string) error {
|
|||
}
|
||||
|
||||
func (s *connection) serverAuthenticate(config *ServerConfig) (*Permissions, error) {
|
||||
var err error
|
||||
sessionID := s.transport.getSessionID()
|
||||
var cache pubKeyCache
|
||||
var perms *Permissions
|
||||
|
||||
authFailures := 0
|
||||
|
||||
userAuthLoop:
|
||||
for {
|
||||
if authFailures >= config.MaxAuthTries && config.MaxAuthTries > 0 {
|
||||
discMsg := &disconnectMsg{
|
||||
Reason: 2,
|
||||
Message: "too many authentication failures",
|
||||
}
|
||||
|
||||
if err := s.transport.writePacket(Marshal(discMsg)); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return nil, discMsg
|
||||
}
|
||||
|
||||
var userAuthReq userAuthRequestMsg
|
||||
if packet, err := s.transport.readPacket(); err != nil {
|
||||
return nil, err
|
||||
|
@ -286,6 +314,11 @@ userAuthLoop:
|
|||
if config.NoClientAuth {
|
||||
authErr = nil
|
||||
}
|
||||
|
||||
// allow initial attempt of 'none' without penalty
|
||||
if authFailures == 0 {
|
||||
authFailures--
|
||||
}
|
||||
case "password":
|
||||
if config.PasswordCallback == nil {
|
||||
authErr = errors.New("ssh: password auth not configured")
|
||||
|
@ -357,6 +390,7 @@ userAuthLoop:
|
|||
if isQuery {
|
||||
// The client can query if the given public key
|
||||
// would be okay.
|
||||
|
||||
if len(payload) > 0 {
|
||||
return nil, parseError(msgUserAuthRequest)
|
||||
}
|
||||
|
@ -385,7 +419,7 @@ userAuthLoop:
|
|||
if !isAcceptableAlgo(sig.Format) {
|
||||
break
|
||||
}
|
||||
signedData := buildDataSignedForAuth(s.transport.getSessionID(), userAuthReq, algoBytes, pubKeyData)
|
||||
signedData := buildDataSignedForAuth(sessionID, userAuthReq, algoBytes, pubKeyData)
|
||||
|
||||
if err := pubKey.Verify(signedData, sig); err != nil {
|
||||
return nil, err
|
||||
|
@ -406,6 +440,8 @@ userAuthLoop:
|
|||
break userAuthLoop
|
||||
}
|
||||
|
||||
authFailures++
|
||||
|
||||
var failureMsg userAuthFailureMsg
|
||||
if config.PasswordCallback != nil {
|
||||
failureMsg.Methods = append(failureMsg.Methods, "password")
|
||||
|
@ -421,12 +457,12 @@ userAuthLoop:
|
|||
return nil, errors.New("ssh: no authentication methods configured but NoClientAuth is also false")
|
||||
}
|
||||
|
||||
if err = s.transport.writePacket(Marshal(&failureMsg)); err != nil {
|
||||
if err := s.transport.writePacket(Marshal(&failureMsg)); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
if err = s.transport.writePacket([]byte{msgUserAuthSuccess}); err != nil {
|
||||
if err := s.transport.writePacket([]byte{msgUserAuthSuccess}); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return perms, nil
|
||||
|
|
|
@ -59,7 +59,8 @@ func dial(handler serverType, t *testing.T) *Client {
|
|||
}()
|
||||
|
||||
config := &ClientConfig{
|
||||
User: "testuser",
|
||||
User: "testuser",
|
||||
HostKeyCallback: InsecureIgnoreHostKey(),
|
||||
}
|
||||
|
||||
conn, chans, reqs, err := NewClientConn(c2, "", config)
|
||||
|
@ -641,7 +642,8 @@ func TestSessionID(t *testing.T) {
|
|||
}
|
||||
serverConf.AddHostKey(testSigners["ecdsa"])
|
||||
clientConf := &ClientConfig{
|
||||
User: "user",
|
||||
HostKeyCallback: InsecureIgnoreHostKey(),
|
||||
User: "user",
|
||||
}
|
||||
|
||||
go func() {
|
||||
|
@ -747,7 +749,9 @@ func TestHostKeyAlgorithms(t *testing.T) {
|
|||
|
||||
// By default, we get the preferred algorithm, which is ECDSA 256.
|
||||
|
||||
clientConf := &ClientConfig{}
|
||||
clientConf := &ClientConfig{
|
||||
HostKeyCallback: InsecureIgnoreHostKey(),
|
||||
}
|
||||
connect(clientConf, KeyAlgoECDSA256)
|
||||
|
||||
// Client asks for RSA explicitly.
|
||||
|
|
115
vendor/src/golang.org/x/crypto/ssh/streamlocal.go
vendored
Normal file
115
vendor/src/golang.org/x/crypto/ssh/streamlocal.go
vendored
Normal file
|
@ -0,0 +1,115 @@
|
|||
package ssh
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"io"
|
||||
"net"
|
||||
)
|
||||
|
||||
// streamLocalChannelOpenDirectMsg is a struct used for SSH_MSG_CHANNEL_OPEN message
|
||||
// with "direct-streamlocal@openssh.com" string.
|
||||
//
|
||||
// See openssh-portable/PROTOCOL, section 2.4. connection: Unix domain socket forwarding
|
||||
// https://github.com/openssh/openssh-portable/blob/master/PROTOCOL#L235
|
||||
type streamLocalChannelOpenDirectMsg struct {
|
||||
socketPath string
|
||||
reserved0 string
|
||||
reserved1 uint32
|
||||
}
|
||||
|
||||
// forwardedStreamLocalPayload is a struct used for SSH_MSG_CHANNEL_OPEN message
|
||||
// with "forwarded-streamlocal@openssh.com" string.
|
||||
type forwardedStreamLocalPayload struct {
|
||||
SocketPath string
|
||||
Reserved0 string
|
||||
}
|
||||
|
||||
// streamLocalChannelForwardMsg is a struct used for SSH2_MSG_GLOBAL_REQUEST message
|
||||
// with "streamlocal-forward@openssh.com"/"cancel-streamlocal-forward@openssh.com" string.
|
||||
type streamLocalChannelForwardMsg struct {
|
||||
socketPath string
|
||||
}
|
||||
|
||||
// ListenUnix is similar to ListenTCP but uses a Unix domain socket.
|
||||
func (c *Client) ListenUnix(socketPath string) (net.Listener, error) {
|
||||
m := streamLocalChannelForwardMsg{
|
||||
socketPath,
|
||||
}
|
||||
// send message
|
||||
ok, _, err := c.SendRequest("streamlocal-forward@openssh.com", true, Marshal(&m))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if !ok {
|
||||
return nil, errors.New("ssh: streamlocal-forward@openssh.com request denied by peer")
|
||||
}
|
||||
ch := c.forwards.add(&net.UnixAddr{Name: socketPath, Net: "unix"})
|
||||
|
||||
return &unixListener{socketPath, c, ch}, nil
|
||||
}
|
||||
|
||||
func (c *Client) dialStreamLocal(socketPath string) (Channel, error) {
|
||||
msg := streamLocalChannelOpenDirectMsg{
|
||||
socketPath: socketPath,
|
||||
}
|
||||
ch, in, err := c.OpenChannel("direct-streamlocal@openssh.com", Marshal(&msg))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
go DiscardRequests(in)
|
||||
return ch, err
|
||||
}
|
||||
|
||||
type unixListener struct {
|
||||
socketPath string
|
||||
|
||||
conn *Client
|
||||
in <-chan forward
|
||||
}
|
||||
|
||||
// Accept waits for and returns the next connection to the listener.
|
||||
func (l *unixListener) Accept() (net.Conn, error) {
|
||||
s, ok := <-l.in
|
||||
if !ok {
|
||||
return nil, io.EOF
|
||||
}
|
||||
ch, incoming, err := s.newCh.Accept()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
go DiscardRequests(incoming)
|
||||
|
||||
return &chanConn{
|
||||
Channel: ch,
|
||||
laddr: &net.UnixAddr{
|
||||
Name: l.socketPath,
|
||||
Net: "unix",
|
||||
},
|
||||
raddr: &net.UnixAddr{
|
||||
Name: "@",
|
||||
Net: "unix",
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Close closes the listener.
|
||||
func (l *unixListener) Close() error {
|
||||
// this also closes the listener.
|
||||
l.conn.forwards.remove(&net.UnixAddr{Name: l.socketPath, Net: "unix"})
|
||||
m := streamLocalChannelForwardMsg{
|
||||
l.socketPath,
|
||||
}
|
||||
ok, _, err := l.conn.SendRequest("cancel-streamlocal-forward@openssh.com", true, Marshal(&m))
|
||||
if err == nil && !ok {
|
||||
err = errors.New("ssh: cancel-streamlocal-forward@openssh.com failed")
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
// Addr returns the listener's network address.
|
||||
func (l *unixListener) Addr() net.Addr {
|
||||
return &net.UnixAddr{
|
||||
Name: l.socketPath,
|
||||
Net: "unix",
|
||||
}
|
||||
}
|
196
vendor/src/golang.org/x/crypto/ssh/tcpip.go
vendored
196
vendor/src/golang.org/x/crypto/ssh/tcpip.go
vendored
|
@ -20,12 +20,20 @@ import (
|
|||
// addr. Incoming connections will be available by calling Accept on
|
||||
// the returned net.Listener. The listener must be serviced, or the
|
||||
// SSH connection may hang.
|
||||
// N must be "tcp", "tcp4", "tcp6", or "unix".
|
||||
func (c *Client) Listen(n, addr string) (net.Listener, error) {
|
||||
laddr, err := net.ResolveTCPAddr(n, addr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
switch n {
|
||||
case "tcp", "tcp4", "tcp6":
|
||||
laddr, err := net.ResolveTCPAddr(n, addr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return c.ListenTCP(laddr)
|
||||
case "unix":
|
||||
return c.ListenUnix(addr)
|
||||
default:
|
||||
return nil, fmt.Errorf("ssh: unsupported protocol: %s", n)
|
||||
}
|
||||
return c.ListenTCP(laddr)
|
||||
}
|
||||
|
||||
// Automatic port allocation is broken with OpenSSH before 6.0. See
|
||||
|
@ -116,7 +124,7 @@ func (c *Client) ListenTCP(laddr *net.TCPAddr) (net.Listener, error) {
|
|||
}
|
||||
|
||||
// Register this forward, using the port number we obtained.
|
||||
ch := c.forwards.add(*laddr)
|
||||
ch := c.forwards.add(laddr)
|
||||
|
||||
return &tcpListener{laddr, c, ch}, nil
|
||||
}
|
||||
|
@ -131,7 +139,7 @@ type forwardList struct {
|
|||
// forwardEntry represents an established mapping of a laddr on a
|
||||
// remote ssh server to a channel connected to a tcpListener.
|
||||
type forwardEntry struct {
|
||||
laddr net.TCPAddr
|
||||
laddr net.Addr
|
||||
c chan forward
|
||||
}
|
||||
|
||||
|
@ -139,16 +147,16 @@ type forwardEntry struct {
|
|||
// arguments to add/remove/lookup should be address as specified in
|
||||
// the original forward-request.
|
||||
type forward struct {
|
||||
newCh NewChannel // the ssh client channel underlying this forward
|
||||
raddr *net.TCPAddr // the raddr of the incoming connection
|
||||
newCh NewChannel // the ssh client channel underlying this forward
|
||||
raddr net.Addr // the raddr of the incoming connection
|
||||
}
|
||||
|
||||
func (l *forwardList) add(addr net.TCPAddr) chan forward {
|
||||
func (l *forwardList) add(addr net.Addr) chan forward {
|
||||
l.Lock()
|
||||
defer l.Unlock()
|
||||
f := forwardEntry{
|
||||
addr,
|
||||
make(chan forward, 1),
|
||||
laddr: addr,
|
||||
c: make(chan forward, 1),
|
||||
}
|
||||
l.entries = append(l.entries, f)
|
||||
return f.c
|
||||
|
@ -176,44 +184,69 @@ func parseTCPAddr(addr string, port uint32) (*net.TCPAddr, error) {
|
|||
|
||||
func (l *forwardList) handleChannels(in <-chan NewChannel) {
|
||||
for ch := range in {
|
||||
var payload forwardedTCPPayload
|
||||
if err := Unmarshal(ch.ExtraData(), &payload); err != nil {
|
||||
ch.Reject(ConnectionFailed, "could not parse forwarded-tcpip payload: "+err.Error())
|
||||
continue
|
||||
}
|
||||
var (
|
||||
laddr net.Addr
|
||||
raddr net.Addr
|
||||
err error
|
||||
)
|
||||
switch channelType := ch.ChannelType(); channelType {
|
||||
case "forwarded-tcpip":
|
||||
var payload forwardedTCPPayload
|
||||
if err = Unmarshal(ch.ExtraData(), &payload); err != nil {
|
||||
ch.Reject(ConnectionFailed, "could not parse forwarded-tcpip payload: "+err.Error())
|
||||
continue
|
||||
}
|
||||
|
||||
// RFC 4254 section 7.2 specifies that incoming
|
||||
// addresses should list the address, in string
|
||||
// format. It is implied that this should be an IP
|
||||
// address, as it would be impossible to connect to it
|
||||
// otherwise.
|
||||
laddr, err := parseTCPAddr(payload.Addr, payload.Port)
|
||||
if err != nil {
|
||||
ch.Reject(ConnectionFailed, err.Error())
|
||||
continue
|
||||
}
|
||||
raddr, err := parseTCPAddr(payload.OriginAddr, payload.OriginPort)
|
||||
if err != nil {
|
||||
ch.Reject(ConnectionFailed, err.Error())
|
||||
continue
|
||||
}
|
||||
// RFC 4254 section 7.2 specifies that incoming
|
||||
// addresses should list the address, in string
|
||||
// format. It is implied that this should be an IP
|
||||
// address, as it would be impossible to connect to it
|
||||
// otherwise.
|
||||
laddr, err = parseTCPAddr(payload.Addr, payload.Port)
|
||||
if err != nil {
|
||||
ch.Reject(ConnectionFailed, err.Error())
|
||||
continue
|
||||
}
|
||||
raddr, err = parseTCPAddr(payload.OriginAddr, payload.OriginPort)
|
||||
if err != nil {
|
||||
ch.Reject(ConnectionFailed, err.Error())
|
||||
continue
|
||||
}
|
||||
|
||||
if ok := l.forward(*laddr, *raddr, ch); !ok {
|
||||
case "forwarded-streamlocal@openssh.com":
|
||||
var payload forwardedStreamLocalPayload
|
||||
if err = Unmarshal(ch.ExtraData(), &payload); err != nil {
|
||||
ch.Reject(ConnectionFailed, "could not parse forwarded-streamlocal@openssh.com payload: "+err.Error())
|
||||
continue
|
||||
}
|
||||
laddr = &net.UnixAddr{
|
||||
Name: payload.SocketPath,
|
||||
Net: "unix",
|
||||
}
|
||||
raddr = &net.UnixAddr{
|
||||
Name: "@",
|
||||
Net: "unix",
|
||||
}
|
||||
default:
|
||||
panic(fmt.Errorf("ssh: unknown channel type %s", channelType))
|
||||
}
|
||||
if ok := l.forward(laddr, raddr, ch); !ok {
|
||||
// Section 7.2, implementations MUST reject spurious incoming
|
||||
// connections.
|
||||
ch.Reject(Prohibited, "no forward for address")
|
||||
continue
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// remove removes the forward entry, and the channel feeding its
|
||||
// listener.
|
||||
func (l *forwardList) remove(addr net.TCPAddr) {
|
||||
func (l *forwardList) remove(addr net.Addr) {
|
||||
l.Lock()
|
||||
defer l.Unlock()
|
||||
for i, f := range l.entries {
|
||||
if addr.IP.Equal(f.laddr.IP) && addr.Port == f.laddr.Port {
|
||||
if addr.Network() == f.laddr.Network() && addr.String() == f.laddr.String() {
|
||||
l.entries = append(l.entries[:i], l.entries[i+1:]...)
|
||||
close(f.c)
|
||||
return
|
||||
|
@ -231,12 +264,12 @@ func (l *forwardList) closeAll() {
|
|||
l.entries = nil
|
||||
}
|
||||
|
||||
func (l *forwardList) forward(laddr, raddr net.TCPAddr, ch NewChannel) bool {
|
||||
func (l *forwardList) forward(laddr, raddr net.Addr, ch NewChannel) bool {
|
||||
l.Lock()
|
||||
defer l.Unlock()
|
||||
for _, f := range l.entries {
|
||||
if laddr.IP.Equal(f.laddr.IP) && laddr.Port == f.laddr.Port {
|
||||
f.c <- forward{ch, &raddr}
|
||||
if laddr.Network() == f.laddr.Network() && laddr.String() == f.laddr.String() {
|
||||
f.c <- forward{newCh: ch, raddr: raddr}
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
@ -262,7 +295,7 @@ func (l *tcpListener) Accept() (net.Conn, error) {
|
|||
}
|
||||
go DiscardRequests(incoming)
|
||||
|
||||
return &tcpChanConn{
|
||||
return &chanConn{
|
||||
Channel: ch,
|
||||
laddr: l.laddr,
|
||||
raddr: s.raddr,
|
||||
|
@ -277,7 +310,7 @@ func (l *tcpListener) Close() error {
|
|||
}
|
||||
|
||||
// this also closes the listener.
|
||||
l.conn.forwards.remove(*l.laddr)
|
||||
l.conn.forwards.remove(l.laddr)
|
||||
ok, _, err := l.conn.SendRequest("cancel-tcpip-forward", true, Marshal(&m))
|
||||
if err == nil && !ok {
|
||||
err = errors.New("ssh: cancel-tcpip-forward failed")
|
||||
|
@ -293,29 +326,52 @@ func (l *tcpListener) Addr() net.Addr {
|
|||
// Dial initiates a connection to the addr from the remote host.
|
||||
// The resulting connection has a zero LocalAddr() and RemoteAddr().
|
||||
func (c *Client) Dial(n, addr string) (net.Conn, error) {
|
||||
// Parse the address into host and numeric port.
|
||||
host, portString, err := net.SplitHostPort(addr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
var ch Channel
|
||||
switch n {
|
||||
case "tcp", "tcp4", "tcp6":
|
||||
// Parse the address into host and numeric port.
|
||||
host, portString, err := net.SplitHostPort(addr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
port, err := strconv.ParseUint(portString, 10, 16)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ch, err = c.dial(net.IPv4zero.String(), 0, host, int(port))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// Use a zero address for local and remote address.
|
||||
zeroAddr := &net.TCPAddr{
|
||||
IP: net.IPv4zero,
|
||||
Port: 0,
|
||||
}
|
||||
return &chanConn{
|
||||
Channel: ch,
|
||||
laddr: zeroAddr,
|
||||
raddr: zeroAddr,
|
||||
}, nil
|
||||
case "unix":
|
||||
var err error
|
||||
ch, err = c.dialStreamLocal(addr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &chanConn{
|
||||
Channel: ch,
|
||||
laddr: &net.UnixAddr{
|
||||
Name: "@",
|
||||
Net: "unix",
|
||||
},
|
||||
raddr: &net.UnixAddr{
|
||||
Name: addr,
|
||||
Net: "unix",
|
||||
},
|
||||
}, nil
|
||||
default:
|
||||
return nil, fmt.Errorf("ssh: unsupported protocol: %s", n)
|
||||
}
|
||||
port, err := strconv.ParseUint(portString, 10, 16)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// Use a zero address for local and remote address.
|
||||
zeroAddr := &net.TCPAddr{
|
||||
IP: net.IPv4zero,
|
||||
Port: 0,
|
||||
}
|
||||
ch, err := c.dial(net.IPv4zero.String(), 0, host, int(port))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &tcpChanConn{
|
||||
Channel: ch,
|
||||
laddr: zeroAddr,
|
||||
raddr: zeroAddr,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// DialTCP connects to the remote address raddr on the network net,
|
||||
|
@ -332,7 +388,7 @@ func (c *Client) DialTCP(n string, laddr, raddr *net.TCPAddr) (net.Conn, error)
|
|||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &tcpChanConn{
|
||||
return &chanConn{
|
||||
Channel: ch,
|
||||
laddr: laddr,
|
||||
raddr: raddr,
|
||||
|
@ -366,26 +422,26 @@ type tcpChan struct {
|
|||
Channel // the backing channel
|
||||
}
|
||||
|
||||
// tcpChanConn fulfills the net.Conn interface without
|
||||
// chanConn fulfills the net.Conn interface without
|
||||
// the tcpChan having to hold laddr or raddr directly.
|
||||
type tcpChanConn struct {
|
||||
type chanConn struct {
|
||||
Channel
|
||||
laddr, raddr net.Addr
|
||||
}
|
||||
|
||||
// LocalAddr returns the local network address.
|
||||
func (t *tcpChanConn) LocalAddr() net.Addr {
|
||||
func (t *chanConn) LocalAddr() net.Addr {
|
||||
return t.laddr
|
||||
}
|
||||
|
||||
// RemoteAddr returns the remote network address.
|
||||
func (t *tcpChanConn) RemoteAddr() net.Addr {
|
||||
func (t *chanConn) RemoteAddr() net.Addr {
|
||||
return t.raddr
|
||||
}
|
||||
|
||||
// SetDeadline sets the read and write deadlines associated
|
||||
// with the connection.
|
||||
func (t *tcpChanConn) SetDeadline(deadline time.Time) error {
|
||||
func (t *chanConn) SetDeadline(deadline time.Time) error {
|
||||
if err := t.SetReadDeadline(deadline); err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -396,12 +452,14 @@ func (t *tcpChanConn) SetDeadline(deadline time.Time) error {
|
|||
// A zero value for t means Read will not time out.
|
||||
// After the deadline, the error from Read will implement net.Error
|
||||
// with Timeout() == true.
|
||||
func (t *tcpChanConn) SetReadDeadline(deadline time.Time) error {
|
||||
func (t *chanConn) SetReadDeadline(deadline time.Time) error {
|
||||
// for compatibility with previous version,
|
||||
// the error message contains "tcpChan"
|
||||
return errors.New("ssh: tcpChan: deadline not supported")
|
||||
}
|
||||
|
||||
// SetWriteDeadline exists to satisfy the net.Conn interface
|
||||
// but is not implemented by this type. It always returns an error.
|
||||
func (t *tcpChanConn) SetWriteDeadline(deadline time.Time) error {
|
||||
func (t *chanConn) SetWriteDeadline(deadline time.Time) error {
|
||||
return errors.New("ssh: tcpChan: deadline not supported")
|
||||
}
|
||||
|
|
|
@ -132,8 +132,11 @@ const (
|
|||
keyPasteEnd
|
||||
)
|
||||
|
||||
var pasteStart = []byte{keyEscape, '[', '2', '0', '0', '~'}
|
||||
var pasteEnd = []byte{keyEscape, '[', '2', '0', '1', '~'}
|
||||
var (
|
||||
crlf = []byte{'\r', '\n'}
|
||||
pasteStart = []byte{keyEscape, '[', '2', '0', '0', '~'}
|
||||
pasteEnd = []byte{keyEscape, '[', '2', '0', '1', '~'}
|
||||
)
|
||||
|
||||
// bytesToKey tries to parse a key sequence from b. If successful, it returns
|
||||
// the key and the remainder of the input. Otherwise it returns utf8.RuneError.
|
||||
|
@ -333,7 +336,7 @@ func (t *Terminal) advanceCursor(places int) {
|
|||
// So, if we are stopping at the end of a line, we
|
||||
// need to write a newline so that our cursor can be
|
||||
// advanced to the next line.
|
||||
t.outBuf = append(t.outBuf, '\n')
|
||||
t.outBuf = append(t.outBuf, '\r', '\n')
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -593,6 +596,35 @@ func (t *Terminal) writeLine(line []rune) {
|
|||
}
|
||||
}
|
||||
|
||||
// writeWithCRLF writes buf to w but replaces all occurrences of \n with \r\n.
|
||||
func writeWithCRLF(w io.Writer, buf []byte) (n int, err error) {
|
||||
for len(buf) > 0 {
|
||||
i := bytes.IndexByte(buf, '\n')
|
||||
todo := len(buf)
|
||||
if i >= 0 {
|
||||
todo = i
|
||||
}
|
||||
|
||||
var nn int
|
||||
nn, err = w.Write(buf[:todo])
|
||||
n += nn
|
||||
if err != nil {
|
||||
return n, err
|
||||
}
|
||||
buf = buf[todo:]
|
||||
|
||||
if i >= 0 {
|
||||
if _, err = w.Write(crlf); err != nil {
|
||||
return n, err
|
||||
}
|
||||
n += 1
|
||||
buf = buf[1:]
|
||||
}
|
||||
}
|
||||
|
||||
return n, nil
|
||||
}
|
||||
|
||||
func (t *Terminal) Write(buf []byte) (n int, err error) {
|
||||
t.lock.Lock()
|
||||
defer t.lock.Unlock()
|
||||
|
@ -600,7 +632,7 @@ func (t *Terminal) Write(buf []byte) (n int, err error) {
|
|||
if t.cursorX == 0 && t.cursorY == 0 {
|
||||
// This is the easy case: there's nothing on the screen that we
|
||||
// have to move out of the way.
|
||||
return t.c.Write(buf)
|
||||
return writeWithCRLF(t.c, buf)
|
||||
}
|
||||
|
||||
// We have a prompt and possibly user input on the screen. We
|
||||
|
@ -620,7 +652,7 @@ func (t *Terminal) Write(buf []byte) (n int, err error) {
|
|||
}
|
||||
t.outBuf = t.outBuf[:0]
|
||||
|
||||
if n, err = t.c.Write(buf); err != nil {
|
||||
if n, err = writeWithCRLF(t.c, buf); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -740,8 +772,6 @@ func (t *Terminal) readLine() (line string, err error) {
|
|||
|
||||
t.remainder = t.inBuf[:n+len(t.remainder)]
|
||||
}
|
||||
|
||||
panic("unreachable") // for Go 1.0.
|
||||
}
|
||||
|
||||
// SetPrompt sets the prompt to be used when reading subsequent lines.
|
||||
|
@ -890,3 +920,32 @@ func (s *stRingBuffer) NthPreviousEntry(n int) (value string, ok bool) {
|
|||
}
|
||||
return s.entries[index], true
|
||||
}
|
||||
|
||||
// readPasswordLine reads from reader until it finds \n or io.EOF.
|
||||
// The slice returned does not include the \n.
|
||||
// readPasswordLine also ignores any \r it finds.
|
||||
func readPasswordLine(reader io.Reader) ([]byte, error) {
|
||||
var buf [1]byte
|
||||
var ret []byte
|
||||
|
||||
for {
|
||||
n, err := reader.Read(buf[:])
|
||||
if n > 0 {
|
||||
switch buf[0] {
|
||||
case '\n':
|
||||
return ret, nil
|
||||
case '\r':
|
||||
// remove \r from passwords on Windows
|
||||
default:
|
||||
ret = append(ret, buf[0])
|
||||
}
|
||||
continue
|
||||
}
|
||||
if err != nil {
|
||||
if err == io.EOF && len(ret) > 0 {
|
||||
return ret, nil
|
||||
}
|
||||
return ret, err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
package terminal
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"io"
|
||||
"os"
|
||||
"testing"
|
||||
|
@ -269,6 +270,50 @@ func TestTerminalSetSize(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestReadPasswordLineEnd(t *testing.T) {
|
||||
var tests = []struct {
|
||||
input string
|
||||
want string
|
||||
}{
|
||||
{"\n", ""},
|
||||
{"\r\n", ""},
|
||||
{"test\r\n", "test"},
|
||||
{"testtesttesttes\n", "testtesttesttes"},
|
||||
{"testtesttesttes\r\n", "testtesttesttes"},
|
||||
{"testtesttesttesttest\n", "testtesttesttesttest"},
|
||||
{"testtesttesttesttest\r\n", "testtesttesttesttest"},
|
||||
}
|
||||
for _, test := range tests {
|
||||
buf := new(bytes.Buffer)
|
||||
if _, err := buf.WriteString(test.input); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
have, err := readPasswordLine(buf)
|
||||
if err != nil {
|
||||
t.Errorf("readPasswordLine(%q) failed: %v", test.input, err)
|
||||
continue
|
||||
}
|
||||
if string(have) != test.want {
|
||||
t.Errorf("readPasswordLine(%q) returns %q, but %q is expected", test.input, string(have), test.want)
|
||||
continue
|
||||
}
|
||||
|
||||
if _, err = buf.WriteString(test.input); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
have, err = readPasswordLine(buf)
|
||||
if err != nil {
|
||||
t.Errorf("readPasswordLine(%q) failed: %v", test.input, err)
|
||||
continue
|
||||
}
|
||||
if string(have) != test.want {
|
||||
t.Errorf("readPasswordLine(%q) returns %q, but %q is expected", test.input, string(have), test.want)
|
||||
continue
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestMakeRawState(t *testing.T) {
|
||||
fd := int(os.Stdout.Fd())
|
||||
if !IsTerminal(fd) {
|
||||
|
@ -289,3 +334,17 @@ func TestMakeRawState(t *testing.T) {
|
|||
t.Errorf("states do not match; was %v, expected %v", raw, st)
|
||||
}
|
||||
}
|
||||
|
||||
func TestOutputNewlines(t *testing.T) {
|
||||
// \n should be changed to \r\n in terminal output.
|
||||
buf := new(bytes.Buffer)
|
||||
term := NewTerminal(buf, ">")
|
||||
|
||||
term.Write([]byte("1\n2\n"))
|
||||
output := string(buf.Bytes())
|
||||
const expected = "1\r\n2\r\n"
|
||||
|
||||
if output != expected {
|
||||
t.Errorf("incorrect output: was %q, expected %q", output, expected)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,7 +17,6 @@
|
|||
package terminal // import "golang.org/x/crypto/ssh/terminal"
|
||||
|
||||
import (
|
||||
"io"
|
||||
"syscall"
|
||||
"unsafe"
|
||||
)
|
||||
|
@ -72,8 +71,10 @@ func GetState(fd int) (*State, error) {
|
|||
// Restore restores the terminal connected to the given file descriptor to a
|
||||
// previous state.
|
||||
func Restore(fd int, state *State) error {
|
||||
_, _, err := syscall.Syscall6(syscall.SYS_IOCTL, uintptr(fd), ioctlWriteTermios, uintptr(unsafe.Pointer(&state.termios)), 0, 0, 0)
|
||||
return err
|
||||
if _, _, err := syscall.Syscall6(syscall.SYS_IOCTL, uintptr(fd), ioctlWriteTermios, uintptr(unsafe.Pointer(&state.termios)), 0, 0, 0); err != 0 {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetSize returns the dimensions of the given terminal.
|
||||
|
@ -86,6 +87,13 @@ func GetSize(fd int) (width, height int, err error) {
|
|||
return int(dimensions[1]), int(dimensions[0]), nil
|
||||
}
|
||||
|
||||
// passwordReader is an io.Reader that reads from a specific file descriptor.
|
||||
type passwordReader int
|
||||
|
||||
func (r passwordReader) Read(buf []byte) (int, error) {
|
||||
return syscall.Read(int(r), buf)
|
||||
}
|
||||
|
||||
// ReadPassword reads a line of input from a terminal without local echo. This
|
||||
// is commonly used for inputting passwords and other sensitive data. The slice
|
||||
// returned does not include the \n.
|
||||
|
@ -107,27 +115,5 @@ func ReadPassword(fd int) ([]byte, error) {
|
|||
syscall.Syscall6(syscall.SYS_IOCTL, uintptr(fd), ioctlWriteTermios, uintptr(unsafe.Pointer(&oldState)), 0, 0, 0)
|
||||
}()
|
||||
|
||||
var buf [16]byte
|
||||
var ret []byte
|
||||
for {
|
||||
n, err := syscall.Read(fd, buf[:])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if n == 0 {
|
||||
if len(ret) == 0 {
|
||||
return nil, io.EOF
|
||||
}
|
||||
break
|
||||
}
|
||||
if buf[n-1] == '\n' {
|
||||
n--
|
||||
}
|
||||
ret = append(ret, buf[:n]...)
|
||||
if n < len(buf) {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
return ret, nil
|
||||
return readPasswordLine(passwordReader(fd))
|
||||
}
|
||||
|
|
73
vendor/src/golang.org/x/crypto/ssh/terminal/util_solaris.go
vendored
Normal file
73
vendor/src/golang.org/x/crypto/ssh/terminal/util_solaris.go
vendored
Normal file
|
@ -0,0 +1,73 @@
|
|||
// Copyright 2015 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.
|
||||
|
||||
// +build solaris
|
||||
|
||||
package terminal // import "golang.org/x/crypto/ssh/terminal"
|
||||
|
||||
import (
|
||||
"golang.org/x/sys/unix"
|
||||
"io"
|
||||
"syscall"
|
||||
)
|
||||
|
||||
// State contains the state of a terminal.
|
||||
type State struct {
|
||||
termios syscall.Termios
|
||||
}
|
||||
|
||||
// IsTerminal returns true if the given file descriptor is a terminal.
|
||||
func IsTerminal(fd int) bool {
|
||||
// see: http://src.illumos.org/source/xref/illumos-gate/usr/src/lib/libbc/libc/gen/common/isatty.c
|
||||
var termio unix.Termio
|
||||
err := unix.IoctlSetTermio(fd, unix.TCGETA, &termio)
|
||||
return err == nil
|
||||
}
|
||||
|
||||
// ReadPassword reads a line of input from a terminal without local echo. This
|
||||
// is commonly used for inputting passwords and other sensitive data. The slice
|
||||
// returned does not include the \n.
|
||||
func ReadPassword(fd int) ([]byte, error) {
|
||||
// see also: http://src.illumos.org/source/xref/illumos-gate/usr/src/lib/libast/common/uwin/getpass.c
|
||||
val, err := unix.IoctlGetTermios(fd, unix.TCGETS)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
oldState := *val
|
||||
|
||||
newState := oldState
|
||||
newState.Lflag &^= syscall.ECHO
|
||||
newState.Lflag |= syscall.ICANON | syscall.ISIG
|
||||
newState.Iflag |= syscall.ICRNL
|
||||
err = unix.IoctlSetTermios(fd, unix.TCSETS, &newState)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
defer unix.IoctlSetTermios(fd, unix.TCSETS, &oldState)
|
||||
|
||||
var buf [16]byte
|
||||
var ret []byte
|
||||
for {
|
||||
n, err := syscall.Read(fd, buf[:])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if n == 0 {
|
||||
if len(ret) == 0 {
|
||||
return nil, io.EOF
|
||||
}
|
||||
break
|
||||
}
|
||||
if buf[n-1] == '\n' {
|
||||
n--
|
||||
}
|
||||
ret = append(ret, buf[:n]...)
|
||||
if n < len(buf) {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
return ret, nil
|
||||
}
|
|
@ -17,7 +17,6 @@
|
|||
package terminal
|
||||
|
||||
import (
|
||||
"io"
|
||||
"syscall"
|
||||
"unsafe"
|
||||
)
|
||||
|
@ -123,6 +122,13 @@ func GetSize(fd int) (width, height int, err error) {
|
|||
return int(info.size.x), int(info.size.y), nil
|
||||
}
|
||||
|
||||
// passwordReader is an io.Reader that reads from a specific Windows HANDLE.
|
||||
type passwordReader int
|
||||
|
||||
func (r passwordReader) Read(buf []byte) (int, error) {
|
||||
return syscall.Read(syscall.Handle(r), buf)
|
||||
}
|
||||
|
||||
// ReadPassword reads a line of input from a terminal without local echo. This
|
||||
// is commonly used for inputting passwords and other sensitive data. The slice
|
||||
// returned does not include the \n.
|
||||
|
@ -145,30 +151,5 @@ func ReadPassword(fd int) ([]byte, error) {
|
|||
syscall.Syscall(procSetConsoleMode.Addr(), 2, uintptr(fd), uintptr(old), 0)
|
||||
}()
|
||||
|
||||
var buf [16]byte
|
||||
var ret []byte
|
||||
for {
|
||||
n, err := syscall.Read(syscall.Handle(fd), buf[:])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if n == 0 {
|
||||
if len(ret) == 0 {
|
||||
return nil, io.EOF
|
||||
}
|
||||
break
|
||||
}
|
||||
if buf[n-1] == '\n' {
|
||||
n--
|
||||
}
|
||||
if n > 0 && buf[n-1] == '\r' {
|
||||
n--
|
||||
}
|
||||
ret = append(ret, buf[:n]...)
|
||||
if n < len(buf) {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
return ret, nil
|
||||
return readPasswordLine(passwordReader(fd))
|
||||
}
|
||||
|
|
|
@ -36,7 +36,8 @@ func TestCertLogin(t *testing.T) {
|
|||
}
|
||||
|
||||
conf := &ssh.ClientConfig{
|
||||
User: username(),
|
||||
User: username(),
|
||||
HostKeyCallback: ssh.InsecureIgnoreHostKey(),
|
||||
}
|
||||
conf.Auth = append(conf.Auth, ssh.PublicKeys(certSigner))
|
||||
client, err := s.TryDial(conf)
|
||||
|
|
128
vendor/src/golang.org/x/crypto/ssh/test/dial_unix_test.go
vendored
Normal file
128
vendor/src/golang.org/x/crypto/ssh/test/dial_unix_test.go
vendored
Normal file
|
@ -0,0 +1,128 @@
|
|||
// 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.
|
||||
|
||||
// +build !windows
|
||||
|
||||
package test
|
||||
|
||||
// direct-tcpip and direct-streamlocal functional tests
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
type dialTester interface {
|
||||
TestServerConn(t *testing.T, c net.Conn)
|
||||
TestClientConn(t *testing.T, c net.Conn)
|
||||
}
|
||||
|
||||
func testDial(t *testing.T, n, listenAddr string, x dialTester) {
|
||||
server := newServer(t)
|
||||
defer server.Shutdown()
|
||||
sshConn := server.Dial(clientConfig())
|
||||
defer sshConn.Close()
|
||||
|
||||
l, err := net.Listen(n, listenAddr)
|
||||
if err != nil {
|
||||
t.Fatalf("Listen: %v", err)
|
||||
}
|
||||
defer l.Close()
|
||||
|
||||
testData := fmt.Sprintf("hello from %s, %s", n, listenAddr)
|
||||
go func() {
|
||||
for {
|
||||
c, err := l.Accept()
|
||||
if err != nil {
|
||||
break
|
||||
}
|
||||
x.TestServerConn(t, c)
|
||||
|
||||
io.WriteString(c, testData)
|
||||
c.Close()
|
||||
}
|
||||
}()
|
||||
|
||||
conn, err := sshConn.Dial(n, l.Addr().String())
|
||||
if err != nil {
|
||||
t.Fatalf("Dial: %v", err)
|
||||
}
|
||||
x.TestClientConn(t, conn)
|
||||
defer conn.Close()
|
||||
b, err := ioutil.ReadAll(conn)
|
||||
if err != nil {
|
||||
t.Fatalf("ReadAll: %v", err)
|
||||
}
|
||||
t.Logf("got %q", string(b))
|
||||
if string(b) != testData {
|
||||
t.Fatalf("expected %q, got %q", testData, string(b))
|
||||
}
|
||||
}
|
||||
|
||||
type tcpDialTester struct {
|
||||
listenAddr string
|
||||
}
|
||||
|
||||
func (x *tcpDialTester) TestServerConn(t *testing.T, c net.Conn) {
|
||||
host := strings.Split(x.listenAddr, ":")[0]
|
||||
prefix := host + ":"
|
||||
if !strings.HasPrefix(c.LocalAddr().String(), prefix) {
|
||||
t.Fatalf("expected to start with %q, got %q", prefix, c.LocalAddr().String())
|
||||
}
|
||||
if !strings.HasPrefix(c.RemoteAddr().String(), prefix) {
|
||||
t.Fatalf("expected to start with %q, got %q", prefix, c.RemoteAddr().String())
|
||||
}
|
||||
}
|
||||
|
||||
func (x *tcpDialTester) TestClientConn(t *testing.T, c net.Conn) {
|
||||
// we use zero addresses. see *Client.Dial.
|
||||
if c.LocalAddr().String() != "0.0.0.0:0" {
|
||||
t.Fatalf("expected \"0.0.0.0:0\", got %q", c.LocalAddr().String())
|
||||
}
|
||||
if c.RemoteAddr().String() != "0.0.0.0:0" {
|
||||
t.Fatalf("expected \"0.0.0.0:0\", got %q", c.RemoteAddr().String())
|
||||
}
|
||||
}
|
||||
|
||||
func TestDialTCP(t *testing.T) {
|
||||
x := &tcpDialTester{
|
||||
listenAddr: "127.0.0.1:0",
|
||||
}
|
||||
testDial(t, "tcp", x.listenAddr, x)
|
||||
}
|
||||
|
||||
type unixDialTester struct {
|
||||
listenAddr string
|
||||
}
|
||||
|
||||
func (x *unixDialTester) TestServerConn(t *testing.T, c net.Conn) {
|
||||
if c.LocalAddr().String() != x.listenAddr {
|
||||
t.Fatalf("expected %q, got %q", x.listenAddr, c.LocalAddr().String())
|
||||
}
|
||||
if c.RemoteAddr().String() != "@" {
|
||||
t.Fatalf("expected \"@\", got %q", c.RemoteAddr().String())
|
||||
}
|
||||
}
|
||||
|
||||
func (x *unixDialTester) TestClientConn(t *testing.T, c net.Conn) {
|
||||
if c.RemoteAddr().String() != x.listenAddr {
|
||||
t.Fatalf("expected %q, got %q", x.listenAddr, c.RemoteAddr().String())
|
||||
}
|
||||
if c.LocalAddr().String() != "@" {
|
||||
t.Fatalf("expected \"@\", got %q", c.LocalAddr().String())
|
||||
}
|
||||
}
|
||||
|
||||
func TestDialUnix(t *testing.T) {
|
||||
addr, cleanup := newTempSocket(t)
|
||||
defer cleanup()
|
||||
x := &unixDialTester{
|
||||
listenAddr: addr,
|
||||
}
|
||||
testDial(t, "unix", x.listenAddr, x)
|
||||
}
|
|
@ -16,13 +16,17 @@ import (
|
|||
"time"
|
||||
)
|
||||
|
||||
func TestPortForward(t *testing.T) {
|
||||
type closeWriter interface {
|
||||
CloseWrite() error
|
||||
}
|
||||
|
||||
func testPortForward(t *testing.T, n, listenAddr string) {
|
||||
server := newServer(t)
|
||||
defer server.Shutdown()
|
||||
conn := server.Dial(clientConfig())
|
||||
defer conn.Close()
|
||||
|
||||
sshListener, err := conn.Listen("tcp", "localhost:0")
|
||||
sshListener, err := conn.Listen(n, listenAddr)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
@ -41,14 +45,14 @@ func TestPortForward(t *testing.T) {
|
|||
}()
|
||||
|
||||
forwardedAddr := sshListener.Addr().String()
|
||||
tcpConn, err := net.Dial("tcp", forwardedAddr)
|
||||
netConn, err := net.Dial(n, forwardedAddr)
|
||||
if err != nil {
|
||||
t.Fatalf("TCP dial failed: %v", err)
|
||||
t.Fatalf("net dial failed: %v", err)
|
||||
}
|
||||
|
||||
readChan := make(chan []byte)
|
||||
go func() {
|
||||
data, _ := ioutil.ReadAll(tcpConn)
|
||||
data, _ := ioutil.ReadAll(netConn)
|
||||
readChan <- data
|
||||
}()
|
||||
|
||||
|
@ -62,14 +66,14 @@ func TestPortForward(t *testing.T) {
|
|||
for len(sent) < 1000*1000 {
|
||||
// Send random sized chunks
|
||||
m := rand.Intn(len(data))
|
||||
n, err := tcpConn.Write(data[:m])
|
||||
n, err := netConn.Write(data[:m])
|
||||
if err != nil {
|
||||
break
|
||||
}
|
||||
sent = append(sent, data[:n]...)
|
||||
}
|
||||
if err := tcpConn.(*net.TCPConn).CloseWrite(); err != nil {
|
||||
t.Errorf("tcpConn.CloseWrite: %v", err)
|
||||
if err := netConn.(closeWriter).CloseWrite(); err != nil {
|
||||
t.Errorf("netConn.CloseWrite: %v", err)
|
||||
}
|
||||
|
||||
read := <-readChan
|
||||
|
@ -86,19 +90,29 @@ func TestPortForward(t *testing.T) {
|
|||
}
|
||||
|
||||
// Check that the forward disappeared.
|
||||
tcpConn, err = net.Dial("tcp", forwardedAddr)
|
||||
netConn, err = net.Dial(n, forwardedAddr)
|
||||
if err == nil {
|
||||
tcpConn.Close()
|
||||
netConn.Close()
|
||||
t.Errorf("still listening to %s after closing", forwardedAddr)
|
||||
}
|
||||
}
|
||||
|
||||
func TestAcceptClose(t *testing.T) {
|
||||
func TestPortForwardTCP(t *testing.T) {
|
||||
testPortForward(t, "tcp", "localhost:0")
|
||||
}
|
||||
|
||||
func TestPortForwardUnix(t *testing.T) {
|
||||
addr, cleanup := newTempSocket(t)
|
||||
defer cleanup()
|
||||
testPortForward(t, "unix", addr)
|
||||
}
|
||||
|
||||
func testAcceptClose(t *testing.T, n, listenAddr string) {
|
||||
server := newServer(t)
|
||||
defer server.Shutdown()
|
||||
conn := server.Dial(clientConfig())
|
||||
|
||||
sshListener, err := conn.Listen("tcp", "localhost:0")
|
||||
sshListener, err := conn.Listen(n, listenAddr)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
@ -124,13 +138,23 @@ func TestAcceptClose(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestAcceptCloseTCP(t *testing.T) {
|
||||
testAcceptClose(t, "tcp", "localhost:0")
|
||||
}
|
||||
|
||||
func TestAcceptCloseUnix(t *testing.T) {
|
||||
addr, cleanup := newTempSocket(t)
|
||||
defer cleanup()
|
||||
testAcceptClose(t, "unix", addr)
|
||||
}
|
||||
|
||||
// Check that listeners exit if the underlying client transport dies.
|
||||
func TestPortForwardConnectionClose(t *testing.T) {
|
||||
func testPortForwardConnectionClose(t *testing.T, n, listenAddr string) {
|
||||
server := newServer(t)
|
||||
defer server.Shutdown()
|
||||
conn := server.Dial(clientConfig())
|
||||
|
||||
sshListener, err := conn.Listen("tcp", "localhost:0")
|
||||
sshListener, err := conn.Listen(n, listenAddr)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
@ -158,3 +182,13 @@ func TestPortForwardConnectionClose(t *testing.T) {
|
|||
t.Logf("quit as expected (error %v)", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestPortForwardConnectionCloseTCP(t *testing.T) {
|
||||
testPortForwardConnectionClose(t, "tcp", "localhost:0")
|
||||
}
|
||||
|
||||
func TestPortForwardConnectionCloseUnix(t *testing.T) {
|
||||
addr, cleanup := newTempSocket(t)
|
||||
defer cleanup()
|
||||
testPortForwardConnectionClose(t, "unix", addr)
|
||||
}
|
||||
|
|
|
@ -1,46 +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.
|
||||
|
||||
// +build !windows
|
||||
|
||||
package test
|
||||
|
||||
// direct-tcpip functional tests
|
||||
|
||||
import (
|
||||
"io"
|
||||
"net"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestDial(t *testing.T) {
|
||||
server := newServer(t)
|
||||
defer server.Shutdown()
|
||||
sshConn := server.Dial(clientConfig())
|
||||
defer sshConn.Close()
|
||||
|
||||
l, err := net.Listen("tcp", "127.0.0.1:0")
|
||||
if err != nil {
|
||||
t.Fatalf("Listen: %v", err)
|
||||
}
|
||||
defer l.Close()
|
||||
|
||||
go func() {
|
||||
for {
|
||||
c, err := l.Accept()
|
||||
if err != nil {
|
||||
break
|
||||
}
|
||||
|
||||
io.WriteString(c, c.RemoteAddr().String())
|
||||
c.Close()
|
||||
}
|
||||
}()
|
||||
|
||||
conn, err := sshConn.Dial("tcp", l.Addr().String())
|
||||
if err != nil {
|
||||
t.Fatalf("Dial: %v", err)
|
||||
}
|
||||
defer conn.Close()
|
||||
}
|
|
@ -266,3 +266,13 @@ func newServer(t *testing.T) *server {
|
|||
},
|
||||
}
|
||||
}
|
||||
|
||||
func newTempSocket(t *testing.T) (string, func()) {
|
||||
dir, err := ioutil.TempDir("", "socket")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
deferFunc := func() { os.RemoveAll(dir) }
|
||||
addr := filepath.Join(dir, "sock")
|
||||
return addr, deferFunc
|
||||
}
|
||||
|
|
|
@ -48,6 +48,22 @@ AAAEAaYmXltfW6nhRo3iWGglRB48lYq0z0Q3I3KyrdutEr6j7d/uFLuDlRbBc4ZVOsx+Gb
|
|||
HKuOrPtLHFvHsjWPwO+/AAAAE2dhcnRvbm1AZ2FydG9ubS14cHMBAg==
|
||||
-----END OPENSSH PRIVATE KEY-----
|
||||
`),
|
||||
"rsa-openssh-format": []byte(`-----BEGIN OPENSSH PRIVATE KEY-----
|
||||
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAlwAAAAdzc2gtcn
|
||||
NhAAAAAwEAAQAAAIEAwa48yfWFi3uIdqzuf9X7C2Zxfea/Iaaw0zIwHudpF8U92WVIiC5l
|
||||
oEuW1+OaVi3UWfIEjWMV1tHGysrHOwtwc34BPCJqJknUQO/KtDTBTJ4Pryhw1bWPC999Lz
|
||||
a+yrCTdNQYBzoROXKExZgPFh9pTMi5wqpHDuOQ2qZFIEI3lT0AAAIQWL0H31i9B98AAAAH
|
||||
c3NoLXJzYQAAAIEAwa48yfWFi3uIdqzuf9X7C2Zxfea/Iaaw0zIwHudpF8U92WVIiC5loE
|
||||
uW1+OaVi3UWfIEjWMV1tHGysrHOwtwc34BPCJqJknUQO/KtDTBTJ4Pryhw1bWPC999Lza+
|
||||
yrCTdNQYBzoROXKExZgPFh9pTMi5wqpHDuOQ2qZFIEI3lT0AAAADAQABAAAAgCThyTGsT4
|
||||
IARDxVMhWl6eiB2ZrgFgWSeJm/NOqtppWgOebsIqPMMg4UVuVFsl422/lE3RkPhVkjGXgE
|
||||
pWvZAdCnmLmApK8wK12vF334lZhZT7t3Z9EzJps88PWEHo7kguf285HcnUM7FlFeissJdk
|
||||
kXly34y7/3X/a6Tclm+iABAAAAQE0xR/KxZ39slwfMv64Rz7WKk1PPskaryI29aHE3mKHk
|
||||
pY2QA+P3QlrKxT/VWUMjHUbNNdYfJm48xu0SGNMRdKMAAABBAORh2NP/06JUV3J9W/2Hju
|
||||
X1ViJuqqcQnJPVzpgSL826EC2xwOECTqoY8uvFpUdD7CtpksIxNVqRIhuNOlz0lqEAAABB
|
||||
ANkaHTTaPojClO0dKJ/Zjs7pWOCGliebBYprQ/Y4r9QLBkC/XaWMS26gFIrjgC7D2Rv+rZ
|
||||
wSD0v0RcmkITP1ZR0AAAAYcHF1ZXJuYUBMdWNreUh5ZHJvLmxvY2FsAQID
|
||||
-----END OPENSSH PRIVATE KEY-----`),
|
||||
"user": []byte(`-----BEGIN EC PRIVATE KEY-----
|
||||
MHcCAQEEILYCAeq8f7V4vSSypRw7pxy8yz3V5W4qg8kSC3zJhqpQoAoGCCqGSM49
|
||||
AwEHoUQDQgAEYcO2xNKiRUYOLEHM7VYAp57HNyKbOdYtHD83Z4hzNPVC4tM5mdGD
|
||||
|
@ -55,3 +71,66 @@ PLL8IEwvYu2wq+lpXfGQnNMbzYf9gspG0w==
|
|||
-----END EC PRIVATE KEY-----
|
||||
`),
|
||||
}
|
||||
|
||||
var PEMEncryptedKeys = []struct {
|
||||
Name string
|
||||
EncryptionKey string
|
||||
PEMBytes []byte
|
||||
}{
|
||||
0: {
|
||||
Name: "rsa-encrypted",
|
||||
EncryptionKey: "r54-G0pher_t3st$",
|
||||
PEMBytes: []byte(`-----BEGIN RSA PRIVATE KEY-----
|
||||
Proc-Type: 4,ENCRYPTED
|
||||
DEK-Info: AES-128-CBC,3E1714DE130BC5E81327F36564B05462
|
||||
|
||||
MqW88sud4fnWk/Jk3fkjh7ydu51ZkHLN5qlQgA4SkAXORPPMj2XvqZOv1v2LOgUV
|
||||
dUevUn8PZK7a9zbZg4QShUSzwE5k6wdB7XKPyBgI39mJ79GBd2U4W3h6KT6jIdWA
|
||||
goQpluxkrzr2/X602IaxLEre97FT9mpKC6zxKCLvyFWVIP9n3OSFS47cTTXyFr+l
|
||||
7PdRhe60nn6jSBgUNk/Q1lAvEQ9fufdPwDYY93F1wyJ6lOr0F1+mzRrMbH67NyKs
|
||||
rG8J1Fa7cIIre7ueKIAXTIne7OAWqpU9UDgQatDtZTbvA7ciqGsSFgiwwW13N+Rr
|
||||
hN8MkODKs9cjtONxSKi05s206A3NDU6STtZ3KuPDjFE1gMJODotOuqSM+cxKfyFq
|
||||
wxpk/CHYCDdMAVBSwxb/vraOHamylL4uCHpJdBHypzf2HABt+lS8Su23uAmL87DR
|
||||
yvyCS/lmpuNTndef6qHPRkoW2EV3xqD3ovosGf7kgwGJUk2ZpCLVteqmYehKlZDK
|
||||
r/Jy+J26ooI2jIg9bjvD1PZq+Mv+2dQ1RlDrPG3PB+rEixw6vBaL9x3jatCd4ej7
|
||||
XG7lb3qO9xFpLsx89tkEcvpGR+broSpUJ6Mu5LBCVmrvqHjvnDhrZVz1brMiQtU9
|
||||
iMZbgXqDLXHd6ERWygk7OTU03u+l1gs+KGMfmS0h0ZYw6KGVLgMnsoxqd6cFSKNB
|
||||
8Ohk9ZTZGCiovlXBUepyu8wKat1k8YlHSfIHoRUJRhhcd7DrmojC+bcbMIZBU22T
|
||||
Pl2ftVRGtcQY23lYd0NNKfebF7ncjuLWQGy+vZW+7cgfI6wPIbfYfP6g7QAutk6W
|
||||
KQx0AoX5woZ6cNxtpIrymaVjSMRRBkKQrJKmRp3pC/lul5E5P2cueMs1fj4OHTbJ
|
||||
lAUv88ywr+R+mRgYQlFW/XQ653f6DT4t6+njfO9oBcPrQDASZel3LjXLpjjYG/N5
|
||||
+BWnVexuJX9ika8HJiFl55oqaKb+WknfNhk5cPY+x7SDV9ywQeMiDZpr0ffeYAEP
|
||||
LlwwiWRDYpO+uwXHSFF3+JjWwjhs8m8g99iFb7U93yKgBB12dCEPPa2ZeH9wUHMJ
|
||||
sreYhNuq6f4iWWSXpzN45inQqtTi8jrJhuNLTT543ErW7DtntBO2rWMhff3aiXbn
|
||||
Uy3qzZM1nPbuCGuBmP9L2dJ3Z5ifDWB4JmOyWY4swTZGt9AVmUxMIKdZpRONx8vz
|
||||
I9u9nbVPGZBcou50Pa0qTLbkWsSL94MNXrARBxzhHC9Zs6XNEtwN7mOuii7uMkVc
|
||||
adrxgknBH1J1N+NX/eTKzUwJuPvDtA+Z5ILWNN9wpZT/7ed8zEnKHPNUexyeT5g3
|
||||
uw9z9jH7ffGxFYlx87oiVPHGOrCXYZYW5uoZE31SCBkbtNuffNRJRKIFeipmpJ3P
|
||||
7bpAG+kGHMelQH6b+5K1Qgsv4tpuSyKeTKpPFH9Av5nN4P1ZBm9N80tzbNWqjSJm
|
||||
S7rYdHnuNEVnUGnRmEUMmVuYZnNBEVN/fP2m2SEwXcP3Uh7TiYlcWw10ygaGmOr7
|
||||
MvMLGkYgQ4Utwnd98mtqa0jr0hK2TcOSFir3AqVvXN3XJj4cVULkrXe4Im1laWgp
|
||||
-----END RSA PRIVATE KEY-----
|
||||
`),
|
||||
},
|
||||
|
||||
1: {
|
||||
Name: "dsa-encrypted",
|
||||
EncryptionKey: "qG0pher-dsa_t3st$",
|
||||
PEMBytes: []byte(`-----BEGIN DSA PRIVATE KEY-----
|
||||
Proc-Type: 4,ENCRYPTED
|
||||
DEK-Info: AES-128-CBC,7CE7A6E4A647DC01AF860210B15ADE3E
|
||||
|
||||
hvnBpI99Hceq/55pYRdOzBLntIEis02JFNXuLEydWL+RJBFDn7tA+vXec0ERJd6J
|
||||
G8JXlSOAhmC2H4uK3q2xR8/Y3yL95n6OIcjvCBiLsV+o3jj1MYJmErxP6zRtq4w3
|
||||
JjIjGHWmaYFSxPKQ6e8fs74HEqaeMV9ONUoTtB+aISmgaBL15Fcoayg245dkBvVl
|
||||
h5Kqspe7yvOBmzA3zjRuxmSCqKJmasXM7mqs3vIrMxZE3XPo1/fWKcPuExgpVQoT
|
||||
HkJZEoIEIIPnPMwT2uYbFJSGgPJVMDT84xz7yvjCdhLmqrsXgs5Qw7Pw0i0c0BUJ
|
||||
b7fDJ2UhdiwSckWGmIhTLlJZzr8K+JpjCDlP+REYBI5meB7kosBnlvCEHdw2EJkH
|
||||
0QDc/2F4xlVrHOLbPRFyu1Oi2Gvbeoo9EsM/DThpd1hKAlb0sF5Y0y0d+owv0PnE
|
||||
R/4X3HWfIdOHsDUvJ8xVWZ4BZk9Zk9qol045DcFCehpr/3hslCrKSZHakLt9GI58
|
||||
vVQJ4L0aYp5nloLfzhViZtKJXRLkySMKdzYkIlNmW1oVGl7tce5UCNI8Nok4j6yn
|
||||
IiHM7GBn+0nJoKTXsOGMIBe3ulKlKVxLjEuk9yivh/8=
|
||||
-----END DSA PRIVATE KEY-----
|
||||
`),
|
||||
},
|
||||
}
|
||||
|
|
50
vendor/src/golang.org/x/crypto/ssh/transport.go
vendored
50
vendor/src/golang.org/x/crypto/ssh/transport.go
vendored
|
@ -8,8 +8,13 @@ import (
|
|||
"bufio"
|
||||
"errors"
|
||||
"io"
|
||||
"log"
|
||||
)
|
||||
|
||||
// debugTransport if set, will print packet types as they go over the
|
||||
// wire. No message decoding is done, to minimize the impact on timing.
|
||||
const debugTransport = false
|
||||
|
||||
const (
|
||||
gcmCipherID = "aes128-gcm@openssh.com"
|
||||
aes128cbcID = "aes128-cbc"
|
||||
|
@ -22,7 +27,9 @@ type packetConn interface {
|
|||
// Encrypt and send a packet of data to the remote peer.
|
||||
writePacket(packet []byte) error
|
||||
|
||||
// Read a packet from the connection
|
||||
// Read a packet from the connection. The read is blocking,
|
||||
// i.e. if error is nil, then the returned byte slice is
|
||||
// always non-empty.
|
||||
readPacket() ([]byte, error)
|
||||
|
||||
// Close closes the write-side of the connection.
|
||||
|
@ -38,7 +45,7 @@ type transport struct {
|
|||
bufReader *bufio.Reader
|
||||
bufWriter *bufio.Writer
|
||||
rand io.Reader
|
||||
|
||||
isClient bool
|
||||
io.Closer
|
||||
}
|
||||
|
||||
|
@ -84,9 +91,38 @@ func (t *transport) prepareKeyChange(algs *algorithms, kexResult *kexResult) err
|
|||
return nil
|
||||
}
|
||||
|
||||
func (t *transport) printPacket(p []byte, write bool) {
|
||||
if len(p) == 0 {
|
||||
return
|
||||
}
|
||||
who := "server"
|
||||
if t.isClient {
|
||||
who = "client"
|
||||
}
|
||||
what := "read"
|
||||
if write {
|
||||
what = "write"
|
||||
}
|
||||
|
||||
log.Println(what, who, p[0])
|
||||
}
|
||||
|
||||
// Read and decrypt next packet.
|
||||
func (t *transport) readPacket() ([]byte, error) {
|
||||
return t.reader.readPacket(t.bufReader)
|
||||
func (t *transport) readPacket() (p []byte, err error) {
|
||||
for {
|
||||
p, err = t.reader.readPacket(t.bufReader)
|
||||
if err != nil {
|
||||
break
|
||||
}
|
||||
if len(p) == 0 || (p[0] != msgIgnore && p[0] != msgDebug) {
|
||||
break
|
||||
}
|
||||
}
|
||||
if debugTransport {
|
||||
t.printPacket(p, false)
|
||||
}
|
||||
|
||||
return p, err
|
||||
}
|
||||
|
||||
func (s *connectionState) readPacket(r *bufio.Reader) ([]byte, error) {
|
||||
|
@ -129,6 +165,9 @@ func (s *connectionState) readPacket(r *bufio.Reader) ([]byte, error) {
|
|||
}
|
||||
|
||||
func (t *transport) writePacket(packet []byte) error {
|
||||
if debugTransport {
|
||||
t.printPacket(packet, true)
|
||||
}
|
||||
return t.writer.writePacket(t.bufWriter, t.rand, packet)
|
||||
}
|
||||
|
||||
|
@ -169,6 +208,8 @@ func newTransport(rwc io.ReadWriteCloser, rand io.Reader, isClient bool) *transp
|
|||
},
|
||||
Closer: rwc,
|
||||
}
|
||||
t.isClient = isClient
|
||||
|
||||
if isClient {
|
||||
t.reader.dir = serverKeys
|
||||
t.writer.dir = clientKeys
|
||||
|
@ -226,6 +267,7 @@ func newPacketCipher(d direction, algs directionAlgorithms, kex *kexResult) (pac
|
|||
|
||||
c := &streamPacketCipher{
|
||||
mac: macModes[algs.MAC].new(macKey),
|
||||
etm: macModes[algs.MAC].etm,
|
||||
}
|
||||
c.macResult = make([]byte, c.mac.Size())
|
||||
|
||||
|
|
30
vendor/src/golang.org/x/net/context/context.go
vendored
30
vendor/src/golang.org/x/net/context/context.go
vendored
|
@ -7,7 +7,7 @@
|
|||
// and between processes.
|
||||
//
|
||||
// Incoming requests to a server should create a Context, and outgoing calls to
|
||||
// servers should accept a Context. The chain of function calls between must
|
||||
// servers should accept a Context. The chain of function calls between must
|
||||
// propagate the Context, optionally replacing it with a modified copy created
|
||||
// using WithDeadline, WithTimeout, WithCancel, or WithValue.
|
||||
//
|
||||
|
@ -16,14 +16,14 @@
|
|||
// propagation:
|
||||
//
|
||||
// Do not store Contexts inside a struct type; instead, pass a Context
|
||||
// explicitly to each function that needs it. The Context should be the first
|
||||
// explicitly to each function that needs it. The Context should be the first
|
||||
// parameter, typically named ctx:
|
||||
//
|
||||
// func DoSomething(ctx context.Context, arg Arg) error {
|
||||
// // ... use ctx ...
|
||||
// }
|
||||
//
|
||||
// Do not pass a nil Context, even if a function permits it. Pass context.TODO
|
||||
// Do not pass a nil Context, even if a function permits it. Pass context.TODO
|
||||
// if you are unsure about which Context to use.
|
||||
//
|
||||
// Use context Values only for request-scoped data that transits processes and
|
||||
|
@ -44,13 +44,13 @@ import "time"
|
|||
// Context's methods may be called by multiple goroutines simultaneously.
|
||||
type Context interface {
|
||||
// Deadline returns the time when work done on behalf of this context
|
||||
// should be canceled. Deadline returns ok==false when no deadline is
|
||||
// set. Successive calls to Deadline return the same results.
|
||||
// should be canceled. Deadline returns ok==false when no deadline is
|
||||
// set. Successive calls to Deadline return the same results.
|
||||
Deadline() (deadline time.Time, ok bool)
|
||||
|
||||
// Done returns a channel that's closed when work done on behalf of this
|
||||
// context should be canceled. Done may return nil if this context can
|
||||
// never be canceled. Successive calls to Done return the same value.
|
||||
// context should be canceled. Done may return nil if this context can
|
||||
// never be canceled. Successive calls to Done return the same value.
|
||||
//
|
||||
// WithCancel arranges for Done to be closed when cancel is called;
|
||||
// WithDeadline arranges for Done to be closed when the deadline
|
||||
|
@ -79,24 +79,24 @@ type Context interface {
|
|||
// a Done channel for cancelation.
|
||||
Done() <-chan struct{}
|
||||
|
||||
// Err returns a non-nil error value after Done is closed. Err returns
|
||||
// Err returns a non-nil error value after Done is closed. Err returns
|
||||
// Canceled if the context was canceled or DeadlineExceeded if the
|
||||
// context's deadline passed. No other values for Err are defined.
|
||||
// context's deadline passed. No other values for Err are defined.
|
||||
// After Done is closed, successive calls to Err return the same value.
|
||||
Err() error
|
||||
|
||||
// Value returns the value associated with this context for key, or nil
|
||||
// if no value is associated with key. Successive calls to Value with
|
||||
// if no value is associated with key. Successive calls to Value with
|
||||
// the same key returns the same result.
|
||||
//
|
||||
// Use context values only for request-scoped data that transits
|
||||
// processes and API boundaries, not for passing optional parameters to
|
||||
// functions.
|
||||
//
|
||||
// A key identifies a specific value in a Context. Functions that wish
|
||||
// A key identifies a specific value in a Context. Functions that wish
|
||||
// to store values in Context typically allocate a key in a global
|
||||
// variable then use that key as the argument to context.WithValue and
|
||||
// Context.Value. A key can be any type that supports equality;
|
||||
// Context.Value. A key can be any type that supports equality;
|
||||
// packages should define keys as an unexported type to avoid
|
||||
// collisions.
|
||||
//
|
||||
|
@ -115,7 +115,7 @@ type Context interface {
|
|||
// // This prevents collisions with keys defined in other packages.
|
||||
// type key int
|
||||
//
|
||||
// // userKey is the key for user.User values in Contexts. It is
|
||||
// // userKey is the key for user.User values in Contexts. It is
|
||||
// // unexported; clients use user.NewContext and user.FromContext
|
||||
// // instead of using this key directly.
|
||||
// var userKey key = 0
|
||||
|
@ -134,14 +134,14 @@ type Context interface {
|
|||
}
|
||||
|
||||
// Background returns a non-nil, empty Context. It is never canceled, has no
|
||||
// values, and has no deadline. It is typically used by the main function,
|
||||
// values, and has no deadline. It is typically used by the main function,
|
||||
// initialization, and tests, and as the top-level Context for incoming
|
||||
// requests.
|
||||
func Background() Context {
|
||||
return background
|
||||
}
|
||||
|
||||
// TODO returns a non-nil, empty Context. Code should use context.TODO when
|
||||
// TODO returns a non-nil, empty Context. Code should use context.TODO when
|
||||
// it's unclear which Context to use or it is not yet available (because the
|
||||
// surrounding function has not yet been extended to accept a Context
|
||||
// parameter). TODO is recognized by static analysis tools that determine
|
||||
|
|
|
@ -243,45 +243,51 @@ func testDeadline(c Context, wait time.Duration, t *testing.T) {
|
|||
}
|
||||
|
||||
func TestDeadline(t *testing.T) {
|
||||
c, _ := WithDeadline(Background(), time.Now().Add(100*time.Millisecond))
|
||||
t.Parallel()
|
||||
const timeUnit = 500 * time.Millisecond
|
||||
c, _ := WithDeadline(Background(), time.Now().Add(1*timeUnit))
|
||||
if got, prefix := fmt.Sprint(c), "context.Background.WithDeadline("; !strings.HasPrefix(got, prefix) {
|
||||
t.Errorf("c.String() = %q want prefix %q", got, prefix)
|
||||
}
|
||||
testDeadline(c, 200*time.Millisecond, t)
|
||||
testDeadline(c, 2*timeUnit, t)
|
||||
|
||||
c, _ = WithDeadline(Background(), time.Now().Add(100*time.Millisecond))
|
||||
c, _ = WithDeadline(Background(), time.Now().Add(1*timeUnit))
|
||||
o := otherContext{c}
|
||||
testDeadline(o, 200*time.Millisecond, t)
|
||||
testDeadline(o, 2*timeUnit, t)
|
||||
|
||||
c, _ = WithDeadline(Background(), time.Now().Add(100*time.Millisecond))
|
||||
c, _ = WithDeadline(Background(), time.Now().Add(1*timeUnit))
|
||||
o = otherContext{c}
|
||||
c, _ = WithDeadline(o, time.Now().Add(300*time.Millisecond))
|
||||
testDeadline(c, 200*time.Millisecond, t)
|
||||
c, _ = WithDeadline(o, time.Now().Add(3*timeUnit))
|
||||
testDeadline(c, 2*timeUnit, t)
|
||||
}
|
||||
|
||||
func TestTimeout(t *testing.T) {
|
||||
c, _ := WithTimeout(Background(), 100*time.Millisecond)
|
||||
t.Parallel()
|
||||
const timeUnit = 500 * time.Millisecond
|
||||
c, _ := WithTimeout(Background(), 1*timeUnit)
|
||||
if got, prefix := fmt.Sprint(c), "context.Background.WithDeadline("; !strings.HasPrefix(got, prefix) {
|
||||
t.Errorf("c.String() = %q want prefix %q", got, prefix)
|
||||
}
|
||||
testDeadline(c, 200*time.Millisecond, t)
|
||||
testDeadline(c, 2*timeUnit, t)
|
||||
|
||||
c, _ = WithTimeout(Background(), 100*time.Millisecond)
|
||||
c, _ = WithTimeout(Background(), 1*timeUnit)
|
||||
o := otherContext{c}
|
||||
testDeadline(o, 200*time.Millisecond, t)
|
||||
testDeadline(o, 2*timeUnit, t)
|
||||
|
||||
c, _ = WithTimeout(Background(), 100*time.Millisecond)
|
||||
c, _ = WithTimeout(Background(), 1*timeUnit)
|
||||
o = otherContext{c}
|
||||
c, _ = WithTimeout(o, 300*time.Millisecond)
|
||||
testDeadline(c, 200*time.Millisecond, t)
|
||||
c, _ = WithTimeout(o, 3*timeUnit)
|
||||
testDeadline(c, 2*timeUnit, t)
|
||||
}
|
||||
|
||||
func TestCanceledTimeout(t *testing.T) {
|
||||
c, _ := WithTimeout(Background(), 200*time.Millisecond)
|
||||
t.Parallel()
|
||||
const timeUnit = 500 * time.Millisecond
|
||||
c, _ := WithTimeout(Background(), 2*timeUnit)
|
||||
o := otherContext{c}
|
||||
c, cancel := WithTimeout(o, 400*time.Millisecond)
|
||||
c, cancel := WithTimeout(o, 4*timeUnit)
|
||||
cancel()
|
||||
time.Sleep(100 * time.Millisecond) // let cancelation propagate
|
||||
time.Sleep(1 * timeUnit) // let cancelation propagate
|
||||
select {
|
||||
case <-c.Done():
|
||||
default:
|
||||
|
|
|
@ -19,6 +19,7 @@ func TestGo17Context(t *testing.T) {
|
|||
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
io.WriteString(w, "ok")
|
||||
}))
|
||||
defer ts.Close()
|
||||
ctx := context.Background()
|
||||
resp, err := Get(ctx, http.DefaultClient, ts.URL)
|
||||
if resp == nil || err != nil {
|
||||
|
|
4
vendor/src/golang.org/x/net/context/go17.go
vendored
4
vendor/src/golang.org/x/net/context/go17.go
vendored
|
@ -35,8 +35,8 @@ func WithCancel(parent Context) (ctx Context, cancel CancelFunc) {
|
|||
}
|
||||
|
||||
// WithDeadline returns a copy of the parent context with the deadline adjusted
|
||||
// to be no later than d. If the parent's deadline is already earlier than d,
|
||||
// WithDeadline(parent, d) is semantically equivalent to parent. The returned
|
||||
// to be no later than d. If the parent's deadline is already earlier than d,
|
||||
// WithDeadline(parent, d) is semantically equivalent to parent. The returned
|
||||
// context's Done channel is closed when the deadline expires, when the returned
|
||||
// cancel function is called, or when the parent context's Done channel is
|
||||
// closed, whichever happens first.
|
||||
|
|
18
vendor/src/golang.org/x/net/context/pre_go17.go
vendored
18
vendor/src/golang.org/x/net/context/pre_go17.go
vendored
|
@ -13,7 +13,7 @@ import (
|
|||
"time"
|
||||
)
|
||||
|
||||
// An emptyCtx is never canceled, has no values, and has no deadline. It is not
|
||||
// An emptyCtx is never canceled, has no values, and has no deadline. It is not
|
||||
// struct{}, since vars of this type must have distinct addresses.
|
||||
type emptyCtx int
|
||||
|
||||
|
@ -104,7 +104,7 @@ func propagateCancel(parent Context, child canceler) {
|
|||
}
|
||||
|
||||
// parentCancelCtx follows a chain of parent references until it finds a
|
||||
// *cancelCtx. This function understands how each of the concrete types in this
|
||||
// *cancelCtx. This function understands how each of the concrete types in this
|
||||
// package represents its parent.
|
||||
func parentCancelCtx(parent Context) (*cancelCtx, bool) {
|
||||
for {
|
||||
|
@ -134,14 +134,14 @@ func removeChild(parent Context, child canceler) {
|
|||
p.mu.Unlock()
|
||||
}
|
||||
|
||||
// A canceler is a context type that can be canceled directly. The
|
||||
// A canceler is a context type that can be canceled directly. The
|
||||
// implementations are *cancelCtx and *timerCtx.
|
||||
type canceler interface {
|
||||
cancel(removeFromParent bool, err error)
|
||||
Done() <-chan struct{}
|
||||
}
|
||||
|
||||
// A cancelCtx can be canceled. When canceled, it also cancels any children
|
||||
// A cancelCtx can be canceled. When canceled, it also cancels any children
|
||||
// that implement canceler.
|
||||
type cancelCtx struct {
|
||||
Context
|
||||
|
@ -193,8 +193,8 @@ func (c *cancelCtx) cancel(removeFromParent bool, err error) {
|
|||
}
|
||||
|
||||
// WithDeadline returns a copy of the parent context with the deadline adjusted
|
||||
// to be no later than d. If the parent's deadline is already earlier than d,
|
||||
// WithDeadline(parent, d) is semantically equivalent to parent. The returned
|
||||
// to be no later than d. If the parent's deadline is already earlier than d,
|
||||
// WithDeadline(parent, d) is semantically equivalent to parent. The returned
|
||||
// context's Done channel is closed when the deadline expires, when the returned
|
||||
// cancel function is called, or when the parent context's Done channel is
|
||||
// closed, whichever happens first.
|
||||
|
@ -226,8 +226,8 @@ func WithDeadline(parent Context, deadline time.Time) (Context, CancelFunc) {
|
|||
return c, func() { c.cancel(true, Canceled) }
|
||||
}
|
||||
|
||||
// A timerCtx carries a timer and a deadline. It embeds a cancelCtx to
|
||||
// implement Done and Err. It implements cancel by stopping its timer then
|
||||
// A timerCtx carries a timer and a deadline. It embeds a cancelCtx to
|
||||
// implement Done and Err. It implements cancel by stopping its timer then
|
||||
// delegating to cancelCtx.cancel.
|
||||
type timerCtx struct {
|
||||
*cancelCtx
|
||||
|
@ -281,7 +281,7 @@ func WithValue(parent Context, key interface{}, val interface{}) Context {
|
|||
return &valueCtx{parent, key, val}
|
||||
}
|
||||
|
||||
// A valueCtx carries a key-value pair. It implements Value for that key and
|
||||
// A valueCtx carries a key-value pair. It implements Value for that key and
|
||||
// delegates all other calls to the embedded Context.
|
||||
type valueCtx struct {
|
||||
Context
|
||||
|
|
10
vendor/src/golang.org/x/sys/unix/asm.s
vendored
10
vendor/src/golang.org/x/sys/unix/asm.s
vendored
|
@ -1,10 +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.
|
||||
|
||||
// +build !gccgo
|
||||
|
||||
#include "textflag.h"
|
||||
|
||||
TEXT ·use(SB),NOSPLIT,$0
|
||||
RET
|
31
vendor/src/golang.org/x/sys/unix/asm_linux_mipsx.s
vendored
Normal file
31
vendor/src/golang.org/x/sys/unix/asm_linux_mipsx.s
vendored
Normal file
|
@ -0,0 +1,31 @@
|
|||
// 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.
|
||||
|
||||
// +build linux
|
||||
// +build mips mipsle
|
||||
// +build !gccgo
|
||||
|
||||
#include "textflag.h"
|
||||
|
||||
//
|
||||
// System calls for mips, Linux
|
||||
//
|
||||
|
||||
// Just jump to package syscall's implementation for all these functions.
|
||||
// The runtime may know about them.
|
||||
|
||||
TEXT ·Syscall(SB),NOSPLIT,$0-28
|
||||
JMP syscall·Syscall(SB)
|
||||
|
||||
TEXT ·Syscall6(SB),NOSPLIT,$0-40
|
||||
JMP syscall·Syscall6(SB)
|
||||
|
||||
TEXT ·Syscall9(SB),NOSPLIT,$0-52
|
||||
JMP syscall·Syscall9(SB)
|
||||
|
||||
TEXT ·RawSyscall(SB),NOSPLIT,$0-28
|
||||
JMP syscall·RawSyscall(SB)
|
||||
|
||||
TEXT ·RawSyscall6(SB),NOSPLIT,$0-40
|
||||
JMP syscall·RawSyscall6(SB)
|
102
vendor/src/golang.org/x/sys/unix/dirent.go
vendored
Normal file
102
vendor/src/golang.org/x/sys/unix/dirent.go
vendored
Normal file
|
@ -0,0 +1,102 @@
|
|||
// Copyright 2009 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.
|
||||
|
||||
// +build darwin dragonfly freebsd linux nacl netbsd openbsd solaris
|
||||
|
||||
package unix
|
||||
|
||||
import "unsafe"
|
||||
|
||||
// readInt returns the size-bytes unsigned integer in native byte order at offset off.
|
||||
func readInt(b []byte, off, size uintptr) (u uint64, ok bool) {
|
||||
if len(b) < int(off+size) {
|
||||
return 0, false
|
||||
}
|
||||
if isBigEndian {
|
||||
return readIntBE(b[off:], size), true
|
||||
}
|
||||
return readIntLE(b[off:], size), true
|
||||
}
|
||||
|
||||
func readIntBE(b []byte, size uintptr) uint64 {
|
||||
switch size {
|
||||
case 1:
|
||||
return uint64(b[0])
|
||||
case 2:
|
||||
_ = b[1] // bounds check hint to compiler; see golang.org/issue/14808
|
||||
return uint64(b[1]) | uint64(b[0])<<8
|
||||
case 4:
|
||||
_ = b[3] // bounds check hint to compiler; see golang.org/issue/14808
|
||||
return uint64(b[3]) | uint64(b[2])<<8 | uint64(b[1])<<16 | uint64(b[0])<<24
|
||||
case 8:
|
||||
_ = b[7] // bounds check hint to compiler; see golang.org/issue/14808
|
||||
return uint64(b[7]) | uint64(b[6])<<8 | uint64(b[5])<<16 | uint64(b[4])<<24 |
|
||||
uint64(b[3])<<32 | uint64(b[2])<<40 | uint64(b[1])<<48 | uint64(b[0])<<56
|
||||
default:
|
||||
panic("syscall: readInt with unsupported size")
|
||||
}
|
||||
}
|
||||
|
||||
func readIntLE(b []byte, size uintptr) uint64 {
|
||||
switch size {
|
||||
case 1:
|
||||
return uint64(b[0])
|
||||
case 2:
|
||||
_ = b[1] // bounds check hint to compiler; see golang.org/issue/14808
|
||||
return uint64(b[0]) | uint64(b[1])<<8
|
||||
case 4:
|
||||
_ = b[3] // bounds check hint to compiler; see golang.org/issue/14808
|
||||
return uint64(b[0]) | uint64(b[1])<<8 | uint64(b[2])<<16 | uint64(b[3])<<24
|
||||
case 8:
|
||||
_ = b[7] // bounds check hint to compiler; see golang.org/issue/14808
|
||||
return uint64(b[0]) | uint64(b[1])<<8 | uint64(b[2])<<16 | uint64(b[3])<<24 |
|
||||
uint64(b[4])<<32 | uint64(b[5])<<40 | uint64(b[6])<<48 | uint64(b[7])<<56
|
||||
default:
|
||||
panic("syscall: readInt with unsupported size")
|
||||
}
|
||||
}
|
||||
|
||||
// ParseDirent parses up to max directory entries in buf,
|
||||
// appending the names to names. It returns the number of
|
||||
// bytes consumed from buf, the number of entries added
|
||||
// to names, and the new names slice.
|
||||
func ParseDirent(buf []byte, max int, names []string) (consumed int, count int, newnames []string) {
|
||||
origlen := len(buf)
|
||||
count = 0
|
||||
for max != 0 && len(buf) > 0 {
|
||||
reclen, ok := direntReclen(buf)
|
||||
if !ok || reclen > uint64(len(buf)) {
|
||||
return origlen, count, names
|
||||
}
|
||||
rec := buf[:reclen]
|
||||
buf = buf[reclen:]
|
||||
ino, ok := direntIno(rec)
|
||||
if !ok {
|
||||
break
|
||||
}
|
||||
if ino == 0 { // File absent in directory.
|
||||
continue
|
||||
}
|
||||
const namoff = uint64(unsafe.Offsetof(Dirent{}.Name))
|
||||
namlen, ok := direntNamlen(rec)
|
||||
if !ok || namoff+namlen > uint64(len(rec)) {
|
||||
break
|
||||
}
|
||||
name := rec[namoff : namoff+namlen]
|
||||
for i, c := range name {
|
||||
if c == 0 {
|
||||
name = name[:i]
|
||||
break
|
||||
}
|
||||
}
|
||||
// Check for useless names before allocating a string.
|
||||
if string(name) == "." || string(name) == ".." {
|
||||
continue
|
||||
}
|
||||
max--
|
||||
count++
|
||||
names = append(names, string(name))
|
||||
}
|
||||
return origlen - len(buf), count, names
|
||||
}
|
9
vendor/src/golang.org/x/sys/unix/endian_big.go
vendored
Normal file
9
vendor/src/golang.org/x/sys/unix/endian_big.go
vendored
Normal file
|
@ -0,0 +1,9 @@
|
|||
// 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.
|
||||
//
|
||||
// +build ppc64 s390x mips mips64
|
||||
|
||||
package unix
|
||||
|
||||
const isBigEndian = true
|
9
vendor/src/golang.org/x/sys/unix/endian_little.go
vendored
Normal file
9
vendor/src/golang.org/x/sys/unix/endian_little.go
vendored
Normal file
|
@ -0,0 +1,9 @@
|
|||
// 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.
|
||||
//
|
||||
// +build 386 amd64 amd64p32 arm arm64 ppc64le mipsle mips64le
|
||||
|
||||
package unix
|
||||
|
||||
const isBigEndian = false
|
|
@ -1,4 +1,4 @@
|
|||
// +build linux,386 linux,arm
|
||||
// +build linux,386 linux,arm linux,mips linux,mipsle
|
||||
|
||||
// Copyright 2014 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
|
|
20
vendor/src/golang.org/x/sys/unix/gccgo_linux_sparc64.go
vendored
Normal file
20
vendor/src/golang.org/x/sys/unix/gccgo_linux_sparc64.go
vendored
Normal file
|
@ -0,0 +1,20 @@
|
|||
// 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.
|
||||
|
||||
// +build gccgo,linux,sparc64
|
||||
|
||||
package unix
|
||||
|
||||
import "syscall"
|
||||
|
||||
//extern sysconf
|
||||
func realSysconf(name int) int64
|
||||
|
||||
func sysconf(name int) (n int64, err syscall.Errno) {
|
||||
r := realSysconf(name)
|
||||
if r < 0 {
|
||||
return 0, syscall.GetErrno()
|
||||
}
|
||||
return r, 0
|
||||
}
|
11
vendor/src/golang.org/x/sys/unix/mkall.sh
vendored
11
vendor/src/golang.org/x/sys/unix/mkall.sh
vendored
|
@ -89,6 +89,8 @@ case "$1" in
|
|||
-syscalls)
|
||||
for i in zsyscall*go
|
||||
do
|
||||
# Run the command line that appears in the first line
|
||||
# of the generated file to regenerate it.
|
||||
sed 1q $i | sed 's;^// ;;' | sh > _$i && gofmt < _$i > $i
|
||||
rm _$i
|
||||
done
|
||||
|
@ -223,6 +225,13 @@ linux_s390x)
|
|||
# package generates its version of the types file.
|
||||
mktypes="GOARCH=$GOARCH go tool cgo -godefs -- -fsigned-char"
|
||||
;;
|
||||
linux_sparc64)
|
||||
GOOSARCH_in=syscall_linux_sparc64.go
|
||||
unistd_h=/usr/include/sparc64-linux-gnu/asm/unistd.h
|
||||
mkerrors="$mkerrors -m64"
|
||||
mksysnum="./mksysnum_linux.pl $unistd_h"
|
||||
mktypes="GOARCH=$GOARCH go tool cgo -godefs"
|
||||
;;
|
||||
netbsd_386)
|
||||
mkerrors="$mkerrors -m32"
|
||||
mksyscall="./mksyscall.pl -l32 -netbsd"
|
||||
|
@ -273,7 +282,7 @@ esac
|
|||
syscall_goos="syscall_bsd.go $syscall_goos"
|
||||
;;
|
||||
esac
|
||||
if [ -n "$mksyscall" ]; then echo "$mksyscall $syscall_goos $GOOSARCH_in |gofmt >zsyscall_$GOOSARCH.go"; fi
|
||||
if [ -n "$mksyscall" ]; then echo "$mksyscall -tags $GOOS,$GOARCH $syscall_goos $GOOSARCH_in |gofmt >zsyscall_$GOOSARCH.go"; fi
|
||||
;;
|
||||
esac
|
||||
if [ -n "$mksysctl" ]; then echo "$mksysctl |gofmt >$zsysctl"; fi
|
||||
|
|
27
vendor/src/golang.org/x/sys/unix/mkerrors.sh
vendored
27
vendor/src/golang.org/x/sys/unix/mkerrors.sh
vendored
|
@ -114,19 +114,25 @@ includes_Linux='
|
|||
#include <sys/time.h>
|
||||
#include <sys/socket.h>
|
||||
#include <linux/if.h>
|
||||
#include <linux/if_alg.h>
|
||||
#include <linux/if_arp.h>
|
||||
#include <linux/if_ether.h>
|
||||
#include <linux/if_tun.h>
|
||||
#include <linux/if_packet.h>
|
||||
#include <linux/if_addr.h>
|
||||
#include <linux/falloc.h>
|
||||
#include <linux/filter.h>
|
||||
#include <linux/netlink.h>
|
||||
#include <linux/random.h>
|
||||
#include <linux/reboot.h>
|
||||
#include <linux/rtnetlink.h>
|
||||
#include <linux/ptrace.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/wait.h>
|
||||
#include <linux/icmpv6.h>
|
||||
#include <linux/serial.h>
|
||||
#include <linux/can.h>
|
||||
#include <linux/vm_sockets.h>
|
||||
#include <net/route.h>
|
||||
#include <asm/termbits.h>
|
||||
|
||||
|
@ -141,6 +147,16 @@ includes_Linux='
|
|||
#ifndef PTRACE_SETREGS
|
||||
#define PTRACE_SETREGS 0xd
|
||||
#endif
|
||||
|
||||
#ifndef SOL_NETLINK
|
||||
#define SOL_NETLINK 270
|
||||
#endif
|
||||
|
||||
#ifdef SOL_BLUETOOTH
|
||||
// SPARC includes this in /usr/include/sparc64-linux-gnu/bits/socket.h
|
||||
// but it is already in bluetooth_linux.go
|
||||
#undef SOL_BLUETOOTH
|
||||
#endif
|
||||
'
|
||||
|
||||
includes_NetBSD='
|
||||
|
@ -304,6 +320,7 @@ ccflags="$@"
|
|||
$2 ~ /^IN_/ ||
|
||||
$2 ~ /^LOCK_(SH|EX|NB|UN)$/ ||
|
||||
$2 ~ /^(AF|SOCK|SO|SOL|IPPROTO|IP|IPV6|ICMP6|TCP|EVFILT|NOTE|EV|SHUT|PROT|MAP|PACKET|MSG|SCM|MCL|DT|MADV|PR)_/ ||
|
||||
$2 ~ /^FALLOC_/ ||
|
||||
$2 == "ICMPV6_FILTER" ||
|
||||
$2 == "SOMAXCONN" ||
|
||||
$2 == "NAME_MAX" ||
|
||||
|
@ -332,8 +349,14 @@ ccflags="$@"
|
|||
$2 !~ /^(BPF_TIMEVAL)$/ &&
|
||||
$2 ~ /^(BPF|DLT)_/ ||
|
||||
$2 ~ /^CLOCK_/ ||
|
||||
$2 ~ /^CAN_/ ||
|
||||
$2 ~ /^ALG_/ ||
|
||||
$2 ~ /^GRND_/ ||
|
||||
$2 ~ /^SPLICE_/ ||
|
||||
$2 ~ /^(VM|VMADDR)_/ ||
|
||||
$2 !~ "WMESGLEN" &&
|
||||
$2 ~ /^W[A-Z0-9]+$/ {printf("\t%s = C.%s\n", $2, $2)}
|
||||
$2 ~ /^W[A-Z0-9]+$/ ||
|
||||
$2 ~ /^BLK/ {printf("\t%s = C.%s\n", $2, $2)}
|
||||
$2 ~ /^__WCOREFLAG$/ {next}
|
||||
$2 ~ /^__W[A-Z0-9]+$/ {printf("\t%s = C.%s\n", substr($2,3), $2)}
|
||||
|
||||
|
@ -447,7 +470,7 @@ main(void)
|
|||
printf("\t%d: \"%s\",\n", e, buf);
|
||||
}
|
||||
printf("}\n\n");
|
||||
|
||||
|
||||
printf("\n\n// Signal table\n");
|
||||
printf("var signals = [...]string {\n");
|
||||
qsort(signals, nelem(signals), sizeof signals[0], intcmp);
|
||||
|
|
25
vendor/src/golang.org/x/sys/unix/mksyscall.pl
vendored
25
vendor/src/golang.org/x/sys/unix/mksyscall.pl
vendored
|
@ -29,6 +29,7 @@ my $openbsd = 0;
|
|||
my $netbsd = 0;
|
||||
my $dragonfly = 0;
|
||||
my $arm = 0; # 64-bit value should use (even, odd)-pair
|
||||
my $tags = ""; # build tags
|
||||
|
||||
if($ARGV[0] eq "-b32") {
|
||||
$_32bit = "big-endian";
|
||||
|
@ -57,14 +58,14 @@ if($ARGV[0] eq "-arm") {
|
|||
$arm = 1;
|
||||
shift;
|
||||
}
|
||||
|
||||
if($ARGV[0] =~ /^-/) {
|
||||
print STDERR "usage: mksyscall.pl [-b32 | -l32] [file ...]\n";
|
||||
exit 1;
|
||||
if($ARGV[0] eq "-tags") {
|
||||
shift;
|
||||
$tags = $ARGV[0];
|
||||
shift;
|
||||
}
|
||||
|
||||
if($ENV{'GOARCH'} eq "" || $ENV{'GOOS'} eq "") {
|
||||
print STDERR "GOARCH or GOOS not defined in environment\n";
|
||||
if($ARGV[0] =~ /^-/) {
|
||||
print STDERR "usage: mksyscall.pl [-b32 | -l32] [-tags x,y] [file ...]\n";
|
||||
exit 1;
|
||||
}
|
||||
|
||||
|
@ -132,7 +133,6 @@ while(<>) {
|
|||
|
||||
# Prepare arguments to Syscall.
|
||||
my @args = ();
|
||||
my @uses = ();
|
||||
my $n = 0;
|
||||
foreach my $p (@in) {
|
||||
my ($name, $type) = parseparam($p);
|
||||
|
@ -143,14 +143,12 @@ while(<>) {
|
|||
$text .= "\t_p$n, $errvar = BytePtrFromString($name)\n";
|
||||
$text .= "\tif $errvar != nil {\n\t\treturn\n\t}\n";
|
||||
push @args, "uintptr(unsafe.Pointer(_p$n))";
|
||||
push @uses, "use(unsafe.Pointer(_p$n))";
|
||||
$n++;
|
||||
} elsif($type eq "string") {
|
||||
print STDERR "$ARGV:$.: $func uses string arguments, but has no error return\n";
|
||||
$text .= "\tvar _p$n *byte\n";
|
||||
$text .= "\t_p$n, _ = BytePtrFromString($name)\n";
|
||||
push @args, "uintptr(unsafe.Pointer(_p$n))";
|
||||
push @uses, "use(unsafe.Pointer(_p$n))";
|
||||
$n++;
|
||||
} elsif($type =~ /^\[\](.*)/) {
|
||||
# Convert slice into pointer, length.
|
||||
|
@ -185,7 +183,7 @@ while(<>) {
|
|||
}
|
||||
} elsif($type eq "int64" && $_32bit ne "") {
|
||||
if(@args % 2 && $arm) {
|
||||
# arm abi specifies 64-bit argument uses
|
||||
# arm abi specifies 64-bit argument uses
|
||||
# (even, odd) pair
|
||||
push @args, "0"
|
||||
}
|
||||
|
@ -278,11 +276,8 @@ while(<>) {
|
|||
} else {
|
||||
$text .= "\t$ret[0], $ret[1], $ret[2] := $call\n";
|
||||
}
|
||||
foreach my $use (@uses) {
|
||||
$text .= "\t$use\n";
|
||||
}
|
||||
$text .= $body;
|
||||
|
||||
|
||||
if ($plan9 && $ret[2] eq "e1") {
|
||||
$text .= "\tif int32(r0) == -1 {\n";
|
||||
$text .= "\t\terr = e1\n";
|
||||
|
@ -307,7 +302,7 @@ print <<EOF;
|
|||
// $cmdline
|
||||
// MACHINE GENERATED BY THE COMMAND ABOVE; DO NOT EDIT
|
||||
|
||||
// +build $ENV{'GOARCH'},$ENV{'GOOS'}
|
||||
// +build $tags
|
||||
|
||||
package unix
|
||||
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
# * The parameter lists must give a type for each argument:
|
||||
# the (x, y, z int) shorthand is not allowed.
|
||||
# * If the return parameter is an error number, it must be named err.
|
||||
# * If go func name needs to be different than its libc name,
|
||||
# * If go func name needs to be different than its libc name,
|
||||
# * or the function is not in libc, name could be specified
|
||||
# * at the end, after "=" sign, like
|
||||
# //sys getsockopt(s int, level int, name int, val uintptr, vallen *_Socklen) (err error) = libsocket.getsockopt
|
||||
|
@ -22,6 +22,7 @@ use strict;
|
|||
my $cmdline = "mksyscall_solaris.pl " . join(' ', @ARGV);
|
||||
my $errors = 0;
|
||||
my $_32bit = "";
|
||||
my $tags = ""; # build tags
|
||||
|
||||
binmode STDOUT;
|
||||
|
||||
|
@ -32,14 +33,14 @@ if($ARGV[0] eq "-b32") {
|
|||
$_32bit = "little-endian";
|
||||
shift;
|
||||
}
|
||||
|
||||
if($ARGV[0] =~ /^-/) {
|
||||
print STDERR "usage: mksyscall_solaris.pl [-b32 | -l32] [file ...]\n";
|
||||
exit 1;
|
||||
if($ARGV[0] eq "-tags") {
|
||||
shift;
|
||||
$tags = $ARGV[0];
|
||||
shift;
|
||||
}
|
||||
|
||||
if($ENV{'GOARCH'} eq "" || $ENV{'GOOS'} eq "") {
|
||||
print STDERR "GOARCH or GOOS not defined in environment\n";
|
||||
if($ARGV[0] =~ /^-/) {
|
||||
print STDERR "usage: mksyscall_solaris.pl [-b32 | -l32] [-tags x,y] [file ...]\n";
|
||||
exit 1;
|
||||
}
|
||||
|
||||
|
@ -138,7 +139,6 @@ while(<>) {
|
|||
|
||||
# Prepare arguments to Syscall.
|
||||
my @args = ();
|
||||
my @uses = ();
|
||||
my $n = 0;
|
||||
foreach my $p (@in) {
|
||||
my ($name, $type) = parseparam($p);
|
||||
|
@ -149,14 +149,12 @@ while(<>) {
|
|||
$text .= "\t_p$n, $errvar = $strconvfunc($name)\n";
|
||||
$text .= "\tif $errvar != nil {\n\t\treturn\n\t}\n";
|
||||
push @args, "uintptr(unsafe.Pointer(_p$n))";
|
||||
push @uses, "use(unsafe.Pointer(_p$n))";
|
||||
$n++;
|
||||
} elsif($type eq "string") {
|
||||
print STDERR "$ARGV:$.: $func uses string arguments, but has no error return\n";
|
||||
$text .= "\tvar _p$n $strconvtype\n";
|
||||
$text .= "\t_p$n, _ = $strconvfunc($name)\n";
|
||||
push @args, "uintptr(unsafe.Pointer(_p$n))";
|
||||
push @uses, "use(unsafe.Pointer(_p$n))";
|
||||
$n++;
|
||||
} elsif($type =~ /^\[\](.*)/) {
|
||||
# Convert slice into pointer, length.
|
||||
|
@ -243,9 +241,6 @@ while(<>) {
|
|||
} else {
|
||||
$text .= "\t$ret[0], $ret[1], $ret[2] := $call\n";
|
||||
}
|
||||
foreach my $use (@uses) {
|
||||
$text .= "\t$use\n";
|
||||
}
|
||||
$text .= $body;
|
||||
|
||||
if ($do_errno) {
|
||||
|
@ -265,7 +260,7 @@ print <<EOF;
|
|||
// $cmdline
|
||||
// MACHINE GENERATED BY THE COMMAND ABOVE; DO NOT EDIT
|
||||
|
||||
// +build $ENV{'GOARCH'},$ENV{'GOOS'}
|
||||
// +build $tags
|
||||
|
||||
package $package
|
||||
|
||||
|
|
|
@ -23,6 +23,8 @@ package unix
|
|||
const(
|
||||
EOF
|
||||
|
||||
my $offset = 0;
|
||||
|
||||
sub fmt {
|
||||
my ($name, $num) = @_;
|
||||
if($num > 999){
|
||||
|
@ -31,15 +33,27 @@ sub fmt {
|
|||
return;
|
||||
}
|
||||
$name =~ y/a-z/A-Z/;
|
||||
$num = $num + $offset;
|
||||
print " SYS_$name = $num;\n";
|
||||
}
|
||||
|
||||
my $prev;
|
||||
open(GCC, "gcc -E -dD $ARGV[0] |") || die "can't run gcc";
|
||||
open(GCC, "gcc -E -dD @ARGV |") || die "can't run gcc";
|
||||
while(<GCC>){
|
||||
if(/^#define __NR_syscalls\s+/) {
|
||||
if(/^#define __NR_Linux\s+([0-9]+)/){
|
||||
# mips/mips64: extract offset
|
||||
$offset = $1;
|
||||
}
|
||||
elsif(/^#define __NR(\w*)_SYSCALL_BASE\s+([0-9]+)/){
|
||||
# arm: extract offset
|
||||
$offset = $1;
|
||||
}
|
||||
elsif(/^#define __NR_syscalls\s+/) {
|
||||
# ignore redefinitions of __NR_syscalls
|
||||
}
|
||||
elsif(/^#define __NR_(\w*)Linux_syscalls\s+/) {
|
||||
# mips/mips64: ignore definitions about the number of syscalls
|
||||
}
|
||||
elsif(/^#define __NR_(\w+)\s+([0-9]+)/){
|
||||
$prev = $2;
|
||||
fmt($1, $2);
|
||||
|
@ -51,6 +65,12 @@ while(<GCC>){
|
|||
elsif(/^#define __NR_(\w+)\s+\(\w+\+\s*([0-9]+)\)/){
|
||||
fmt($1, $prev+$2)
|
||||
}
|
||||
elsif(/^#define __NR_(\w+)\s+\(__NR_Linux \+ ([0-9]+)/){
|
||||
fmt($1, $2);
|
||||
}
|
||||
elsif(/^#define __NR_(\w+)\s+\(__NR_SYSCALL_BASE \+ ([0-9]+)/){
|
||||
fmt($1, $2);
|
||||
}
|
||||
}
|
||||
|
||||
print <<EOF;
|
||||
|
|
38
vendor/src/golang.org/x/sys/unix/openbsd_pledge.go
vendored
Normal file
38
vendor/src/golang.org/x/sys/unix/openbsd_pledge.go
vendored
Normal file
|
@ -0,0 +1,38 @@
|
|||
// 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.
|
||||
|
||||
// +build openbsd
|
||||
// +build 386 amd64 arm
|
||||
|
||||
package unix
|
||||
|
||||
import (
|
||||
"syscall"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
const (
|
||||
SYS_PLEDGE = 108
|
||||
)
|
||||
|
||||
// Pledge implements the pledge syscall. For more information see pledge(2).
|
||||
func Pledge(promises string, paths []string) error {
|
||||
promisesPtr, err := syscall.BytePtrFromString(promises)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
promisesUnsafe, pathsUnsafe := unsafe.Pointer(promisesPtr), unsafe.Pointer(nil)
|
||||
if paths != nil {
|
||||
var pathsPtr []*byte
|
||||
if pathsPtr, err = syscall.SlicePtrFromStrings(paths); err != nil {
|
||||
return err
|
||||
}
|
||||
pathsUnsafe = unsafe.Pointer(&pathsPtr[0])
|
||||
}
|
||||
_, _, e := syscall.Syscall(SYS_PLEDGE, uintptr(promisesUnsafe), uintptr(pathsUnsafe), 0)
|
||||
if e != 0 {
|
||||
return e
|
||||
}
|
||||
return nil
|
||||
}
|
113
vendor/src/golang.org/x/sys/unix/openbsd_test.go
vendored
Normal file
113
vendor/src/golang.org/x/sys/unix/openbsd_test.go
vendored
Normal file
|
@ -0,0 +1,113 @@
|
|||
// 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.
|
||||
|
||||
// +build openbsd
|
||||
|
||||
// This, on the face of it, bizarre testing mechanism is necessary because
|
||||
// the only reliable way to gauge whether or not a pledge(2) call has succeeded
|
||||
// is that the program has been killed as a result of breaking its pledge.
|
||||
|
||||
package unix_test
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
type testProc struct {
|
||||
fn func() // should always exit instead of returning
|
||||
cleanup func() error // for instance, delete coredumps from testing pledge
|
||||
success bool // whether zero-exit means success or failure
|
||||
}
|
||||
|
||||
var (
|
||||
testProcs = map[string]testProc{}
|
||||
procName = ""
|
||||
)
|
||||
|
||||
const (
|
||||
optName = "sys-unix-internal-procname"
|
||||
)
|
||||
|
||||
func init() {
|
||||
flag.StringVar(&procName, optName, "", "internal use only")
|
||||
}
|
||||
|
||||
// testCmd generates a proper command that, when executed, runs the test
|
||||
// corresponding to the given key.
|
||||
func testCmd(procName string) (*exec.Cmd, error) {
|
||||
exe, err := filepath.Abs(os.Args[0])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cmd := exec.Command(exe, "-"+optName+"="+procName)
|
||||
cmd.Stdout, cmd.Stderr = os.Stdout, os.Stderr
|
||||
return cmd, nil
|
||||
}
|
||||
|
||||
// ExitsCorrectly is a comprehensive, one-line-of-use wrapper for testing
|
||||
// a testProc with a key.
|
||||
func ExitsCorrectly(procName string, t *testing.T) {
|
||||
s := testProcs[procName]
|
||||
c, err := testCmd(procName)
|
||||
defer func() {
|
||||
if s.cleanup() != nil {
|
||||
t.Fatalf("Failed to run cleanup for %s", procName)
|
||||
}
|
||||
}()
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to construct command for %s", procName)
|
||||
}
|
||||
if (c.Run() == nil) != s.success {
|
||||
result := "succeed"
|
||||
if !s.success {
|
||||
result = "fail"
|
||||
}
|
||||
t.Fatalf("Process did not %s when it was supposed to", result)
|
||||
}
|
||||
}
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
flag.Parse()
|
||||
if procName != "" {
|
||||
testProcs[procName].fn()
|
||||
}
|
||||
os.Exit(m.Run())
|
||||
}
|
||||
|
||||
// For example, add a test for pledge.
|
||||
func init() {
|
||||
testProcs["pledge"] = testProc{
|
||||
func() {
|
||||
fmt.Println(unix.Pledge("", nil))
|
||||
os.Exit(0)
|
||||
},
|
||||
func() error {
|
||||
files, err := ioutil.ReadDir(".")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, file := range files {
|
||||
if filepath.Ext(file.Name()) == ".core" {
|
||||
if err := os.Remove(file.Name()); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
},
|
||||
false,
|
||||
}
|
||||
}
|
||||
|
||||
func TestPledge(t *testing.T) {
|
||||
ExitsCorrectly("pledge", t)
|
||||
}
|
7
vendor/src/golang.org/x/sys/unix/syscall.go
vendored
7
vendor/src/golang.org/x/sys/unix/syscall.go
vendored
|
@ -21,8 +21,6 @@
|
|||
// holds a value of type syscall.Errno.
|
||||
package unix // import "golang.org/x/sys/unix"
|
||||
|
||||
import "unsafe"
|
||||
|
||||
// ByteSliceFromString returns a NUL-terminated slice of bytes
|
||||
// containing the text of s. If s contains a NUL byte at any
|
||||
// location, it returns (nil, EINVAL).
|
||||
|
@ -69,8 +67,3 @@ func (tv *Timeval) Nano() int64 {
|
|||
}
|
||||
|
||||
func TimevalToNsec(tv Timeval) int64 { return int64(tv.Sec)*1e9 + int64(tv.Usec)*1e3 }
|
||||
|
||||
// use is a no-op, but the compiler cannot see that it is.
|
||||
// Calling use(p) ensures that p is kept live until that point.
|
||||
//go:noescape
|
||||
func use(p unsafe.Pointer)
|
||||
|
|
18
vendor/src/golang.org/x/sys/unix/syscall_bsd.go
vendored
18
vendor/src/golang.org/x/sys/unix/syscall_bsd.go
vendored
|
@ -470,25 +470,11 @@ func Sysctl(name string) (string, error) {
|
|||
}
|
||||
|
||||
func SysctlArgs(name string, args ...int) (string, error) {
|
||||
mib, err := sysctlmib(name, args...)
|
||||
buf, err := SysctlRaw(name, args...)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
// Find size.
|
||||
n := uintptr(0)
|
||||
if err := sysctl(mib, nil, &n, nil, 0); err != nil {
|
||||
return "", err
|
||||
}
|
||||
if n == 0 {
|
||||
return "", nil
|
||||
}
|
||||
|
||||
// Read into buffer of that size.
|
||||
buf := make([]byte, n)
|
||||
if err := sysctl(mib, &buf[0], &n, nil, 0); err != nil {
|
||||
return "", err
|
||||
}
|
||||
n := len(buf)
|
||||
|
||||
// Throw away terminating NUL.
|
||||
if n > 0 && buf[n-1] == '\x00' {
|
||||
|
|
|
@ -76,32 +76,16 @@ func nametomib(name string) (mib []_C_int, err error) {
|
|||
return buf[0 : n/siz], nil
|
||||
}
|
||||
|
||||
// ParseDirent parses up to max directory entries in buf,
|
||||
// appending the names to names. It returns the number
|
||||
// bytes consumed from buf, the number of entries added
|
||||
// to names, and the new names slice.
|
||||
func ParseDirent(buf []byte, max int, names []string) (consumed int, count int, newnames []string) {
|
||||
origlen := len(buf)
|
||||
for max != 0 && len(buf) > 0 {
|
||||
dirent := (*Dirent)(unsafe.Pointer(&buf[0]))
|
||||
if dirent.Reclen == 0 {
|
||||
buf = nil
|
||||
break
|
||||
}
|
||||
buf = buf[dirent.Reclen:]
|
||||
if dirent.Ino == 0 { // File absent in directory.
|
||||
continue
|
||||
}
|
||||
bytes := (*[10000]byte)(unsafe.Pointer(&dirent.Name[0]))
|
||||
var name = string(bytes[0:dirent.Namlen])
|
||||
if name == "." || name == ".." { // Useless names
|
||||
continue
|
||||
}
|
||||
max--
|
||||
count++
|
||||
names = append(names, name)
|
||||
}
|
||||
return origlen - len(buf), count, names
|
||||
func direntIno(buf []byte) (uint64, bool) {
|
||||
return readInt(buf, unsafe.Offsetof(Dirent{}.Ino), unsafe.Sizeof(Dirent{}.Ino))
|
||||
}
|
||||
|
||||
func direntReclen(buf []byte) (uint64, bool) {
|
||||
return readInt(buf, unsafe.Offsetof(Dirent{}.Reclen), unsafe.Sizeof(Dirent{}.Reclen))
|
||||
}
|
||||
|
||||
func direntNamlen(buf []byte) (uint64, bool) {
|
||||
return readInt(buf, unsafe.Offsetof(Dirent{}.Namlen), unsafe.Sizeof(Dirent{}.Namlen))
|
||||
}
|
||||
|
||||
//sys ptrace(request int, pid int, addr uintptr, data uintptr) (err error)
|
||||
|
@ -144,7 +128,6 @@ func getAttrList(path string, attrList attrList, attrBuf []byte, options uint) (
|
|||
uintptr(options),
|
||||
0,
|
||||
)
|
||||
use(unsafe.Pointer(_p0))
|
||||
if e1 != 0 {
|
||||
return nil, e1
|
||||
}
|
||||
|
@ -197,7 +180,6 @@ func Getfsstat(buf []Statfs_t, flags int) (n int, err error) {
|
|||
bufsize = unsafe.Sizeof(Statfs_t{}) * uintptr(len(buf))
|
||||
}
|
||||
r0, _, e1 := Syscall(SYS_GETFSSTAT64, uintptr(_p0), bufsize, uintptr(flags))
|
||||
use(unsafe.Pointer(_p0))
|
||||
n = int(r0)
|
||||
if e1 != 0 {
|
||||
err = e1
|
||||
|
|
|
@ -56,29 +56,20 @@ func nametomib(name string) (mib []_C_int, err error) {
|
|||
return buf[0 : n/siz], nil
|
||||
}
|
||||
|
||||
// ParseDirent parses up to max directory entries in buf,
|
||||
// appending the names to names. It returns the number
|
||||
// bytes consumed from buf, the number of entries added
|
||||
// to names, and the new names slice.
|
||||
func ParseDirent(buf []byte, max int, names []string) (consumed int, count int, newnames []string) {
|
||||
origlen := len(buf)
|
||||
for max != 0 && len(buf) > 0 {
|
||||
dirent := (*Dirent)(unsafe.Pointer(&buf[0]))
|
||||
reclen := int(16+dirent.Namlen+1+7) & ^7
|
||||
buf = buf[reclen:]
|
||||
if dirent.Fileno == 0 { // File absent in directory.
|
||||
continue
|
||||
}
|
||||
bytes := (*[10000]byte)(unsafe.Pointer(&dirent.Name[0]))
|
||||
var name = string(bytes[0:dirent.Namlen])
|
||||
if name == "." || name == ".." { // Useless names
|
||||
continue
|
||||
}
|
||||
max--
|
||||
count++
|
||||
names = append(names, name)
|
||||
func direntIno(buf []byte) (uint64, bool) {
|
||||
return readInt(buf, unsafe.Offsetof(Dirent{}.Ino), unsafe.Sizeof(Dirent{}.Ino))
|
||||
}
|
||||
|
||||
func direntReclen(buf []byte) (uint64, bool) {
|
||||
namlen, ok := direntNamlen(buf)
|
||||
if !ok {
|
||||
return 0, false
|
||||
}
|
||||
return origlen - len(buf), count, names
|
||||
return (16 + namlen + 1 + 7) & ^7, true
|
||||
}
|
||||
|
||||
func direntNamlen(buf []byte) (uint64, bool) {
|
||||
return readInt(buf, unsafe.Offsetof(Dirent{}.Namlen), unsafe.Sizeof(Dirent{}.Namlen))
|
||||
}
|
||||
|
||||
//sysnb pipe() (r int, w int, err error)
|
||||
|
@ -109,7 +100,6 @@ func Getfsstat(buf []Statfs_t, flags int) (n int, err error) {
|
|||
bufsize = unsafe.Sizeof(Statfs_t{}) * uintptr(len(buf))
|
||||
}
|
||||
r0, _, e1 := Syscall(SYS_GETFSSTAT, uintptr(_p0), bufsize, uintptr(flags))
|
||||
use(unsafe.Pointer(_p0))
|
||||
n = int(r0)
|
||||
if e1 != 0 {
|
||||
err = e1
|
||||
|
|
|
@ -54,32 +54,16 @@ func nametomib(name string) (mib []_C_int, err error) {
|
|||
return buf[0 : n/siz], nil
|
||||
}
|
||||
|
||||
// ParseDirent parses up to max directory entries in buf,
|
||||
// appending the names to names. It returns the number
|
||||
// bytes consumed from buf, the number of entries added
|
||||
// to names, and the new names slice.
|
||||
func ParseDirent(buf []byte, max int, names []string) (consumed int, count int, newnames []string) {
|
||||
origlen := len(buf)
|
||||
for max != 0 && len(buf) > 0 {
|
||||
dirent := (*Dirent)(unsafe.Pointer(&buf[0]))
|
||||
if dirent.Reclen == 0 {
|
||||
buf = nil
|
||||
break
|
||||
}
|
||||
buf = buf[dirent.Reclen:]
|
||||
if dirent.Fileno == 0 { // File absent in directory.
|
||||
continue
|
||||
}
|
||||
bytes := (*[10000]byte)(unsafe.Pointer(&dirent.Name[0]))
|
||||
var name = string(bytes[0:dirent.Namlen])
|
||||
if name == "." || name == ".." { // Useless names
|
||||
continue
|
||||
}
|
||||
max--
|
||||
count++
|
||||
names = append(names, name)
|
||||
}
|
||||
return origlen - len(buf), count, names
|
||||
func direntIno(buf []byte) (uint64, bool) {
|
||||
return readInt(buf, unsafe.Offsetof(Dirent{}.Fileno), unsafe.Sizeof(Dirent{}.Fileno))
|
||||
}
|
||||
|
||||
func direntReclen(buf []byte) (uint64, bool) {
|
||||
return readInt(buf, unsafe.Offsetof(Dirent{}.Reclen), unsafe.Sizeof(Dirent{}.Reclen))
|
||||
}
|
||||
|
||||
func direntNamlen(buf []byte) (uint64, bool) {
|
||||
return readInt(buf, unsafe.Offsetof(Dirent{}.Namlen), unsafe.Sizeof(Dirent{}.Namlen))
|
||||
}
|
||||
|
||||
//sysnb pipe() (r int, w int, err error)
|
||||
|
@ -129,7 +113,6 @@ func Getfsstat(buf []Statfs_t, flags int) (n int, err error) {
|
|||
bufsize = unsafe.Sizeof(Statfs_t{}) * uintptr(len(buf))
|
||||
}
|
||||
r0, _, e1 := Syscall(SYS_GETFSSTAT, uintptr(_p0), bufsize, uintptr(flags))
|
||||
use(unsafe.Pointer(_p0))
|
||||
n = int(r0)
|
||||
if e1 != 0 {
|
||||
err = e1
|
||||
|
|
|
@ -7,18 +7,14 @@
|
|||
package unix_test
|
||||
|
||||
import (
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
func TestSysctUint64(t *testing.T) {
|
||||
_, err := unix.SysctlUint64("vm.max_kernel_address")
|
||||
func TestSysctlUint64(t *testing.T) {
|
||||
_, err := unix.SysctlUint64("security.mac.labeled")
|
||||
if err != nil {
|
||||
if os.Getenv("GO_BUILDER_NAME") == "freebsd-386-gce101" {
|
||||
t.Skipf("Ignoring known failing test (golang.org/issue/15186). Failed with: %v", err)
|
||||
}
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
|
266
vendor/src/golang.org/x/sys/unix/syscall_linux.go
vendored
266
vendor/src/golang.org/x/sys/unix/syscall_linux.go
vendored
|
@ -69,10 +69,10 @@ func Ppoll(fds []PollFd, timeout *Timespec, sigmask *Sigset_t) (n int, err error
|
|||
return ppoll(&fds[0], len(fds), timeout, sigmask)
|
||||
}
|
||||
|
||||
//sys readlinkat(dirfd int, path string, buf []byte) (n int, err error)
|
||||
//sys Readlinkat(dirfd int, path string, buf []byte) (n int, err error)
|
||||
|
||||
func Readlink(path string, buf []byte) (n int, err error) {
|
||||
return readlinkat(AT_FDCWD, path, buf)
|
||||
return Readlinkat(AT_FDCWD, path, buf)
|
||||
}
|
||||
|
||||
func Rename(oldpath string, newpath string) (err error) {
|
||||
|
@ -80,24 +80,20 @@ func Rename(oldpath string, newpath string) (err error) {
|
|||
}
|
||||
|
||||
func Rmdir(path string) error {
|
||||
return unlinkat(AT_FDCWD, path, AT_REMOVEDIR)
|
||||
return Unlinkat(AT_FDCWD, path, AT_REMOVEDIR)
|
||||
}
|
||||
|
||||
//sys symlinkat(oldpath string, newdirfd int, newpath string) (err error)
|
||||
//sys Symlinkat(oldpath string, newdirfd int, newpath string) (err error)
|
||||
|
||||
func Symlink(oldpath string, newpath string) (err error) {
|
||||
return symlinkat(oldpath, AT_FDCWD, newpath)
|
||||
return Symlinkat(oldpath, AT_FDCWD, newpath)
|
||||
}
|
||||
|
||||
func Unlink(path string) error {
|
||||
return unlinkat(AT_FDCWD, path, 0)
|
||||
return Unlinkat(AT_FDCWD, path, 0)
|
||||
}
|
||||
|
||||
//sys unlinkat(dirfd int, path string, flags int) (err error)
|
||||
|
||||
func Unlinkat(dirfd int, path string, flags int) error {
|
||||
return unlinkat(dirfd, path, flags)
|
||||
}
|
||||
//sys Unlinkat(dirfd int, path string, flags int) (err error)
|
||||
|
||||
//sys utimes(path string, times *[2]Timeval) (err error)
|
||||
|
||||
|
@ -143,8 +139,7 @@ func UtimesNano(path string, ts []Timespec) error {
|
|||
// in 2.6.22, Released, 8 July 2007) then fall back to utimes
|
||||
var tv [2]Timeval
|
||||
for i := 0; i < 2; i++ {
|
||||
tv[i].Sec = ts[i].Sec
|
||||
tv[i].Usec = ts[i].Nsec / 1000
|
||||
tv[i] = NsecToTimeval(TimespecToNsec(ts[i]))
|
||||
}
|
||||
return utimes(path, (*[2]Timeval)(unsafe.Pointer(&tv[0])))
|
||||
}
|
||||
|
@ -416,6 +411,168 @@ func (sa *SockaddrHCI) sockaddr() (unsafe.Pointer, _Socklen, error) {
|
|||
return unsafe.Pointer(&sa.raw), SizeofSockaddrHCI, nil
|
||||
}
|
||||
|
||||
// SockaddrCAN implements the Sockaddr interface for AF_CAN type sockets.
|
||||
// The RxID and TxID fields are used for transport protocol addressing in
|
||||
// (CAN_TP16, CAN_TP20, CAN_MCNET, and CAN_ISOTP), they can be left with
|
||||
// zero values for CAN_RAW and CAN_BCM sockets as they have no meaning.
|
||||
//
|
||||
// The SockaddrCAN struct must be bound to the socket file descriptor
|
||||
// using Bind before the CAN socket can be used.
|
||||
//
|
||||
// // Read one raw CAN frame
|
||||
// fd, _ := Socket(AF_CAN, SOCK_RAW, CAN_RAW)
|
||||
// addr := &SockaddrCAN{Ifindex: index}
|
||||
// Bind(fd, addr)
|
||||
// frame := make([]byte, 16)
|
||||
// Read(fd, frame)
|
||||
//
|
||||
// The full SocketCAN documentation can be found in the linux kernel
|
||||
// archives at: https://www.kernel.org/doc/Documentation/networking/can.txt
|
||||
type SockaddrCAN struct {
|
||||
Ifindex int
|
||||
RxID uint32
|
||||
TxID uint32
|
||||
raw RawSockaddrCAN
|
||||
}
|
||||
|
||||
func (sa *SockaddrCAN) sockaddr() (unsafe.Pointer, _Socklen, error) {
|
||||
if sa.Ifindex < 0 || sa.Ifindex > 0x7fffffff {
|
||||
return nil, 0, EINVAL
|
||||
}
|
||||
sa.raw.Family = AF_CAN
|
||||
sa.raw.Ifindex = int32(sa.Ifindex)
|
||||
rx := (*[4]byte)(unsafe.Pointer(&sa.RxID))
|
||||
for i := 0; i < 4; i++ {
|
||||
sa.raw.Addr[i] = rx[i]
|
||||
}
|
||||
tx := (*[4]byte)(unsafe.Pointer(&sa.TxID))
|
||||
for i := 0; i < 4; i++ {
|
||||
sa.raw.Addr[i+4] = tx[i]
|
||||
}
|
||||
return unsafe.Pointer(&sa.raw), SizeofSockaddrCAN, nil
|
||||
}
|
||||
|
||||
// SockaddrALG implements the Sockaddr interface for AF_ALG type sockets.
|
||||
// SockaddrALG enables userspace access to the Linux kernel's cryptography
|
||||
// subsystem. The Type and Name fields specify which type of hash or cipher
|
||||
// should be used with a given socket.
|
||||
//
|
||||
// To create a file descriptor that provides access to a hash or cipher, both
|
||||
// Bind and Accept must be used. Once the setup process is complete, input
|
||||
// data can be written to the socket, processed by the kernel, and then read
|
||||
// back as hash output or ciphertext.
|
||||
//
|
||||
// Here is an example of using an AF_ALG socket with SHA1 hashing.
|
||||
// The initial socket setup process is as follows:
|
||||
//
|
||||
// // Open a socket to perform SHA1 hashing.
|
||||
// fd, _ := unix.Socket(unix.AF_ALG, unix.SOCK_SEQPACKET, 0)
|
||||
// addr := &unix.SockaddrALG{Type: "hash", Name: "sha1"}
|
||||
// unix.Bind(fd, addr)
|
||||
// // Note: unix.Accept does not work at this time; must invoke accept()
|
||||
// // manually using unix.Syscall.
|
||||
// hashfd, _, _ := unix.Syscall(unix.SYS_ACCEPT, uintptr(fd), 0, 0)
|
||||
//
|
||||
// Once a file descriptor has been returned from Accept, it may be used to
|
||||
// perform SHA1 hashing. The descriptor is not safe for concurrent use, but
|
||||
// may be re-used repeatedly with subsequent Write and Read operations.
|
||||
//
|
||||
// When hashing a small byte slice or string, a single Write and Read may
|
||||
// be used:
|
||||
//
|
||||
// // Assume hashfd is already configured using the setup process.
|
||||
// hash := os.NewFile(hashfd, "sha1")
|
||||
// // Hash an input string and read the results. Each Write discards
|
||||
// // previous hash state. Read always reads the current state.
|
||||
// b := make([]byte, 20)
|
||||
// for i := 0; i < 2; i++ {
|
||||
// io.WriteString(hash, "Hello, world.")
|
||||
// hash.Read(b)
|
||||
// fmt.Println(hex.EncodeToString(b))
|
||||
// }
|
||||
// // Output:
|
||||
// // 2ae01472317d1935a84797ec1983ae243fc6aa28
|
||||
// // 2ae01472317d1935a84797ec1983ae243fc6aa28
|
||||
//
|
||||
// For hashing larger byte slices, or byte streams such as those read from
|
||||
// a file or socket, use Sendto with MSG_MORE to instruct the kernel to update
|
||||
// the hash digest instead of creating a new one for a given chunk and finalizing it.
|
||||
//
|
||||
// // Assume hashfd and addr are already configured using the setup process.
|
||||
// hash := os.NewFile(hashfd, "sha1")
|
||||
// // Hash the contents of a file.
|
||||
// f, _ := os.Open("/tmp/linux-4.10-rc7.tar.xz")
|
||||
// b := make([]byte, 4096)
|
||||
// for {
|
||||
// n, err := f.Read(b)
|
||||
// if err == io.EOF {
|
||||
// break
|
||||
// }
|
||||
// unix.Sendto(hashfd, b[:n], unix.MSG_MORE, addr)
|
||||
// }
|
||||
// hash.Read(b)
|
||||
// fmt.Println(hex.EncodeToString(b))
|
||||
// // Output: 85cdcad0c06eef66f805ecce353bec9accbeecc5
|
||||
//
|
||||
// For more information, see: http://www.chronox.de/crypto-API/crypto/userspace-if.html.
|
||||
type SockaddrALG struct {
|
||||
Type string
|
||||
Name string
|
||||
Feature uint32
|
||||
Mask uint32
|
||||
raw RawSockaddrALG
|
||||
}
|
||||
|
||||
func (sa *SockaddrALG) sockaddr() (unsafe.Pointer, _Socklen, error) {
|
||||
// Leave room for NUL byte terminator.
|
||||
if len(sa.Type) > 13 {
|
||||
return nil, 0, EINVAL
|
||||
}
|
||||
if len(sa.Name) > 63 {
|
||||
return nil, 0, EINVAL
|
||||
}
|
||||
|
||||
sa.raw.Family = AF_ALG
|
||||
sa.raw.Feat = sa.Feature
|
||||
sa.raw.Mask = sa.Mask
|
||||
|
||||
typ, err := ByteSliceFromString(sa.Type)
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
name, err := ByteSliceFromString(sa.Name)
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
|
||||
copy(sa.raw.Type[:], typ)
|
||||
copy(sa.raw.Name[:], name)
|
||||
|
||||
return unsafe.Pointer(&sa.raw), SizeofSockaddrALG, nil
|
||||
}
|
||||
|
||||
// SockaddrVM implements the Sockaddr interface for AF_VSOCK type sockets.
|
||||
// SockaddrVM provides access to Linux VM sockets: a mechanism that enables
|
||||
// bidirectional communication between a hypervisor and its guest virtual
|
||||
// machines.
|
||||
type SockaddrVM struct {
|
||||
// CID and Port specify a context ID and port address for a VM socket.
|
||||
// Guests have a unique CID, and hosts may have a well-known CID of:
|
||||
// - VMADDR_CID_HYPERVISOR: refers to the hypervisor process.
|
||||
// - VMADDR_CID_HOST: refers to other processes on the host.
|
||||
CID uint32
|
||||
Port uint32
|
||||
raw RawSockaddrVM
|
||||
}
|
||||
|
||||
func (sa *SockaddrVM) sockaddr() (unsafe.Pointer, _Socklen, error) {
|
||||
sa.raw.Family = AF_VSOCK
|
||||
sa.raw.Port = sa.Port
|
||||
sa.raw.Cid = sa.CID
|
||||
|
||||
return unsafe.Pointer(&sa.raw), SizeofSockaddrVM, nil
|
||||
}
|
||||
|
||||
func anyToSockaddr(rsa *RawSockaddrAny) (Sockaddr, error) {
|
||||
switch rsa.Addr.Family {
|
||||
case AF_NETLINK:
|
||||
|
@ -485,6 +642,14 @@ func anyToSockaddr(rsa *RawSockaddrAny) (Sockaddr, error) {
|
|||
sa.Addr[i] = pp.Addr[i]
|
||||
}
|
||||
return sa, nil
|
||||
|
||||
case AF_VSOCK:
|
||||
pp := (*RawSockaddrVM)(unsafe.Pointer(rsa))
|
||||
sa := &SockaddrVM{
|
||||
CID: pp.Cid,
|
||||
Port: pp.Port,
|
||||
}
|
||||
return sa, nil
|
||||
}
|
||||
return nil, EAFNOSUPPORT
|
||||
}
|
||||
|
@ -579,6 +744,13 @@ func GetsockoptUcred(fd, level, opt int) (*Ucred, error) {
|
|||
return &value, err
|
||||
}
|
||||
|
||||
func GetsockoptTCPInfo(fd, level, opt int) (*TCPInfo, error) {
|
||||
var value TCPInfo
|
||||
vallen := _Socklen(SizeofTCPInfo)
|
||||
err := getsockopt(fd, level, opt, unsafe.Pointer(&value), &vallen)
|
||||
return &value, err
|
||||
}
|
||||
|
||||
func SetsockoptIPMreqn(fd, level, opt int, mreq *IPMreqn) (err error) {
|
||||
return setsockopt(fd, level, opt, unsafe.Pointer(mreq), unsafe.Sizeof(*mreq))
|
||||
}
|
||||
|
@ -716,6 +888,10 @@ func PtracePeekData(pid int, addr uintptr, out []byte) (count int, err error) {
|
|||
return ptracePeek(PTRACE_PEEKDATA, pid, addr, out)
|
||||
}
|
||||
|
||||
func PtracePeekUser(pid int, addr uintptr, out []byte) (count int, err error) {
|
||||
return ptracePeek(PTRACE_PEEKUSR, pid, addr, out)
|
||||
}
|
||||
|
||||
func ptracePoke(pokeReq int, peekReq int, pid int, addr uintptr, data []byte) (count int, err error) {
|
||||
// As for ptracePeek, we need to align our accesses to deal
|
||||
// with the possibility of straddling an invalid page.
|
||||
|
@ -814,38 +990,24 @@ func Reboot(cmd int) (err error) {
|
|||
return reboot(LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2, cmd, "")
|
||||
}
|
||||
|
||||
func clen(n []byte) int {
|
||||
for i := 0; i < len(n); i++ {
|
||||
if n[i] == 0 {
|
||||
return i
|
||||
}
|
||||
}
|
||||
return len(n)
|
||||
}
|
||||
|
||||
func ReadDirent(fd int, buf []byte) (n int, err error) {
|
||||
return Getdents(fd, buf)
|
||||
}
|
||||
|
||||
func ParseDirent(buf []byte, max int, names []string) (consumed int, count int, newnames []string) {
|
||||
origlen := len(buf)
|
||||
count = 0
|
||||
for max != 0 && len(buf) > 0 {
|
||||
dirent := (*Dirent)(unsafe.Pointer(&buf[0]))
|
||||
buf = buf[dirent.Reclen:]
|
||||
if dirent.Ino == 0 { // File absent in directory.
|
||||
continue
|
||||
}
|
||||
bytes := (*[10000]byte)(unsafe.Pointer(&dirent.Name[0]))
|
||||
var name = string(bytes[0:clen(bytes[:])])
|
||||
if name == "." || name == ".." { // Useless names
|
||||
continue
|
||||
}
|
||||
max--
|
||||
count++
|
||||
names = append(names, name)
|
||||
func direntIno(buf []byte) (uint64, bool) {
|
||||
return readInt(buf, unsafe.Offsetof(Dirent{}.Ino), unsafe.Sizeof(Dirent{}.Ino))
|
||||
}
|
||||
|
||||
func direntReclen(buf []byte) (uint64, bool) {
|
||||
return readInt(buf, unsafe.Offsetof(Dirent{}.Reclen), unsafe.Sizeof(Dirent{}.Reclen))
|
||||
}
|
||||
|
||||
func direntNamlen(buf []byte) (uint64, bool) {
|
||||
reclen, ok := direntReclen(buf)
|
||||
if !ok {
|
||||
return 0, false
|
||||
}
|
||||
return origlen - len(buf), count, names
|
||||
return reclen - uint64(unsafe.Offsetof(Dirent{}.Name)), true
|
||||
}
|
||||
|
||||
//sys mount(source string, target string, fstype string, flags uintptr, data *byte) (err error)
|
||||
|
@ -903,7 +1065,9 @@ func Getpgrp() (pid int) {
|
|||
//sysnb Getpid() (pid int)
|
||||
//sysnb Getppid() (ppid int)
|
||||
//sys Getpriority(which int, who int) (prio int, err error)
|
||||
//sys Getrandom(buf []byte, flags int) (n int, err error)
|
||||
//sysnb Getrusage(who int, rusage *Rusage) (err error)
|
||||
//sysnb Getsid(pid int) (sid int, err error)
|
||||
//sysnb Gettid() (tid int)
|
||||
//sys Getxattr(path string, attr string, dest []byte) (sz int, err error)
|
||||
//sys InotifyAddWatch(fd int, pathname string, mask uint32) (watchdesc int, err error)
|
||||
|
@ -916,7 +1080,7 @@ func Getpgrp() (pid int) {
|
|||
//sys Mknodat(dirfd int, path string, mode uint32, dev int) (err error)
|
||||
//sys Nanosleep(time *Timespec, leftover *Timespec) (err error)
|
||||
//sys PivotRoot(newroot string, putold string) (err error) = SYS_PIVOT_ROOT
|
||||
//sysnb prlimit(pid int, resource int, old *Rlimit, newlimit *Rlimit) (err error) = SYS_PRLIMIT64
|
||||
//sysnb prlimit(pid int, resource int, newlimit *Rlimit, old *Rlimit) (err error) = SYS_PRLIMIT64
|
||||
//sys Prctl(option int, arg2 uintptr, arg3 uintptr, arg4 uintptr, arg5 uintptr) (err error)
|
||||
//sys read(fd int, p []byte) (n int, err error)
|
||||
//sys Removexattr(path string, attr string) (err error)
|
||||
|
@ -982,6 +1146,25 @@ func Munmap(b []byte) (err error) {
|
|||
//sys Mlockall(flags int) (err error)
|
||||
//sys Munlockall() (err error)
|
||||
|
||||
// Vmsplice splices user pages from a slice of Iovecs into a pipe specified by fd,
|
||||
// using the specified flags.
|
||||
func Vmsplice(fd int, iovs []Iovec, flags int) (int, error) {
|
||||
n, _, errno := Syscall6(
|
||||
SYS_VMSPLICE,
|
||||
uintptr(fd),
|
||||
uintptr(unsafe.Pointer(&iovs[0])),
|
||||
uintptr(len(iovs)),
|
||||
uintptr(flags),
|
||||
0,
|
||||
0,
|
||||
)
|
||||
if errno != 0 {
|
||||
return 0, syscall.Errno(errno)
|
||||
}
|
||||
|
||||
return int(n), nil
|
||||
}
|
||||
|
||||
/*
|
||||
* Unimplemented
|
||||
*/
|
||||
|
@ -1109,7 +1292,6 @@ func Munmap(b []byte) (err error) {
|
|||
// Utimensat
|
||||
// Vfork
|
||||
// Vhangup
|
||||
// Vmsplice
|
||||
// Vserver
|
||||
// Waitid
|
||||
// _Sysctl
|
||||
|
|
|
@ -6,8 +6,6 @@
|
|||
|
||||
package unix
|
||||
|
||||
import "syscall"
|
||||
|
||||
//sys Dup2(oldfd int, newfd int) (err error)
|
||||
//sys EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error)
|
||||
//sys Fadvise(fd int, offset int64, length int64, advice int) (err error) = SYS_FADVISE64
|
||||
|
@ -63,9 +61,6 @@ import "syscall"
|
|||
//sys sendmsg(s int, msg *Msghdr, flags int) (n int, err error)
|
||||
//sys mmap(addr uintptr, length uintptr, prot int, flags int, fd int, offset int64) (xaddr uintptr, err error)
|
||||
|
||||
//go:noescape
|
||||
func gettimeofday(tv *Timeval) (err syscall.Errno)
|
||||
|
||||
func Gettimeofday(tv *Timeval) (err error) {
|
||||
errno := gettimeofday(tv)
|
||||
if errno != 0 {
|
||||
|
|
13
vendor/src/golang.org/x/sys/unix/syscall_linux_amd64_gc.go
vendored
Normal file
13
vendor/src/golang.org/x/sys/unix/syscall_linux_amd64_gc.go
vendored
Normal file
|
@ -0,0 +1,13 @@
|
|||
// 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.
|
||||
|
||||
// +build amd64,linux
|
||||
// +build !gccgo
|
||||
|
||||
package unix
|
||||
|
||||
import "syscall"
|
||||
|
||||
//go:noescape
|
||||
func gettimeofday(tv *Timeval) (err syscall.Errno)
|
|
@ -6,8 +6,6 @@
|
|||
|
||||
package unix
|
||||
|
||||
const _SYS_dup = SYS_DUP3
|
||||
|
||||
//sys EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error) = SYS_EPOLL_PWAIT
|
||||
//sys Fchown(fd int, uid int, gid int) (err error)
|
||||
//sys Fstat(fd int, stat *Stat_t) (err error)
|
||||
|
|
|
@ -7,13 +7,6 @@
|
|||
|
||||
package unix
|
||||
|
||||
// Linux introduced getdents64 syscall for N64 ABI only in 3.10
|
||||
// (May 21 2013, rev dec33abaafc89bcbd78f85fad0513170415a26d5),
|
||||
// to support older kernels, we have to use getdents for mips64.
|
||||
// Also note that struct dirent is different for these two.
|
||||
// Lookup linux_dirent{,64} in kernel source code for details.
|
||||
const _SYS_getdents = SYS_GETDENTS
|
||||
|
||||
//sys EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error)
|
||||
//sys Fchown(fd int, uid int, gid int) (err error)
|
||||
//sys Fstatfs(fd int, buf *Statfs_t) (err error)
|
||||
|
|
239
vendor/src/golang.org/x/sys/unix/syscall_linux_mipsx.go
vendored
Normal file
239
vendor/src/golang.org/x/sys/unix/syscall_linux_mipsx.go
vendored
Normal file
|
@ -0,0 +1,239 @@
|
|||
// 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.
|
||||
|
||||
// +build linux
|
||||
// +build mips mipsle
|
||||
|
||||
package unix
|
||||
|
||||
import (
|
||||
"syscall"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
func Syscall9(trap, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2 uintptr, err syscall.Errno)
|
||||
|
||||
//sys Dup2(oldfd int, newfd int) (err error)
|
||||
//sys Fchown(fd int, uid int, gid int) (err error)
|
||||
//sys Ftruncate(fd int, length int64) (err error) = SYS_FTRUNCATE64
|
||||
//sysnb Getegid() (egid int)
|
||||
//sysnb Geteuid() (euid int)
|
||||
//sysnb Getgid() (gid int)
|
||||
//sysnb Getuid() (uid int)
|
||||
//sys Lchown(path string, uid int, gid int) (err error)
|
||||
//sys Listen(s int, n int) (err error)
|
||||
//sys Pread(fd int, p []byte, offset int64) (n int, err error) = SYS_PREAD64
|
||||
//sys Pwrite(fd int, p []byte, offset int64) (n int, err error) = SYS_PWRITE64
|
||||
//sys Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, err error) = SYS__NEWSELECT
|
||||
//sys sendfile(outfd int, infd int, offset *int64, count int) (written int, err error) = SYS_SENDFILE64
|
||||
//sys Setfsgid(gid int) (err error)
|
||||
//sys Setfsuid(uid int) (err error)
|
||||
//sysnb Setregid(rgid int, egid int) (err error)
|
||||
//sysnb Setresgid(rgid int, egid int, sgid int) (err error)
|
||||
//sysnb Setresuid(ruid int, euid int, suid int) (err error)
|
||||
|
||||
//sysnb Setreuid(ruid int, euid int) (err error)
|
||||
//sys Shutdown(fd int, how int) (err error)
|
||||
//sys Splice(rfd int, roff *int64, wfd int, woff *int64, len int, flags int) (n int64, err error)
|
||||
|
||||
//sys SyncFileRange(fd int, off int64, n int64, flags int) (err error)
|
||||
//sys Truncate(path string, length int64) (err error) = SYS_TRUNCATE64
|
||||
//sys accept(s int, rsa *RawSockaddrAny, addrlen *_Socklen) (fd int, err error)
|
||||
//sys accept4(s int, rsa *RawSockaddrAny, addrlen *_Socklen, flags int) (fd int, err error)
|
||||
//sys bind(s int, addr unsafe.Pointer, addrlen _Socklen) (err error)
|
||||
//sys connect(s int, addr unsafe.Pointer, addrlen _Socklen) (err error)
|
||||
//sysnb getgroups(n int, list *_Gid_t) (nn int, err error)
|
||||
//sysnb setgroups(n int, list *_Gid_t) (err error)
|
||||
//sys getsockopt(s int, level int, name int, val unsafe.Pointer, vallen *_Socklen) (err error)
|
||||
//sys setsockopt(s int, level int, name int, val unsafe.Pointer, vallen uintptr) (err error)
|
||||
//sysnb socket(domain int, typ int, proto int) (fd int, err error)
|
||||
//sysnb socketpair(domain int, typ int, proto int, fd *[2]int32) (err error)
|
||||
//sysnb getpeername(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (err error)
|
||||
//sysnb getsockname(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (err error)
|
||||
//sys recvfrom(fd int, p []byte, flags int, from *RawSockaddrAny, fromlen *_Socklen) (n int, err error)
|
||||
//sys sendto(s int, buf []byte, flags int, to unsafe.Pointer, addrlen _Socklen) (err error)
|
||||
//sys recvmsg(s int, msg *Msghdr, flags int) (n int, err error)
|
||||
//sys sendmsg(s int, msg *Msghdr, flags int) (n int, err error)
|
||||
|
||||
//sysnb InotifyInit() (fd int, err error)
|
||||
//sys Ioperm(from int, num int, on int) (err error)
|
||||
//sys Iopl(level int) (err error)
|
||||
|
||||
//sysnb Gettimeofday(tv *Timeval) (err error)
|
||||
//sysnb Time(t *Time_t) (tt Time_t, err error)
|
||||
|
||||
//sys Lstat(path string, stat *Stat_t) (err error) = SYS_LSTAT64
|
||||
//sys Fstat(fd int, stat *Stat_t) (err error) = SYS_FSTAT64
|
||||
//sys Stat(path string, stat *Stat_t) (err error) = SYS_STAT64
|
||||
|
||||
//sys Utime(path string, buf *Utimbuf) (err error)
|
||||
//sys EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error)
|
||||
//sys Pause() (err error)
|
||||
|
||||
func Fstatfs(fd int, buf *Statfs_t) (err error) {
|
||||
_, _, e := Syscall(SYS_FSTATFS64, uintptr(fd), unsafe.Sizeof(*buf), uintptr(unsafe.Pointer(buf)))
|
||||
if e != 0 {
|
||||
err = errnoErr(e)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func Statfs(path string, buf *Statfs_t) (err error) {
|
||||
p, err := BytePtrFromString(path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, _, e := Syscall(SYS_STATFS64, uintptr(unsafe.Pointer(p)), unsafe.Sizeof(*buf), uintptr(unsafe.Pointer(buf)))
|
||||
if e != 0 {
|
||||
err = errnoErr(e)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func Seek(fd int, offset int64, whence int) (off int64, err error) {
|
||||
_, _, e := Syscall6(SYS__LLSEEK, uintptr(fd), uintptr(offset>>32), uintptr(offset), uintptr(unsafe.Pointer(&off)), uintptr(whence), 0)
|
||||
if e != 0 {
|
||||
err = errnoErr(e)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func TimespecToNsec(ts Timespec) int64 { return int64(ts.Sec)*1e9 + int64(ts.Nsec) }
|
||||
|
||||
func NsecToTimespec(nsec int64) (ts Timespec) {
|
||||
ts.Sec = int32(nsec / 1e9)
|
||||
ts.Nsec = int32(nsec % 1e9)
|
||||
return
|
||||
}
|
||||
|
||||
func NsecToTimeval(nsec int64) (tv Timeval) {
|
||||
nsec += 999 // round up to microsecond
|
||||
tv.Sec = int32(nsec / 1e9)
|
||||
tv.Usec = int32(nsec % 1e9 / 1e3)
|
||||
return
|
||||
}
|
||||
|
||||
//sysnb pipe2(p *[2]_C_int, flags int) (err error)
|
||||
|
||||
func Pipe2(p []int, flags int) (err error) {
|
||||
if len(p) != 2 {
|
||||
return EINVAL
|
||||
}
|
||||
var pp [2]_C_int
|
||||
err = pipe2(&pp, flags)
|
||||
p[0] = int(pp[0])
|
||||
p[1] = int(pp[1])
|
||||
return
|
||||
}
|
||||
|
||||
func Pipe(p []int) (err error) {
|
||||
if len(p) != 2 {
|
||||
return EINVAL
|
||||
}
|
||||
var pp [2]_C_int
|
||||
err = pipe2(&pp, 0)
|
||||
p[0] = int(pp[0])
|
||||
p[1] = int(pp[1])
|
||||
return
|
||||
}
|
||||
|
||||
//sys mmap2(addr uintptr, length uintptr, prot int, flags int, fd int, pageOffset uintptr) (xaddr uintptr, err error)
|
||||
|
||||
func mmap(addr uintptr, length uintptr, prot int, flags int, fd int, offset int64) (xaddr uintptr, err error) {
|
||||
page := uintptr(offset / 4096)
|
||||
if offset != int64(page)*4096 {
|
||||
return 0, EINVAL
|
||||
}
|
||||
return mmap2(addr, length, prot, flags, fd, page)
|
||||
}
|
||||
|
||||
const rlimInf32 = ^uint32(0)
|
||||
const rlimInf64 = ^uint64(0)
|
||||
|
||||
type rlimit32 struct {
|
||||
Cur uint32
|
||||
Max uint32
|
||||
}
|
||||
|
||||
//sysnb getrlimit(resource int, rlim *rlimit32) (err error) = SYS_GETRLIMIT
|
||||
|
||||
func Getrlimit(resource int, rlim *Rlimit) (err error) {
|
||||
err = prlimit(0, resource, nil, rlim)
|
||||
if err != ENOSYS {
|
||||
return err
|
||||
}
|
||||
|
||||
rl := rlimit32{}
|
||||
err = getrlimit(resource, &rl)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if rl.Cur == rlimInf32 {
|
||||
rlim.Cur = rlimInf64
|
||||
} else {
|
||||
rlim.Cur = uint64(rl.Cur)
|
||||
}
|
||||
|
||||
if rl.Max == rlimInf32 {
|
||||
rlim.Max = rlimInf64
|
||||
} else {
|
||||
rlim.Max = uint64(rl.Max)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
//sysnb setrlimit(resource int, rlim *rlimit32) (err error) = SYS_SETRLIMIT
|
||||
|
||||
func Setrlimit(resource int, rlim *Rlimit) (err error) {
|
||||
err = prlimit(0, resource, rlim, nil)
|
||||
if err != ENOSYS {
|
||||
return err
|
||||
}
|
||||
|
||||
rl := rlimit32{}
|
||||
if rlim.Cur == rlimInf64 {
|
||||
rl.Cur = rlimInf32
|
||||
} else if rlim.Cur < uint64(rlimInf32) {
|
||||
rl.Cur = uint32(rlim.Cur)
|
||||
} else {
|
||||
return EINVAL
|
||||
}
|
||||
if rlim.Max == rlimInf64 {
|
||||
rl.Max = rlimInf32
|
||||
} else if rlim.Max < uint64(rlimInf32) {
|
||||
rl.Max = uint32(rlim.Max)
|
||||
} else {
|
||||
return EINVAL
|
||||
}
|
||||
|
||||
return setrlimit(resource, &rl)
|
||||
}
|
||||
|
||||
func (r *PtraceRegs) PC() uint64 { return uint64(r.Regs[64]) }
|
||||
|
||||
func (r *PtraceRegs) SetPC(pc uint64) { r.Regs[64] = uint32(pc) }
|
||||
|
||||
func (iov *Iovec) SetLen(length int) {
|
||||
iov.Len = uint32(length)
|
||||
}
|
||||
|
||||
func (msghdr *Msghdr) SetControllen(length int) {
|
||||
msghdr.Controllen = uint32(length)
|
||||
}
|
||||
|
||||
func (cmsg *Cmsghdr) SetLen(length int) {
|
||||
cmsg.Len = uint32(length)
|
||||
}
|
||||
|
||||
//sys poll(fds *PollFd, nfds int, timeout int) (n int, err error)
|
||||
|
||||
func Poll(fds []PollFd, timeout int) (n int, err error) {
|
||||
if len(fds) == 0 {
|
||||
return poll(nil, 0, timeout)
|
||||
}
|
||||
return poll(&fds[0], len(fds), timeout)
|
||||
}
|
||||
|
||||
func Getpagesize() int { return 4096 }
|
|
@ -132,7 +132,6 @@ func (cmsg *Cmsghdr) SetLen(length int) {
|
|||
func mmap(addr uintptr, length uintptr, prot int, flags int, fd int, offset int64) (xaddr uintptr, err error) {
|
||||
mmap_args := [6]uintptr{addr, length, uintptr(prot), uintptr(flags), uintptr(fd), uintptr(offset)}
|
||||
r0, _, e1 := Syscall(SYS_MMAP, uintptr(unsafe.Pointer(&mmap_args[0])), 0, 0)
|
||||
use(unsafe.Pointer(&mmap_args[0]))
|
||||
xaddr = uintptr(r0)
|
||||
if e1 != 0 {
|
||||
err = errnoErr(e1)
|
||||
|
|
169
vendor/src/golang.org/x/sys/unix/syscall_linux_sparc64.go
vendored
Normal file
169
vendor/src/golang.org/x/sys/unix/syscall_linux_sparc64.go
vendored
Normal file
|
@ -0,0 +1,169 @@
|
|||
// Copyright 2009 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.
|
||||
|
||||
// +build sparc64,linux
|
||||
|
||||
package unix
|
||||
|
||||
import (
|
||||
"sync/atomic"
|
||||
"syscall"
|
||||
)
|
||||
|
||||
//sys EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error)
|
||||
//sys Dup2(oldfd int, newfd int) (err error)
|
||||
//sys Fchown(fd int, uid int, gid int) (err error)
|
||||
//sys Fstat(fd int, stat *Stat_t) (err error)
|
||||
//sys Fstatfs(fd int, buf *Statfs_t) (err error)
|
||||
//sys Ftruncate(fd int, length int64) (err error)
|
||||
//sysnb Getegid() (egid int)
|
||||
//sysnb Geteuid() (euid int)
|
||||
//sysnb Getgid() (gid int)
|
||||
//sysnb Getrlimit(resource int, rlim *Rlimit) (err error)
|
||||
//sysnb Getuid() (uid int)
|
||||
//sysnb InotifyInit() (fd int, err error)
|
||||
//sys Lchown(path string, uid int, gid int) (err error)
|
||||
//sys Listen(s int, n int) (err error)
|
||||
//sys Lstat(path string, stat *Stat_t) (err error)
|
||||
//sys Pause() (err error)
|
||||
//sys Pread(fd int, p []byte, offset int64) (n int, err error) = SYS_PREAD64
|
||||
//sys Pwrite(fd int, p []byte, offset int64) (n int, err error) = SYS_PWRITE64
|
||||
//sys Seek(fd int, offset int64, whence int) (off int64, err error) = SYS_LSEEK
|
||||
//sys Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, err error)
|
||||
//sys sendfile(outfd int, infd int, offset *int64, count int) (written int, err error)
|
||||
//sys Setfsgid(gid int) (err error)
|
||||
//sys Setfsuid(uid int) (err error)
|
||||
//sysnb Setregid(rgid int, egid int) (err error)
|
||||
//sysnb Setresgid(rgid int, egid int, sgid int) (err error)
|
||||
//sysnb Setresuid(ruid int, euid int, suid int) (err error)
|
||||
//sysnb Setrlimit(resource int, rlim *Rlimit) (err error)
|
||||
//sysnb Setreuid(ruid int, euid int) (err error)
|
||||
//sys Shutdown(fd int, how int) (err error)
|
||||
//sys Splice(rfd int, roff *int64, wfd int, woff *int64, len int, flags int) (n int64, err error)
|
||||
//sys Stat(path string, stat *Stat_t) (err error)
|
||||
//sys Statfs(path string, buf *Statfs_t) (err error)
|
||||
//sys SyncFileRange(fd int, off int64, n int64, flags int) (err error)
|
||||
//sys Truncate(path string, length int64) (err error)
|
||||
//sys accept(s int, rsa *RawSockaddrAny, addrlen *_Socklen) (fd int, err error)
|
||||
//sys accept4(s int, rsa *RawSockaddrAny, addrlen *_Socklen, flags int) (fd int, err error)
|
||||
//sys bind(s int, addr unsafe.Pointer, addrlen _Socklen) (err error)
|
||||
//sys connect(s int, addr unsafe.Pointer, addrlen _Socklen) (err error)
|
||||
//sysnb getgroups(n int, list *_Gid_t) (nn int, err error)
|
||||
//sysnb setgroups(n int, list *_Gid_t) (err error)
|
||||
//sys getsockopt(s int, level int, name int, val unsafe.Pointer, vallen *_Socklen) (err error)
|
||||
//sys setsockopt(s int, level int, name int, val unsafe.Pointer, vallen uintptr) (err error)
|
||||
//sysnb socket(domain int, typ int, proto int) (fd int, err error)
|
||||
//sysnb socketpair(domain int, typ int, proto int, fd *[2]int32) (err error)
|
||||
//sysnb getpeername(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (err error)
|
||||
//sysnb getsockname(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (err error)
|
||||
//sys recvfrom(fd int, p []byte, flags int, from *RawSockaddrAny, fromlen *_Socklen) (n int, err error)
|
||||
//sys sendto(s int, buf []byte, flags int, to unsafe.Pointer, addrlen _Socklen) (err error)
|
||||
//sys recvmsg(s int, msg *Msghdr, flags int) (n int, err error)
|
||||
//sys sendmsg(s int, msg *Msghdr, flags int) (n int, err error)
|
||||
//sys mmap(addr uintptr, length uintptr, prot int, flags int, fd int, offset int64) (xaddr uintptr, err error)
|
||||
|
||||
func sysconf(name int) (n int64, err syscall.Errno)
|
||||
|
||||
// pageSize caches the value of Getpagesize, since it can't change
|
||||
// once the system is booted.
|
||||
var pageSize int64 // accessed atomically
|
||||
|
||||
func Getpagesize() int {
|
||||
n := atomic.LoadInt64(&pageSize)
|
||||
if n == 0 {
|
||||
n, _ = sysconf(_SC_PAGESIZE)
|
||||
atomic.StoreInt64(&pageSize, n)
|
||||
}
|
||||
return int(n)
|
||||
}
|
||||
|
||||
func Ioperm(from int, num int, on int) (err error) {
|
||||
return ENOSYS
|
||||
}
|
||||
|
||||
func Iopl(level int) (err error) {
|
||||
return ENOSYS
|
||||
}
|
||||
|
||||
//sysnb Gettimeofday(tv *Timeval) (err error)
|
||||
|
||||
func Time(t *Time_t) (tt Time_t, err error) {
|
||||
var tv Timeval
|
||||
err = Gettimeofday(&tv)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
if t != nil {
|
||||
*t = Time_t(tv.Sec)
|
||||
}
|
||||
return Time_t(tv.Sec), nil
|
||||
}
|
||||
|
||||
//sys Utime(path string, buf *Utimbuf) (err error)
|
||||
|
||||
func TimespecToNsec(ts Timespec) int64 { return int64(ts.Sec)*1e9 + int64(ts.Nsec) }
|
||||
|
||||
func NsecToTimespec(nsec int64) (ts Timespec) {
|
||||
ts.Sec = nsec / 1e9
|
||||
ts.Nsec = nsec % 1e9
|
||||
return
|
||||
}
|
||||
|
||||
func NsecToTimeval(nsec int64) (tv Timeval) {
|
||||
nsec += 999 // round up to microsecond
|
||||
tv.Sec = nsec / 1e9
|
||||
tv.Usec = int32(nsec % 1e9 / 1e3)
|
||||
return
|
||||
}
|
||||
|
||||
func (r *PtraceRegs) PC() uint64 { return r.Tpc }
|
||||
|
||||
func (r *PtraceRegs) SetPC(pc uint64) { r.Tpc = pc }
|
||||
|
||||
func (iov *Iovec) SetLen(length int) {
|
||||
iov.Len = uint64(length)
|
||||
}
|
||||
|
||||
func (msghdr *Msghdr) SetControllen(length int) {
|
||||
msghdr.Controllen = uint64(length)
|
||||
}
|
||||
|
||||
func (cmsg *Cmsghdr) SetLen(length int) {
|
||||
cmsg.Len = uint64(length)
|
||||
}
|
||||
|
||||
//sysnb pipe(p *[2]_C_int) (err error)
|
||||
|
||||
func Pipe(p []int) (err error) {
|
||||
if len(p) != 2 {
|
||||
return EINVAL
|
||||
}
|
||||
var pp [2]_C_int
|
||||
err = pipe(&pp)
|
||||
p[0] = int(pp[0])
|
||||
p[1] = int(pp[1])
|
||||
return
|
||||
}
|
||||
|
||||
//sysnb pipe2(p *[2]_C_int, flags int) (err error)
|
||||
|
||||
func Pipe2(p []int, flags int) (err error) {
|
||||
if len(p) != 2 {
|
||||
return EINVAL
|
||||
}
|
||||
var pp [2]_C_int
|
||||
err = pipe2(&pp, flags)
|
||||
p[0] = int(pp[0])
|
||||
p[1] = int(pp[1])
|
||||
return
|
||||
}
|
||||
|
||||
//sys poll(fds *PollFd, nfds int, timeout int) (n int, err error)
|
||||
|
||||
func Poll(fds []PollFd, timeout int) (n int, err error) {
|
||||
if len(fds) == 0 {
|
||||
return poll(nil, 0, timeout)
|
||||
}
|
||||
return poll(&fds[0], len(fds), timeout)
|
||||
}
|
|
@ -93,32 +93,16 @@ func nametomib(name string) (mib []_C_int, err error) {
|
|||
return mib, nil
|
||||
}
|
||||
|
||||
// ParseDirent parses up to max directory entries in buf,
|
||||
// appending the names to names. It returns the number
|
||||
// bytes consumed from buf, the number of entries added
|
||||
// to names, and the new names slice.
|
||||
func ParseDirent(buf []byte, max int, names []string) (consumed int, count int, newnames []string) {
|
||||
origlen := len(buf)
|
||||
for max != 0 && len(buf) > 0 {
|
||||
dirent := (*Dirent)(unsafe.Pointer(&buf[0]))
|
||||
if dirent.Reclen == 0 {
|
||||
buf = nil
|
||||
break
|
||||
}
|
||||
buf = buf[dirent.Reclen:]
|
||||
if dirent.Fileno == 0 { // File absent in directory.
|
||||
continue
|
||||
}
|
||||
bytes := (*[10000]byte)(unsafe.Pointer(&dirent.Name[0]))
|
||||
var name = string(bytes[0:dirent.Namlen])
|
||||
if name == "." || name == ".." { // Useless names
|
||||
continue
|
||||
}
|
||||
max--
|
||||
count++
|
||||
names = append(names, name)
|
||||
}
|
||||
return origlen - len(buf), count, names
|
||||
func direntIno(buf []byte) (uint64, bool) {
|
||||
return readInt(buf, unsafe.Offsetof(Dirent{}.Fileno), unsafe.Sizeof(Dirent{}.Fileno))
|
||||
}
|
||||
|
||||
func direntReclen(buf []byte) (uint64, bool) {
|
||||
return readInt(buf, unsafe.Offsetof(Dirent{}.Reclen), unsafe.Sizeof(Dirent{}.Reclen))
|
||||
}
|
||||
|
||||
func direntNamlen(buf []byte) (uint64, bool) {
|
||||
return readInt(buf, unsafe.Offsetof(Dirent{}.Namlen), unsafe.Sizeof(Dirent{}.Namlen))
|
||||
}
|
||||
|
||||
//sysnb pipe() (fd1 int, fd2 int, err error)
|
||||
|
|
|
@ -53,32 +53,16 @@ func nametomib(name string) (mib []_C_int, err error) {
|
|||
return nil, EINVAL
|
||||
}
|
||||
|
||||
// ParseDirent parses up to max directory entries in buf,
|
||||
// appending the names to names. It returns the number
|
||||
// bytes consumed from buf, the number of entries added
|
||||
// to names, and the new names slice.
|
||||
func ParseDirent(buf []byte, max int, names []string) (consumed int, count int, newnames []string) {
|
||||
origlen := len(buf)
|
||||
for max != 0 && len(buf) > 0 {
|
||||
dirent := (*Dirent)(unsafe.Pointer(&buf[0]))
|
||||
if dirent.Reclen == 0 {
|
||||
buf = nil
|
||||
break
|
||||
}
|
||||
buf = buf[dirent.Reclen:]
|
||||
if dirent.Fileno == 0 { // File absent in directory.
|
||||
continue
|
||||
}
|
||||
bytes := (*[10000]byte)(unsafe.Pointer(&dirent.Name[0]))
|
||||
var name = string(bytes[0:dirent.Namlen])
|
||||
if name == "." || name == ".." { // Useless names
|
||||
continue
|
||||
}
|
||||
max--
|
||||
count++
|
||||
names = append(names, name)
|
||||
}
|
||||
return origlen - len(buf), count, names
|
||||
func direntIno(buf []byte) (uint64, bool) {
|
||||
return readInt(buf, unsafe.Offsetof(Dirent{}.Fileno), unsafe.Sizeof(Dirent{}.Fileno))
|
||||
}
|
||||
|
||||
func direntReclen(buf []byte) (uint64, bool) {
|
||||
return readInt(buf, unsafe.Offsetof(Dirent{}.Reclen), unsafe.Sizeof(Dirent{}.Reclen))
|
||||
}
|
||||
|
||||
func direntNamlen(buf []byte) (uint64, bool) {
|
||||
return readInt(buf, unsafe.Offsetof(Dirent{}.Namlen), unsafe.Sizeof(Dirent{}.Namlen))
|
||||
}
|
||||
|
||||
//sysnb pipe(p *[2]_C_int) (err error)
|
||||
|
@ -111,7 +95,6 @@ func Getfsstat(buf []Statfs_t, flags int) (n int, err error) {
|
|||
bufsize = unsafe.Sizeof(Statfs_t{}) * uintptr(len(buf))
|
||||
}
|
||||
r0, _, e1 := Syscall(SYS_GETFSSTAT, uintptr(_p0), bufsize, uintptr(flags))
|
||||
use(unsafe.Pointer(_p0))
|
||||
n = int(r0)
|
||||
if e1 != 0 {
|
||||
err = e1
|
||||
|
|
|
@ -44,46 +44,36 @@ func clen(n []byte) int {
|
|||
return len(n)
|
||||
}
|
||||
|
||||
// ParseDirent parses up to max directory entries in buf,
|
||||
// appending the names to names. It returns the number
|
||||
// bytes consumed from buf, the number of entries added
|
||||
// to names, and the new names slice.
|
||||
func ParseDirent(buf []byte, max int, names []string) (consumed int, count int, newnames []string) {
|
||||
origlen := len(buf)
|
||||
for max != 0 && len(buf) > 0 {
|
||||
dirent := (*Dirent)(unsafe.Pointer(&buf[0]))
|
||||
if dirent.Reclen == 0 {
|
||||
buf = nil
|
||||
break
|
||||
}
|
||||
buf = buf[dirent.Reclen:]
|
||||
if dirent.Ino == 0 { // File absent in directory.
|
||||
continue
|
||||
}
|
||||
bytes := (*[10000]byte)(unsafe.Pointer(&dirent.Name[0]))
|
||||
var name = string(bytes[0:clen(bytes[:])])
|
||||
if name == "." || name == ".." { // Useless names
|
||||
continue
|
||||
}
|
||||
max--
|
||||
count++
|
||||
names = append(names, name)
|
||||
}
|
||||
return origlen - len(buf), count, names
|
||||
func direntIno(buf []byte) (uint64, bool) {
|
||||
return readInt(buf, unsafe.Offsetof(Dirent{}.Ino), unsafe.Sizeof(Dirent{}.Ino))
|
||||
}
|
||||
|
||||
func pipe() (r uintptr, w uintptr, err uintptr)
|
||||
func direntReclen(buf []byte) (uint64, bool) {
|
||||
return readInt(buf, unsafe.Offsetof(Dirent{}.Reclen), unsafe.Sizeof(Dirent{}.Reclen))
|
||||
}
|
||||
|
||||
func direntNamlen(buf []byte) (uint64, bool) {
|
||||
reclen, ok := direntReclen(buf)
|
||||
if !ok {
|
||||
return 0, false
|
||||
}
|
||||
return reclen - uint64(unsafe.Offsetof(Dirent{}.Name)), true
|
||||
}
|
||||
|
||||
//sysnb pipe(p *[2]_C_int) (n int, err error)
|
||||
|
||||
func Pipe(p []int) (err error) {
|
||||
if len(p) != 2 {
|
||||
return EINVAL
|
||||
}
|
||||
r0, w0, e1 := pipe()
|
||||
if e1 != 0 {
|
||||
err = syscall.Errno(e1)
|
||||
var pp [2]_C_int
|
||||
n, err := pipe(&pp)
|
||||
if n != 0 {
|
||||
return err
|
||||
}
|
||||
p[0], p[1] = int(r0), int(w0)
|
||||
return
|
||||
p[0] = int(pp[0])
|
||||
p[1] = int(pp[1])
|
||||
return nil
|
||||
}
|
||||
|
||||
func (sa *SockaddrInet4) sockaddr() (unsafe.Pointer, _Socklen, error) {
|
||||
|
@ -269,24 +259,34 @@ func (w WaitStatus) StopSignal() syscall.Signal {
|
|||
|
||||
func (w WaitStatus) TrapCause() int { return -1 }
|
||||
|
||||
func wait4(pid uintptr, wstatus *WaitStatus, options uintptr, rusage *Rusage) (wpid uintptr, err uintptr)
|
||||
//sys wait4(pid int32, statusp *_C_int, options int, rusage *Rusage) (wpid int32, err error)
|
||||
|
||||
func Wait4(pid int, wstatus *WaitStatus, options int, rusage *Rusage) (wpid int, err error) {
|
||||
r0, e1 := wait4(uintptr(pid), wstatus, uintptr(options), rusage)
|
||||
if e1 != 0 {
|
||||
err = syscall.Errno(e1)
|
||||
func Wait4(pid int, wstatus *WaitStatus, options int, rusage *Rusage) (int, error) {
|
||||
var status _C_int
|
||||
rpid, err := wait4(int32(pid), &status, options, rusage)
|
||||
wpid := int(rpid)
|
||||
if wpid == -1 {
|
||||
return wpid, err
|
||||
}
|
||||
return int(r0), err
|
||||
if wstatus != nil {
|
||||
*wstatus = WaitStatus(status)
|
||||
}
|
||||
return wpid, nil
|
||||
}
|
||||
|
||||
func gethostname() (name string, err uintptr)
|
||||
//sys gethostname(buf []byte) (n int, err error)
|
||||
|
||||
func Gethostname() (name string, err error) {
|
||||
name, e1 := gethostname()
|
||||
if e1 != 0 {
|
||||
err = syscall.Errno(e1)
|
||||
var buf [MaxHostNameLen]byte
|
||||
n, err := gethostname(buf[:])
|
||||
if n != 0 {
|
||||
return "", err
|
||||
}
|
||||
return name, err
|
||||
n = clen(buf[:])
|
||||
if n < 1 {
|
||||
return "", EFAULT
|
||||
}
|
||||
return string(buf[:n]), nil
|
||||
}
|
||||
|
||||
//sys utimes(path string, times *[2]Timeval) (err error)
|
||||
|
|
|
@ -49,11 +49,6 @@ func errnoErr(e syscall.Errno) error {
|
|||
return e
|
||||
}
|
||||
|
||||
func Syscall(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err syscall.Errno)
|
||||
func Syscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err syscall.Errno)
|
||||
func RawSyscall(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err syscall.Errno)
|
||||
func RawSyscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err syscall.Errno)
|
||||
|
||||
// Mmap manager, for use by operating system-specific implementations.
|
||||
|
||||
type mmapper struct {
|
||||
|
|
15
vendor/src/golang.org/x/sys/unix/syscall_unix_gc.go
vendored
Normal file
15
vendor/src/golang.org/x/sys/unix/syscall_unix_gc.go
vendored
Normal file
|
@ -0,0 +1,15 @@
|
|||
// 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.
|
||||
|
||||
// +build darwin dragonfly freebsd linux netbsd openbsd solaris
|
||||
// +build !gccgo
|
||||
|
||||
package unix
|
||||
|
||||
import "syscall"
|
||||
|
||||
func Syscall(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err syscall.Errno)
|
||||
func Syscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err syscall.Errno)
|
||||
func RawSyscall(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err syscall.Errno)
|
||||
func RawSyscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err syscall.Errno)
|
23
vendor/src/golang.org/x/sys/unix/types_linux.go
vendored
23
vendor/src/golang.org/x/sys/unix/types_linux.go
vendored
|
@ -58,6 +58,9 @@ package unix
|
|||
#include <utime.h>
|
||||
#include <bluetooth/bluetooth.h>
|
||||
#include <bluetooth/hci.h>
|
||||
#include <linux/can.h>
|
||||
#include <linux/if_alg.h>
|
||||
#include <linux/vm_sockets.h>
|
||||
|
||||
#ifdef TCSETS2
|
||||
// On systems that have "struct termios2" use this as type Termios.
|
||||
|
@ -105,6 +108,9 @@ typedef struct pt_regs PtraceRegs;
|
|||
typedef struct user PtraceRegs;
|
||||
#elif defined(__s390x__)
|
||||
typedef struct _user_regs_struct PtraceRegs;
|
||||
#elif defined(__sparc__)
|
||||
#include <asm/ptrace.h>
|
||||
typedef struct pt_regs PtraceRegs;
|
||||
#else
|
||||
typedef struct user_regs_struct PtraceRegs;
|
||||
#endif
|
||||
|
@ -122,11 +128,11 @@ typedef struct {} ptracePer;
|
|||
// The real epoll_event is a union, and godefs doesn't handle it well.
|
||||
struct my_epoll_event {
|
||||
uint32_t events;
|
||||
#if defined(__ARM_EABI__) || defined(__aarch64__)
|
||||
#if defined(__ARM_EABI__) || defined(__aarch64__) || (defined(__mips__) && _MIPS_SIM == _ABIO32)
|
||||
// padding is not specified in linux/eventpoll.h but added to conform to the
|
||||
// alignment requirements of EABI
|
||||
int32_t padFd;
|
||||
#elif defined(__powerpc64__) || defined(__s390x__)
|
||||
#elif defined(__powerpc64__) || defined(__s390x__) || defined(__sparc__)
|
||||
int32_t _padFd;
|
||||
#endif
|
||||
int32_t fd;
|
||||
|
@ -215,6 +221,12 @@ type RawSockaddrNetlink C.struct_sockaddr_nl
|
|||
|
||||
type RawSockaddrHCI C.struct_sockaddr_hci
|
||||
|
||||
type RawSockaddrCAN C.struct_sockaddr_can
|
||||
|
||||
type RawSockaddrALG C.struct_sockaddr_alg
|
||||
|
||||
type RawSockaddrVM C.struct_sockaddr_vm
|
||||
|
||||
type RawSockaddr C.struct_sockaddr
|
||||
|
||||
type RawSockaddrAny C.struct_sockaddr_any
|
||||
|
@ -255,6 +267,9 @@ const (
|
|||
SizeofSockaddrLinklayer = C.sizeof_struct_sockaddr_ll
|
||||
SizeofSockaddrNetlink = C.sizeof_struct_sockaddr_nl
|
||||
SizeofSockaddrHCI = C.sizeof_struct_sockaddr_hci
|
||||
SizeofSockaddrCAN = C.sizeof_struct_sockaddr_can
|
||||
SizeofSockaddrALG = C.sizeof_struct_sockaddr_alg
|
||||
SizeofSockaddrVM = C.sizeof_struct_sockaddr_vm
|
||||
SizeofLinger = C.sizeof_struct_linger
|
||||
SizeofIPMreq = C.sizeof_struct_ip_mreq
|
||||
SizeofIPMreqn = C.sizeof_struct_ip_mreqn
|
||||
|
@ -445,6 +460,10 @@ const (
|
|||
|
||||
type Sigset_t C.sigset_t
|
||||
|
||||
// sysconf information
|
||||
|
||||
const _SC_PAGESIZE = C._SC_PAGESIZE
|
||||
|
||||
// Terminal handling
|
||||
|
||||
type Termios C.termios_t
|
||||
|
|
|
@ -22,6 +22,7 @@ package unix
|
|||
#define __USE_LEGACY_PROTOTYPES__ // iovec
|
||||
#include <dirent.h>
|
||||
#include <fcntl.h>
|
||||
#include <netdb.h>
|
||||
#include <limits.h>
|
||||
#include <signal.h>
|
||||
#include <termios.h>
|
||||
|
@ -81,6 +82,7 @@ const (
|
|||
sizeofLong = C.sizeof_long
|
||||
sizeofLongLong = C.sizeof_longlong
|
||||
PathMax = C.PATH_MAX
|
||||
MaxHostNameLen = C.MAXHOSTNAMELEN
|
||||
)
|
||||
|
||||
// Basic types
|
||||
|
|
|
@ -51,8 +51,16 @@ const (
|
|||
AF_TIPC = 0x1e
|
||||
AF_UNIX = 0x1
|
||||
AF_UNSPEC = 0x0
|
||||
AF_VSOCK = 0x28
|
||||
AF_WANPIPE = 0x19
|
||||
AF_X25 = 0x9
|
||||
ALG_OP_DECRYPT = 0x0
|
||||
ALG_OP_ENCRYPT = 0x1
|
||||
ALG_SET_AEAD_ASSOCLEN = 0x4
|
||||
ALG_SET_AEAD_AUTHSIZE = 0x5
|
||||
ALG_SET_IV = 0x2
|
||||
ALG_SET_KEY = 0x1
|
||||
ALG_SET_OP = 0x3
|
||||
ARPHRD_ADAPT = 0x108
|
||||
ARPHRD_APPLETLK = 0x8
|
||||
ARPHRD_ARCNET = 0x7
|
||||
|
@ -145,6 +153,21 @@ const (
|
|||
B75 = 0x2
|
||||
B921600 = 0x1007
|
||||
B9600 = 0xd
|
||||
BLKBSZGET = 0x80041270
|
||||
BLKBSZSET = 0x40041271
|
||||
BLKFLSBUF = 0x1261
|
||||
BLKFRAGET = 0x1265
|
||||
BLKFRASET = 0x1264
|
||||
BLKGETSIZE = 0x1260
|
||||
BLKGETSIZE64 = 0x80041272
|
||||
BLKRAGET = 0x1263
|
||||
BLKRASET = 0x1262
|
||||
BLKROGET = 0x125e
|
||||
BLKROSET = 0x125d
|
||||
BLKRRPART = 0x125f
|
||||
BLKSECTGET = 0x1267
|
||||
BLKSECTSET = 0x1266
|
||||
BLKSSZGET = 0x1268
|
||||
BOTHER = 0x1000
|
||||
BPF_A = 0x10
|
||||
BPF_ABS = 0x20
|
||||
|
@ -190,6 +213,25 @@ const (
|
|||
BS0 = 0x0
|
||||
BS1 = 0x2000
|
||||
BSDLY = 0x2000
|
||||
CAN_BCM = 0x2
|
||||
CAN_EFF_FLAG = 0x80000000
|
||||
CAN_EFF_ID_BITS = 0x1d
|
||||
CAN_EFF_MASK = 0x1fffffff
|
||||
CAN_ERR_FLAG = 0x20000000
|
||||
CAN_ERR_MASK = 0x1fffffff
|
||||
CAN_INV_FILTER = 0x20000000
|
||||
CAN_ISOTP = 0x6
|
||||
CAN_MAX_DLC = 0x8
|
||||
CAN_MAX_DLEN = 0x8
|
||||
CAN_MCNET = 0x5
|
||||
CAN_MTU = 0x10
|
||||
CAN_NPROTO = 0x7
|
||||
CAN_RAW = 0x1
|
||||
CAN_RTR_FLAG = 0x40000000
|
||||
CAN_SFF_ID_BITS = 0xb
|
||||
CAN_SFF_MASK = 0x7ff
|
||||
CAN_TP16 = 0x3
|
||||
CAN_TP20 = 0x4
|
||||
CBAUD = 0x100f
|
||||
CBAUDEX = 0x1000
|
||||
CFLUSH = 0xf
|
||||
|
@ -366,6 +408,12 @@ const (
|
|||
EXTA = 0xe
|
||||
EXTB = 0xf
|
||||
EXTPROC = 0x10000
|
||||
FALLOC_FL_COLLAPSE_RANGE = 0x8
|
||||
FALLOC_FL_INSERT_RANGE = 0x20
|
||||
FALLOC_FL_KEEP_SIZE = 0x1
|
||||
FALLOC_FL_NO_HIDE_STALE = 0x4
|
||||
FALLOC_FL_PUNCH_HOLE = 0x2
|
||||
FALLOC_FL_ZERO_RANGE = 0x10
|
||||
FD_CLOEXEC = 0x1
|
||||
FD_SETSIZE = 0x400
|
||||
FF0 = 0x0
|
||||
|
@ -405,6 +453,8 @@ const (
|
|||
F_ULOCK = 0x0
|
||||
F_UNLCK = 0x2
|
||||
F_WRLCK = 0x1
|
||||
GRND_NONBLOCK = 0x1
|
||||
GRND_RANDOM = 0x2
|
||||
HUPCL = 0x400
|
||||
IBSHIFT = 0x10
|
||||
ICANON = 0x2
|
||||
|
@ -789,6 +839,7 @@ const (
|
|||
NLM_F_ATOMIC = 0x400
|
||||
NLM_F_CREATE = 0x400
|
||||
NLM_F_DUMP = 0x300
|
||||
NLM_F_DUMP_FILTERED = 0x20
|
||||
NLM_F_DUMP_INTR = 0x10
|
||||
NLM_F_ECHO = 0x8
|
||||
NLM_F_EXCL = 0x200
|
||||
|
@ -1228,6 +1279,7 @@ const (
|
|||
SOL_IP = 0x0
|
||||
SOL_IPV6 = 0x29
|
||||
SOL_IRDA = 0x10a
|
||||
SOL_NETLINK = 0x10e
|
||||
SOL_PACKET = 0x107
|
||||
SOL_RAW = 0xff
|
||||
SOL_SOCKET = 0x1
|
||||
|
@ -1273,6 +1325,17 @@ const (
|
|||
SO_TIMESTAMPING = 0x25
|
||||
SO_TIMESTAMPNS = 0x23
|
||||
SO_TYPE = 0x3
|
||||
SO_VM_SOCKETS_BUFFER_MAX_SIZE = 0x2
|
||||
SO_VM_SOCKETS_BUFFER_MIN_SIZE = 0x1
|
||||
SO_VM_SOCKETS_BUFFER_SIZE = 0x0
|
||||
SO_VM_SOCKETS_CONNECT_TIMEOUT = 0x6
|
||||
SO_VM_SOCKETS_NONBLOCK_TXRX = 0x7
|
||||
SO_VM_SOCKETS_PEER_HOST_VM_ID = 0x3
|
||||
SO_VM_SOCKETS_TRUSTED = 0x5
|
||||
SPLICE_F_GIFT = 0x8
|
||||
SPLICE_F_MORE = 0x4
|
||||
SPLICE_F_MOVE = 0x1
|
||||
SPLICE_F_NONBLOCK = 0x2
|
||||
S_BLKSIZE = 0x200
|
||||
S_IEXEC = 0x40
|
||||
S_IFBLK = 0x6000
|
||||
|
@ -1445,6 +1508,11 @@ const (
|
|||
VINTR = 0x0
|
||||
VKILL = 0x3
|
||||
VLNEXT = 0xf
|
||||
VMADDR_CID_ANY = 0xffffffff
|
||||
VMADDR_CID_HOST = 0x2
|
||||
VMADDR_CID_HYPERVISOR = 0x0
|
||||
VMADDR_CID_RESERVED = 0x1
|
||||
VMADDR_PORT_ANY = 0xffffffff
|
||||
VMIN = 0x6
|
||||
VQUIT = 0x1
|
||||
VREPRINT = 0xc
|
||||
|
|
|
@ -51,8 +51,16 @@ const (
|
|||
AF_TIPC = 0x1e
|
||||
AF_UNIX = 0x1
|
||||
AF_UNSPEC = 0x0
|
||||
AF_VSOCK = 0x28
|
||||
AF_WANPIPE = 0x19
|
||||
AF_X25 = 0x9
|
||||
ALG_OP_DECRYPT = 0x0
|
||||
ALG_OP_ENCRYPT = 0x1
|
||||
ALG_SET_AEAD_ASSOCLEN = 0x4
|
||||
ALG_SET_AEAD_AUTHSIZE = 0x5
|
||||
ALG_SET_IV = 0x2
|
||||
ALG_SET_KEY = 0x1
|
||||
ALG_SET_OP = 0x3
|
||||
ARPHRD_ADAPT = 0x108
|
||||
ARPHRD_APPLETLK = 0x8
|
||||
ARPHRD_ARCNET = 0x7
|
||||
|
@ -145,6 +153,21 @@ const (
|
|||
B75 = 0x2
|
||||
B921600 = 0x1007
|
||||
B9600 = 0xd
|
||||
BLKBSZGET = 0x80081270
|
||||
BLKBSZSET = 0x40081271
|
||||
BLKFLSBUF = 0x1261
|
||||
BLKFRAGET = 0x1265
|
||||
BLKFRASET = 0x1264
|
||||
BLKGETSIZE = 0x1260
|
||||
BLKGETSIZE64 = 0x80081272
|
||||
BLKRAGET = 0x1263
|
||||
BLKRASET = 0x1262
|
||||
BLKROGET = 0x125e
|
||||
BLKROSET = 0x125d
|
||||
BLKRRPART = 0x125f
|
||||
BLKSECTGET = 0x1267
|
||||
BLKSECTSET = 0x1266
|
||||
BLKSSZGET = 0x1268
|
||||
BOTHER = 0x1000
|
||||
BPF_A = 0x10
|
||||
BPF_ABS = 0x20
|
||||
|
@ -190,6 +213,25 @@ const (
|
|||
BS0 = 0x0
|
||||
BS1 = 0x2000
|
||||
BSDLY = 0x2000
|
||||
CAN_BCM = 0x2
|
||||
CAN_EFF_FLAG = 0x80000000
|
||||
CAN_EFF_ID_BITS = 0x1d
|
||||
CAN_EFF_MASK = 0x1fffffff
|
||||
CAN_ERR_FLAG = 0x20000000
|
||||
CAN_ERR_MASK = 0x1fffffff
|
||||
CAN_INV_FILTER = 0x20000000
|
||||
CAN_ISOTP = 0x6
|
||||
CAN_MAX_DLC = 0x8
|
||||
CAN_MAX_DLEN = 0x8
|
||||
CAN_MCNET = 0x5
|
||||
CAN_MTU = 0x10
|
||||
CAN_NPROTO = 0x7
|
||||
CAN_RAW = 0x1
|
||||
CAN_RTR_FLAG = 0x40000000
|
||||
CAN_SFF_ID_BITS = 0xb
|
||||
CAN_SFF_MASK = 0x7ff
|
||||
CAN_TP16 = 0x3
|
||||
CAN_TP20 = 0x4
|
||||
CBAUD = 0x100f
|
||||
CBAUDEX = 0x1000
|
||||
CFLUSH = 0xf
|
||||
|
@ -366,6 +408,12 @@ const (
|
|||
EXTA = 0xe
|
||||
EXTB = 0xf
|
||||
EXTPROC = 0x10000
|
||||
FALLOC_FL_COLLAPSE_RANGE = 0x8
|
||||
FALLOC_FL_INSERT_RANGE = 0x20
|
||||
FALLOC_FL_KEEP_SIZE = 0x1
|
||||
FALLOC_FL_NO_HIDE_STALE = 0x4
|
||||
FALLOC_FL_PUNCH_HOLE = 0x2
|
||||
FALLOC_FL_ZERO_RANGE = 0x10
|
||||
FD_CLOEXEC = 0x1
|
||||
FD_SETSIZE = 0x400
|
||||
FF0 = 0x0
|
||||
|
@ -405,6 +453,8 @@ const (
|
|||
F_ULOCK = 0x0
|
||||
F_UNLCK = 0x2
|
||||
F_WRLCK = 0x1
|
||||
GRND_NONBLOCK = 0x1
|
||||
GRND_RANDOM = 0x2
|
||||
HUPCL = 0x400
|
||||
IBSHIFT = 0x10
|
||||
ICANON = 0x2
|
||||
|
@ -747,6 +797,7 @@ const (
|
|||
NETLINK_ADD_MEMBERSHIP = 0x1
|
||||
NETLINK_AUDIT = 0x9
|
||||
NETLINK_BROADCAST_ERROR = 0x4
|
||||
NETLINK_CAP_ACK = 0xa
|
||||
NETLINK_CONNECTOR = 0xb
|
||||
NETLINK_CRYPTO = 0x15
|
||||
NETLINK_DNRTMSG = 0xe
|
||||
|
@ -759,14 +810,19 @@ const (
|
|||
NETLINK_IP6_FW = 0xd
|
||||
NETLINK_ISCSI = 0x8
|
||||
NETLINK_KOBJECT_UEVENT = 0xf
|
||||
NETLINK_LISTEN_ALL_NSID = 0x8
|
||||
NETLINK_LIST_MEMBERSHIPS = 0x9
|
||||
NETLINK_NETFILTER = 0xc
|
||||
NETLINK_NFLOG = 0x5
|
||||
NETLINK_NO_ENOBUFS = 0x5
|
||||
NETLINK_PKTINFO = 0x3
|
||||
NETLINK_RDMA = 0x14
|
||||
NETLINK_ROUTE = 0x0
|
||||
NETLINK_RX_RING = 0x6
|
||||
NETLINK_SCSITRANSPORT = 0x12
|
||||
NETLINK_SELINUX = 0x7
|
||||
NETLINK_SOCK_DIAG = 0x4
|
||||
NETLINK_TX_RING = 0x7
|
||||
NETLINK_UNUSED = 0x1
|
||||
NETLINK_USERSOCK = 0x2
|
||||
NETLINK_XFRM = 0x6
|
||||
|
@ -789,6 +845,7 @@ const (
|
|||
NLM_F_ATOMIC = 0x400
|
||||
NLM_F_CREATE = 0x400
|
||||
NLM_F_DUMP = 0x300
|
||||
NLM_F_DUMP_FILTERED = 0x20
|
||||
NLM_F_DUMP_INTR = 0x10
|
||||
NLM_F_ECHO = 0x8
|
||||
NLM_F_EXCL = 0x200
|
||||
|
@ -1229,6 +1286,7 @@ const (
|
|||
SOL_IP = 0x0
|
||||
SOL_IPV6 = 0x29
|
||||
SOL_IRDA = 0x10a
|
||||
SOL_NETLINK = 0x10e
|
||||
SOL_PACKET = 0x107
|
||||
SOL_RAW = 0xff
|
||||
SOL_SOCKET = 0x1
|
||||
|
@ -1274,6 +1332,17 @@ const (
|
|||
SO_TIMESTAMPING = 0x25
|
||||
SO_TIMESTAMPNS = 0x23
|
||||
SO_TYPE = 0x3
|
||||
SO_VM_SOCKETS_BUFFER_MAX_SIZE = 0x2
|
||||
SO_VM_SOCKETS_BUFFER_MIN_SIZE = 0x1
|
||||
SO_VM_SOCKETS_BUFFER_SIZE = 0x0
|
||||
SO_VM_SOCKETS_CONNECT_TIMEOUT = 0x6
|
||||
SO_VM_SOCKETS_NONBLOCK_TXRX = 0x7
|
||||
SO_VM_SOCKETS_PEER_HOST_VM_ID = 0x3
|
||||
SO_VM_SOCKETS_TRUSTED = 0x5
|
||||
SPLICE_F_GIFT = 0x8
|
||||
SPLICE_F_MORE = 0x4
|
||||
SPLICE_F_MOVE = 0x1
|
||||
SPLICE_F_NONBLOCK = 0x2
|
||||
S_BLKSIZE = 0x200
|
||||
S_IEXEC = 0x40
|
||||
S_IFBLK = 0x6000
|
||||
|
@ -1446,7 +1515,13 @@ const (
|
|||
VINTR = 0x0
|
||||
VKILL = 0x3
|
||||
VLNEXT = 0xf
|
||||
VMADDR_CID_ANY = 0xffffffff
|
||||
VMADDR_CID_HOST = 0x2
|
||||
VMADDR_CID_HYPERVISOR = 0x0
|
||||
VMADDR_CID_RESERVED = 0x1
|
||||
VMADDR_PORT_ANY = 0xffffffff
|
||||
VMIN = 0x6
|
||||
VM_SOCKETS_INVALID_VERSION = 0xffffffff
|
||||
VQUIT = 0x1
|
||||
VREPRINT = 0xc
|
||||
VSTART = 0x8
|
||||
|
|
|
@ -50,8 +50,16 @@ const (
|
|||
AF_TIPC = 0x1e
|
||||
AF_UNIX = 0x1
|
||||
AF_UNSPEC = 0x0
|
||||
AF_VSOCK = 0x28
|
||||
AF_WANPIPE = 0x19
|
||||
AF_X25 = 0x9
|
||||
ALG_OP_DECRYPT = 0x0
|
||||
ALG_OP_ENCRYPT = 0x1
|
||||
ALG_SET_AEAD_ASSOCLEN = 0x4
|
||||
ALG_SET_AEAD_AUTHSIZE = 0x5
|
||||
ALG_SET_IV = 0x2
|
||||
ALG_SET_KEY = 0x1
|
||||
ALG_SET_OP = 0x3
|
||||
ARPHRD_ADAPT = 0x108
|
||||
ARPHRD_APPLETLK = 0x8
|
||||
ARPHRD_ARCNET = 0x7
|
||||
|
@ -141,6 +149,21 @@ const (
|
|||
B75 = 0x2
|
||||
B921600 = 0x1007
|
||||
B9600 = 0xd
|
||||
BLKBSZGET = 0x80081270
|
||||
BLKBSZSET = 0x40081271
|
||||
BLKFLSBUF = 0x1261
|
||||
BLKFRAGET = 0x1265
|
||||
BLKFRASET = 0x1264
|
||||
BLKGETSIZE = 0x1260
|
||||
BLKGETSIZE64 = 0x80081272
|
||||
BLKRAGET = 0x1263
|
||||
BLKRASET = 0x1262
|
||||
BLKROGET = 0x125e
|
||||
BLKROSET = 0x125d
|
||||
BLKRRPART = 0x125f
|
||||
BLKSECTGET = 0x1267
|
||||
BLKSECTSET = 0x1266
|
||||
BLKSSZGET = 0x1268
|
||||
BOTHER = 0x1000
|
||||
BPF_A = 0x10
|
||||
BPF_ABS = 0x20
|
||||
|
@ -186,6 +209,25 @@ const (
|
|||
BS0 = 0x0
|
||||
BS1 = 0x2000
|
||||
BSDLY = 0x2000
|
||||
CAN_BCM = 0x2
|
||||
CAN_EFF_FLAG = 0x80000000
|
||||
CAN_EFF_ID_BITS = 0x1d
|
||||
CAN_EFF_MASK = 0x1fffffff
|
||||
CAN_ERR_FLAG = 0x20000000
|
||||
CAN_ERR_MASK = 0x1fffffff
|
||||
CAN_INV_FILTER = 0x20000000
|
||||
CAN_ISOTP = 0x6
|
||||
CAN_MAX_DLC = 0x8
|
||||
CAN_MAX_DLEN = 0x8
|
||||
CAN_MCNET = 0x5
|
||||
CAN_MTU = 0x10
|
||||
CAN_NPROTO = 0x7
|
||||
CAN_RAW = 0x1
|
||||
CAN_RTR_FLAG = 0x40000000
|
||||
CAN_SFF_ID_BITS = 0xb
|
||||
CAN_SFF_MASK = 0x7ff
|
||||
CAN_TP16 = 0x3
|
||||
CAN_TP20 = 0x4
|
||||
CBAUD = 0x100f
|
||||
CBAUDEX = 0x1000
|
||||
CFLUSH = 0xf
|
||||
|
@ -351,6 +393,12 @@ const (
|
|||
EXTA = 0xe
|
||||
EXTB = 0xf
|
||||
EXTPROC = 0x10000
|
||||
FALLOC_FL_COLLAPSE_RANGE = 0x8
|
||||
FALLOC_FL_INSERT_RANGE = 0x20
|
||||
FALLOC_FL_KEEP_SIZE = 0x1
|
||||
FALLOC_FL_NO_HIDE_STALE = 0x4
|
||||
FALLOC_FL_PUNCH_HOLE = 0x2
|
||||
FALLOC_FL_ZERO_RANGE = 0x10
|
||||
FD_CLOEXEC = 0x1
|
||||
FD_SETSIZE = 0x400
|
||||
FF0 = 0x0
|
||||
|
@ -390,6 +438,8 @@ const (
|
|||
F_ULOCK = 0x0
|
||||
F_UNLCK = 0x2
|
||||
F_WRLCK = 0x1
|
||||
GRND_NONBLOCK = 0x1
|
||||
GRND_RANDOM = 0x2
|
||||
HUPCL = 0x400
|
||||
IBSHIFT = 0x10
|
||||
ICANON = 0x2
|
||||
|
@ -707,6 +757,7 @@ const (
|
|||
NETLINK_AUDIT = 0x9
|
||||
NETLINK_BROADCAST_ERROR = 0x4
|
||||
NETLINK_CONNECTOR = 0xb
|
||||
NETLINK_CRYPTO = 0x15
|
||||
NETLINK_DNRTMSG = 0xe
|
||||
NETLINK_DROP_MEMBERSHIP = 0x2
|
||||
NETLINK_ECRYPTFS = 0x13
|
||||
|
@ -723,8 +774,11 @@ const (
|
|||
NETLINK_PKTINFO = 0x3
|
||||
NETLINK_RDMA = 0x14
|
||||
NETLINK_ROUTE = 0x0
|
||||
NETLINK_RX_RING = 0x6
|
||||
NETLINK_SCSITRANSPORT = 0x12
|
||||
NETLINK_SELINUX = 0x7
|
||||
NETLINK_SOCK_DIAG = 0x4
|
||||
NETLINK_TX_RING = 0x7
|
||||
NETLINK_UNUSED = 0x1
|
||||
NETLINK_USERSOCK = 0x2
|
||||
NETLINK_XFRM = 0x6
|
||||
|
@ -747,6 +801,7 @@ const (
|
|||
NLM_F_ATOMIC = 0x400
|
||||
NLM_F_CREATE = 0x400
|
||||
NLM_F_DUMP = 0x300
|
||||
NLM_F_DUMP_FILTERED = 0x20
|
||||
NLM_F_ECHO = 0x8
|
||||
NLM_F_EXCL = 0x200
|
||||
NLM_F_MATCH = 0x200
|
||||
|
@ -1152,6 +1207,7 @@ const (
|
|||
SOL_IP = 0x0
|
||||
SOL_IPV6 = 0x29
|
||||
SOL_IRDA = 0x10a
|
||||
SOL_NETLINK = 0x10e
|
||||
SOL_PACKET = 0x107
|
||||
SOL_RAW = 0xff
|
||||
SOL_SOCKET = 0x1
|
||||
|
@ -1197,6 +1253,17 @@ const (
|
|||
SO_TIMESTAMPING = 0x25
|
||||
SO_TIMESTAMPNS = 0x23
|
||||
SO_TYPE = 0x3
|
||||
SO_VM_SOCKETS_BUFFER_MAX_SIZE = 0x2
|
||||
SO_VM_SOCKETS_BUFFER_MIN_SIZE = 0x1
|
||||
SO_VM_SOCKETS_BUFFER_SIZE = 0x0
|
||||
SO_VM_SOCKETS_CONNECT_TIMEOUT = 0x6
|
||||
SO_VM_SOCKETS_NONBLOCK_TXRX = 0x7
|
||||
SO_VM_SOCKETS_PEER_HOST_VM_ID = 0x3
|
||||
SO_VM_SOCKETS_TRUSTED = 0x5
|
||||
SPLICE_F_GIFT = 0x8
|
||||
SPLICE_F_MORE = 0x4
|
||||
SPLICE_F_MOVE = 0x1
|
||||
SPLICE_F_NONBLOCK = 0x2
|
||||
S_BLKSIZE = 0x200
|
||||
S_IEXEC = 0x40
|
||||
S_IFBLK = 0x6000
|
||||
|
@ -1369,6 +1436,11 @@ const (
|
|||
VINTR = 0x0
|
||||
VKILL = 0x3
|
||||
VLNEXT = 0xf
|
||||
VMADDR_CID_ANY = 0xffffffff
|
||||
VMADDR_CID_HOST = 0x2
|
||||
VMADDR_CID_HYPERVISOR = 0x0
|
||||
VMADDR_CID_RESERVED = 0x1
|
||||
VMADDR_PORT_ANY = 0xffffffff
|
||||
VMIN = 0x6
|
||||
VQUIT = 0x1
|
||||
VREPRINT = 0xc
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue