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",
|
"importpath": "golang.org/x/crypto/curve25519",
|
||||||
"repository": "https://go.googlesource.com/crypto",
|
"repository": "https://go.googlesource.com/crypto",
|
||||||
"revision": "81372b2fc2f10bef2a7f338da115c315a56b2726",
|
"revision": "efac7f277b17c19894091e358c6130cb6bd51117",
|
||||||
"branch": "master",
|
"branch": "master",
|
||||||
"path": "/curve25519"
|
"path": "/curve25519"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"importpath": "golang.org/x/crypto/ed25519",
|
"importpath": "golang.org/x/crypto/ed25519",
|
||||||
"repository": "https://go.googlesource.com/crypto",
|
"repository": "https://go.googlesource.com/crypto",
|
||||||
"revision": "81372b2fc2f10bef2a7f338da115c315a56b2726",
|
"revision": "efac7f277b17c19894091e358c6130cb6bd51117",
|
||||||
"branch": "master",
|
"branch": "master",
|
||||||
"path": "/ed25519"
|
"path": "/ed25519"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"importpath": "golang.org/x/crypto/pbkdf2",
|
"importpath": "golang.org/x/crypto/pbkdf2",
|
||||||
"repository": "https://go.googlesource.com/crypto",
|
"repository": "https://go.googlesource.com/crypto",
|
||||||
"revision": "81372b2fc2f10bef2a7f338da115c315a56b2726",
|
"revision": "efac7f277b17c19894091e358c6130cb6bd51117",
|
||||||
"branch": "master",
|
"branch": "master",
|
||||||
"path": "/pbkdf2"
|
"path": "/pbkdf2"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"importpath": "golang.org/x/crypto/poly1305",
|
"importpath": "golang.org/x/crypto/poly1305",
|
||||||
"repository": "https://go.googlesource.com/crypto",
|
"repository": "https://go.googlesource.com/crypto",
|
||||||
"revision": "5f31782cfb2b6373211f8f9fbf31283fa234b570",
|
"revision": "efac7f277b17c19894091e358c6130cb6bd51117",
|
||||||
"branch": "master",
|
"branch": "master",
|
||||||
"path": "/poly1305"
|
"path": "/poly1305"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"importpath": "golang.org/x/crypto/scrypt",
|
"importpath": "golang.org/x/crypto/scrypt",
|
||||||
"repository": "https://go.googlesource.com/crypto",
|
"repository": "https://go.googlesource.com/crypto",
|
||||||
"revision": "81372b2fc2f10bef2a7f338da115c315a56b2726",
|
"revision": "efac7f277b17c19894091e358c6130cb6bd51117",
|
||||||
"branch": "master",
|
"branch": "master",
|
||||||
"path": "/scrypt"
|
"path": "/scrypt"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"importpath": "golang.org/x/crypto/ssh",
|
"importpath": "golang.org/x/crypto/ssh",
|
||||||
"repository": "https://go.googlesource.com/crypto",
|
"repository": "https://go.googlesource.com/crypto",
|
||||||
"revision": "81372b2fc2f10bef2a7f338da115c315a56b2726",
|
"revision": "efac7f277b17c19894091e358c6130cb6bd51117",
|
||||||
"branch": "master",
|
"branch": "master",
|
||||||
"path": "/ssh"
|
"path": "/ssh"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"importpath": "golang.org/x/net/context",
|
"importpath": "golang.org/x/net/context",
|
||||||
"repository": "https://go.googlesource.com/net",
|
"repository": "https://go.googlesource.com/net",
|
||||||
"revision": "de35ec43e7a9aabd6a9c54d2898220ea7e44de7d",
|
"revision": "5602c733f70afc6dcec6766be0d5034d4c4f14de",
|
||||||
"branch": "master",
|
"branch": "master",
|
||||||
"path": "/context"
|
"path": "/context"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"importpath": "golang.org/x/sys/unix",
|
"importpath": "golang.org/x/sys/unix",
|
||||||
"repository": "https://go.googlesource.com/sys",
|
"repository": "https://go.googlesource.com/sys",
|
||||||
"revision": "30de6d19a3bd89a5f38ae4028e23aaa5582648af",
|
"revision": "f3918c30c5c2cb527c0b071a27c35120a6c0719a",
|
||||||
"branch": "master",
|
"branch": "master",
|
||||||
"path": "/unix"
|
"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
|
// +build amd64,!gccgo,!appengine
|
||||||
|
|
||||||
DATA ·REDMASK51(SB)/8, $0x0007FFFFFFFFFFFF
|
// These constants cannot be encoded in non-MOVQ immediates.
|
||||||
GLOBL ·REDMASK51(SB), 8, $8
|
// We access them directly from memory instead.
|
||||||
|
|
||||||
DATA ·_121666_213(SB)/8, $996687872
|
DATA ·_121666_213(SB)/8, $996687872
|
||||||
GLOBL ·_121666_213(SB), 8, $8
|
GLOBL ·_121666_213(SB), 8, $8
|
||||||
|
|
|
@ -2,87 +2,64 @@
|
||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// 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
|
// +build amd64,!gccgo,!appengine
|
||||||
|
|
||||||
// func cswap(inout *[5]uint64, v uint64)
|
// func cswap(inout *[4][5]uint64, v uint64)
|
||||||
TEXT ·cswap(SB),7,$0
|
TEXT ·cswap(SB),7,$0
|
||||||
MOVQ inout+0(FP),DI
|
MOVQ inout+0(FP),DI
|
||||||
MOVQ v+8(FP),SI
|
MOVQ v+8(FP),SI
|
||||||
|
|
||||||
CMPQ SI,$1
|
SUBQ $1, SI
|
||||||
MOVQ 0(DI),SI
|
NOTQ SI
|
||||||
MOVQ 80(DI),DX
|
MOVQ SI, X15
|
||||||
MOVQ 8(DI),CX
|
PSHUFD $0x44, X15, X15
|
||||||
MOVQ 88(DI),R8
|
|
||||||
MOVQ SI,R9
|
MOVOU 0(DI), X0
|
||||||
CMOVQEQ DX,SI
|
MOVOU 16(DI), X2
|
||||||
CMOVQEQ R9,DX
|
MOVOU 32(DI), X4
|
||||||
MOVQ CX,R9
|
MOVOU 48(DI), X6
|
||||||
CMOVQEQ R8,CX
|
MOVOU 64(DI), X8
|
||||||
CMOVQEQ R9,R8
|
MOVOU 80(DI), X1
|
||||||
MOVQ SI,0(DI)
|
MOVOU 96(DI), X3
|
||||||
MOVQ DX,80(DI)
|
MOVOU 112(DI), X5
|
||||||
MOVQ CX,8(DI)
|
MOVOU 128(DI), X7
|
||||||
MOVQ R8,88(DI)
|
MOVOU 144(DI), X9
|
||||||
MOVQ 16(DI),SI
|
|
||||||
MOVQ 96(DI),DX
|
MOVO X1, X10
|
||||||
MOVQ 24(DI),CX
|
MOVO X3, X11
|
||||||
MOVQ 104(DI),R8
|
MOVO X5, X12
|
||||||
MOVQ SI,R9
|
MOVO X7, X13
|
||||||
CMOVQEQ DX,SI
|
MOVO X9, X14
|
||||||
CMOVQEQ R9,DX
|
|
||||||
MOVQ CX,R9
|
PXOR X0, X10
|
||||||
CMOVQEQ R8,CX
|
PXOR X2, X11
|
||||||
CMOVQEQ R9,R8
|
PXOR X4, X12
|
||||||
MOVQ SI,16(DI)
|
PXOR X6, X13
|
||||||
MOVQ DX,96(DI)
|
PXOR X8, X14
|
||||||
MOVQ CX,24(DI)
|
PAND X15, X10
|
||||||
MOVQ R8,104(DI)
|
PAND X15, X11
|
||||||
MOVQ 32(DI),SI
|
PAND X15, X12
|
||||||
MOVQ 112(DI),DX
|
PAND X15, X13
|
||||||
MOVQ 40(DI),CX
|
PAND X15, X14
|
||||||
MOVQ 120(DI),R8
|
PXOR X10, X0
|
||||||
MOVQ SI,R9
|
PXOR X10, X1
|
||||||
CMOVQEQ DX,SI
|
PXOR X11, X2
|
||||||
CMOVQEQ R9,DX
|
PXOR X11, X3
|
||||||
MOVQ CX,R9
|
PXOR X12, X4
|
||||||
CMOVQEQ R8,CX
|
PXOR X12, X5
|
||||||
CMOVQEQ R9,R8
|
PXOR X13, X6
|
||||||
MOVQ SI,32(DI)
|
PXOR X13, X7
|
||||||
MOVQ DX,112(DI)
|
PXOR X14, X8
|
||||||
MOVQ CX,40(DI)
|
PXOR X14, X9
|
||||||
MOVQ R8,120(DI)
|
|
||||||
MOVQ 48(DI),SI
|
MOVOU X0, 0(DI)
|
||||||
MOVQ 128(DI),DX
|
MOVOU X2, 16(DI)
|
||||||
MOVQ 56(DI),CX
|
MOVOU X4, 32(DI)
|
||||||
MOVQ 136(DI),R8
|
MOVOU X6, 48(DI)
|
||||||
MOVQ SI,R9
|
MOVOU X8, 64(DI)
|
||||||
CMOVQEQ DX,SI
|
MOVOU X1, 80(DI)
|
||||||
CMOVQEQ R9,DX
|
MOVOU X3, 96(DI)
|
||||||
MOVQ CX,R9
|
MOVOU X5, 112(DI)
|
||||||
CMOVQEQ R8,CX
|
MOVOU X7, 128(DI)
|
||||||
CMOVQEQ R9,R8
|
MOVOU X9, 144(DI)
|
||||||
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
|
|
||||||
RET
|
RET
|
||||||
|
|
|
@ -8,6 +8,10 @@
|
||||||
|
|
||||||
package curve25519
|
package curve25519
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/binary"
|
||||||
|
)
|
||||||
|
|
||||||
// This code is a port of the public domain, "ref10" implementation of
|
// This code is a port of the public domain, "ref10" implementation of
|
||||||
// curve25519 from SUPERCOP 20130419 by D. J. Bernstein.
|
// curve25519 from SUPERCOP 20130419 by D. J. Bernstein.
|
||||||
|
|
||||||
|
@ -50,17 +54,11 @@ func feCopy(dst, src *fieldElement) {
|
||||||
//
|
//
|
||||||
// Preconditions: b in {0,1}.
|
// Preconditions: b in {0,1}.
|
||||||
func feCSwap(f, g *fieldElement, b int32) {
|
func feCSwap(f, g *fieldElement, b int32) {
|
||||||
var x fieldElement
|
|
||||||
b = -b
|
b = -b
|
||||||
for i := range x {
|
|
||||||
x[i] = b & (f[i] ^ g[i])
|
|
||||||
}
|
|
||||||
|
|
||||||
for i := range f {
|
for i := range f {
|
||||||
f[i] ^= x[i]
|
t := b & (f[i] ^ g[i])
|
||||||
}
|
f[i] ^= t
|
||||||
for i := range g {
|
g[i] ^= t
|
||||||
g[i] ^= x[i]
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -75,12 +73,7 @@ func load3(in []byte) int64 {
|
||||||
|
|
||||||
// load4 reads a 32-bit, little-endian value from in.
|
// load4 reads a 32-bit, little-endian value from in.
|
||||||
func load4(in []byte) int64 {
|
func load4(in []byte) int64 {
|
||||||
var r int64
|
return int64(binary.LittleEndian.Uint32(in))
|
||||||
r = int64(in[0])
|
|
||||||
r |= int64(in[1]) << 8
|
|
||||||
r |= int64(in[2]) << 16
|
|
||||||
r |= int64(in[3]) << 24
|
|
||||||
return r
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func feFromBytes(dst *fieldElement, src *[32]byte) {
|
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)
|
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
|
// +build amd64,!gccgo,!appengine
|
||||||
|
|
||||||
|
#include "const_amd64.h"
|
||||||
|
|
||||||
// func freeze(inout *[5]uint64)
|
// func freeze(inout *[5]uint64)
|
||||||
TEXT ·freeze(SB),7,$96-8
|
TEXT ·freeze(SB),7,$0-8
|
||||||
MOVQ inout+0(FP), DI
|
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 0(DI),SI
|
||||||
MOVQ 8(DI),DX
|
MOVQ 8(DI),DX
|
||||||
MOVQ 16(DI),CX
|
MOVQ 16(DI),CX
|
||||||
MOVQ 24(DI),R8
|
MOVQ 24(DI),R8
|
||||||
MOVQ 32(DI),R9
|
MOVQ 32(DI),R9
|
||||||
MOVQ ·REDMASK51(SB),AX
|
MOVQ $REDMASK51,AX
|
||||||
MOVQ AX,R10
|
MOVQ AX,R10
|
||||||
SUBQ $18,R10
|
SUBQ $18,R10
|
||||||
MOVQ $3,R11
|
MOVQ $3,R11
|
||||||
|
@ -81,14 +70,4 @@ REDUCELOOP:
|
||||||
MOVQ CX,16(DI)
|
MOVQ CX,16(DI)
|
||||||
MOVQ R8,24(DI)
|
MOVQ R8,24(DI)
|
||||||
MOVQ R9,32(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
|
RET
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -7,36 +7,24 @@
|
||||||
|
|
||||||
// +build amd64,!gccgo,!appengine
|
// +build amd64,!gccgo,!appengine
|
||||||
|
|
||||||
|
#include "const_amd64.h"
|
||||||
|
|
||||||
// func mul(dest, a, b *[5]uint64)
|
// 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 dest+0(FP), DI
|
||||||
MOVQ a+8(FP), SI
|
MOVQ a+8(FP), SI
|
||||||
MOVQ b+16(FP), DX
|
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 DX,CX
|
||||||
MOVQ 24(SI),DX
|
MOVQ 24(SI),DX
|
||||||
IMUL3Q $19,DX,AX
|
IMUL3Q $19,DX,AX
|
||||||
MOVQ AX,64(SP)
|
MOVQ AX,0(SP)
|
||||||
MULQ 16(CX)
|
MULQ 16(CX)
|
||||||
MOVQ AX,R8
|
MOVQ AX,R8
|
||||||
MOVQ DX,R9
|
MOVQ DX,R9
|
||||||
MOVQ 32(SI),DX
|
MOVQ 32(SI),DX
|
||||||
IMUL3Q $19,DX,AX
|
IMUL3Q $19,DX,AX
|
||||||
MOVQ AX,72(SP)
|
MOVQ AX,8(SP)
|
||||||
MULQ 8(CX)
|
MULQ 8(CX)
|
||||||
ADDQ AX,R8
|
ADDQ AX,R8
|
||||||
ADCQ DX,R9
|
ADCQ DX,R9
|
||||||
|
@ -111,11 +99,11 @@ TEXT ·mul(SB),0,$128-24
|
||||||
MULQ 8(CX)
|
MULQ 8(CX)
|
||||||
ADDQ AX,BX
|
ADDQ AX,BX
|
||||||
ADCQ DX,BP
|
ADCQ DX,BP
|
||||||
MOVQ 64(SP),AX
|
MOVQ 0(SP),AX
|
||||||
MULQ 24(CX)
|
MULQ 24(CX)
|
||||||
ADDQ AX,R10
|
ADDQ AX,R10
|
||||||
ADCQ DX,R11
|
ADCQ DX,R11
|
||||||
MOVQ 64(SP),AX
|
MOVQ 0(SP),AX
|
||||||
MULQ 32(CX)
|
MULQ 32(CX)
|
||||||
ADDQ AX,R12
|
ADDQ AX,R12
|
||||||
ADCQ DX,R13
|
ADCQ DX,R13
|
||||||
|
@ -123,19 +111,19 @@ TEXT ·mul(SB),0,$128-24
|
||||||
MULQ 0(CX)
|
MULQ 0(CX)
|
||||||
ADDQ AX,BX
|
ADDQ AX,BX
|
||||||
ADCQ DX,BP
|
ADCQ DX,BP
|
||||||
MOVQ 72(SP),AX
|
MOVQ 8(SP),AX
|
||||||
MULQ 16(CX)
|
MULQ 16(CX)
|
||||||
ADDQ AX,R10
|
ADDQ AX,R10
|
||||||
ADCQ DX,R11
|
ADCQ DX,R11
|
||||||
MOVQ 72(SP),AX
|
MOVQ 8(SP),AX
|
||||||
MULQ 24(CX)
|
MULQ 24(CX)
|
||||||
ADDQ AX,R12
|
ADDQ AX,R12
|
||||||
ADCQ DX,R13
|
ADCQ DX,R13
|
||||||
MOVQ 72(SP),AX
|
MOVQ 8(SP),AX
|
||||||
MULQ 32(CX)
|
MULQ 32(CX)
|
||||||
ADDQ AX,R14
|
ADDQ AX,R14
|
||||||
ADCQ DX,R15
|
ADCQ DX,R15
|
||||||
MOVQ ·REDMASK51(SB),SI
|
MOVQ $REDMASK51,SI
|
||||||
SHLQ $13,R9:R8
|
SHLQ $13,R9:R8
|
||||||
ANDQ SI,R8
|
ANDQ SI,R8
|
||||||
SHLQ $13,R11:R10
|
SHLQ $13,R11:R10
|
||||||
|
@ -178,14 +166,4 @@ TEXT ·mul(SB),0,$128-24
|
||||||
MOVQ R9,16(DI)
|
MOVQ R9,16(DI)
|
||||||
MOVQ AX,24(DI)
|
MOVQ AX,24(DI)
|
||||||
MOVQ R10,32(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
|
RET
|
||||||
|
|
|
@ -7,24 +7,13 @@
|
||||||
|
|
||||||
// +build amd64,!gccgo,!appengine
|
// +build amd64,!gccgo,!appengine
|
||||||
|
|
||||||
|
#include "const_amd64.h"
|
||||||
|
|
||||||
// func square(out, in *[5]uint64)
|
// func square(out, in *[5]uint64)
|
||||||
TEXT ·square(SB),7,$96-16
|
TEXT ·square(SB),7,$0-16
|
||||||
MOVQ out+0(FP), DI
|
MOVQ out+0(FP), DI
|
||||||
MOVQ in+8(FP), SI
|
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
|
MOVQ 0(SI),AX
|
||||||
MULQ 0(SI)
|
MULQ 0(SI)
|
||||||
MOVQ AX,CX
|
MOVQ AX,CX
|
||||||
|
@ -97,7 +86,7 @@ TEXT ·square(SB),7,$96-16
|
||||||
MULQ 32(SI)
|
MULQ 32(SI)
|
||||||
ADDQ AX,R13
|
ADDQ AX,R13
|
||||||
ADCQ DX,R14
|
ADCQ DX,R14
|
||||||
MOVQ ·REDMASK51(SB),SI
|
MOVQ $REDMASK51,SI
|
||||||
SHLQ $13,R8:CX
|
SHLQ $13,R8:CX
|
||||||
ANDQ SI,CX
|
ANDQ SI,CX
|
||||||
SHLQ $13,R10:R9
|
SHLQ $13,R10:R9
|
||||||
|
@ -140,14 +129,4 @@ TEXT ·square(SB),7,$96-16
|
||||||
MOVQ R9,16(DI)
|
MOVQ R9,16(DI)
|
||||||
MOVQ AX,24(DI)
|
MOVQ AX,24(DI)
|
||||||
MOVQ R10,32(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
|
RET
|
||||||
|
|
|
@ -6,10 +6,14 @@ package poly1305
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"encoding/hex"
|
||||||
|
"flag"
|
||||||
"testing"
|
"testing"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var stressFlag = flag.Bool("stress", false, "run slow stress tests")
|
||||||
|
|
||||||
var testData = []struct {
|
var testData = []struct {
|
||||||
in, k, correct []byte
|
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{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},
|
[]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) {
|
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 TestSum(t *testing.T) { testSum(t, false) }
|
||||||
func TestSumUnaligned(t *testing.T) { testSum(t, true) }
|
func TestSumUnaligned(t *testing.T) { testSum(t, true) }
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
// +build amd64,!gccgo,!appengine,go1.7
|
// +build amd64,!gccgo,!appengine
|
||||||
|
|
||||||
package poly1305
|
package poly1305
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
// +build amd64,!gccgo,!appengine,go1.7
|
// +build amd64,!gccgo,!appengine
|
||||||
|
|
||||||
#include "textflag.h"
|
#include "textflag.h"
|
||||||
|
|
||||||
|
@ -54,9 +54,9 @@
|
||||||
ADCQ t3, h1; \
|
ADCQ t3, h1; \
|
||||||
ADCQ $0, h2
|
ADCQ $0, h2
|
||||||
|
|
||||||
DATA poly1305Mask<>+0x00(SB)/8, $0x0FFFFFFC0FFFFFFF
|
DATA ·poly1305Mask<>+0x00(SB)/8, $0x0FFFFFFC0FFFFFFF
|
||||||
DATA poly1305Mask<>+0x08(SB)/8, $0x0FFFFFFC0FFFFFFC
|
DATA ·poly1305Mask<>+0x08(SB)/8, $0x0FFFFFFC0FFFFFFC
|
||||||
GLOBL poly1305Mask<>(SB), RODATA, $16
|
GLOBL ·poly1305Mask<>(SB), RODATA, $16
|
||||||
|
|
||||||
// func poly1305(out *[16]byte, m *byte, mlen uint64, key *[32]key)
|
// func poly1305(out *[16]byte, m *byte, mlen uint64, key *[32]key)
|
||||||
TEXT ·poly1305(SB), $0-32
|
TEXT ·poly1305(SB), $0-32
|
||||||
|
@ -67,8 +67,8 @@ TEXT ·poly1305(SB), $0-32
|
||||||
|
|
||||||
MOVQ 0(AX), R11
|
MOVQ 0(AX), R11
|
||||||
MOVQ 8(AX), R12
|
MOVQ 8(AX), R12
|
||||||
ANDQ poly1305Mask<>(SB), R11 // r0
|
ANDQ ·poly1305Mask<>(SB), R11 // r0
|
||||||
ANDQ poly1305Mask<>+8(SB), R12 // r1
|
ANDQ ·poly1305Mask<>+8(SB), R12 // r1
|
||||||
XORQ R8, R8 // h0
|
XORQ R8, R8 // h0
|
||||||
XORQ R9, R9 // h1
|
XORQ R9, R9 // h1
|
||||||
XORQ R10, R10 // h2
|
XORQ R10, R10 // h2
|
||||||
|
|
201
vendor/src/golang.org/x/crypto/poly1305/sum_arm.s
vendored
201
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
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// +build arm,!gccgo,!appengine,!nacl
|
||||||
|
|
||||||
#include "textflag.h"
|
#include "textflag.h"
|
||||||
|
|
||||||
// This code was translated into a form compatible with 5a from the public
|
// 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.
|
// 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<>+0x00(SB)/4, $0x3ffffff
|
DATA ·poly1305_init_constants_armv6<>+0x08(SB)/4, $0x3ffc0ff
|
||||||
DATA poly1305_init_constants_armv6<>+0x04(SB)/4, $0x3ffff03
|
DATA ·poly1305_init_constants_armv6<>+0x0c(SB)/4, $0x3f03fff
|
||||||
DATA poly1305_init_constants_armv6<>+0x08(SB)/4, $0x3ffc0ff
|
DATA ·poly1305_init_constants_armv6<>+0x10(SB)/4, $0x00fffff
|
||||||
DATA poly1305_init_constants_armv6<>+0x0c(SB)/4, $0x3f03fff
|
GLOBL ·poly1305_init_constants_armv6<>(SB), 8, $20
|
||||||
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
|
// Warning: the linker may use R11 to synthesize certain instructions. Please
|
||||||
// take care and verify that no synthetic instructions use it.
|
// take care and verify that no synthetic instructions use it.
|
||||||
|
|
||||||
TEXT poly1305_init_ext_armv6<>(SB), NOSPLIT|NOFRAME, $0
|
TEXT poly1305_init_ext_armv6<>(SB), NOSPLIT, $0
|
||||||
MOVM.DB.W [R4-R11], (R13)
|
// 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]
|
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, R8
|
||||||
MOVW R2>>26, R9
|
MOVW R2>>26, R9
|
||||||
MOVW R3>>20, g
|
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 [R2-R6], (R0)
|
||||||
MOVM.IA.W (R1), [R2-R5]
|
MOVM.IA.W (R1), [R2-R5]
|
||||||
MOVM.IA [R2-R6], (R0)
|
MOVM.IA [R2-R6], (R0)
|
||||||
MOVM.IA.W (R13), [R4-R11]
|
ADD $20, R13, R0
|
||||||
|
MOVM.DA (R0), [R4-R7]
|
||||||
RET
|
RET
|
||||||
|
|
||||||
#define MOVW_UNALIGNED(Rsrc, Rdst, Rtmp, offset) \
|
#define MOVW_UNALIGNED(Rsrc, Rdst, Rtmp, offset) \
|
||||||
|
@ -59,20 +65,26 @@ TEXT poly1305_init_ext_armv6<>(SB), NOSPLIT|NOFRAME, $0
|
||||||
MOVBU (offset+3)(Rsrc), Rtmp; \
|
MOVBU (offset+3)(Rsrc), Rtmp; \
|
||||||
MOVBU Rtmp, (offset+3)(Rdst)
|
MOVBU Rtmp, (offset+3)(Rdst)
|
||||||
|
|
||||||
TEXT poly1305_blocks_armv6<>(SB), NOSPLIT|NOFRAME, $0
|
TEXT poly1305_blocks_armv6<>(SB), NOSPLIT, $0
|
||||||
MOVM.DB.W [R4, R5, R6, R7, R8, R9, g, R11, R14], (R13)
|
// Needs 24 bytes of stack for saved registers and then 88 bytes of
|
||||||
SUB $128, R13
|
// scratch space after that. We assume that 24 bytes at (R13) have
|
||||||
MOVW R0, 36(R13)
|
// already been used: four bytes for the link register saved in the
|
||||||
MOVW R1, 40(R13)
|
// prelude of poly1305_auth_armv6, four bytes for saving the value of g
|
||||||
MOVW R2, 44(R13)
|
// 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 R1, R14
|
||||||
MOVW R2, R12
|
MOVW R2, R12
|
||||||
MOVW 56(R0), R8
|
MOVW 56(R0), R8
|
||||||
WORD $0xe1180008 // TST R8, R8 not working see issue 5921
|
WORD $0xe1180008 // TST R8, R8 not working see issue 5921
|
||||||
EOR R6, R6, R6
|
EOR R6, R6, R6
|
||||||
MOVW.EQ $(1<<24), R6
|
MOVW.EQ $(1<<24), R6
|
||||||
MOVW R6, 32(R13)
|
MOVW R6, 84(R13)
|
||||||
ADD $64, R13, g
|
ADD $116, R13, g
|
||||||
MOVM.IA (R0), [R0-R9]
|
MOVM.IA (R0), [R0-R9]
|
||||||
MOVM.IA [R0-R4], (g)
|
MOVM.IA [R0-R4], (g)
|
||||||
CMP $16, R12
|
CMP $16, R12
|
||||||
|
@ -81,7 +93,7 @@ TEXT poly1305_blocks_armv6<>(SB), NOSPLIT|NOFRAME, $0
|
||||||
poly1305_blocks_armv6_mainloop:
|
poly1305_blocks_armv6_mainloop:
|
||||||
WORD $0xe31e0003 // TST R14, #3 not working see issue 5921
|
WORD $0xe31e0003 // TST R14, #3 not working see issue 5921
|
||||||
BEQ poly1305_blocks_armv6_mainloop_aligned
|
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, 0)
|
||||||
MOVW_UNALIGNED(R14, g, R0, 4)
|
MOVW_UNALIGNED(R14, g, R0, 4)
|
||||||
MOVW_UNALIGNED(R14, g, R0, 8)
|
MOVW_UNALIGNED(R14, g, R0, 8)
|
||||||
|
@ -97,21 +109,21 @@ poly1305_blocks_armv6_mainloop_loaded:
|
||||||
MOVW R0>>26, g
|
MOVW R0>>26, g
|
||||||
MOVW R1>>20, R11
|
MOVW R1>>20, R11
|
||||||
MOVW R2>>14, R12
|
MOVW R2>>14, R12
|
||||||
MOVW R14, 40(R13)
|
MOVW R14, 92(R13)
|
||||||
MOVW R3>>8, R4
|
MOVW R3>>8, R4
|
||||||
ORR R1<<6, g, g
|
ORR R1<<6, g, g
|
||||||
ORR R2<<12, R11, R11
|
ORR R2<<12, R11, R11
|
||||||
ORR R3<<18, R12, R12
|
ORR R3<<18, R12, R12
|
||||||
BIC $0xfc000000, R0, R0
|
BIC $0xfc000000, R0, R0
|
||||||
BIC $0xfc000000, g, g
|
BIC $0xfc000000, g, g
|
||||||
MOVW 32(R13), R3
|
MOVW 84(R13), R3
|
||||||
BIC $0xfc000000, R11, R11
|
BIC $0xfc000000, R11, R11
|
||||||
BIC $0xfc000000, R12, R12
|
BIC $0xfc000000, R12, R12
|
||||||
ADD R0, R5, R5
|
ADD R0, R5, R5
|
||||||
ADD g, R6, R6
|
ADD g, R6, R6
|
||||||
ORR R3, R4, R4
|
ORR R3, R4, R4
|
||||||
ADD R11, R7, R7
|
ADD R11, R7, R7
|
||||||
ADD $64, R13, R14
|
ADD $116, R13, R14
|
||||||
ADD R12, R8, R8
|
ADD R12, R8, R8
|
||||||
ADD R4, R9, R9
|
ADD R4, R9, R9
|
||||||
MOVM.IA (R14), [R0-R4]
|
MOVM.IA (R14), [R0-R4]
|
||||||
|
@ -127,10 +139,10 @@ poly1305_blocks_armv6_mainloop_loaded:
|
||||||
MULALU R0, R8, (R14, R12)
|
MULALU R0, R8, (R14, R12)
|
||||||
MULALU R0, R9, (R11, g)
|
MULALU R0, R9, (R11, g)
|
||||||
MULALU R4, R9, (R14, R12)
|
MULALU R4, R9, (R14, R12)
|
||||||
MOVW g, 24(R13)
|
MOVW g, 76(R13)
|
||||||
MOVW R11, 28(R13)
|
MOVW R11, 80(R13)
|
||||||
MOVW R12, 16(R13)
|
MOVW R12, 68(R13)
|
||||||
MOVW R14, 20(R13)
|
MOVW R14, 72(R13)
|
||||||
MULLU R2, R5, (R11, g)
|
MULLU R2, R5, (R11, g)
|
||||||
MULLU R1, R5, (R14, R12)
|
MULLU R1, R5, (R14, R12)
|
||||||
MULALU R1, R6, (R11, g)
|
MULALU R1, R6, (R11, g)
|
||||||
|
@ -143,16 +155,17 @@ poly1305_blocks_armv6_mainloop_loaded:
|
||||||
MULALU R3, R8, (R14, R12)
|
MULALU R3, R8, (R14, R12)
|
||||||
MULALU R3, R9, (R11, g)
|
MULALU R3, R9, (R11, g)
|
||||||
MULALU R2, R9, (R14, R12)
|
MULALU R2, R9, (R14, R12)
|
||||||
MOVW g, 8(R13)
|
MOVW g, 60(R13)
|
||||||
MOVW R11, 12(R13)
|
MOVW R11, 64(R13)
|
||||||
MOVW R12, 0(R13)
|
MOVW R12, 52(R13)
|
||||||
MOVW R14, w+4(SP)
|
MOVW R14, 56(R13)
|
||||||
MULLU R0, R5, (R11, g)
|
MULLU R0, R5, (R11, g)
|
||||||
MULALU R4, R6, (R11, g)
|
MULALU R4, R6, (R11, g)
|
||||||
MULALU R3, R7, (R11, g)
|
MULALU R3, R7, (R11, g)
|
||||||
MULALU R2, R8, (R11, g)
|
MULALU R2, R8, (R11, g)
|
||||||
MULALU R1, R9, (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 g>>26, R12
|
||||||
MOVW R4>>26, R14
|
MOVW R4>>26, R14
|
||||||
ORR R11<<6, R12, R12
|
ORR R11<<6, R12, R12
|
||||||
|
@ -183,23 +196,23 @@ poly1305_blocks_armv6_mainloop_loaded:
|
||||||
MOVW R4>>26, R12
|
MOVW R4>>26, R12
|
||||||
BIC $0xfc000000, R4, R8
|
BIC $0xfc000000, R4, R8
|
||||||
ADD R12, R6, R9
|
ADD R12, R6, R9
|
||||||
MOVW w+44(SP), R12
|
MOVW 96(R13), R12
|
||||||
MOVW w+40(SP), R14
|
MOVW 92(R13), R14
|
||||||
MOVW R0, R6
|
MOVW R0, R6
|
||||||
CMP $32, R12
|
CMP $32, R12
|
||||||
SUB $16, R12, R12
|
SUB $16, R12, R12
|
||||||
MOVW R12, 44(R13)
|
MOVW R12, 96(R13)
|
||||||
BHS poly1305_blocks_armv6_mainloop
|
BHS poly1305_blocks_armv6_mainloop
|
||||||
|
|
||||||
poly1305_blocks_armv6_done:
|
poly1305_blocks_armv6_done:
|
||||||
MOVW 36(R13), R12
|
MOVW 88(R13), R12
|
||||||
MOVW R5, 20(R12)
|
MOVW R5, 20(R12)
|
||||||
MOVW R6, 24(R12)
|
MOVW R6, 24(R12)
|
||||||
MOVW R7, 28(R12)
|
MOVW R7, 28(R12)
|
||||||
MOVW R8, 32(R12)
|
MOVW R8, 32(R12)
|
||||||
MOVW R9, 36(R12)
|
MOVW R9, 36(R12)
|
||||||
ADD $128, R13, R13
|
ADD $48, R13, R0
|
||||||
MOVM.IA.W (R13), [R4, R5, R6, R7, R8, R9, g, R11, R14]
|
MOVM.DA (R0), [R4-R8, R14]
|
||||||
RET
|
RET
|
||||||
|
|
||||||
#define MOVHUP_UNALIGNED(Rsrc, Rdst, Rtmp) \
|
#define MOVHUP_UNALIGNED(Rsrc, Rdst, Rtmp) \
|
||||||
|
@ -212,9 +225,60 @@ poly1305_blocks_armv6_done:
|
||||||
MOVHUP_UNALIGNED(Rsrc, Rdst, Rtmp); \
|
MOVHUP_UNALIGNED(Rsrc, Rdst, Rtmp); \
|
||||||
MOVHUP_UNALIGNED(Rsrc, Rdst, Rtmp)
|
MOVHUP_UNALIGNED(Rsrc, Rdst, Rtmp)
|
||||||
|
|
||||||
TEXT poly1305_finish_ext_armv6<>(SB), NOSPLIT | NOFRAME, $0
|
// func poly1305_auth_armv6(out *[16]byte, m *byte, mlen uint32, key *[32]key)
|
||||||
MOVM.DB.W [R4, R5, R6, R7, R8, R9, g, R11, R14], (R13)
|
TEXT ·poly1305_auth_armv6(SB), $196-16
|
||||||
SUB $16, R13, R13
|
// 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 R0, R5
|
||||||
MOVW R1, R6
|
MOVW R1, R6
|
||||||
MOVW R2, R7
|
MOVW R2, R7
|
||||||
|
@ -222,11 +286,11 @@ TEXT poly1305_finish_ext_armv6<>(SB), NOSPLIT | NOFRAME, $0
|
||||||
AND.S R2, R2, R2
|
AND.S R2, R2, R2
|
||||||
BEQ poly1305_finish_ext_armv6_noremaining
|
BEQ poly1305_finish_ext_armv6_noremaining
|
||||||
EOR R0, R0
|
EOR R0, R0
|
||||||
MOVW R13, R9
|
ADD $8, R13, R9 // 8 = offset to 16 byte scratch space
|
||||||
MOVW R0, 0(R13)
|
MOVW R0, (R9)
|
||||||
MOVW R0, 4(R13)
|
MOVW R0, 4(R9)
|
||||||
MOVW R0, 8(R13)
|
MOVW R0, 8(R9)
|
||||||
MOVW R0, 12(R13)
|
MOVW R0, 12(R9)
|
||||||
WORD $0xe3110003 // TST R1, #3 not working see issue 5921
|
WORD $0xe3110003 // TST R1, #3 not working see issue 5921
|
||||||
BEQ poly1305_finish_ext_armv6_aligned
|
BEQ poly1305_finish_ext_armv6_aligned
|
||||||
WORD $0xe3120008 // TST R2, #8 not working see issue 5921
|
WORD $0xe3120008 // TST R2, #8 not working see issue 5921
|
||||||
|
@ -274,7 +338,7 @@ poly1305_finish_ext_armv6_skip1:
|
||||||
MOVBU R11, 0(R9)
|
MOVBU R11, 0(R9)
|
||||||
MOVW R11, 56(R5)
|
MOVW R11, 56(R5)
|
||||||
MOVW R5, R0
|
MOVW R5, R0
|
||||||
MOVW R13, R1
|
ADD $8, R13, R1
|
||||||
MOVW $16, R2
|
MOVW $16, R2
|
||||||
BL poly1305_blocks_armv6<>(SB)
|
BL poly1305_blocks_armv6<>(SB)
|
||||||
|
|
||||||
|
@ -313,14 +377,14 @@ poly1305_finish_ext_armv6_noremaining:
|
||||||
MOVW $-(1<<26), R12
|
MOVW $-(1<<26), R12
|
||||||
ADD R11>>26, R12, R12
|
ADD R11>>26, R12, R12
|
||||||
BIC $0xfc000000, R11, R11
|
BIC $0xfc000000, R11, R11
|
||||||
ADD R12, R4, R14
|
ADD R12, R4, R9
|
||||||
MOVW R14>>31, R12
|
MOVW R9>>31, R12
|
||||||
SUB $1, R12
|
SUB $1, R12
|
||||||
AND R12, R6, R6
|
AND R12, R6, R6
|
||||||
AND R12, R7, R7
|
AND R12, R7, R7
|
||||||
AND R12, g, g
|
AND R12, g, g
|
||||||
AND R12, R11, R11
|
AND R12, R11, R11
|
||||||
AND R12, R14, R14
|
AND R12, R9, R9
|
||||||
MVN R12, R12
|
MVN R12, R12
|
||||||
AND R12, R0, R0
|
AND R12, R0, R0
|
||||||
AND R12, R1, R1
|
AND R12, R1, R1
|
||||||
|
@ -331,7 +395,7 @@ poly1305_finish_ext_armv6_noremaining:
|
||||||
ORR R7, R1, R1
|
ORR R7, R1, R1
|
||||||
ORR g, R2, R2
|
ORR g, R2, R2
|
||||||
ORR R11, R3, R3
|
ORR R11, R3, R3
|
||||||
ORR R14, R4, R4
|
ORR R9, R4, R4
|
||||||
ORR R1<<26, R0, R0
|
ORR R1<<26, R0, R0
|
||||||
MOVW R1>>6, R1
|
MOVW R1>>6, R1
|
||||||
ORR R2<<20, R1, R1
|
ORR R2<<20, R1, R1
|
||||||
|
@ -359,36 +423,5 @@ poly1305_finish_ext_armv6_noremaining:
|
||||||
EOR R7, R7, R7
|
EOR R7, R7, R7
|
||||||
MOVM.IA.W [R0-R7], (R12)
|
MOVM.IA.W [R0-R7], (R12)
|
||||||
MOVM.IA [R0-R7], (R12)
|
MOVM.IA [R0-R7], (R12)
|
||||||
ADD $16, R13, R13
|
MOVW 4(R13), g
|
||||||
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
|
|
||||||
RET
|
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)
|
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) {
|
func testAgentInterface(t *testing.T, agent Agent, key interface{}, cert *ssh.Certificate, lifetimeSecs uint32) {
|
||||||
signer, err := ssh.NewSignerFromKey(key)
|
signer, err := ssh.NewSignerFromKey(key)
|
||||||
if err != nil {
|
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 {
|
if err := pubKey.Verify(data, sig); err != nil {
|
||||||
t.Fatalf("Verify(%s): %v", pubKey.Type(), err)
|
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) {
|
func TestAgent(t *testing.T) {
|
||||||
for _, keyType := range []string{"rsa", "dsa", "ecdsa", "ed25519"} {
|
for _, keyType := range []string{"rsa", "dsa", "ecdsa", "ed25519"} {
|
||||||
testAgent(t, testPrivateKeys[keyType], nil, 0)
|
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"])
|
cert.SignCert(rand.Reader, testSigners["ecdsa"])
|
||||||
|
|
||||||
testAgent(t, testPrivateKeys["rsa"], cert, 0)
|
testAgent(t, testPrivateKeys["rsa"], cert, 0)
|
||||||
}
|
testKeyring(t, testPrivateKeys["rsa"], cert, 1)
|
||||||
|
|
||||||
func TestConstraints(t *testing.T) {
|
|
||||||
testAgent(t, testPrivateKeys["rsa"], nil, 3600 /* lifetime in seconds */)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// netPipe is analogous to net.Pipe, but it uses a real net.Conn, and
|
// 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
|
// therefore is buffered (net.Pipe deadlocks if both sides start with
|
||||||
// a write.)
|
// a write.)
|
||||||
func netPipe() (net.Conn, net.Conn, error) {
|
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 {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
|
@ -217,7 +233,9 @@ func TestAuth(t *testing.T) {
|
||||||
conn.Close()
|
conn.Close()
|
||||||
}()
|
}()
|
||||||
|
|
||||||
conf := ssh.ClientConfig{}
|
conf := ssh.ClientConfig{
|
||||||
|
HostKeyCallback: ssh.InsecureIgnoreHostKey(),
|
||||||
|
}
|
||||||
conf.Auth = append(conf.Auth, ssh.PublicKeysCallback(agent.Signers))
|
conf.Auth = append(conf.Auth, ssh.PublicKeysCallback(agent.Signers))
|
||||||
conn, _, _, err := ssh.NewClientConn(b, "", &conf)
|
conn, _, _, err := ssh.NewClientConn(b, "", &conf)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -6,8 +6,8 @@ package agent_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"log"
|
"log"
|
||||||
"os"
|
|
||||||
"net"
|
"net"
|
||||||
|
"os"
|
||||||
|
|
||||||
"golang.org/x/crypto/ssh"
|
"golang.org/x/crypto/ssh"
|
||||||
"golang.org/x/crypto/ssh/agent"
|
"golang.org/x/crypto/ssh/agent"
|
||||||
|
@ -29,6 +29,7 @@ func ExampleClientAgent() {
|
||||||
// wants it.
|
// wants it.
|
||||||
ssh.PublicKeysCallback(agentClient.Signers),
|
ssh.PublicKeysCallback(agentClient.Signers),
|
||||||
},
|
},
|
||||||
|
HostKeyCallback: ssh.InsecureIgnoreHostKey(),
|
||||||
}
|
}
|
||||||
|
|
||||||
sshc, err := ssh.Dial("tcp", "localhost:22", config)
|
sshc, err := ssh.Dial("tcp", "localhost:22", config)
|
||||||
|
|
|
@ -11,6 +11,7 @@ import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"sync"
|
"sync"
|
||||||
|
"time"
|
||||||
|
|
||||||
"golang.org/x/crypto/ssh"
|
"golang.org/x/crypto/ssh"
|
||||||
)
|
)
|
||||||
|
@ -18,6 +19,7 @@ import (
|
||||||
type privKey struct {
|
type privKey struct {
|
||||||
signer ssh.Signer
|
signer ssh.Signer
|
||||||
comment string
|
comment string
|
||||||
|
expire *time.Time
|
||||||
}
|
}
|
||||||
|
|
||||||
type keyring struct {
|
type keyring struct {
|
||||||
|
@ -48,15 +50,9 @@ func (r *keyring) RemoveAll() error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove removes all identities with the given public key.
|
// removeLocked does the actual key removal. The caller must already be holding the
|
||||||
func (r *keyring) Remove(key ssh.PublicKey) error {
|
// keyring mutex.
|
||||||
r.mu.Lock()
|
func (r *keyring) removeLocked(want []byte) error {
|
||||||
defer r.mu.Unlock()
|
|
||||||
if r.locked {
|
|
||||||
return errLocked
|
|
||||||
}
|
|
||||||
|
|
||||||
want := key.Marshal()
|
|
||||||
found := false
|
found := false
|
||||||
for i := 0; i < len(r.keys); {
|
for i := 0; i < len(r.keys); {
|
||||||
if bytes.Equal(r.keys[i].signer.PublicKey().Marshal(), want) {
|
if bytes.Equal(r.keys[i].signer.PublicKey().Marshal(), want) {
|
||||||
|
@ -75,7 +71,18 @@ func (r *keyring) Remove(key ssh.PublicKey) error {
|
||||||
return nil
|
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 {
|
func (r *keyring) Lock(passphrase []byte) error {
|
||||||
r.mu.Lock()
|
r.mu.Lock()
|
||||||
defer r.mu.Unlock()
|
defer r.mu.Unlock()
|
||||||
|
@ -104,6 +111,17 @@ func (r *keyring) Unlock(passphrase []byte) error {
|
||||||
return nil
|
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.
|
// List returns the identities known to the agent.
|
||||||
func (r *keyring) List() ([]*Key, error) {
|
func (r *keyring) List() ([]*Key, error) {
|
||||||
r.mu.Lock()
|
r.mu.Lock()
|
||||||
|
@ -113,6 +131,7 @@ func (r *keyring) List() ([]*Key, error) {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
r.expireKeysLocked()
|
||||||
var ids []*Key
|
var ids []*Key
|
||||||
for _, k := range r.keys {
|
for _, k := range r.keys {
|
||||||
pub := k.signer.PublicKey()
|
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
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -159,6 +188,7 @@ func (r *keyring) Sign(key ssh.PublicKey, data []byte) (*ssh.Signature, error) {
|
||||||
return nil, errLocked
|
return nil, errLocked
|
||||||
}
|
}
|
||||||
|
|
||||||
|
r.expireKeysLocked()
|
||||||
wanted := key.Marshal()
|
wanted := key.Marshal()
|
||||||
for _, k := range r.keys {
|
for _, k := range r.keys {
|
||||||
if bytes.Equal(k.signer.PublicKey().Marshal(), wanted) {
|
if bytes.Equal(k.signer.PublicKey().Marshal(), wanted) {
|
||||||
|
@ -176,6 +206,7 @@ func (r *keyring) Signers() ([]ssh.Signer, error) {
|
||||||
return nil, errLocked
|
return nil, errLocked
|
||||||
}
|
}
|
||||||
|
|
||||||
|
r.expireKeysLocked()
|
||||||
s := make([]ssh.Signer, 0, len(r.keys))
|
s := make([]ssh.Signer, 0, len(r.keys))
|
||||||
for _, k := range r.keys {
|
for _, k := range r.keys {
|
||||||
s = append(s, k.signer)
|
s = append(s, k.signer)
|
||||||
|
|
|
@ -4,9 +4,7 @@
|
||||||
|
|
||||||
package agent
|
package agent
|
||||||
|
|
||||||
import (
|
import "testing"
|
||||||
"testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
func addTestKey(t *testing.T, a Agent, keyName string) {
|
func addTestKey(t *testing.T, a Agent, keyName string) {
|
||||||
err := a.Add(AddedKey{
|
err := a.Add(AddedKey{
|
||||||
|
|
|
@ -56,7 +56,9 @@ func TestSetupForwardAgent(t *testing.T) {
|
||||||
incoming <- conn
|
incoming <- conn
|
||||||
}()
|
}()
|
||||||
|
|
||||||
conf := ssh.ClientConfig{}
|
conf := ssh.ClientConfig{
|
||||||
|
HostKeyCallback: ssh.InsecureIgnoreHostKey(),
|
||||||
|
}
|
||||||
conn, chans, reqs, err := ssh.NewClientConn(b, "", &conf)
|
conn, chans, reqs, err := ssh.NewClientConn(b, "", &conf)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("NewClientConn: %v", err)
|
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
|
// HostKeyFallback is called when CertChecker.CheckHostKey encounters a
|
||||||
// public key that is not a certificate. It must implement host key
|
// public key that is not a certificate. It must implement host key
|
||||||
// validation or else, if nil, all such keys are rejected.
|
// 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
|
// IsRevoked is called for each certificate so that revocation checking
|
||||||
// can be implemented. It should return true if the given certificate
|
// 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(),
|
pending: newBuffer(),
|
||||||
extPending: newBuffer(),
|
extPending: newBuffer(),
|
||||||
direction: direction,
|
direction: direction,
|
||||||
incomingRequests: make(chan *Request, 16),
|
incomingRequests: make(chan *Request, chanSize),
|
||||||
msg: make(chan interface{}, 16),
|
msg: make(chan interface{}, chanSize),
|
||||||
chanType: chanType,
|
chanType: chanType,
|
||||||
extraData: extraData,
|
extraData: extraData,
|
||||||
mux: m,
|
mux: m,
|
||||||
|
|
50
vendor/src/golang.org/x/crypto/ssh/cipher.go
vendored
50
vendor/src/golang.org/x/crypto/ssh/cipher.go
vendored
|
@ -135,6 +135,7 @@ const prefixLen = 5
|
||||||
type streamPacketCipher struct {
|
type streamPacketCipher struct {
|
||||||
mac hash.Hash
|
mac hash.Hash
|
||||||
cipher cipher.Stream
|
cipher cipher.Stream
|
||||||
|
etm bool
|
||||||
|
|
||||||
// The following members are to avoid per-packet allocations.
|
// The following members are to avoid per-packet allocations.
|
||||||
prefix [prefixLen]byte
|
prefix [prefixLen]byte
|
||||||
|
@ -150,7 +151,14 @@ func (s *streamPacketCipher) readPacket(seqNum uint32, r io.Reader) ([]byte, err
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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[:])
|
s.cipher.XORKeyStream(s.prefix[:], s.prefix[:])
|
||||||
|
}
|
||||||
|
|
||||||
length := binary.BigEndian.Uint32(s.prefix[0:4])
|
length := binary.BigEndian.Uint32(s.prefix[0:4])
|
||||||
paddingLength := uint32(s.prefix[4])
|
paddingLength := uint32(s.prefix[4])
|
||||||
|
|
||||||
|
@ -159,7 +167,12 @@ func (s *streamPacketCipher) readPacket(seqNum uint32, r io.Reader) ([]byte, err
|
||||||
s.mac.Reset()
|
s.mac.Reset()
|
||||||
binary.BigEndian.PutUint32(s.seqNumBytes[:], seqNum)
|
binary.BigEndian.PutUint32(s.seqNumBytes[:], seqNum)
|
||||||
s.mac.Write(s.seqNumBytes[:])
|
s.mac.Write(s.seqNumBytes[:])
|
||||||
|
if s.etm {
|
||||||
|
s.mac.Write(s.prefix[:4])
|
||||||
|
s.mac.Write(encryptedPaddingLength[:])
|
||||||
|
} else {
|
||||||
s.mac.Write(s.prefix[:])
|
s.mac.Write(s.prefix[:])
|
||||||
|
}
|
||||||
macSize = uint32(s.mac.Size())
|
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:]
|
mac := s.packetData[length-1:]
|
||||||
data := s.packetData[:length-1]
|
data := s.packetData[:length-1]
|
||||||
|
|
||||||
|
if s.mac != nil && s.etm {
|
||||||
|
s.mac.Write(data)
|
||||||
|
}
|
||||||
|
|
||||||
s.cipher.XORKeyStream(data, data)
|
s.cipher.XORKeyStream(data, data)
|
||||||
|
|
||||||
if s.mac != nil {
|
if s.mac != nil {
|
||||||
|
if !s.etm {
|
||||||
s.mac.Write(data)
|
s.mac.Write(data)
|
||||||
|
}
|
||||||
s.macResult = s.mac.Sum(s.macResult[:0])
|
s.macResult = s.mac.Sum(s.macResult[:0])
|
||||||
if subtle.ConstantTimeCompare(s.macResult, mac) != 1 {
|
if subtle.ConstantTimeCompare(s.macResult, mac) != 1 {
|
||||||
return nil, errors.New("ssh: MAC failure")
|
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")
|
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 {
|
if paddingLength < 4 {
|
||||||
paddingLength += packetSizeMultiple
|
paddingLength += packetSizeMultiple
|
||||||
}
|
}
|
||||||
|
@ -220,15 +246,37 @@ func (s *streamPacketCipher) writePacket(seqNum uint32, w io.Writer, rand io.Rea
|
||||||
s.mac.Reset()
|
s.mac.Reset()
|
||||||
binary.BigEndian.PutUint32(s.seqNumBytes[:], seqNum)
|
binary.BigEndian.PutUint32(s.seqNumBytes[:], seqNum)
|
||||||
s.mac.Write(s.seqNumBytes[:])
|
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[:])
|
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(packet)
|
||||||
s.mac.Write(padding)
|
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(s.prefix[:], s.prefix[:])
|
||||||
|
}
|
||||||
|
|
||||||
s.cipher.XORKeyStream(packet, packet)
|
s.cipher.XORKeyStream(packet, packet)
|
||||||
s.cipher.XORKeyStream(padding, padding)
|
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)
|
||||||
|
}
|
||||||
|
|
||||||
if _, err := w.Write(s.prefix[:]); err != nil {
|
if _, err := w.Write(s.prefix[:]); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,20 +26,21 @@ func TestPacketCiphers(t *testing.T) {
|
||||||
defer delete(cipherModes, aes128cbcID)
|
defer delete(cipherModes, aes128cbcID)
|
||||||
|
|
||||||
for cipher := range cipherModes {
|
for cipher := range cipherModes {
|
||||||
|
for mac := range macModes {
|
||||||
kr := &kexResult{Hash: crypto.SHA1}
|
kr := &kexResult{Hash: crypto.SHA1}
|
||||||
algs := directionAlgorithms{
|
algs := directionAlgorithms{
|
||||||
Cipher: cipher,
|
Cipher: cipher,
|
||||||
MAC: "hmac-sha1",
|
MAC: mac,
|
||||||
Compression: "none",
|
Compression: "none",
|
||||||
}
|
}
|
||||||
client, err := newPacketCipher(clientKeys, algs, kr)
|
client, err := newPacketCipher(clientKeys, algs, kr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("newPacketCipher(client, %q): %v", cipher, err)
|
t.Errorf("newPacketCipher(client, %q, %q): %v", cipher, mac, err)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
server, err := newPacketCipher(clientKeys, algs, kr)
|
server, err := newPacketCipher(clientKeys, algs, kr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("newPacketCipher(client, %q): %v", cipher, err)
|
t.Errorf("newPacketCipher(client, %q, %q): %v", cipher, mac, err)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -47,18 +48,19 @@ func TestPacketCiphers(t *testing.T) {
|
||||||
input := []byte(want)
|
input := []byte(want)
|
||||||
buf := &bytes.Buffer{}
|
buf := &bytes.Buffer{}
|
||||||
if err := client.writePacket(0, buf, rand.Reader, input); err != nil {
|
if err := client.writePacket(0, buf, rand.Reader, input); err != nil {
|
||||||
t.Errorf("writePacket(%q): %v", cipher, err)
|
t.Errorf("writePacket(%q, %q): %v", cipher, mac, err)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
packet, err := server.readPacket(0, buf)
|
packet, err := server.readPacket(0, buf)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("readPacket(%q): %v", cipher, err)
|
t.Errorf("readPacket(%q, %q): %v", cipher, mac, err)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
if string(packet) != want {
|
if string(packet) != want {
|
||||||
t.Errorf("roundtrip(%q): got %q, want %q", cipher, 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
|
package ssh
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
|
@ -13,7 +14,7 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
// Client implements a traditional SSH client that supports shells,
|
// 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 {
|
type Client struct {
|
||||||
Conn
|
Conn
|
||||||
|
|
||||||
|
@ -40,7 +41,7 @@ func (c *Client) HandleChannelOpen(channelType string) <-chan NewChannel {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
ch = make(chan NewChannel, 16)
|
ch = make(chan NewChannel, chanSize)
|
||||||
c.channelHandlers[channelType] = ch
|
c.channelHandlers[channelType] = ch
|
||||||
return ch
|
return ch
|
||||||
}
|
}
|
||||||
|
@ -59,6 +60,7 @@ func NewClient(c Conn, chans <-chan NewChannel, reqs <-chan *Request) *Client {
|
||||||
conn.forwards.closeAll()
|
conn.forwards.closeAll()
|
||||||
}()
|
}()
|
||||||
go conn.forwards.handleChannels(conn.HandleChannelOpen("forwarded-tcpip"))
|
go conn.forwards.handleChannels(conn.HandleChannelOpen("forwarded-tcpip"))
|
||||||
|
go conn.forwards.handleChannels(conn.HandleChannelOpen("forwarded-streamlocal@openssh.com"))
|
||||||
return conn
|
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) {
|
func NewClientConn(c net.Conn, addr string, config *ClientConfig) (Conn, <-chan NewChannel, <-chan *Request, error) {
|
||||||
fullConf := *config
|
fullConf := *config
|
||||||
fullConf.SetDefaults()
|
fullConf.SetDefaults()
|
||||||
|
if fullConf.HostKeyCallback == nil {
|
||||||
|
c.Close()
|
||||||
|
return nil, nil, nil, errors.New("ssh: must specify HostKeyCallback")
|
||||||
|
}
|
||||||
|
|
||||||
conn := &connection{
|
conn := &connection{
|
||||||
sshConn: sshConn{conn: c},
|
sshConn: sshConn{conn: c},
|
||||||
}
|
}
|
||||||
|
@ -97,13 +104,11 @@ func (c *connection) clientHandshake(dialAddress string, config *ClientConfig) e
|
||||||
c.transport = newClientTransport(
|
c.transport = newClientTransport(
|
||||||
newTransport(c.sshConn.conn, config.Rand, true /* is client */),
|
newTransport(c.sshConn.conn, config.Rand, true /* is client */),
|
||||||
c.clientVersion, c.serverVersion, config, dialAddress, c.sshConn.RemoteAddr())
|
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
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// We just did the key change, so the session ID is established.
|
|
||||||
c.sessionID = c.transport.getSessionID()
|
c.sessionID = c.transport.getSessionID()
|
||||||
|
|
||||||
return c.clientAuthenticate(config)
|
return c.clientAuthenticate(config)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -175,6 +180,13 @@ func Dial(network, addr string, config *ClientConfig) (*Client, error) {
|
||||||
return NewClient(c, chans, reqs), nil
|
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
|
// A ClientConfig structure is used to configure a Client. It must not be
|
||||||
// modified after having been passed to an SSH function.
|
// modified after having been passed to an SSH function.
|
||||||
type ClientConfig struct {
|
type ClientConfig struct {
|
||||||
|
@ -190,10 +202,12 @@ type ClientConfig struct {
|
||||||
// be used during authentication.
|
// be used during authentication.
|
||||||
Auth []AuthMethod
|
Auth []AuthMethod
|
||||||
|
|
||||||
// HostKeyCallback, if not nil, is called during the cryptographic
|
// HostKeyCallback is called during the cryptographic
|
||||||
// handshake to validate the server's host key. A nil HostKeyCallback
|
// handshake to validate the server's host key. The client
|
||||||
// implies that all host keys are accepted.
|
// configuration must supply this callback for the connection
|
||||||
HostKeyCallback func(hostname string, remote net.Addr, key PublicKey) error
|
// 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
|
// ClientVersion contains the version identification string that will
|
||||||
// be used for the connection. If empty, a reasonable default is used.
|
// 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.
|
// A Timeout of zero means no timeout.
|
||||||
Timeout time.Duration
|
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.
|
// then any untried methods suggested by the server.
|
||||||
tried := make(map[string]bool)
|
tried := make(map[string]bool)
|
||||||
var lastMethods []string
|
var lastMethods []string
|
||||||
|
|
||||||
|
sessionID := c.transport.getSessionID()
|
||||||
for auth := AuthMethod(new(noneAuth)); auth != nil; {
|
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 {
|
if err != nil {
|
||||||
return err
|
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) {
|
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
|
// Authentication is performed by sending an enquiry to test if a key is
|
||||||
// enquiry to test if each key is acceptable to the remote. The second
|
// acceptable to the remote. If the key is acceptable, the client will
|
||||||
// stage attempts to authenticate with the valid keys obtained in the
|
// attempt to authenticate with the valid key. If not the client will repeat
|
||||||
// first stage.
|
// the process with the remaining keys.
|
||||||
|
|
||||||
signers, err := cb()
|
signers, err := cb()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, nil, err
|
return false, nil, err
|
||||||
}
|
}
|
||||||
var validKeys []Signer
|
var methods []string
|
||||||
for _, signer := range signers {
|
for _, signer := range signers {
|
||||||
if ok, err := validateKey(signer.PublicKey(), user, c); ok {
|
ok, err := validateKey(signer.PublicKey(), user, c)
|
||||||
validKeys = append(validKeys, signer)
|
|
||||||
} else {
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, nil, err
|
return false, nil, err
|
||||||
}
|
}
|
||||||
}
|
if !ok {
|
||||||
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
// methods that may continue if this auth is not successful.
|
|
||||||
var methods []string
|
|
||||||
for _, signer := range validKeys {
|
|
||||||
pub := signer.PublicKey()
|
pub := signer.PublicKey()
|
||||||
|
|
||||||
pubKey := pub.Marshal()
|
pubKey := pub.Marshal()
|
||||||
sign, err := signer.Sign(rand, buildDataSignedForAuth(session, userAuthRequestMsg{
|
sign, err := signer.Sign(rand, buildDataSignedForAuth(session, userAuthRequestMsg{
|
||||||
User: user,
|
User: user,
|
||||||
|
@ -234,13 +231,29 @@ func (cb publicKeyCallback) auth(session []byte, user string, c packetConn, rand
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, nil, err
|
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 success, methods, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return false, methods, nil
|
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.
|
// validateKey validates the key provided is acceptable to the server.
|
||||||
func validateKey(key PublicKey, user string, c packetConn) (bool, error) {
|
func validateKey(key PublicKey, user string, c packetConn) (bool, error) {
|
||||||
pubKey := key.Marshal()
|
pubKey := key.Marshal()
|
||||||
|
|
|
@ -76,9 +76,6 @@ func tryAuth(t *testing.T, config *ClientConfig) error {
|
||||||
}
|
}
|
||||||
return nil, errors.New("keyboard-interactive failed")
|
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"])
|
serverConfig.AddHostKey(testSigners["rsa"])
|
||||||
|
|
||||||
|
@ -93,6 +90,7 @@ func TestClientAuthPublicKey(t *testing.T) {
|
||||||
Auth: []AuthMethod{
|
Auth: []AuthMethod{
|
||||||
PublicKeys(testSigners["rsa"]),
|
PublicKeys(testSigners["rsa"]),
|
||||||
},
|
},
|
||||||
|
HostKeyCallback: InsecureIgnoreHostKey(),
|
||||||
}
|
}
|
||||||
if err := tryAuth(t, config); err != nil {
|
if err := tryAuth(t, config); err != nil {
|
||||||
t.Fatalf("unable to dial remote side: %s", err)
|
t.Fatalf("unable to dial remote side: %s", err)
|
||||||
|
@ -105,6 +103,7 @@ func TestAuthMethodPassword(t *testing.T) {
|
||||||
Auth: []AuthMethod{
|
Auth: []AuthMethod{
|
||||||
Password(clientPassword),
|
Password(clientPassword),
|
||||||
},
|
},
|
||||||
|
HostKeyCallback: InsecureIgnoreHostKey(),
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := tryAuth(t, config); err != nil {
|
if err := tryAuth(t, config); err != nil {
|
||||||
|
@ -124,6 +123,7 @@ func TestAuthMethodFallback(t *testing.T) {
|
||||||
return "WRONG", nil
|
return "WRONG", nil
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
|
HostKeyCallback: InsecureIgnoreHostKey(),
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := tryAuth(t, config); err != nil {
|
if err := tryAuth(t, config); err != nil {
|
||||||
|
@ -142,6 +142,7 @@ func TestAuthMethodWrongPassword(t *testing.T) {
|
||||||
Password("wrong"),
|
Password("wrong"),
|
||||||
PublicKeys(testSigners["rsa"]),
|
PublicKeys(testSigners["rsa"]),
|
||||||
},
|
},
|
||||||
|
HostKeyCallback: InsecureIgnoreHostKey(),
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := tryAuth(t, config); err != nil {
|
if err := tryAuth(t, config); err != nil {
|
||||||
|
@ -159,6 +160,7 @@ func TestAuthMethodKeyboardInteractive(t *testing.T) {
|
||||||
Auth: []AuthMethod{
|
Auth: []AuthMethod{
|
||||||
KeyboardInteractive(answers.Challenge),
|
KeyboardInteractive(answers.Challenge),
|
||||||
},
|
},
|
||||||
|
HostKeyCallback: InsecureIgnoreHostKey(),
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := tryAuth(t, config); err != nil {
|
if err := tryAuth(t, config); err != nil {
|
||||||
|
@ -204,6 +206,7 @@ func TestAuthMethodRSAandDSA(t *testing.T) {
|
||||||
Auth: []AuthMethod{
|
Auth: []AuthMethod{
|
||||||
PublicKeys(testSigners["dsa"], testSigners["rsa"]),
|
PublicKeys(testSigners["dsa"], testSigners["rsa"]),
|
||||||
},
|
},
|
||||||
|
HostKeyCallback: InsecureIgnoreHostKey(),
|
||||||
}
|
}
|
||||||
if err := tryAuth(t, config); err != nil {
|
if err := tryAuth(t, config); err != nil {
|
||||||
t.Fatalf("client could not authenticate with rsa key: %v", err)
|
t.Fatalf("client could not authenticate with rsa key: %v", err)
|
||||||
|
@ -220,6 +223,7 @@ func TestClientHMAC(t *testing.T) {
|
||||||
Config: Config{
|
Config: Config{
|
||||||
MACs: []string{mac},
|
MACs: []string{mac},
|
||||||
},
|
},
|
||||||
|
HostKeyCallback: InsecureIgnoreHostKey(),
|
||||||
}
|
}
|
||||||
if err := tryAuth(t, config); err != nil {
|
if err := tryAuth(t, config); err != nil {
|
||||||
t.Fatalf("client could not authenticate with mac algo %s: %v", mac, err)
|
t.Fatalf("client could not authenticate with mac algo %s: %v", mac, err)
|
||||||
|
@ -255,6 +259,7 @@ func TestClientUnsupportedKex(t *testing.T) {
|
||||||
Config: Config{
|
Config: Config{
|
||||||
KeyExchanges: []string{"diffie-hellman-group-exchange-sha256"}, // not currently supported
|
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") {
|
if err := tryAuth(t, config); err == nil || !strings.Contains(err.Error(), "common algorithm") {
|
||||||
t.Errorf("got %v, expected 'common algorithm'", err)
|
t.Errorf("got %v, expected 'common algorithm'", err)
|
||||||
|
@ -275,21 +280,22 @@ func TestClientLoginCert(t *testing.T) {
|
||||||
|
|
||||||
clientConfig := &ClientConfig{
|
clientConfig := &ClientConfig{
|
||||||
User: "user",
|
User: "user",
|
||||||
|
HostKeyCallback: InsecureIgnoreHostKey(),
|
||||||
}
|
}
|
||||||
clientConfig.Auth = append(clientConfig.Auth, PublicKeys(certSigner))
|
clientConfig.Auth = append(clientConfig.Auth, PublicKeys(certSigner))
|
||||||
|
|
||||||
t.Log("should succeed")
|
// should succeed
|
||||||
if err := tryAuth(t, clientConfig); err != nil {
|
if err := tryAuth(t, clientConfig); err != nil {
|
||||||
t.Errorf("cert login failed: %v", err)
|
t.Errorf("cert login failed: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
t.Log("corrupted signature")
|
// corrupted signature
|
||||||
cert.Signature.Blob[0]++
|
cert.Signature.Blob[0]++
|
||||||
if err := tryAuth(t, clientConfig); err == nil {
|
if err := tryAuth(t, clientConfig); err == nil {
|
||||||
t.Errorf("cert login passed with corrupted sig")
|
t.Errorf("cert login passed with corrupted sig")
|
||||||
}
|
}
|
||||||
|
|
||||||
t.Log("revoked")
|
// revoked
|
||||||
cert.Serial = 666
|
cert.Serial = 666
|
||||||
cert.SignCert(rand.Reader, testSigners["ecdsa"])
|
cert.SignCert(rand.Reader, testSigners["ecdsa"])
|
||||||
if err := tryAuth(t, clientConfig); err == nil {
|
if err := tryAuth(t, clientConfig); err == nil {
|
||||||
|
@ -297,13 +303,13 @@ func TestClientLoginCert(t *testing.T) {
|
||||||
}
|
}
|
||||||
cert.Serial = 1
|
cert.Serial = 1
|
||||||
|
|
||||||
t.Log("sign with wrong key")
|
// sign with wrong key
|
||||||
cert.SignCert(rand.Reader, testSigners["dsa"])
|
cert.SignCert(rand.Reader, testSigners["dsa"])
|
||||||
if err := tryAuth(t, clientConfig); err == nil {
|
if err := tryAuth(t, clientConfig); err == nil {
|
||||||
t.Errorf("cert login passed with non-authoritative key")
|
t.Errorf("cert login passed with non-authoritative key")
|
||||||
}
|
}
|
||||||
|
|
||||||
t.Log("host cert")
|
// host cert
|
||||||
cert.CertType = HostCert
|
cert.CertType = HostCert
|
||||||
cert.SignCert(rand.Reader, testSigners["ecdsa"])
|
cert.SignCert(rand.Reader, testSigners["ecdsa"])
|
||||||
if err := tryAuth(t, clientConfig); err == nil {
|
if err := tryAuth(t, clientConfig); err == nil {
|
||||||
|
@ -311,14 +317,14 @@ func TestClientLoginCert(t *testing.T) {
|
||||||
}
|
}
|
||||||
cert.CertType = UserCert
|
cert.CertType = UserCert
|
||||||
|
|
||||||
t.Log("principal specified")
|
// principal specified
|
||||||
cert.ValidPrincipals = []string{"user"}
|
cert.ValidPrincipals = []string{"user"}
|
||||||
cert.SignCert(rand.Reader, testSigners["ecdsa"])
|
cert.SignCert(rand.Reader, testSigners["ecdsa"])
|
||||||
if err := tryAuth(t, clientConfig); err != nil {
|
if err := tryAuth(t, clientConfig); err != nil {
|
||||||
t.Errorf("cert login failed: %v", err)
|
t.Errorf("cert login failed: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
t.Log("wrong principal specified")
|
// wrong principal specified
|
||||||
cert.ValidPrincipals = []string{"fred"}
|
cert.ValidPrincipals = []string{"fred"}
|
||||||
cert.SignCert(rand.Reader, testSigners["ecdsa"])
|
cert.SignCert(rand.Reader, testSigners["ecdsa"])
|
||||||
if err := tryAuth(t, clientConfig); err == nil {
|
if err := tryAuth(t, clientConfig); err == nil {
|
||||||
|
@ -326,22 +332,22 @@ func TestClientLoginCert(t *testing.T) {
|
||||||
}
|
}
|
||||||
cert.ValidPrincipals = nil
|
cert.ValidPrincipals = nil
|
||||||
|
|
||||||
t.Log("added critical option")
|
// added critical option
|
||||||
cert.CriticalOptions = map[string]string{"root-access": "yes"}
|
cert.CriticalOptions = map[string]string{"root-access": "yes"}
|
||||||
cert.SignCert(rand.Reader, testSigners["ecdsa"])
|
cert.SignCert(rand.Reader, testSigners["ecdsa"])
|
||||||
if err := tryAuth(t, clientConfig); err == nil {
|
if err := tryAuth(t, clientConfig); err == nil {
|
||||||
t.Errorf("cert login passed with unrecognized critical option")
|
t.Errorf("cert login passed with unrecognized critical option")
|
||||||
}
|
}
|
||||||
|
|
||||||
t.Log("allowed source address")
|
// allowed source address
|
||||||
cert.CriticalOptions = map[string]string{"source-address": "127.0.0.42/24"}
|
cert.CriticalOptions = map[string]string{"source-address": "127.0.0.42/24,::42/120"}
|
||||||
cert.SignCert(rand.Reader, testSigners["ecdsa"])
|
cert.SignCert(rand.Reader, testSigners["ecdsa"])
|
||||||
if err := tryAuth(t, clientConfig); err != nil {
|
if err := tryAuth(t, clientConfig); err != nil {
|
||||||
t.Errorf("cert login with source-address failed: %v", err)
|
t.Errorf("cert login with source-address failed: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
t.Log("disallowed source address")
|
// disallowed source address
|
||||||
cert.CriticalOptions = map[string]string{"source-address": "127.0.0.42"}
|
cert.CriticalOptions = map[string]string{"source-address": "127.0.0.42,::42"}
|
||||||
cert.SignCert(rand.Reader, testSigners["ecdsa"])
|
cert.SignCert(rand.Reader, testSigners["ecdsa"])
|
||||||
if err := tryAuth(t, clientConfig); err == nil {
|
if err := tryAuth(t, clientConfig); err == nil {
|
||||||
t.Errorf("cert login with source-address succeeded")
|
t.Errorf("cert login with source-address succeeded")
|
||||||
|
@ -364,6 +370,7 @@ func testPermissionsPassing(withPermissions bool, t *testing.T) {
|
||||||
Auth: []AuthMethod{
|
Auth: []AuthMethod{
|
||||||
PublicKeys(testSigners["rsa"]),
|
PublicKeys(testSigners["rsa"]),
|
||||||
},
|
},
|
||||||
|
HostKeyCallback: InsecureIgnoreHostKey(),
|
||||||
}
|
}
|
||||||
if withPermissions {
|
if withPermissions {
|
||||||
clientConfig.User = "permissions"
|
clientConfig.User = "permissions"
|
||||||
|
@ -410,6 +417,7 @@ func TestRetryableAuth(t *testing.T) {
|
||||||
}), 2),
|
}), 2),
|
||||||
PublicKeys(testSigners["rsa"]),
|
PublicKeys(testSigners["rsa"]),
|
||||||
},
|
},
|
||||||
|
HostKeyCallback: InsecureIgnoreHostKey(),
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := tryAuth(t, config); err != nil {
|
if err := tryAuth(t, config); err != nil {
|
||||||
|
@ -431,6 +439,7 @@ func ExampleRetryableAuthMethod(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
config := &ClientConfig{
|
config := &ClientConfig{
|
||||||
|
HostKeyCallback: InsecureIgnoreHostKey(),
|
||||||
User: user,
|
User: user,
|
||||||
Auth: []AuthMethod{
|
Auth: []AuthMethod{
|
||||||
RetryableAuthMethod(KeyboardInteractiveChallenge(Cb), NumberOfPrompts),
|
RetryableAuthMethod(KeyboardInteractiveChallenge(Cb), NumberOfPrompts),
|
||||||
|
@ -452,6 +461,7 @@ func TestClientAuthNone(t *testing.T) {
|
||||||
|
|
||||||
clientConfig := &ClientConfig{
|
clientConfig := &ClientConfig{
|
||||||
User: user,
|
User: user,
|
||||||
|
HostKeyCallback: InsecureIgnoreHostKey(),
|
||||||
}
|
}
|
||||||
|
|
||||||
c1, c2, err := netPipe()
|
c1, c2, err := netPipe()
|
||||||
|
@ -464,9 +474,106 @@ func TestClientAuthNone(t *testing.T) {
|
||||||
go NewClientConn(c2, "", clientConfig)
|
go NewClientConn(c2, "", clientConfig)
|
||||||
serverConn, err := newServer(c1, serverConfig)
|
serverConn, err := newServer(c1, serverConfig)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal("newServer: %v", err)
|
t.Fatalf("newServer: %v", err)
|
||||||
}
|
}
|
||||||
if serverConn.User() != user {
|
if serverConn.User() != user {
|
||||||
t.Fatalf("server: got %q, want %q", 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 (
|
import (
|
||||||
"net"
|
"net"
|
||||||
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -13,6 +14,7 @@ func testClientVersion(t *testing.T, config *ClientConfig, expected string) {
|
||||||
clientConn, serverConn := net.Pipe()
|
clientConn, serverConn := net.Pipe()
|
||||||
defer clientConn.Close()
|
defer clientConn.Close()
|
||||||
receivedVersion := make(chan string, 1)
|
receivedVersion := make(chan string, 1)
|
||||||
|
config.HostKeyCallback = InsecureIgnoreHostKey()
|
||||||
go func() {
|
go func() {
|
||||||
version, err := readVersion(serverConn)
|
version, err := readVersion(serverConn)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -37,3 +39,43 @@ func TestCustomClientVersion(t *testing.T) {
|
||||||
func TestDefaultClientVersion(t *testing.T) {
|
func TestDefaultClientVersion(t *testing.T) {
|
||||||
testClientVersion(t, &ClientConfig{}, packageVersion)
|
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"
|
"crypto/rand"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
"math"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
_ "crypto/sha1"
|
_ "crypto/sha1"
|
||||||
|
@ -40,7 +41,7 @@ var supportedKexAlgos = []string{
|
||||||
kexAlgoDH14SHA1, kexAlgoDH1SHA1,
|
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.
|
// of authenticating servers) in preference order.
|
||||||
var supportedHostKeyAlgos = []string{
|
var supportedHostKeyAlgos = []string{
|
||||||
CertAlgoRSAv01, CertAlgoDSAv01, CertAlgoECDSA256v01,
|
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
|
// 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.
|
// because they have reached the end of their useful life.
|
||||||
var supportedMACs = []string{
|
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}
|
var supportedCompressions = []string{compressionNone}
|
||||||
|
@ -104,6 +105,21 @@ type directionAlgorithms struct {
|
||||||
Compression string
|
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 {
|
type algorithms struct {
|
||||||
kex string
|
kex string
|
||||||
hostKey string
|
hostKey string
|
||||||
|
@ -171,7 +187,7 @@ type Config struct {
|
||||||
|
|
||||||
// The maximum number of bytes sent or received after which a
|
// The maximum number of bytes sent or received after which a
|
||||||
// new key is negotiated. It must be at least 256. If
|
// 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
|
RekeyThreshold uint64
|
||||||
|
|
||||||
// The allowed key exchanges algorithms. If unspecified then a
|
// The allowed key exchanges algorithms. If unspecified then a
|
||||||
|
@ -215,11 +231,12 @@ func (c *Config) SetDefaults() {
|
||||||
}
|
}
|
||||||
|
|
||||||
if c.RekeyThreshold == 0 {
|
if c.RekeyThreshold == 0 {
|
||||||
// RFC 4253, section 9 suggests rekeying after 1G.
|
// cipher specific default
|
||||||
c.RekeyThreshold = 1 << 30
|
} else if c.RekeyThreshold < minRekeyThreshold {
|
||||||
}
|
|
||||||
if c.RekeyThreshold < minRekeyThreshold {
|
|
||||||
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:
|
References:
|
||||||
[PROTOCOL.certkeys]: http://cvsweb.openbsd.org/cgi-bin/cvsweb/src/usr.bin/ssh/PROTOCOL.certkeys?rev=HEAD
|
[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
|
[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"
|
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
|
package ssh_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bufio"
|
||||||
"bytes"
|
"bytes"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"log"
|
"log"
|
||||||
"net"
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"golang.org/x/crypto/ssh"
|
"golang.org/x/crypto/ssh"
|
||||||
"golang.org/x/crypto/ssh/terminal"
|
"golang.org/x/crypto/ssh/terminal"
|
||||||
)
|
)
|
||||||
|
|
||||||
func ExampleNewServerConn() {
|
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
|
// An SSH server is represented by a ServerConfig, which holds
|
||||||
// certificate details and handles authentication of ServerConns.
|
// certificate details and handles authentication of ServerConns.
|
||||||
config := &ssh.ServerConfig{
|
config := &ssh.ServerConfig{
|
||||||
|
// Remove to disable password auth.
|
||||||
PasswordCallback: func(c ssh.ConnMetadata, pass []byte) (*ssh.Permissions, error) {
|
PasswordCallback: func(c ssh.ConnMetadata, pass []byte) (*ssh.Permissions, error) {
|
||||||
// Should use constant-time compare (or better, salt+hash) in
|
// Should use constant-time compare (or better, salt+hash) in
|
||||||
// a production setting.
|
// a production setting.
|
||||||
|
@ -28,16 +52,24 @@ func ExampleNewServerConn() {
|
||||||
}
|
}
|
||||||
return nil, fmt.Errorf("password rejected for %q", c.User())
|
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")
|
privateBytes, err := ioutil.ReadFile("id_rsa")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic("Failed to load private key")
|
log.Fatal("Failed to load private key: ", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
private, err := ssh.ParsePrivateKey(privateBytes)
|
private, err := ssh.ParsePrivateKey(privateBytes)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic("Failed to parse private key")
|
log.Fatal("Failed to parse private key: ", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
config.AddHostKey(private)
|
config.AddHostKey(private)
|
||||||
|
@ -46,18 +78,18 @@ func ExampleNewServerConn() {
|
||||||
// accepted.
|
// accepted.
|
||||||
listener, err := net.Listen("tcp", "0.0.0.0:2022")
|
listener, err := net.Listen("tcp", "0.0.0.0:2022")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic("failed to listen for connection")
|
log.Fatal("failed to listen for connection: ", err)
|
||||||
}
|
}
|
||||||
nConn, err := listener.Accept()
|
nConn, err := listener.Accept()
|
||||||
if err != nil {
|
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
|
// Before use, a handshake must be performed on the incoming
|
||||||
// net.Conn.
|
// net.Conn.
|
||||||
_, chans, reqs, err := ssh.NewServerConn(nConn, config)
|
_, chans, reqs, err := ssh.NewServerConn(nConn, config)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic("failed to handshake")
|
log.Fatal("failed to handshake: ", err)
|
||||||
}
|
}
|
||||||
// The incoming Request channel must be serviced.
|
// The incoming Request channel must be serviced.
|
||||||
go ssh.DiscardRequests(reqs)
|
go ssh.DiscardRequests(reqs)
|
||||||
|
@ -74,7 +106,7 @@ func ExampleNewServerConn() {
|
||||||
}
|
}
|
||||||
channel, requests, err := newChannel.Accept()
|
channel, requests, err := newChannel.Accept()
|
||||||
if err != nil {
|
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",
|
// Sessions have out-of-band requests such as "shell",
|
||||||
|
@ -82,18 +114,7 @@ func ExampleNewServerConn() {
|
||||||
// "shell" request.
|
// "shell" request.
|
||||||
go func(in <-chan *ssh.Request) {
|
go func(in <-chan *ssh.Request) {
|
||||||
for req := range in {
|
for req := range in {
|
||||||
ok := false
|
req.Reply(req.Type == "shell", nil)
|
||||||
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)
|
|
||||||
}
|
}
|
||||||
}(requests)
|
}(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() {
|
func ExampleDial() {
|
||||||
|
var hostKey ssh.PublicKey
|
||||||
// An SSH client is represented with a ClientConn.
|
// An SSH client is represented with a ClientConn.
|
||||||
//
|
//
|
||||||
// To authenticate with the remote server you must pass at least one
|
// 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{
|
config := &ssh.ClientConfig{
|
||||||
User: "username",
|
User: "username",
|
||||||
Auth: []ssh.AuthMethod{
|
Auth: []ssh.AuthMethod{
|
||||||
ssh.Password("yourpassword"),
|
ssh.Password("yourpassword"),
|
||||||
},
|
},
|
||||||
|
HostKeyCallback: ssh.FixedHostKey(hostKey),
|
||||||
}
|
}
|
||||||
client, err := ssh.Dial("tcp", "yourserver.com:22", config)
|
client, err := ssh.Dial("tcp", "yourserver.com:22", config)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic("Failed to dial: " + err.Error())
|
log.Fatal("Failed to dial: ", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Each ClientConn can support multiple interactive sessions,
|
// Each ClientConn can support multiple interactive sessions,
|
||||||
// represented by a Session.
|
// represented by a Session.
|
||||||
session, err := client.NewSession()
|
session, err := client.NewSession()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic("Failed to create session: " + err.Error())
|
log.Fatal("Failed to create session: ", err)
|
||||||
}
|
}
|
||||||
defer session.Close()
|
defer session.Close()
|
||||||
|
|
||||||
|
@ -141,12 +205,13 @@ func ExampleDial() {
|
||||||
var b bytes.Buffer
|
var b bytes.Buffer
|
||||||
session.Stdout = &b
|
session.Stdout = &b
|
||||||
if err := session.Run("/usr/bin/whoami"); err != nil {
|
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())
|
fmt.Println(b.String())
|
||||||
}
|
}
|
||||||
|
|
||||||
func ExamplePublicKeys() {
|
func ExamplePublicKeys() {
|
||||||
|
var hostKey ssh.PublicKey
|
||||||
// A public key may be used to authenticate against the remote
|
// A public key may be used to authenticate against the remote
|
||||||
// server by using an unencrypted PEM-encoded private key file.
|
// server by using an unencrypted PEM-encoded private key file.
|
||||||
//
|
//
|
||||||
|
@ -169,6 +234,7 @@ func ExamplePublicKeys() {
|
||||||
// Use the PublicKeys method for remote authentication.
|
// Use the PublicKeys method for remote authentication.
|
||||||
ssh.PublicKeys(signer),
|
ssh.PublicKeys(signer),
|
||||||
},
|
},
|
||||||
|
HostKeyCallback: ssh.FixedHostKey(hostKey),
|
||||||
}
|
}
|
||||||
|
|
||||||
// Connect to the remote server and perform the SSH handshake.
|
// Connect to the remote server and perform the SSH handshake.
|
||||||
|
@ -180,23 +246,25 @@ func ExamplePublicKeys() {
|
||||||
}
|
}
|
||||||
|
|
||||||
func ExampleClient_Listen() {
|
func ExampleClient_Listen() {
|
||||||
|
var hostKey ssh.PublicKey
|
||||||
config := &ssh.ClientConfig{
|
config := &ssh.ClientConfig{
|
||||||
User: "username",
|
User: "username",
|
||||||
Auth: []ssh.AuthMethod{
|
Auth: []ssh.AuthMethod{
|
||||||
ssh.Password("password"),
|
ssh.Password("password"),
|
||||||
},
|
},
|
||||||
|
HostKeyCallback: ssh.FixedHostKey(hostKey),
|
||||||
}
|
}
|
||||||
// Dial your ssh server.
|
// Dial your ssh server.
|
||||||
conn, err := ssh.Dial("tcp", "localhost:22", config)
|
conn, err := ssh.Dial("tcp", "localhost:22", config)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("unable to connect: %s", err)
|
log.Fatal("unable to connect: ", err)
|
||||||
}
|
}
|
||||||
defer conn.Close()
|
defer conn.Close()
|
||||||
|
|
||||||
// Request the remote side to open port 8080 on all interfaces.
|
// Request the remote side to open port 8080 on all interfaces.
|
||||||
l, err := conn.Listen("tcp", "0.0.0.0:8080")
|
l, err := conn.Listen("tcp", "0.0.0.0:8080")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("unable to register tcp forward: %v", err)
|
log.Fatal("unable to register tcp forward: ", err)
|
||||||
}
|
}
|
||||||
defer l.Close()
|
defer l.Close()
|
||||||
|
|
||||||
|
@ -207,23 +275,25 @@ func ExampleClient_Listen() {
|
||||||
}
|
}
|
||||||
|
|
||||||
func ExampleSession_RequestPty() {
|
func ExampleSession_RequestPty() {
|
||||||
|
var hostKey ssh.PublicKey
|
||||||
// Create client config
|
// Create client config
|
||||||
config := &ssh.ClientConfig{
|
config := &ssh.ClientConfig{
|
||||||
User: "username",
|
User: "username",
|
||||||
Auth: []ssh.AuthMethod{
|
Auth: []ssh.AuthMethod{
|
||||||
ssh.Password("password"),
|
ssh.Password("password"),
|
||||||
},
|
},
|
||||||
|
HostKeyCallback: ssh.FixedHostKey(hostKey),
|
||||||
}
|
}
|
||||||
// Connect to ssh server
|
// Connect to ssh server
|
||||||
conn, err := ssh.Dial("tcp", "localhost:22", config)
|
conn, err := ssh.Dial("tcp", "localhost:22", config)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("unable to connect: %s", err)
|
log.Fatal("unable to connect: ", err)
|
||||||
}
|
}
|
||||||
defer conn.Close()
|
defer conn.Close()
|
||||||
// Create a session
|
// Create a session
|
||||||
session, err := conn.NewSession()
|
session, err := conn.NewSession()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("unable to create session: %s", err)
|
log.Fatal("unable to create session: ", err)
|
||||||
}
|
}
|
||||||
defer session.Close()
|
defer session.Close()
|
||||||
// Set up terminal modes
|
// Set up terminal modes
|
||||||
|
@ -233,11 +303,11 @@ func ExampleSession_RequestPty() {
|
||||||
ssh.TTY_OP_OSPEED: 14400, // output speed = 14.4kbaud
|
ssh.TTY_OP_OSPEED: 14400, // output speed = 14.4kbaud
|
||||||
}
|
}
|
||||||
// Request pseudo terminal
|
// Request pseudo terminal
|
||||||
if err := session.RequestPty("xterm", 80, 40, modes); err != nil {
|
if err := session.RequestPty("xterm", 40, 80, modes); err != nil {
|
||||||
log.Fatalf("request for pseudo terminal failed: %s", err)
|
log.Fatal("request for pseudo terminal failed: ", err)
|
||||||
}
|
}
|
||||||
// Start remote shell
|
// Start remote shell
|
||||||
if err := session.Shell(); err != nil {
|
if err := session.Shell(); err != nil {
|
||||||
log.Fatalf("failed to start shell: %s", err)
|
log.Fatal("failed to start shell: ", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
451
vendor/src/golang.org/x/crypto/ssh/handshake.go
vendored
451
vendor/src/golang.org/x/crypto/ssh/handshake.go
vendored
|
@ -19,6 +19,11 @@ import (
|
||||||
// messages are wrong when using ECDH.
|
// messages are wrong when using ECDH.
|
||||||
const debugHandshake = false
|
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
|
// keyingTransport is a packet based transport that supports key
|
||||||
// changes. It need not be thread-safe. It should pass through
|
// changes. It need not be thread-safe. It should pass through
|
||||||
// msgNewKeys in both directions.
|
// msgNewKeys in both directions.
|
||||||
|
@ -53,34 +58,60 @@ type handshakeTransport struct {
|
||||||
incoming chan []byte
|
incoming chan []byte
|
||||||
readError error
|
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
|
// data for host key checking
|
||||||
hostKeyCallback func(hostname string, remote net.Addr, key PublicKey) error
|
hostKeyCallback HostKeyCallback
|
||||||
dialAddress string
|
dialAddress string
|
||||||
remoteAddr net.Addr
|
remoteAddr net.Addr
|
||||||
|
|
||||||
readSinceKex uint64
|
// Algorithms agreed in the last key exchange.
|
||||||
|
algorithms *algorithms
|
||||||
|
|
||||||
// Protects the writing side of the connection
|
readPacketsLeft uint32
|
||||||
mu sync.Mutex
|
readBytesLeft int64
|
||||||
cond *sync.Cond
|
|
||||||
sentInitPacket []byte
|
writePacketsLeft uint32
|
||||||
sentInitMsg *kexInitMsg
|
writeBytesLeft int64
|
||||||
writtenSinceKex uint64
|
|
||||||
writeError error
|
|
||||||
|
|
||||||
// The session ID or nil if first kex did not complete yet.
|
// The session ID or nil if first kex did not complete yet.
|
||||||
sessionID []byte
|
sessionID []byte
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type pendingKex struct {
|
||||||
|
otherInit []byte
|
||||||
|
done chan error
|
||||||
|
}
|
||||||
|
|
||||||
func newHandshakeTransport(conn keyingTransport, config *Config, clientVersion, serverVersion []byte) *handshakeTransport {
|
func newHandshakeTransport(conn keyingTransport, config *Config, clientVersion, serverVersion []byte) *handshakeTransport {
|
||||||
t := &handshakeTransport{
|
t := &handshakeTransport{
|
||||||
conn: conn,
|
conn: conn,
|
||||||
serverVersion: serverVersion,
|
serverVersion: serverVersion,
|
||||||
clientVersion: clientVersion,
|
clientVersion: clientVersion,
|
||||||
incoming: make(chan []byte, 16),
|
incoming: make(chan []byte, chanSize),
|
||||||
|
requestKex: make(chan struct{}, 1),
|
||||||
|
startKex: make(chan *pendingKex, 1),
|
||||||
|
|
||||||
config: config,
|
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
|
return t
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -95,6 +126,7 @@ func newClientTransport(conn keyingTransport, clientVersion, serverVersion []byt
|
||||||
t.hostKeyAlgorithms = supportedHostKeyAlgos
|
t.hostKeyAlgorithms = supportedHostKeyAlgos
|
||||||
}
|
}
|
||||||
go t.readLoop()
|
go t.readLoop()
|
||||||
|
go t.kexLoop()
|
||||||
return t
|
return t
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -102,6 +134,7 @@ func newServerTransport(conn keyingTransport, clientVersion, serverVersion []byt
|
||||||
t := newHandshakeTransport(conn, &config.Config, clientVersion, serverVersion)
|
t := newHandshakeTransport(conn, &config.Config, clientVersion, serverVersion)
|
||||||
t.hostKeys = config.hostKeys
|
t.hostKeys = config.hostKeys
|
||||||
go t.readLoop()
|
go t.readLoop()
|
||||||
|
go t.kexLoop()
|
||||||
return t
|
return t
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -109,6 +142,20 @@ func (t *handshakeTransport) getSessionID() []byte {
|
||||||
return t.sessionID
|
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 {
|
func (t *handshakeTransport) id() string {
|
||||||
if len(t.hostKeys) > 0 {
|
if len(t.hostKeys) > 0 {
|
||||||
return "server"
|
return "server"
|
||||||
|
@ -116,6 +163,20 @@ func (t *handshakeTransport) id() string {
|
||||||
return "client"
|
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) {
|
func (t *handshakeTransport) readPacket() ([]byte, error) {
|
||||||
p, ok := <-t.incoming
|
p, ok := <-t.incoming
|
||||||
if !ok {
|
if !ok {
|
||||||
|
@ -125,8 +186,10 @@ func (t *handshakeTransport) readPacket() ([]byte, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *handshakeTransport) readLoop() {
|
func (t *handshakeTransport) readLoop() {
|
||||||
|
first := true
|
||||||
for {
|
for {
|
||||||
p, err := t.readOnePacket()
|
p, err := t.readOnePacket(first)
|
||||||
|
first = false
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.readError = err
|
t.readError = err
|
||||||
close(t.incoming)
|
close(t.incoming)
|
||||||
|
@ -138,67 +201,217 @@ func (t *handshakeTransport) readLoop() {
|
||||||
t.incoming <- p
|
t.incoming <- p
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we can't read, declare the writing part dead too.
|
// 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) pushPacket(p []byte) error {
|
||||||
|
if debugHandshake {
|
||||||
|
t.printPacket(p, true)
|
||||||
|
}
|
||||||
|
return t.conn.writePacket(p)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *handshakeTransport) getWriteError() error {
|
||||||
t.mu.Lock()
|
t.mu.Lock()
|
||||||
defer t.mu.Unlock()
|
defer t.mu.Unlock()
|
||||||
if t.writeError == nil {
|
return t.writeError
|
||||||
t.writeError = t.readError
|
|
||||||
}
|
|
||||||
t.cond.Broadcast()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *handshakeTransport) readOnePacket() ([]byte, error) {
|
func (t *handshakeTransport) recordWriteError(err error) {
|
||||||
if t.readSinceKex > t.config.RekeyThreshold {
|
t.mu.Lock()
|
||||||
if err := t.requestKeyChange(); err != nil {
|
defer t.mu.Unlock()
|
||||||
return nil, err
|
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()
|
p, err := t.conn.readPacket()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
t.readSinceKex += uint64(len(p))
|
if t.readPacketsLeft > 0 {
|
||||||
if debugHandshake {
|
t.readPacketsLeft--
|
||||||
if p[0] == msgChannelData || p[0] == msgChannelExtendedData {
|
|
||||||
log.Printf("%s got data (packet %d bytes)", t.id(), len(p))
|
|
||||||
} else {
|
} else {
|
||||||
msg, err := decode(p)
|
t.requestKeyExchange()
|
||||||
log.Printf("%s got %T %v (%v)", t.id(), msg, msg, err)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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 {
|
if p[0] != msgKexInit {
|
||||||
return p, nil
|
return p, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
t.mu.Lock()
|
|
||||||
|
|
||||||
firstKex := t.sessionID == nil
|
firstKex := t.sessionID == nil
|
||||||
|
|
||||||
err = t.enterKeyExchangeLocked(p)
|
kex := pendingKex{
|
||||||
if err != nil {
|
done: make(chan error, 1),
|
||||||
// drop connection
|
otherInit: p,
|
||||||
t.conn.Close()
|
|
||||||
t.writeError = err
|
|
||||||
}
|
}
|
||||||
|
t.startKex <- &kex
|
||||||
|
err = <-kex.done
|
||||||
|
|
||||||
if debugHandshake {
|
if debugHandshake {
|
||||||
log.Printf("%s exited key exchange (first %v), err %v", t.id(), firstKex, err)
|
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 {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
t.readSinceKex = 0
|
t.resetReadThresholds()
|
||||||
|
|
||||||
// By default, a key exchange is hidden from higher layers by
|
// By default, a key exchange is hidden from higher layers by
|
||||||
// translating it into msgIgnore.
|
// translating it into msgIgnore.
|
||||||
|
@ -213,61 +426,16 @@ func (t *handshakeTransport) readOnePacket() ([]byte, error) {
|
||||||
return successPacket, nil
|
return successPacket, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// keyChangeCategory describes whether a key exchange is the first on a
|
// sendKexInit sends a key change message.
|
||||||
// connection, or a subsequent one.
|
func (t *handshakeTransport) sendKexInit() error {
|
||||||
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
|
|
||||||
|
|
||||||
t.mu.Lock()
|
t.mu.Lock()
|
||||||
// If this is the initial key change, but we already have a sessionID,
|
defer t.mu.Unlock()
|
||||||
// then do nothing because the key exchange has already completed
|
if t.sentInitMsg != nil {
|
||||||
// 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,
|
// kexInits may be sent either in response to the other side,
|
||||||
// or because our side wants to initiate a key change, so we
|
// 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
|
// may have already sent a kexInit. In that case, don't send a
|
||||||
// second kexInit.
|
// second kexInit.
|
||||||
if t.sentInitMsg != nil {
|
return nil
|
||||||
return t.sentInitMsg, t.sentInitPacket, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
msg := &kexInitMsg{
|
msg := &kexInitMsg{
|
||||||
|
@ -295,53 +463,65 @@ func (t *handshakeTransport) sendKexInitLocked(isFirst keyChangeCategory) (*kexI
|
||||||
packetCopy := make([]byte, len(packet))
|
packetCopy := make([]byte, len(packet))
|
||||||
copy(packetCopy, packet)
|
copy(packetCopy, packet)
|
||||||
|
|
||||||
if err := t.conn.writePacket(packetCopy); err != nil {
|
if err := t.pushPacket(packetCopy); err != nil {
|
||||||
return nil, nil, err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
t.sentInitMsg = msg
|
t.sentInitMsg = msg
|
||||||
t.sentInitPacket = packet
|
t.sentInitPacket = packet
|
||||||
return msg, packet, nil
|
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *handshakeTransport) writePacket(p []byte) error {
|
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] {
|
switch p[0] {
|
||||||
case msgKexInit:
|
case msgKexInit:
|
||||||
return errors.New("ssh: only handshakeTransport can send kexInit")
|
return errors.New("ssh: only handshakeTransport can send kexInit")
|
||||||
case msgNewKeys:
|
case msgNewKeys:
|
||||||
return errors.New("ssh: only handshakeTransport can send newKeys")
|
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 {
|
func (t *handshakeTransport) Close() error {
|
||||||
return t.conn.Close()
|
return t.conn.Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
// enterKeyExchange runs the key exchange. t.mu must be held while running this.
|
func (t *handshakeTransport) enterKeyExchange(otherInitPacket []byte) error {
|
||||||
func (t *handshakeTransport) enterKeyExchangeLocked(otherInitPacket []byte) error {
|
|
||||||
if debugHandshake {
|
if debugHandshake {
|
||||||
log.Printf("%s entered key exchange", t.id())
|
log.Printf("%s entered key exchange", t.id())
|
||||||
}
|
}
|
||||||
myInit, myInitPacket, err := t.sendKexInitLocked(subsequentKeyExchange)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
otherInit := &kexInitMsg{}
|
otherInit := &kexInitMsg{}
|
||||||
if err := Unmarshal(otherInitPacket, otherInit); err != nil {
|
if err := Unmarshal(otherInitPacket, otherInit); err != nil {
|
||||||
|
@ -352,26 +532,35 @@ func (t *handshakeTransport) enterKeyExchangeLocked(otherInitPacket []byte) erro
|
||||||
clientVersion: t.clientVersion,
|
clientVersion: t.clientVersion,
|
||||||
serverVersion: t.serverVersion,
|
serverVersion: t.serverVersion,
|
||||||
clientKexInit: otherInitPacket,
|
clientKexInit: otherInitPacket,
|
||||||
serverKexInit: myInitPacket,
|
serverKexInit: t.sentInitPacket,
|
||||||
}
|
}
|
||||||
|
|
||||||
clientInit := otherInit
|
clientInit := otherInit
|
||||||
serverInit := myInit
|
serverInit := t.sentInitMsg
|
||||||
if len(t.hostKeys) == 0 {
|
if len(t.hostKeys) == 0 {
|
||||||
clientInit = myInit
|
clientInit, serverInit = serverInit, clientInit
|
||||||
serverInit = otherInit
|
|
||||||
|
|
||||||
magics.clientKexInit = myInitPacket
|
magics.clientKexInit = t.sentInitPacket
|
||||||
magics.serverKexInit = otherInitPacket
|
magics.serverKexInit = otherInitPacket
|
||||||
}
|
}
|
||||||
|
|
||||||
algs, err := findAgreedAlgorithms(clientInit, serverInit)
|
var err error
|
||||||
|
t.algorithms, err = findAgreedAlgorithms(clientInit, serverInit)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// We don't send FirstKexFollows, but we handle receiving it.
|
// 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,
|
// other side sent a kex message for the wrong algorithm,
|
||||||
// which we have to ignore.
|
// which we have to ignore.
|
||||||
if _, err := t.conn.readPacket(); err != nil {
|
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 {
|
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
|
var result *kexResult
|
||||||
if len(t.hostKeys) > 0 {
|
if len(t.hostKeys) > 0 {
|
||||||
result, err = t.server(kex, algs, &magics)
|
result, err = t.server(kex, t.algorithms, &magics)
|
||||||
} else {
|
} else {
|
||||||
result, err = t.client(kex, algs, &magics)
|
result, err = t.client(kex, t.algorithms, &magics)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -400,7 +589,9 @@ func (t *handshakeTransport) enterKeyExchangeLocked(otherInitPacket []byte) erro
|
||||||
}
|
}
|
||||||
result.SessionID = t.sessionID
|
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 {
|
if err = t.conn.writePacket([]byte{msgNewKeys}); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -440,12 +631,10 @@ func (t *handshakeTransport) client(kex kexAlgorithm, algs *algorithms, magics *
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if t.hostKeyCallback != nil {
|
|
||||||
err = t.hostKeyCallback(t.dialAddress, t.remoteAddr, hostKey)
|
err = t.hostKeyCallback(t.dialAddress, t.remoteAddr, hostKey)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return result, nil
|
return result, nil
|
||||||
}
|
}
|
||||||
|
|
408
vendor/src/golang.org/x/crypto/ssh/handshake_test.go
vendored
408
vendor/src/golang.org/x/crypto/ssh/handshake_test.go
vendored
|
@ -9,6 +9,7 @@ import (
|
||||||
"crypto/rand"
|
"crypto/rand"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io"
|
||||||
"net"
|
"net"
|
||||||
"reflect"
|
"reflect"
|
||||||
"runtime"
|
"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
|
// therefore is buffered (net.Pipe deadlocks if both sides start with
|
||||||
// a write.)
|
// a write.)
|
||||||
func netPipe() (net.Conn, net.Conn, error) {
|
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 {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
|
@ -58,14 +59,46 @@ func netPipe() (net.Conn, net.Conn, error) {
|
||||||
return c1, c2, nil
|
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()
|
a, b, err := netPipe()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
trC := newTransport(a, rand.Reader, true)
|
var trC, trS keyingTransport
|
||||||
trS := newTransport(b, rand.Reader, false)
|
|
||||||
|
trC = newTransport(a, rand.Reader, true)
|
||||||
|
trS = newTransport(b, rand.Reader, false)
|
||||||
|
if noise {
|
||||||
|
trC = addNoiseTransport(trC)
|
||||||
|
trS = addNoiseTransport(trS)
|
||||||
|
}
|
||||||
clientConf.SetDefaults()
|
clientConf.SetDefaults()
|
||||||
|
|
||||||
v := []byte("version")
|
v := []byte("version")
|
||||||
|
@ -77,6 +110,13 @@ func handshakePair(clientConf *ClientConfig, addr string) (client *handshakeTran
|
||||||
serverConf.SetDefaults()
|
serverConf.SetDefaults()
|
||||||
server = newServerTransport(trS, v, v, serverConf)
|
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
|
return client, server, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -84,8 +124,14 @@ func TestHandshakeBasic(t *testing.T) {
|
||||||
if runtime.GOOS == "plan9" {
|
if runtime.GOOS == "plan9" {
|
||||||
t.Skip("see golang.org/issue/7237")
|
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 {
|
if err != nil {
|
||||||
t.Fatalf("handshakePair: %v", err)
|
t.Fatalf("handshakePair: %v", err)
|
||||||
}
|
}
|
||||||
|
@ -93,240 +139,195 @@ func TestHandshakeBasic(t *testing.T) {
|
||||||
defer trC.Close()
|
defer trC.Close()
|
||||||
defer trS.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() {
|
go func() {
|
||||||
|
defer close(clientDone)
|
||||||
// Client writes a bunch of stuff, and does a key
|
// Client writes a bunch of stuff, and does a key
|
||||||
// change in the middle. This should not confuse the
|
// change in the middle. This should not confuse the
|
||||||
// handshake in progress
|
// handshake in progress. We do this twice, so we test
|
||||||
for i := 0; i < 10; i++ {
|
// that the packet buffer is reset correctly.
|
||||||
|
for i := 0; i < N; i++ {
|
||||||
p := []byte{msgRequestSuccess, byte(i)}
|
p := []byte{msgRequestSuccess, byte(i)}
|
||||||
if err := trC.writePacket(p); err != nil {
|
if err := trC.writePacket(p); err != nil {
|
||||||
t.Fatalf("sendPacket: %v", err)
|
t.Fatalf("sendPacket: %v", err)
|
||||||
}
|
}
|
||||||
if i == 5 {
|
if (i % 10) == 5 {
|
||||||
|
<-gotHalf
|
||||||
// halfway through, we request a key change.
|
// halfway through, we request a key change.
|
||||||
err := trC.sendKexInit(subsequentKeyExchange)
|
trC.requestKeyExchange()
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("sendKexInit: %v", err)
|
// 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
|
// Server checks that client messages come in cleanly
|
||||||
i := 0
|
i := 0
|
||||||
for {
|
err = nil
|
||||||
p, err := trS.readPacket()
|
for ; i < N; i++ {
|
||||||
|
var p []byte
|
||||||
|
p, err = trS.readPacket()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
if p[0] == msgNewKeys {
|
if (i % 10) == 5 {
|
||||||
continue
|
gotHalf <- 1
|
||||||
}
|
}
|
||||||
|
|
||||||
want := []byte{msgRequestSuccess, byte(i)}
|
want := []byte{msgRequestSuccess, byte(i)}
|
||||||
if bytes.Compare(p, want) != 0 {
|
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)
|
t.Errorf("received %d messages, want 10.", i)
|
||||||
}
|
}
|
||||||
|
|
||||||
// If all went well, we registered exactly 1 key change.
|
close(checker.called)
|
||||||
if len(checker.calls) != 1 {
|
if _, ok := <-checker.called; ok {
|
||||||
t.Fatalf("got %d host key checks, want 1", len(checker.calls))
|
// If all went well, we registered exactly 2 key changes: one
|
||||||
}
|
// that establishes the session, and one that we requested
|
||||||
|
// additionally.
|
||||||
pub := testSigners["ecdsa"].PublicKey()
|
t.Fatalf("got another host key checks after 2 handshakes")
|
||||||
want := fmt.Sprintf("%s %v %s %x", "addr", trC.remoteAddr, pub.Type(), pub.Marshal())
|
|
||||||
if want != checker.calls[0] {
|
|
||||||
t.Errorf("got %q want %q for host key check", checker.calls[0], want)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestHandshakeError(t *testing.T) {
|
|
||||||
checker := &testChecker{}
|
|
||||||
trC, trS, err := handshakePair(&ClientConfig{HostKeyCallback: checker.Check}, "bad")
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("handshakePair: %v", err)
|
|
||||||
}
|
|
||||||
defer trC.Close()
|
|
||||||
defer trS.Close()
|
|
||||||
|
|
||||||
// send a packet
|
|
||||||
packet := []byte{msgRequestSuccess, 42}
|
|
||||||
if err := trC.writePacket(packet); err != nil {
|
|
||||||
t.Errorf("writePacket: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Now request a key change.
|
|
||||||
err = trC.sendKexInit(subsequentKeyExchange)
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("sendKexInit: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// the key change will fail, and afterwards we can't write.
|
|
||||||
if err := trC.writePacket([]byte{msgRequestSuccess, 43}); err == nil {
|
|
||||||
t.Errorf("writePacket after botched rekey succeeded.")
|
|
||||||
}
|
|
||||||
|
|
||||||
readback, err := trS.readPacket()
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("server closed too soon: %v", err)
|
|
||||||
}
|
|
||||||
if bytes.Compare(readback, packet) != 0 {
|
|
||||||
t.Errorf("got %q want %q", readback, packet)
|
|
||||||
}
|
|
||||||
readback, err = trS.readPacket()
|
|
||||||
if err == nil {
|
|
||||||
t.Errorf("got a message %q after failed key change", readback)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestForceFirstKex(t *testing.T) {
|
func TestForceFirstKex(t *testing.T) {
|
||||||
|
// like handshakePair, but must access the keyingTransport.
|
||||||
checker := &testChecker{}
|
checker := &testChecker{}
|
||||||
trC, trS, err := handshakePair(&ClientConfig{HostKeyCallback: checker.Check}, "addr")
|
clientConf := &ClientConfig{HostKeyCallback: checker.Check}
|
||||||
|
a, b, err := netPipe()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("handshakePair: %v", err)
|
t.Fatalf("netPipe: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
defer trC.Close()
|
var trC, trS keyingTransport
|
||||||
defer trS.Close()
|
|
||||||
|
|
||||||
|
trC = newTransport(a, rand.Reader, true)
|
||||||
|
|
||||||
|
// This is the disallowed packet:
|
||||||
trC.writePacket(Marshal(&serviceRequestMsg{serviceUserAuth}))
|
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
|
// We setup the initial key exchange, but the remote side
|
||||||
// tries to send serviceRequestMsg in cleartext, which is
|
// tries to send serviceRequestMsg in cleartext, which is
|
||||||
// disallowed.
|
// disallowed.
|
||||||
|
|
||||||
err = trS.sendKexInit(firstKeyExchange)
|
if err := server.waitSession(); err == nil {
|
||||||
if err == nil {
|
|
||||||
t.Errorf("server first kex init should reject unexpected packet")
|
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) {
|
func TestHandshakeAutoRekeyWrite(t *testing.T) {
|
||||||
checker := &testChecker{}
|
checker := &syncChecker{
|
||||||
|
called: make(chan int, 10),
|
||||||
|
waitCall: nil,
|
||||||
|
}
|
||||||
clientConf := &ClientConfig{HostKeyCallback: checker.Check}
|
clientConf := &ClientConfig{HostKeyCallback: checker.Check}
|
||||||
clientConf.RekeyThreshold = 500
|
clientConf.RekeyThreshold = 500
|
||||||
trC, trS, err := handshakePair(clientConf, "addr")
|
trC, trS, err := handshakePair(clientConf, "addr", false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("handshakePair: %v", err)
|
t.Fatalf("handshakePair: %v", err)
|
||||||
}
|
}
|
||||||
defer trC.Close()
|
defer trC.Close()
|
||||||
defer trS.Close()
|
defer trS.Close()
|
||||||
|
|
||||||
for i := 0; i < 5; i++ {
|
input := make([]byte, 251)
|
||||||
packet := make([]byte, 251)
|
input[0] = msgRequestSuccess
|
||||||
packet[0] = msgRequestSuccess
|
|
||||||
if err := trC.writePacket(packet); err != nil {
|
|
||||||
t.Errorf("writePacket: %v", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
done := make(chan int, 1)
|
||||||
|
const numPacket = 5
|
||||||
|
go func() {
|
||||||
|
defer close(done)
|
||||||
j := 0
|
j := 0
|
||||||
for ; j < 5; j++ {
|
for ; j < numPacket; j++ {
|
||||||
_, err := trS.readPacket()
|
if p, err := trS.readPacket(); err != nil {
|
||||||
if err != nil {
|
|
||||||
break
|
break
|
||||||
|
} else if !bytes.Equal(input, p) {
|
||||||
|
t.Errorf("got packet type %d, want %d", p[0], input[0])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if j != 5 {
|
if j != numPacket {
|
||||||
t.Errorf("got %d, want 5 messages", j)
|
t.Errorf("got %d, want 5 messages", j)
|
||||||
}
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
if len(checker.calls) != 2 {
|
<-checker.called
|
||||||
t.Errorf("got %d key changes, wanted 2", len(checker.calls))
|
|
||||||
|
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)
|
||||||
}
|
}
|
||||||
|
if i == 2 {
|
||||||
|
// Make sure the kex is in progress.
|
||||||
|
<-checker.called
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
<-done
|
||||||
}
|
}
|
||||||
|
|
||||||
type syncChecker struct {
|
type syncChecker struct {
|
||||||
|
waitCall chan int
|
||||||
called chan int
|
called chan int
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *syncChecker) Check(dialAddr string, addr net.Addr, key PublicKey) error {
|
func (c *syncChecker) Check(dialAddr string, addr net.Addr, key PublicKey) error {
|
||||||
t.called <- 1
|
c.called <- 1
|
||||||
|
if c.waitCall != nil {
|
||||||
|
<-c.waitCall
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestHandshakeAutoRekeyRead(t *testing.T) {
|
func TestHandshakeAutoRekeyRead(t *testing.T) {
|
||||||
sync := &syncChecker{make(chan int, 2)}
|
sync := &syncChecker{
|
||||||
|
called: make(chan int, 2),
|
||||||
|
waitCall: nil,
|
||||||
|
}
|
||||||
clientConf := &ClientConfig{
|
clientConf := &ClientConfig{
|
||||||
HostKeyCallback: sync.Check,
|
HostKeyCallback: sync.Check,
|
||||||
}
|
}
|
||||||
clientConf.RekeyThreshold = 500
|
clientConf.RekeyThreshold = 500
|
||||||
|
|
||||||
trC, trS, err := handshakePair(clientConf, "addr")
|
trC, trS, err := handshakePair(clientConf, "addr", false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("handshakePair: %v", err)
|
t.Fatalf("handshakePair: %v", err)
|
||||||
}
|
}
|
||||||
|
@ -338,12 +339,19 @@ func TestHandshakeAutoRekeyRead(t *testing.T) {
|
||||||
if err := trS.writePacket(packet); err != nil {
|
if err := trS.writePacket(packet); err != nil {
|
||||||
t.Fatalf("writePacket: %v", err)
|
t.Fatalf("writePacket: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// While we read out the packet, a key change will be
|
// While we read out the packet, a key change will be
|
||||||
// initiated.
|
// initiated.
|
||||||
|
done := make(chan int, 1)
|
||||||
|
go func() {
|
||||||
|
defer close(done)
|
||||||
if _, err := trC.readPacket(); err != nil {
|
if _, err := trC.readPacket(); err != nil {
|
||||||
t.Fatalf("readPacket(client): %v", err)
|
t.Fatalf("readPacket(client): %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}()
|
||||||
|
|
||||||
|
<-done
|
||||||
<-sync.called
|
<-sync.called
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -357,6 +365,7 @@ type errorKeyingTransport struct {
|
||||||
func (n *errorKeyingTransport) prepareKeyChange(*algorithms, *kexResult) error {
|
func (n *errorKeyingTransport) prepareKeyChange(*algorithms, *kexResult) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (n *errorKeyingTransport) getSessionID() []byte {
|
func (n *errorKeyingTransport) getSessionID() []byte {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -383,20 +392,32 @@ func (n *errorKeyingTransport) readPacket() ([]byte, error) {
|
||||||
|
|
||||||
func TestHandshakeErrorHandlingRead(t *testing.T) {
|
func TestHandshakeErrorHandlingRead(t *testing.T) {
|
||||||
for i := 0; i < 20; i++ {
|
for i := 0; i < 20; i++ {
|
||||||
testHandshakeErrorHandlingN(t, i, -1)
|
testHandshakeErrorHandlingN(t, i, -1, false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestHandshakeErrorHandlingWrite(t *testing.T) {
|
func TestHandshakeErrorHandlingWrite(t *testing.T) {
|
||||||
for i := 0; i < 20; i++ {
|
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
|
// testHandshakeErrorHandlingN runs handshakes, injecting errors. If
|
||||||
// handshakeTransport deadlocks, the go runtime will detect it and
|
// handshakeTransport deadlocks, the go runtime will detect it and
|
||||||
// panic.
|
// 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)})
|
msg := Marshal(&serviceRequestMsg{strings.Repeat("x", int(minRekeyThreshold)/4)})
|
||||||
|
|
||||||
a, b := memPipe()
|
a, b := memPipe()
|
||||||
|
@ -409,25 +430,31 @@ func testHandshakeErrorHandlingN(t *testing.T, readLimit, writeLimit int) {
|
||||||
serverConn := newHandshakeTransport(&errorKeyingTransport{a, readLimit, writeLimit}, &serverConf, []byte{'a'}, []byte{'b'})
|
serverConn := newHandshakeTransport(&errorKeyingTransport{a, readLimit, writeLimit}, &serverConf, []byte{'a'}, []byte{'b'})
|
||||||
serverConn.hostKeys = []Signer{key}
|
serverConn.hostKeys = []Signer{key}
|
||||||
go serverConn.readLoop()
|
go serverConn.readLoop()
|
||||||
|
go serverConn.kexLoop()
|
||||||
|
|
||||||
clientConf := Config{RekeyThreshold: 10 * minRekeyThreshold}
|
clientConf := Config{RekeyThreshold: 10 * minRekeyThreshold}
|
||||||
clientConf.SetDefaults()
|
clientConf.SetDefaults()
|
||||||
clientConn := newHandshakeTransport(&errorKeyingTransport{b, -1, -1}, &clientConf, []byte{'a'}, []byte{'b'})
|
clientConn := newHandshakeTransport(&errorKeyingTransport{b, -1, -1}, &clientConf, []byte{'a'}, []byte{'b'})
|
||||||
clientConn.hostKeyAlgorithms = []string{key.PublicKey().Type()}
|
clientConn.hostKeyAlgorithms = []string{key.PublicKey().Type()}
|
||||||
|
clientConn.hostKeyCallback = InsecureIgnoreHostKey()
|
||||||
go clientConn.readLoop()
|
go clientConn.readLoop()
|
||||||
|
go clientConn.kexLoop()
|
||||||
|
|
||||||
var wg sync.WaitGroup
|
var wg sync.WaitGroup
|
||||||
wg.Add(4)
|
|
||||||
|
|
||||||
for _, hs := range []packetConn{serverConn, clientConn} {
|
for _, hs := range []packetConn{serverConn, clientConn} {
|
||||||
|
if !coupled {
|
||||||
|
wg.Add(2)
|
||||||
go func(c packetConn) {
|
go func(c packetConn) {
|
||||||
for {
|
for i := 0; ; i++ {
|
||||||
err := c.writePacket(msg)
|
str := fmt.Sprintf("%08x", i) + strings.Repeat("x", int(minRekeyThreshold)/4-8)
|
||||||
|
err := c.writePacket(Marshal(&serviceRequestMsg{str}))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
wg.Done()
|
wg.Done()
|
||||||
|
c.Close()
|
||||||
}(hs)
|
}(hs)
|
||||||
go func(c packetConn) {
|
go func(c packetConn) {
|
||||||
for {
|
for {
|
||||||
|
@ -438,8 +465,23 @@ func testHandshakeErrorHandlingN(t *testing.T, readLimit, writeLimit int) {
|
||||||
}
|
}
|
||||||
wg.Done()
|
wg.Done()
|
||||||
}(hs)
|
}(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()
|
wg.Wait()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -448,7 +490,7 @@ func TestDisconnect(t *testing.T) {
|
||||||
t.Skip("see golang.org/issue/7237")
|
t.Skip("see golang.org/issue/7237")
|
||||||
}
|
}
|
||||||
checker := &testChecker{}
|
checker := &testChecker{}
|
||||||
trC, trS, err := handshakePair(&ClientConfig{HostKeyCallback: checker.Check}, "addr")
|
trC, trS, err := handshakePair(&ClientConfig{HostKeyCallback: checker.Check}, "addr", false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("handshakePair: %v", err)
|
t.Fatalf("handshakePair: %v", err)
|
||||||
}
|
}
|
||||||
|
@ -484,3 +526,31 @@ func TestDisconnect(t *testing.T) {
|
||||||
t.Errorf("readPacket 3 succeeded")
|
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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
26
vendor/src/golang.org/x/crypto/ssh/kex.go
vendored
26
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.
|
// dhGroup is a multiplicative group suitable for implementing Diffie-Hellman key agreement.
|
||||||
type dhGroup struct {
|
type dhGroup struct {
|
||||||
g, p *big.Int
|
g, p, pMinus1 *big.Int
|
||||||
}
|
}
|
||||||
|
|
||||||
func (group *dhGroup) diffieHellman(theirPublic, myPrivate *big.Int) (*big.Int, error) {
|
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 nil, errors.New("ssh: DH parameter out of bounds")
|
||||||
}
|
}
|
||||||
return new(big.Int).Exp(theirPublic, myPrivate, group.p), nil
|
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) {
|
func (group *dhGroup) Client(c packetConn, randSource io.Reader, magics *handshakeMagics) (*kexResult, error) {
|
||||||
hashFunc := crypto.SHA1
|
hashFunc := crypto.SHA1
|
||||||
|
|
||||||
x, err := rand.Int(randSource, group.p)
|
var x *big.Int
|
||||||
if err != nil {
|
for {
|
||||||
|
var err error
|
||||||
|
if x, err = rand.Int(randSource, group.pMinus1); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
if x.Sign() > 0 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
X := new(big.Int).Exp(group.g, x, group.p)
|
X := new(big.Int).Exp(group.g, x, group.p)
|
||||||
kexDHInit := kexDHInitMsg{
|
kexDHInit := kexDHInitMsg{
|
||||||
X: X,
|
X: X,
|
||||||
|
@ -146,10 +153,15 @@ func (group *dhGroup) Server(c packetConn, randSource io.Reader, magics *handsha
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
y, err := rand.Int(randSource, group.p)
|
var y *big.Int
|
||||||
if err != nil {
|
for {
|
||||||
|
if y, err = rand.Int(randSource, group.pMinus1); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
if y.Sign() > 0 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Y := new(big.Int).Exp(group.g, y, group.p)
|
Y := new(big.Int).Exp(group.g, y, group.p)
|
||||||
kInt, err := group.diffieHellman(kexDHInit.X, y)
|
kInt, err := group.diffieHellman(kexDHInit.X, y)
|
||||||
|
@ -373,6 +385,7 @@ func init() {
|
||||||
kexAlgoMap[kexAlgoDH1SHA1] = &dhGroup{
|
kexAlgoMap[kexAlgoDH1SHA1] = &dhGroup{
|
||||||
g: new(big.Int).SetInt64(2),
|
g: new(big.Int).SetInt64(2),
|
||||||
p: p,
|
p: p,
|
||||||
|
pMinus1: new(big.Int).Sub(p, bigOne),
|
||||||
}
|
}
|
||||||
|
|
||||||
// This is the group called diffie-hellman-group14-sha1 in RFC
|
// This is the group called diffie-hellman-group14-sha1 in RFC
|
||||||
|
@ -382,6 +395,7 @@ func init() {
|
||||||
kexAlgoMap[kexAlgoDH14SHA1] = &dhGroup{
|
kexAlgoMap[kexAlgoDH14SHA1] = &dhGroup{
|
||||||
g: new(big.Int).SetInt64(2),
|
g: new(big.Int).SetInt64(2),
|
||||||
p: p,
|
p: p,
|
||||||
|
pMinus1: new(big.Int).Sub(p, bigOne),
|
||||||
}
|
}
|
||||||
|
|
||||||
kexAlgoMap[kexAlgoECDH521] = &ecdh{elliptic.P521()}
|
kexAlgoMap[kexAlgoECDH521] = &ecdh{elliptic.P521()}
|
||||||
|
|
147
vendor/src/golang.org/x/crypto/ssh/keys.go
vendored
147
vendor/src/golang.org/x/crypto/ssh/keys.go
vendored
|
@ -10,10 +10,13 @@ import (
|
||||||
"crypto/dsa"
|
"crypto/dsa"
|
||||||
"crypto/ecdsa"
|
"crypto/ecdsa"
|
||||||
"crypto/elliptic"
|
"crypto/elliptic"
|
||||||
|
"crypto/md5"
|
||||||
"crypto/rsa"
|
"crypto/rsa"
|
||||||
|
"crypto/sha256"
|
||||||
"crypto/x509"
|
"crypto/x509"
|
||||||
"encoding/asn1"
|
"encoding/asn1"
|
||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
|
"encoding/hex"
|
||||||
"encoding/pem"
|
"encoding/pem"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
@ -281,6 +284,12 @@ type PublicKey interface {
|
||||||
Verify(data []byte, sig *Signature) error
|
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.
|
// A Signer can create signatures that verify against a public key.
|
||||||
type Signer interface {
|
type Signer interface {
|
||||||
// PublicKey returns an associated PublicKey instance.
|
// 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)
|
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
|
type dsaPublicKey dsa.PublicKey
|
||||||
|
|
||||||
func (r *dsaPublicKey) Type() string {
|
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")
|
return errors.New("ssh: signature did not verify")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (k *dsaPublicKey) CryptoPublicKey() crypto.PublicKey {
|
||||||
|
return (*dsa.PublicKey)(k)
|
||||||
|
}
|
||||||
|
|
||||||
type dsaPrivateKey struct {
|
type dsaPrivateKey struct {
|
||||||
*dsa.PrivateKey
|
*dsa.PrivateKey
|
||||||
}
|
}
|
||||||
|
@ -509,6 +526,10 @@ func (key ed25519PublicKey) Verify(b []byte, sig *Signature) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (k ed25519PublicKey) CryptoPublicKey() crypto.PublicKey {
|
||||||
|
return ed25519.PublicKey(k)
|
||||||
|
}
|
||||||
|
|
||||||
func supportedEllipticCurve(curve elliptic.Curve) bool {
|
func supportedEllipticCurve(curve elliptic.Curve) bool {
|
||||||
return curve == elliptic.P256() || curve == elliptic.P384() || curve == elliptic.P521()
|
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")
|
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,
|
// NewSignerFromKey takes an *rsa.PrivateKey, *dsa.PrivateKey,
|
||||||
// *ecdsa.PrivateKey or any other crypto.Signer and returns a corresponding
|
// *ecdsa.PrivateKey or any other crypto.Signer and returns a corresponding
|
||||||
// Signer instance. ECDSA keys must use P-256, P-384 or P-521.
|
// 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,
|
// NewPublicKey takes an *rsa.PublicKey, *dsa.PublicKey, *ecdsa.PublicKey,
|
||||||
// ed25519.PublicKey, or any other crypto.Signer and returns a corresponding
|
// or ed25519.PublicKey returns a corresponding PublicKey instance.
|
||||||
// Signer instance. ECDSA keys must use P-256, P-384 or P-521.
|
// ECDSA keys must use P-256, P-384 or P-521.
|
||||||
func NewPublicKey(key interface{}) (PublicKey, error) {
|
func NewPublicKey(key interface{}) (PublicKey, error) {
|
||||||
switch key := key.(type) {
|
switch key := key.(type) {
|
||||||
case *rsa.PublicKey:
|
case *rsa.PublicKey:
|
||||||
|
@ -731,6 +756,14 @@ func ParsePrivateKey(pemBytes []byte) (Signer, error) {
|
||||||
return NewSignerFromKey(key)
|
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
|
// ParseRawPrivateKey returns a private key from a PEM encoded private key. It
|
||||||
// supports RSA (PKCS#1), DSA (OpenSSL), and ECDSA private keys.
|
// supports RSA (PKCS#1), DSA (OpenSSL), and ECDSA private keys.
|
||||||
func ParseRawPrivateKey(pemBytes []byte) (interface{}, error) {
|
func ParseRawPrivateKey(pemBytes []byte) (interface{}, error) {
|
||||||
|
@ -739,6 +772,10 @@ func ParseRawPrivateKey(pemBytes []byte) (interface{}, error) {
|
||||||
return nil, errors.New("ssh: no key found")
|
return nil, errors.New("ssh: no key found")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if encryptedBlock(block) {
|
||||||
|
return nil, errors.New("ssh: cannot decode encrypted private keys")
|
||||||
|
}
|
||||||
|
|
||||||
switch block.Type {
|
switch block.Type {
|
||||||
case "RSA PRIVATE KEY":
|
case "RSA PRIVATE KEY":
|
||||||
return x509.ParsePKCS1PrivateKey(block.Bytes)
|
return x509.ParsePKCS1PrivateKey(block.Bytes)
|
||||||
|
@ -761,8 +798,8 @@ func ParseDSAPrivateKey(der []byte) (*dsa.PrivateKey, error) {
|
||||||
P *big.Int
|
P *big.Int
|
||||||
Q *big.Int
|
Q *big.Int
|
||||||
G *big.Int
|
G *big.Int
|
||||||
Priv *big.Int
|
|
||||||
Pub *big.Int
|
Pub *big.Int
|
||||||
|
Priv *big.Int
|
||||||
}
|
}
|
||||||
rest, err := asn1.Unmarshal(der, &k)
|
rest, err := asn1.Unmarshal(der, &k)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -779,15 +816,15 @@ func ParseDSAPrivateKey(der []byte) (*dsa.PrivateKey, error) {
|
||||||
Q: k.Q,
|
Q: k.Q,
|
||||||
G: k.G,
|
G: k.G,
|
||||||
},
|
},
|
||||||
Y: k.Priv,
|
Y: k.Pub,
|
||||||
},
|
},
|
||||||
X: k.Pub,
|
X: k.Priv,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implemented based on the documentation at
|
// Implemented based on the documentation at
|
||||||
// https://github.com/openssh/openssh-portable/blob/master/PROTOCOL.key
|
// 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)
|
magic := append([]byte("openssh-key-v1"), 0)
|
||||||
if !bytes.Equal(magic, key[0:len(magic)]) {
|
if !bytes.Equal(magic, key[0:len(magic)]) {
|
||||||
return nil, errors.New("ssh: invalid openssh private key format")
|
return nil, errors.New("ssh: invalid openssh private key format")
|
||||||
|
@ -807,14 +844,15 @@ func parseOpenSSHPrivateKey(key []byte) (*ed25519.PrivateKey, error) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if w.KdfName != "none" || w.CipherName != "none" {
|
||||||
|
return nil, errors.New("ssh: cannot decode encrypted private keys")
|
||||||
|
}
|
||||||
|
|
||||||
pk1 := struct {
|
pk1 := struct {
|
||||||
Check1 uint32
|
Check1 uint32
|
||||||
Check2 uint32
|
Check2 uint32
|
||||||
Keytype string
|
Keytype string
|
||||||
Pub []byte
|
Rest []byte `ssh:"rest"`
|
||||||
Priv []byte
|
|
||||||
Comment string
|
|
||||||
Pad []byte `ssh:"rest"`
|
|
||||||
}{}
|
}{}
|
||||||
|
|
||||||
if err := Unmarshal(w.PrivKeyBlock, &pk1); err != nil {
|
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")
|
return nil, errors.New("ssh: checkint mismatch")
|
||||||
}
|
}
|
||||||
|
|
||||||
// we only handle ed25519 keys currently
|
// we only handle ed25519 and rsa keys currently
|
||||||
if pk1.Keytype != KeyAlgoED25519 {
|
switch pk1.Keytype {
|
||||||
return nil, errors.New("ssh: unhandled key type")
|
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 pk1.Pad {
|
for i, b := range key.Pad {
|
||||||
if int(b) != i+1 {
|
if int(b) != i+1 {
|
||||||
return nil, errors.New("ssh: padding not as expected")
|
return nil, errors.New("ssh: padding not as expected")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(pk1.Priv) != ed25519.PrivateKeySize {
|
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")
|
return nil, errors.New("ssh: private key unexpected length")
|
||||||
}
|
}
|
||||||
|
|
||||||
pk := ed25519.PrivateKey(make([]byte, ed25519.PrivateKeySize))
|
for i, b := range key.Pad {
|
||||||
copy(pk, pk1.Priv)
|
if int(b) != i+1 {
|
||||||
return &pk, nil
|
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")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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
|
||||||
}
|
}
|
||||||
|
|
34
vendor/src/golang.org/x/crypto/ssh/keys_test.go
vendored
34
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) {
|
func TestParseDSA(t *testing.T) {
|
||||||
// We actually exercise the ParsePrivateKey codepath here, as opposed to
|
// We actually exercise the ParsePrivateKey codepath here, as opposed to
|
||||||
// using the ParseRawPrivateKey+NewSignerFromKey path that testdata_test.go
|
// using the ParseRawPrivateKey+NewSignerFromKey path that testdata_test.go
|
||||||
|
@ -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 {
|
type macMode struct {
|
||||||
keySize int
|
keySize int
|
||||||
|
etm bool
|
||||||
new func(key []byte) hash.Hash
|
new func(key []byte) hash.Hash
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -45,13 +46,16 @@ func (t truncatingMAC) Size() int {
|
||||||
func (t truncatingMAC) BlockSize() int { return t.hmac.BlockSize() }
|
func (t truncatingMAC) BlockSize() int { return t.hmac.BlockSize() }
|
||||||
|
|
||||||
var macModes = map[string]*macMode{
|
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)
|
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)
|
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)}
|
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 {
|
func newMux(p packetConn) *mux {
|
||||||
m := &mux{
|
m := &mux{
|
||||||
conn: p,
|
conn: p,
|
||||||
incomingChannels: make(chan NewChannel, 16),
|
incomingChannels: make(chan NewChannel, chanSize),
|
||||||
globalResponses: make(chan interface{}, 1),
|
globalResponses: make(chan interface{}, 1),
|
||||||
incomingRequests: make(chan *Request, 16),
|
incomingRequests: make(chan *Request, chanSize),
|
||||||
errCond: newCond(),
|
errCond: newCond(),
|
||||||
}
|
}
|
||||||
if debugMux {
|
if debugMux {
|
||||||
|
|
|
@ -499,4 +499,7 @@ func TestDebug(t *testing.T) {
|
||||||
if debugHandshake {
|
if debugHandshake {
|
||||||
t.Error("handshake debug switched on")
|
t.Error("handshake debug switched on")
|
||||||
}
|
}
|
||||||
|
if debugTransport {
|
||||||
|
t.Error("transport debug switched on")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
50
vendor/src/golang.org/x/crypto/ssh/server.go
vendored
50
vendor/src/golang.org/x/crypto/ssh/server.go
vendored
|
@ -10,6 +10,7 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"net"
|
"net"
|
||||||
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
// The Permissions type holds fine-grained permissions that are
|
// The Permissions type holds fine-grained permissions that are
|
||||||
|
@ -44,6 +45,12 @@ type ServerConfig struct {
|
||||||
// authenticating.
|
// authenticating.
|
||||||
NoClientAuth bool
|
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
|
// PasswordCallback, if non-nil, is called when a user
|
||||||
// attempts to authenticate using a password.
|
// attempts to authenticate using a password.
|
||||||
PasswordCallback func(conn ConnMetadata, password []byte) (*Permissions, error)
|
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
|
// Request and NewChannel channels must be serviced, or the connection
|
||||||
// will hang.
|
// will hang.
|
||||||
func NewServerConn(c net.Conn, config *ServerConfig) (*ServerConn, <-chan NewChannel, <-chan *Request, error) {
|
func NewServerConn(c net.Conn, config *ServerConfig) (*ServerConn, <-chan NewChannel, <-chan *Request, error) {
|
||||||
|
if config.MaxAuthTries == 0 {
|
||||||
|
config.MaxAuthTries = 6
|
||||||
|
}
|
||||||
|
|
||||||
fullConf := *config
|
fullConf := *config
|
||||||
fullConf.SetDefaults()
|
fullConf.SetDefaults()
|
||||||
s := &connection{
|
s := &connection{
|
||||||
|
@ -188,7 +199,7 @@ func (s *connection) serverHandshake(config *ServerConfig) (*Permissions, error)
|
||||||
tr := newTransport(s.sshConn.conn, config.Rand, false /* not client */)
|
tr := newTransport(s.sshConn.conn, config.Rand, false /* not client */)
|
||||||
s.transport = newServerTransport(tr, s.clientVersion, s.serverVersion, config)
|
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
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -231,7 +242,7 @@ func isAcceptableAlgo(algo string) bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func checkSourceAddress(addr net.Addr, sourceAddr string) error {
|
func checkSourceAddress(addr net.Addr, sourceAddrs string) error {
|
||||||
if addr == nil {
|
if addr == nil {
|
||||||
return errors.New("ssh: no address known for client, but source-address match required")
|
return errors.New("ssh: no address known for client, but source-address match required")
|
||||||
}
|
}
|
||||||
|
@ -241,8 +252,9 @@ 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)
|
return fmt.Errorf("ssh: remote address %v is not an TCP address when checking source-address match", addr)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for _, sourceAddr := range strings.Split(sourceAddrs, ",") {
|
||||||
if allowedIP := net.ParseIP(sourceAddr); allowedIP != nil {
|
if allowedIP := net.ParseIP(sourceAddr); allowedIP != nil {
|
||||||
if bytes.Equal(allowedIP, tcpAddr.IP) {
|
if allowedIP.Equal(tcpAddr.IP) {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -255,17 +267,33 @@ func checkSourceAddress(addr net.Addr, sourceAddr string) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return fmt.Errorf("ssh: remote address %v is not allowed because of source-address restriction", addr)
|
return fmt.Errorf("ssh: remote address %v is not allowed because of source-address restriction", addr)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *connection) serverAuthenticate(config *ServerConfig) (*Permissions, error) {
|
func (s *connection) serverAuthenticate(config *ServerConfig) (*Permissions, error) {
|
||||||
var err error
|
sessionID := s.transport.getSessionID()
|
||||||
var cache pubKeyCache
|
var cache pubKeyCache
|
||||||
var perms *Permissions
|
var perms *Permissions
|
||||||
|
|
||||||
|
authFailures := 0
|
||||||
|
|
||||||
userAuthLoop:
|
userAuthLoop:
|
||||||
for {
|
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
|
var userAuthReq userAuthRequestMsg
|
||||||
if packet, err := s.transport.readPacket(); err != nil {
|
if packet, err := s.transport.readPacket(); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -286,6 +314,11 @@ userAuthLoop:
|
||||||
if config.NoClientAuth {
|
if config.NoClientAuth {
|
||||||
authErr = nil
|
authErr = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// allow initial attempt of 'none' without penalty
|
||||||
|
if authFailures == 0 {
|
||||||
|
authFailures--
|
||||||
|
}
|
||||||
case "password":
|
case "password":
|
||||||
if config.PasswordCallback == nil {
|
if config.PasswordCallback == nil {
|
||||||
authErr = errors.New("ssh: password auth not configured")
|
authErr = errors.New("ssh: password auth not configured")
|
||||||
|
@ -357,6 +390,7 @@ userAuthLoop:
|
||||||
if isQuery {
|
if isQuery {
|
||||||
// The client can query if the given public key
|
// The client can query if the given public key
|
||||||
// would be okay.
|
// would be okay.
|
||||||
|
|
||||||
if len(payload) > 0 {
|
if len(payload) > 0 {
|
||||||
return nil, parseError(msgUserAuthRequest)
|
return nil, parseError(msgUserAuthRequest)
|
||||||
}
|
}
|
||||||
|
@ -385,7 +419,7 @@ userAuthLoop:
|
||||||
if !isAcceptableAlgo(sig.Format) {
|
if !isAcceptableAlgo(sig.Format) {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
signedData := buildDataSignedForAuth(s.transport.getSessionID(), userAuthReq, algoBytes, pubKeyData)
|
signedData := buildDataSignedForAuth(sessionID, userAuthReq, algoBytes, pubKeyData)
|
||||||
|
|
||||||
if err := pubKey.Verify(signedData, sig); err != nil {
|
if err := pubKey.Verify(signedData, sig); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -406,6 +440,8 @@ userAuthLoop:
|
||||||
break userAuthLoop
|
break userAuthLoop
|
||||||
}
|
}
|
||||||
|
|
||||||
|
authFailures++
|
||||||
|
|
||||||
var failureMsg userAuthFailureMsg
|
var failureMsg userAuthFailureMsg
|
||||||
if config.PasswordCallback != nil {
|
if config.PasswordCallback != nil {
|
||||||
failureMsg.Methods = append(failureMsg.Methods, "password")
|
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")
|
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
|
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 nil, err
|
||||||
}
|
}
|
||||||
return perms, nil
|
return perms, nil
|
||||||
|
|
|
@ -60,6 +60,7 @@ func dial(handler serverType, t *testing.T) *Client {
|
||||||
|
|
||||||
config := &ClientConfig{
|
config := &ClientConfig{
|
||||||
User: "testuser",
|
User: "testuser",
|
||||||
|
HostKeyCallback: InsecureIgnoreHostKey(),
|
||||||
}
|
}
|
||||||
|
|
||||||
conn, chans, reqs, err := NewClientConn(c2, "", config)
|
conn, chans, reqs, err := NewClientConn(c2, "", config)
|
||||||
|
@ -641,6 +642,7 @@ func TestSessionID(t *testing.T) {
|
||||||
}
|
}
|
||||||
serverConf.AddHostKey(testSigners["ecdsa"])
|
serverConf.AddHostKey(testSigners["ecdsa"])
|
||||||
clientConf := &ClientConfig{
|
clientConf := &ClientConfig{
|
||||||
|
HostKeyCallback: InsecureIgnoreHostKey(),
|
||||||
User: "user",
|
User: "user",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -747,7 +749,9 @@ func TestHostKeyAlgorithms(t *testing.T) {
|
||||||
|
|
||||||
// By default, we get the preferred algorithm, which is ECDSA 256.
|
// By default, we get the preferred algorithm, which is ECDSA 256.
|
||||||
|
|
||||||
clientConf := &ClientConfig{}
|
clientConf := &ClientConfig{
|
||||||
|
HostKeyCallback: InsecureIgnoreHostKey(),
|
||||||
|
}
|
||||||
connect(clientConf, KeyAlgoECDSA256)
|
connect(clientConf, KeyAlgoECDSA256)
|
||||||
|
|
||||||
// Client asks for RSA explicitly.
|
// 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",
|
||||||
|
}
|
||||||
|
}
|
118
vendor/src/golang.org/x/crypto/ssh/tcpip.go
vendored
118
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
|
// addr. Incoming connections will be available by calling Accept on
|
||||||
// the returned net.Listener. The listener must be serviced, or the
|
// the returned net.Listener. The listener must be serviced, or the
|
||||||
// SSH connection may hang.
|
// SSH connection may hang.
|
||||||
|
// N must be "tcp", "tcp4", "tcp6", or "unix".
|
||||||
func (c *Client) Listen(n, addr string) (net.Listener, error) {
|
func (c *Client) Listen(n, addr string) (net.Listener, error) {
|
||||||
|
switch n {
|
||||||
|
case "tcp", "tcp4", "tcp6":
|
||||||
laddr, err := net.ResolveTCPAddr(n, addr)
|
laddr, err := net.ResolveTCPAddr(n, addr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return c.ListenTCP(laddr)
|
return c.ListenTCP(laddr)
|
||||||
|
case "unix":
|
||||||
|
return c.ListenUnix(addr)
|
||||||
|
default:
|
||||||
|
return nil, fmt.Errorf("ssh: unsupported protocol: %s", n)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Automatic port allocation is broken with OpenSSH before 6.0. See
|
// 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.
|
// 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
|
return &tcpListener{laddr, c, ch}, nil
|
||||||
}
|
}
|
||||||
|
@ -131,7 +139,7 @@ type forwardList struct {
|
||||||
// forwardEntry represents an established mapping of a laddr on a
|
// forwardEntry represents an established mapping of a laddr on a
|
||||||
// remote ssh server to a channel connected to a tcpListener.
|
// remote ssh server to a channel connected to a tcpListener.
|
||||||
type forwardEntry struct {
|
type forwardEntry struct {
|
||||||
laddr net.TCPAddr
|
laddr net.Addr
|
||||||
c chan forward
|
c chan forward
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -140,15 +148,15 @@ type forwardEntry struct {
|
||||||
// the original forward-request.
|
// the original forward-request.
|
||||||
type forward struct {
|
type forward struct {
|
||||||
newCh NewChannel // the ssh client channel underlying this forward
|
newCh NewChannel // the ssh client channel underlying this forward
|
||||||
raddr *net.TCPAddr // the raddr of the incoming connection
|
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()
|
l.Lock()
|
||||||
defer l.Unlock()
|
defer l.Unlock()
|
||||||
f := forwardEntry{
|
f := forwardEntry{
|
||||||
addr,
|
laddr: addr,
|
||||||
make(chan forward, 1),
|
c: make(chan forward, 1),
|
||||||
}
|
}
|
||||||
l.entries = append(l.entries, f)
|
l.entries = append(l.entries, f)
|
||||||
return f.c
|
return f.c
|
||||||
|
@ -176,8 +184,15 @@ func parseTCPAddr(addr string, port uint32) (*net.TCPAddr, error) {
|
||||||
|
|
||||||
func (l *forwardList) handleChannels(in <-chan NewChannel) {
|
func (l *forwardList) handleChannels(in <-chan NewChannel) {
|
||||||
for ch := range in {
|
for ch := range in {
|
||||||
|
var (
|
||||||
|
laddr net.Addr
|
||||||
|
raddr net.Addr
|
||||||
|
err error
|
||||||
|
)
|
||||||
|
switch channelType := ch.ChannelType(); channelType {
|
||||||
|
case "forwarded-tcpip":
|
||||||
var payload forwardedTCPPayload
|
var payload forwardedTCPPayload
|
||||||
if err := Unmarshal(ch.ExtraData(), &payload); err != nil {
|
if err = Unmarshal(ch.ExtraData(), &payload); err != nil {
|
||||||
ch.Reject(ConnectionFailed, "could not parse forwarded-tcpip payload: "+err.Error())
|
ch.Reject(ConnectionFailed, "could not parse forwarded-tcpip payload: "+err.Error())
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
@ -187,33 +202,51 @@ func (l *forwardList) handleChannels(in <-chan NewChannel) {
|
||||||
// format. It is implied that this should be an IP
|
// format. It is implied that this should be an IP
|
||||||
// address, as it would be impossible to connect to it
|
// address, as it would be impossible to connect to it
|
||||||
// otherwise.
|
// otherwise.
|
||||||
laddr, err := parseTCPAddr(payload.Addr, payload.Port)
|
laddr, err = parseTCPAddr(payload.Addr, payload.Port)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ch.Reject(ConnectionFailed, err.Error())
|
ch.Reject(ConnectionFailed, err.Error())
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
raddr, err := parseTCPAddr(payload.OriginAddr, payload.OriginPort)
|
raddr, err = parseTCPAddr(payload.OriginAddr, payload.OriginPort)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ch.Reject(ConnectionFailed, err.Error())
|
ch.Reject(ConnectionFailed, err.Error())
|
||||||
continue
|
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
|
// Section 7.2, implementations MUST reject spurious incoming
|
||||||
// connections.
|
// connections.
|
||||||
ch.Reject(Prohibited, "no forward for address")
|
ch.Reject(Prohibited, "no forward for address")
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// remove removes the forward entry, and the channel feeding its
|
// remove removes the forward entry, and the channel feeding its
|
||||||
// listener.
|
// listener.
|
||||||
func (l *forwardList) remove(addr net.TCPAddr) {
|
func (l *forwardList) remove(addr net.Addr) {
|
||||||
l.Lock()
|
l.Lock()
|
||||||
defer l.Unlock()
|
defer l.Unlock()
|
||||||
for i, f := range l.entries {
|
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:]...)
|
l.entries = append(l.entries[:i], l.entries[i+1:]...)
|
||||||
close(f.c)
|
close(f.c)
|
||||||
return
|
return
|
||||||
|
@ -231,12 +264,12 @@ func (l *forwardList) closeAll() {
|
||||||
l.entries = nil
|
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()
|
l.Lock()
|
||||||
defer l.Unlock()
|
defer l.Unlock()
|
||||||
for _, f := range l.entries {
|
for _, f := range l.entries {
|
||||||
if laddr.IP.Equal(f.laddr.IP) && laddr.Port == f.laddr.Port {
|
if laddr.Network() == f.laddr.Network() && laddr.String() == f.laddr.String() {
|
||||||
f.c <- forward{ch, &raddr}
|
f.c <- forward{newCh: ch, raddr: raddr}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -262,7 +295,7 @@ func (l *tcpListener) Accept() (net.Conn, error) {
|
||||||
}
|
}
|
||||||
go DiscardRequests(incoming)
|
go DiscardRequests(incoming)
|
||||||
|
|
||||||
return &tcpChanConn{
|
return &chanConn{
|
||||||
Channel: ch,
|
Channel: ch,
|
||||||
laddr: l.laddr,
|
laddr: l.laddr,
|
||||||
raddr: s.raddr,
|
raddr: s.raddr,
|
||||||
|
@ -277,7 +310,7 @@ func (l *tcpListener) Close() error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// this also closes the listener.
|
// 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))
|
ok, _, err := l.conn.SendRequest("cancel-tcpip-forward", true, Marshal(&m))
|
||||||
if err == nil && !ok {
|
if err == nil && !ok {
|
||||||
err = errors.New("ssh: cancel-tcpip-forward failed")
|
err = errors.New("ssh: cancel-tcpip-forward failed")
|
||||||
|
@ -293,6 +326,9 @@ func (l *tcpListener) Addr() net.Addr {
|
||||||
// Dial initiates a connection to the addr from the remote host.
|
// Dial initiates a connection to the addr from the remote host.
|
||||||
// The resulting connection has a zero LocalAddr() and RemoteAddr().
|
// The resulting connection has a zero LocalAddr() and RemoteAddr().
|
||||||
func (c *Client) Dial(n, addr string) (net.Conn, error) {
|
func (c *Client) Dial(n, addr string) (net.Conn, error) {
|
||||||
|
var ch Channel
|
||||||
|
switch n {
|
||||||
|
case "tcp", "tcp4", "tcp6":
|
||||||
// Parse the address into host and numeric port.
|
// Parse the address into host and numeric port.
|
||||||
host, portString, err := net.SplitHostPort(addr)
|
host, portString, err := net.SplitHostPort(addr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -302,20 +338,40 @@ func (c *Client) Dial(n, addr string) (net.Conn, error) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
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.
|
// Use a zero address for local and remote address.
|
||||||
zeroAddr := &net.TCPAddr{
|
zeroAddr := &net.TCPAddr{
|
||||||
IP: net.IPv4zero,
|
IP: net.IPv4zero,
|
||||||
Port: 0,
|
Port: 0,
|
||||||
}
|
}
|
||||||
ch, err := c.dial(net.IPv4zero.String(), 0, host, int(port))
|
return &chanConn{
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return &tcpChanConn{
|
|
||||||
Channel: ch,
|
Channel: ch,
|
||||||
laddr: zeroAddr,
|
laddr: zeroAddr,
|
||||||
raddr: zeroAddr,
|
raddr: zeroAddr,
|
||||||
}, nil
|
}, 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)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// DialTCP connects to the remote address raddr on the network net,
|
// 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 {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return &tcpChanConn{
|
return &chanConn{
|
||||||
Channel: ch,
|
Channel: ch,
|
||||||
laddr: laddr,
|
laddr: laddr,
|
||||||
raddr: raddr,
|
raddr: raddr,
|
||||||
|
@ -366,26 +422,26 @@ type tcpChan struct {
|
||||||
Channel // the backing channel
|
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.
|
// the tcpChan having to hold laddr or raddr directly.
|
||||||
type tcpChanConn struct {
|
type chanConn struct {
|
||||||
Channel
|
Channel
|
||||||
laddr, raddr net.Addr
|
laddr, raddr net.Addr
|
||||||
}
|
}
|
||||||
|
|
||||||
// LocalAddr returns the local network address.
|
// LocalAddr returns the local network address.
|
||||||
func (t *tcpChanConn) LocalAddr() net.Addr {
|
func (t *chanConn) LocalAddr() net.Addr {
|
||||||
return t.laddr
|
return t.laddr
|
||||||
}
|
}
|
||||||
|
|
||||||
// RemoteAddr returns the remote network address.
|
// RemoteAddr returns the remote network address.
|
||||||
func (t *tcpChanConn) RemoteAddr() net.Addr {
|
func (t *chanConn) RemoteAddr() net.Addr {
|
||||||
return t.raddr
|
return t.raddr
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetDeadline sets the read and write deadlines associated
|
// SetDeadline sets the read and write deadlines associated
|
||||||
// with the connection.
|
// 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 {
|
if err := t.SetReadDeadline(deadline); err != nil {
|
||||||
return err
|
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.
|
// A zero value for t means Read will not time out.
|
||||||
// After the deadline, the error from Read will implement net.Error
|
// After the deadline, the error from Read will implement net.Error
|
||||||
// with Timeout() == true.
|
// 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")
|
return errors.New("ssh: tcpChan: deadline not supported")
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetWriteDeadline exists to satisfy the net.Conn interface
|
// SetWriteDeadline exists to satisfy the net.Conn interface
|
||||||
// but is not implemented by this type. It always returns an error.
|
// 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")
|
return errors.New("ssh: tcpChan: deadline not supported")
|
||||||
}
|
}
|
||||||
|
|
|
@ -132,8 +132,11 @@ const (
|
||||||
keyPasteEnd
|
keyPasteEnd
|
||||||
)
|
)
|
||||||
|
|
||||||
var pasteStart = []byte{keyEscape, '[', '2', '0', '0', '~'}
|
var (
|
||||||
var pasteEnd = []byte{keyEscape, '[', '2', '0', '1', '~'}
|
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
|
// 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.
|
// 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
|
// So, if we are stopping at the end of a line, we
|
||||||
// need to write a newline so that our cursor can be
|
// need to write a newline so that our cursor can be
|
||||||
// advanced to the next line.
|
// 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) {
|
func (t *Terminal) Write(buf []byte) (n int, err error) {
|
||||||
t.lock.Lock()
|
t.lock.Lock()
|
||||||
defer t.lock.Unlock()
|
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 {
|
if t.cursorX == 0 && t.cursorY == 0 {
|
||||||
// This is the easy case: there's nothing on the screen that we
|
// This is the easy case: there's nothing on the screen that we
|
||||||
// have to move out of the way.
|
// 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
|
// 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]
|
t.outBuf = t.outBuf[:0]
|
||||||
|
|
||||||
if n, err = t.c.Write(buf); err != nil {
|
if n, err = writeWithCRLF(t.c, buf); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -740,8 +772,6 @@ func (t *Terminal) readLine() (line string, err error) {
|
||||||
|
|
||||||
t.remainder = t.inBuf[:n+len(t.remainder)]
|
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.
|
// 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
|
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
|
package terminal
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"io"
|
"io"
|
||||||
"os"
|
"os"
|
||||||
"testing"
|
"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) {
|
func TestMakeRawState(t *testing.T) {
|
||||||
fd := int(os.Stdout.Fd())
|
fd := int(os.Stdout.Fd())
|
||||||
if !IsTerminal(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)
|
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"
|
package terminal // import "golang.org/x/crypto/ssh/terminal"
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"io"
|
|
||||||
"syscall"
|
"syscall"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
)
|
)
|
||||||
|
@ -72,9 +71,11 @@ func GetState(fd int) (*State, error) {
|
||||||
// Restore restores the terminal connected to the given file descriptor to a
|
// Restore restores the terminal connected to the given file descriptor to a
|
||||||
// previous state.
|
// previous state.
|
||||||
func Restore(fd int, state *State) error {
|
func Restore(fd int, state *State) error {
|
||||||
_, _, err := syscall.Syscall6(syscall.SYS_IOCTL, uintptr(fd), ioctlWriteTermios, uintptr(unsafe.Pointer(&state.termios)), 0, 0, 0)
|
if _, _, err := syscall.Syscall6(syscall.SYS_IOCTL, uintptr(fd), ioctlWriteTermios, uintptr(unsafe.Pointer(&state.termios)), 0, 0, 0); err != 0 {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// GetSize returns the dimensions of the given terminal.
|
// GetSize returns the dimensions of the given terminal.
|
||||||
func GetSize(fd int) (width, height int, err error) {
|
func GetSize(fd int) (width, height int, err error) {
|
||||||
|
@ -86,6 +87,13 @@ func GetSize(fd int) (width, height int, err error) {
|
||||||
return int(dimensions[1]), int(dimensions[0]), nil
|
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
|
// 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
|
// is commonly used for inputting passwords and other sensitive data. The slice
|
||||||
// returned does not include the \n.
|
// 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)
|
syscall.Syscall6(syscall.SYS_IOCTL, uintptr(fd), ioctlWriteTermios, uintptr(unsafe.Pointer(&oldState)), 0, 0, 0)
|
||||||
}()
|
}()
|
||||||
|
|
||||||
var buf [16]byte
|
return readPasswordLine(passwordReader(fd))
|
||||||
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
|
|
||||||
}
|
}
|
||||||
|
|
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
|
package terminal
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"io"
|
|
||||||
"syscall"
|
"syscall"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
)
|
)
|
||||||
|
@ -123,6 +122,13 @@ func GetSize(fd int) (width, height int, err error) {
|
||||||
return int(info.size.x), int(info.size.y), nil
|
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
|
// 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
|
// is commonly used for inputting passwords and other sensitive data. The slice
|
||||||
// returned does not include the \n.
|
// 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)
|
syscall.Syscall(procSetConsoleMode.Addr(), 2, uintptr(fd), uintptr(old), 0)
|
||||||
}()
|
}()
|
||||||
|
|
||||||
var buf [16]byte
|
return readPasswordLine(passwordReader(fd))
|
||||||
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
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,6 +37,7 @@ func TestCertLogin(t *testing.T) {
|
||||||
|
|
||||||
conf := &ssh.ClientConfig{
|
conf := &ssh.ClientConfig{
|
||||||
User: username(),
|
User: username(),
|
||||||
|
HostKeyCallback: ssh.InsecureIgnoreHostKey(),
|
||||||
}
|
}
|
||||||
conf.Auth = append(conf.Auth, ssh.PublicKeys(certSigner))
|
conf.Auth = append(conf.Auth, ssh.PublicKeys(certSigner))
|
||||||
client, err := s.TryDial(conf)
|
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"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestPortForward(t *testing.T) {
|
type closeWriter interface {
|
||||||
|
CloseWrite() error
|
||||||
|
}
|
||||||
|
|
||||||
|
func testPortForward(t *testing.T, n, listenAddr string) {
|
||||||
server := newServer(t)
|
server := newServer(t)
|
||||||
defer server.Shutdown()
|
defer server.Shutdown()
|
||||||
conn := server.Dial(clientConfig())
|
conn := server.Dial(clientConfig())
|
||||||
defer conn.Close()
|
defer conn.Close()
|
||||||
|
|
||||||
sshListener, err := conn.Listen("tcp", "localhost:0")
|
sshListener, err := conn.Listen(n, listenAddr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
@ -41,14 +45,14 @@ func TestPortForward(t *testing.T) {
|
||||||
}()
|
}()
|
||||||
|
|
||||||
forwardedAddr := sshListener.Addr().String()
|
forwardedAddr := sshListener.Addr().String()
|
||||||
tcpConn, err := net.Dial("tcp", forwardedAddr)
|
netConn, err := net.Dial(n, forwardedAddr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("TCP dial failed: %v", err)
|
t.Fatalf("net dial failed: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
readChan := make(chan []byte)
|
readChan := make(chan []byte)
|
||||||
go func() {
|
go func() {
|
||||||
data, _ := ioutil.ReadAll(tcpConn)
|
data, _ := ioutil.ReadAll(netConn)
|
||||||
readChan <- data
|
readChan <- data
|
||||||
}()
|
}()
|
||||||
|
|
||||||
|
@ -62,14 +66,14 @@ func TestPortForward(t *testing.T) {
|
||||||
for len(sent) < 1000*1000 {
|
for len(sent) < 1000*1000 {
|
||||||
// Send random sized chunks
|
// Send random sized chunks
|
||||||
m := rand.Intn(len(data))
|
m := rand.Intn(len(data))
|
||||||
n, err := tcpConn.Write(data[:m])
|
n, err := netConn.Write(data[:m])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
sent = append(sent, data[:n]...)
|
sent = append(sent, data[:n]...)
|
||||||
}
|
}
|
||||||
if err := tcpConn.(*net.TCPConn).CloseWrite(); err != nil {
|
if err := netConn.(closeWriter).CloseWrite(); err != nil {
|
||||||
t.Errorf("tcpConn.CloseWrite: %v", err)
|
t.Errorf("netConn.CloseWrite: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
read := <-readChan
|
read := <-readChan
|
||||||
|
@ -86,19 +90,29 @@ func TestPortForward(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check that the forward disappeared.
|
// Check that the forward disappeared.
|
||||||
tcpConn, err = net.Dial("tcp", forwardedAddr)
|
netConn, err = net.Dial(n, forwardedAddr)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
tcpConn.Close()
|
netConn.Close()
|
||||||
t.Errorf("still listening to %s after closing", forwardedAddr)
|
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)
|
server := newServer(t)
|
||||||
defer server.Shutdown()
|
defer server.Shutdown()
|
||||||
conn := server.Dial(clientConfig())
|
conn := server.Dial(clientConfig())
|
||||||
|
|
||||||
sshListener, err := conn.Listen("tcp", "localhost:0")
|
sshListener, err := conn.Listen(n, listenAddr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
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.
|
// 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)
|
server := newServer(t)
|
||||||
defer server.Shutdown()
|
defer server.Shutdown()
|
||||||
conn := server.Dial(clientConfig())
|
conn := server.Dial(clientConfig())
|
||||||
|
|
||||||
sshListener, err := conn.Listen("tcp", "localhost:0")
|
sshListener, err := conn.Listen(n, listenAddr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
@ -158,3 +182,13 @@ func TestPortForwardConnectionClose(t *testing.T) {
|
||||||
t.Logf("quit as expected (error %v)", err)
|
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==
|
HKuOrPtLHFvHsjWPwO+/AAAAE2dhcnRvbm1AZ2FydG9ubS14cHMBAg==
|
||||||
-----END OPENSSH PRIVATE KEY-----
|
-----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-----
|
"user": []byte(`-----BEGIN EC PRIVATE KEY-----
|
||||||
MHcCAQEEILYCAeq8f7V4vSSypRw7pxy8yz3V5W4qg8kSC3zJhqpQoAoGCCqGSM49
|
MHcCAQEEILYCAeq8f7V4vSSypRw7pxy8yz3V5W4qg8kSC3zJhqpQoAoGCCqGSM49
|
||||||
AwEHoUQDQgAEYcO2xNKiRUYOLEHM7VYAp57HNyKbOdYtHD83Z4hzNPVC4tM5mdGD
|
AwEHoUQDQgAEYcO2xNKiRUYOLEHM7VYAp57HNyKbOdYtHD83Z4hzNPVC4tM5mdGD
|
||||||
|
@ -55,3 +71,66 @@ PLL8IEwvYu2wq+lpXfGQnNMbzYf9gspG0w==
|
||||||
-----END EC PRIVATE KEY-----
|
-----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"
|
"bufio"
|
||||||
"errors"
|
"errors"
|
||||||
"io"
|
"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 (
|
const (
|
||||||
gcmCipherID = "aes128-gcm@openssh.com"
|
gcmCipherID = "aes128-gcm@openssh.com"
|
||||||
aes128cbcID = "aes128-cbc"
|
aes128cbcID = "aes128-cbc"
|
||||||
|
@ -22,7 +27,9 @@ type packetConn interface {
|
||||||
// Encrypt and send a packet of data to the remote peer.
|
// Encrypt and send a packet of data to the remote peer.
|
||||||
writePacket(packet []byte) error
|
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)
|
readPacket() ([]byte, error)
|
||||||
|
|
||||||
// Close closes the write-side of the connection.
|
// Close closes the write-side of the connection.
|
||||||
|
@ -38,7 +45,7 @@ type transport struct {
|
||||||
bufReader *bufio.Reader
|
bufReader *bufio.Reader
|
||||||
bufWriter *bufio.Writer
|
bufWriter *bufio.Writer
|
||||||
rand io.Reader
|
rand io.Reader
|
||||||
|
isClient bool
|
||||||
io.Closer
|
io.Closer
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -84,9 +91,38 @@ func (t *transport) prepareKeyChange(algs *algorithms, kexResult *kexResult) err
|
||||||
return nil
|
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.
|
// Read and decrypt next packet.
|
||||||
func (t *transport) readPacket() ([]byte, error) {
|
func (t *transport) readPacket() (p []byte, err error) {
|
||||||
return t.reader.readPacket(t.bufReader)
|
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) {
|
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 {
|
func (t *transport) writePacket(packet []byte) error {
|
||||||
|
if debugTransport {
|
||||||
|
t.printPacket(packet, true)
|
||||||
|
}
|
||||||
return t.writer.writePacket(t.bufWriter, t.rand, packet)
|
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,
|
Closer: rwc,
|
||||||
}
|
}
|
||||||
|
t.isClient = isClient
|
||||||
|
|
||||||
if isClient {
|
if isClient {
|
||||||
t.reader.dir = serverKeys
|
t.reader.dir = serverKeys
|
||||||
t.writer.dir = clientKeys
|
t.writer.dir = clientKeys
|
||||||
|
@ -226,6 +267,7 @@ func newPacketCipher(d direction, algs directionAlgorithms, kex *kexResult) (pac
|
||||||
|
|
||||||
c := &streamPacketCipher{
|
c := &streamPacketCipher{
|
||||||
mac: macModes[algs.MAC].new(macKey),
|
mac: macModes[algs.MAC].new(macKey),
|
||||||
|
etm: macModes[algs.MAC].etm,
|
||||||
}
|
}
|
||||||
c.macResult = make([]byte, c.mac.Size())
|
c.macResult = make([]byte, c.mac.Size())
|
||||||
|
|
||||||
|
|
|
@ -243,45 +243,51 @@ func testDeadline(c Context, wait time.Duration, t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestDeadline(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) {
|
if got, prefix := fmt.Sprint(c), "context.Background.WithDeadline("; !strings.HasPrefix(got, prefix) {
|
||||||
t.Errorf("c.String() = %q want prefix %q", 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}
|
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}
|
o = otherContext{c}
|
||||||
c, _ = WithDeadline(o, time.Now().Add(300*time.Millisecond))
|
c, _ = WithDeadline(o, time.Now().Add(3*timeUnit))
|
||||||
testDeadline(c, 200*time.Millisecond, t)
|
testDeadline(c, 2*timeUnit, t)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestTimeout(t *testing.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) {
|
if got, prefix := fmt.Sprint(c), "context.Background.WithDeadline("; !strings.HasPrefix(got, prefix) {
|
||||||
t.Errorf("c.String() = %q want prefix %q", 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}
|
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}
|
o = otherContext{c}
|
||||||
c, _ = WithTimeout(o, 300*time.Millisecond)
|
c, _ = WithTimeout(o, 3*timeUnit)
|
||||||
testDeadline(c, 200*time.Millisecond, t)
|
testDeadline(c, 2*timeUnit, t)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestCanceledTimeout(t *testing.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}
|
o := otherContext{c}
|
||||||
c, cancel := WithTimeout(o, 400*time.Millisecond)
|
c, cancel := WithTimeout(o, 4*timeUnit)
|
||||||
cancel()
|
cancel()
|
||||||
time.Sleep(100 * time.Millisecond) // let cancelation propagate
|
time.Sleep(1 * timeUnit) // let cancelation propagate
|
||||||
select {
|
select {
|
||||||
case <-c.Done():
|
case <-c.Done():
|
||||||
default:
|
default:
|
||||||
|
|
|
@ -19,6 +19,7 @@ func TestGo17Context(t *testing.T) {
|
||||||
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
io.WriteString(w, "ok")
|
io.WriteString(w, "ok")
|
||||||
}))
|
}))
|
||||||
|
defer ts.Close()
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
resp, err := Get(ctx, http.DefaultClient, ts.URL)
|
resp, err := Get(ctx, http.DefaultClient, ts.URL)
|
||||||
if resp == nil || err != nil {
|
if resp == nil || err != nil {
|
||||||
|
|
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.
|
// Copyright 2014 The Go Authors. All rights reserved.
|
||||||
// Use of this source code is governed by a BSD-style
|
// 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)
|
-syscalls)
|
||||||
for i in zsyscall*go
|
for i in zsyscall*go
|
||||||
do
|
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
|
sed 1q $i | sed 's;^// ;;' | sh > _$i && gofmt < _$i > $i
|
||||||
rm _$i
|
rm _$i
|
||||||
done
|
done
|
||||||
|
@ -223,6 +225,13 @@ linux_s390x)
|
||||||
# package generates its version of the types file.
|
# package generates its version of the types file.
|
||||||
mktypes="GOARCH=$GOARCH go tool cgo -godefs -- -fsigned-char"
|
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)
|
netbsd_386)
|
||||||
mkerrors="$mkerrors -m32"
|
mkerrors="$mkerrors -m32"
|
||||||
mksyscall="./mksyscall.pl -l32 -netbsd"
|
mksyscall="./mksyscall.pl -l32 -netbsd"
|
||||||
|
@ -273,7 +282,7 @@ esac
|
||||||
syscall_goos="syscall_bsd.go $syscall_goos"
|
syscall_goos="syscall_bsd.go $syscall_goos"
|
||||||
;;
|
;;
|
||||||
esac
|
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
|
esac
|
||||||
if [ -n "$mksysctl" ]; then echo "$mksysctl |gofmt >$zsysctl"; fi
|
if [ -n "$mksysctl" ]; then echo "$mksysctl |gofmt >$zsysctl"; fi
|
||||||
|
|
25
vendor/src/golang.org/x/sys/unix/mkerrors.sh
vendored
25
vendor/src/golang.org/x/sys/unix/mkerrors.sh
vendored
|
@ -114,19 +114,25 @@ includes_Linux='
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
#include <linux/if.h>
|
#include <linux/if.h>
|
||||||
|
#include <linux/if_alg.h>
|
||||||
#include <linux/if_arp.h>
|
#include <linux/if_arp.h>
|
||||||
#include <linux/if_ether.h>
|
#include <linux/if_ether.h>
|
||||||
#include <linux/if_tun.h>
|
#include <linux/if_tun.h>
|
||||||
#include <linux/if_packet.h>
|
#include <linux/if_packet.h>
|
||||||
#include <linux/if_addr.h>
|
#include <linux/if_addr.h>
|
||||||
|
#include <linux/falloc.h>
|
||||||
#include <linux/filter.h>
|
#include <linux/filter.h>
|
||||||
#include <linux/netlink.h>
|
#include <linux/netlink.h>
|
||||||
|
#include <linux/random.h>
|
||||||
#include <linux/reboot.h>
|
#include <linux/reboot.h>
|
||||||
#include <linux/rtnetlink.h>
|
#include <linux/rtnetlink.h>
|
||||||
#include <linux/ptrace.h>
|
#include <linux/ptrace.h>
|
||||||
#include <linux/sched.h>
|
#include <linux/sched.h>
|
||||||
#include <linux/wait.h>
|
#include <linux/wait.h>
|
||||||
#include <linux/icmpv6.h>
|
#include <linux/icmpv6.h>
|
||||||
|
#include <linux/serial.h>
|
||||||
|
#include <linux/can.h>
|
||||||
|
#include <linux/vm_sockets.h>
|
||||||
#include <net/route.h>
|
#include <net/route.h>
|
||||||
#include <asm/termbits.h>
|
#include <asm/termbits.h>
|
||||||
|
|
||||||
|
@ -141,6 +147,16 @@ includes_Linux='
|
||||||
#ifndef PTRACE_SETREGS
|
#ifndef PTRACE_SETREGS
|
||||||
#define PTRACE_SETREGS 0xd
|
#define PTRACE_SETREGS 0xd
|
||||||
#endif
|
#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='
|
includes_NetBSD='
|
||||||
|
@ -304,6 +320,7 @@ ccflags="$@"
|
||||||
$2 ~ /^IN_/ ||
|
$2 ~ /^IN_/ ||
|
||||||
$2 ~ /^LOCK_(SH|EX|NB|UN)$/ ||
|
$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 ~ /^(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 == "ICMPV6_FILTER" ||
|
||||||
$2 == "SOMAXCONN" ||
|
$2 == "SOMAXCONN" ||
|
||||||
$2 == "NAME_MAX" ||
|
$2 == "NAME_MAX" ||
|
||||||
|
@ -332,8 +349,14 @@ ccflags="$@"
|
||||||
$2 !~ /^(BPF_TIMEVAL)$/ &&
|
$2 !~ /^(BPF_TIMEVAL)$/ &&
|
||||||
$2 ~ /^(BPF|DLT)_/ ||
|
$2 ~ /^(BPF|DLT)_/ ||
|
||||||
$2 ~ /^CLOCK_/ ||
|
$2 ~ /^CLOCK_/ ||
|
||||||
|
$2 ~ /^CAN_/ ||
|
||||||
|
$2 ~ /^ALG_/ ||
|
||||||
|
$2 ~ /^GRND_/ ||
|
||||||
|
$2 ~ /^SPLICE_/ ||
|
||||||
|
$2 ~ /^(VM|VMADDR)_/ ||
|
||||||
$2 !~ "WMESGLEN" &&
|
$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 ~ /^__WCOREFLAG$/ {next}
|
||||||
$2 ~ /^__W[A-Z0-9]+$/ {printf("\t%s = C.%s\n", substr($2,3), $2)}
|
$2 ~ /^__W[A-Z0-9]+$/ {printf("\t%s = C.%s\n", substr($2,3), $2)}
|
||||||
|
|
||||||
|
|
21
vendor/src/golang.org/x/sys/unix/mksyscall.pl
vendored
21
vendor/src/golang.org/x/sys/unix/mksyscall.pl
vendored
|
@ -29,6 +29,7 @@ my $openbsd = 0;
|
||||||
my $netbsd = 0;
|
my $netbsd = 0;
|
||||||
my $dragonfly = 0;
|
my $dragonfly = 0;
|
||||||
my $arm = 0; # 64-bit value should use (even, odd)-pair
|
my $arm = 0; # 64-bit value should use (even, odd)-pair
|
||||||
|
my $tags = ""; # build tags
|
||||||
|
|
||||||
if($ARGV[0] eq "-b32") {
|
if($ARGV[0] eq "-b32") {
|
||||||
$_32bit = "big-endian";
|
$_32bit = "big-endian";
|
||||||
|
@ -57,14 +58,14 @@ if($ARGV[0] eq "-arm") {
|
||||||
$arm = 1;
|
$arm = 1;
|
||||||
shift;
|
shift;
|
||||||
}
|
}
|
||||||
|
if($ARGV[0] eq "-tags") {
|
||||||
if($ARGV[0] =~ /^-/) {
|
shift;
|
||||||
print STDERR "usage: mksyscall.pl [-b32 | -l32] [file ...]\n";
|
$tags = $ARGV[0];
|
||||||
exit 1;
|
shift;
|
||||||
}
|
}
|
||||||
|
|
||||||
if($ENV{'GOARCH'} eq "" || $ENV{'GOOS'} eq "") {
|
if($ARGV[0] =~ /^-/) {
|
||||||
print STDERR "GOARCH or GOOS not defined in environment\n";
|
print STDERR "usage: mksyscall.pl [-b32 | -l32] [-tags x,y] [file ...]\n";
|
||||||
exit 1;
|
exit 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -132,7 +133,6 @@ while(<>) {
|
||||||
|
|
||||||
# Prepare arguments to Syscall.
|
# Prepare arguments to Syscall.
|
||||||
my @args = ();
|
my @args = ();
|
||||||
my @uses = ();
|
|
||||||
my $n = 0;
|
my $n = 0;
|
||||||
foreach my $p (@in) {
|
foreach my $p (@in) {
|
||||||
my ($name, $type) = parseparam($p);
|
my ($name, $type) = parseparam($p);
|
||||||
|
@ -143,14 +143,12 @@ while(<>) {
|
||||||
$text .= "\t_p$n, $errvar = BytePtrFromString($name)\n";
|
$text .= "\t_p$n, $errvar = BytePtrFromString($name)\n";
|
||||||
$text .= "\tif $errvar != nil {\n\t\treturn\n\t}\n";
|
$text .= "\tif $errvar != nil {\n\t\treturn\n\t}\n";
|
||||||
push @args, "uintptr(unsafe.Pointer(_p$n))";
|
push @args, "uintptr(unsafe.Pointer(_p$n))";
|
||||||
push @uses, "use(unsafe.Pointer(_p$n))";
|
|
||||||
$n++;
|
$n++;
|
||||||
} elsif($type eq "string") {
|
} elsif($type eq "string") {
|
||||||
print STDERR "$ARGV:$.: $func uses string arguments, but has no error return\n";
|
print STDERR "$ARGV:$.: $func uses string arguments, but has no error return\n";
|
||||||
$text .= "\tvar _p$n *byte\n";
|
$text .= "\tvar _p$n *byte\n";
|
||||||
$text .= "\t_p$n, _ = BytePtrFromString($name)\n";
|
$text .= "\t_p$n, _ = BytePtrFromString($name)\n";
|
||||||
push @args, "uintptr(unsafe.Pointer(_p$n))";
|
push @args, "uintptr(unsafe.Pointer(_p$n))";
|
||||||
push @uses, "use(unsafe.Pointer(_p$n))";
|
|
||||||
$n++;
|
$n++;
|
||||||
} elsif($type =~ /^\[\](.*)/) {
|
} elsif($type =~ /^\[\](.*)/) {
|
||||||
# Convert slice into pointer, length.
|
# Convert slice into pointer, length.
|
||||||
|
@ -278,9 +276,6 @@ while(<>) {
|
||||||
} else {
|
} else {
|
||||||
$text .= "\t$ret[0], $ret[1], $ret[2] := $call\n";
|
$text .= "\t$ret[0], $ret[1], $ret[2] := $call\n";
|
||||||
}
|
}
|
||||||
foreach my $use (@uses) {
|
|
||||||
$text .= "\t$use\n";
|
|
||||||
}
|
|
||||||
$text .= $body;
|
$text .= $body;
|
||||||
|
|
||||||
if ($plan9 && $ret[2] eq "e1") {
|
if ($plan9 && $ret[2] eq "e1") {
|
||||||
|
@ -307,7 +302,7 @@ print <<EOF;
|
||||||
// $cmdline
|
// $cmdline
|
||||||
// MACHINE GENERATED BY THE COMMAND ABOVE; DO NOT EDIT
|
// MACHINE GENERATED BY THE COMMAND ABOVE; DO NOT EDIT
|
||||||
|
|
||||||
// +build $ENV{'GOARCH'},$ENV{'GOOS'}
|
// +build $tags
|
||||||
|
|
||||||
package unix
|
package unix
|
||||||
|
|
||||||
|
|
|
@ -22,6 +22,7 @@ use strict;
|
||||||
my $cmdline = "mksyscall_solaris.pl " . join(' ', @ARGV);
|
my $cmdline = "mksyscall_solaris.pl " . join(' ', @ARGV);
|
||||||
my $errors = 0;
|
my $errors = 0;
|
||||||
my $_32bit = "";
|
my $_32bit = "";
|
||||||
|
my $tags = ""; # build tags
|
||||||
|
|
||||||
binmode STDOUT;
|
binmode STDOUT;
|
||||||
|
|
||||||
|
@ -32,14 +33,14 @@ if($ARGV[0] eq "-b32") {
|
||||||
$_32bit = "little-endian";
|
$_32bit = "little-endian";
|
||||||
shift;
|
shift;
|
||||||
}
|
}
|
||||||
|
if($ARGV[0] eq "-tags") {
|
||||||
if($ARGV[0] =~ /^-/) {
|
shift;
|
||||||
print STDERR "usage: mksyscall_solaris.pl [-b32 | -l32] [file ...]\n";
|
$tags = $ARGV[0];
|
||||||
exit 1;
|
shift;
|
||||||
}
|
}
|
||||||
|
|
||||||
if($ENV{'GOARCH'} eq "" || $ENV{'GOOS'} eq "") {
|
if($ARGV[0] =~ /^-/) {
|
||||||
print STDERR "GOARCH or GOOS not defined in environment\n";
|
print STDERR "usage: mksyscall_solaris.pl [-b32 | -l32] [-tags x,y] [file ...]\n";
|
||||||
exit 1;
|
exit 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -138,7 +139,6 @@ while(<>) {
|
||||||
|
|
||||||
# Prepare arguments to Syscall.
|
# Prepare arguments to Syscall.
|
||||||
my @args = ();
|
my @args = ();
|
||||||
my @uses = ();
|
|
||||||
my $n = 0;
|
my $n = 0;
|
||||||
foreach my $p (@in) {
|
foreach my $p (@in) {
|
||||||
my ($name, $type) = parseparam($p);
|
my ($name, $type) = parseparam($p);
|
||||||
|
@ -149,14 +149,12 @@ while(<>) {
|
||||||
$text .= "\t_p$n, $errvar = $strconvfunc($name)\n";
|
$text .= "\t_p$n, $errvar = $strconvfunc($name)\n";
|
||||||
$text .= "\tif $errvar != nil {\n\t\treturn\n\t}\n";
|
$text .= "\tif $errvar != nil {\n\t\treturn\n\t}\n";
|
||||||
push @args, "uintptr(unsafe.Pointer(_p$n))";
|
push @args, "uintptr(unsafe.Pointer(_p$n))";
|
||||||
push @uses, "use(unsafe.Pointer(_p$n))";
|
|
||||||
$n++;
|
$n++;
|
||||||
} elsif($type eq "string") {
|
} elsif($type eq "string") {
|
||||||
print STDERR "$ARGV:$.: $func uses string arguments, but has no error return\n";
|
print STDERR "$ARGV:$.: $func uses string arguments, but has no error return\n";
|
||||||
$text .= "\tvar _p$n $strconvtype\n";
|
$text .= "\tvar _p$n $strconvtype\n";
|
||||||
$text .= "\t_p$n, _ = $strconvfunc($name)\n";
|
$text .= "\t_p$n, _ = $strconvfunc($name)\n";
|
||||||
push @args, "uintptr(unsafe.Pointer(_p$n))";
|
push @args, "uintptr(unsafe.Pointer(_p$n))";
|
||||||
push @uses, "use(unsafe.Pointer(_p$n))";
|
|
||||||
$n++;
|
$n++;
|
||||||
} elsif($type =~ /^\[\](.*)/) {
|
} elsif($type =~ /^\[\](.*)/) {
|
||||||
# Convert slice into pointer, length.
|
# Convert slice into pointer, length.
|
||||||
|
@ -243,9 +241,6 @@ while(<>) {
|
||||||
} else {
|
} else {
|
||||||
$text .= "\t$ret[0], $ret[1], $ret[2] := $call\n";
|
$text .= "\t$ret[0], $ret[1], $ret[2] := $call\n";
|
||||||
}
|
}
|
||||||
foreach my $use (@uses) {
|
|
||||||
$text .= "\t$use\n";
|
|
||||||
}
|
|
||||||
$text .= $body;
|
$text .= $body;
|
||||||
|
|
||||||
if ($do_errno) {
|
if ($do_errno) {
|
||||||
|
@ -265,7 +260,7 @@ print <<EOF;
|
||||||
// $cmdline
|
// $cmdline
|
||||||
// MACHINE GENERATED BY THE COMMAND ABOVE; DO NOT EDIT
|
// MACHINE GENERATED BY THE COMMAND ABOVE; DO NOT EDIT
|
||||||
|
|
||||||
// +build $ENV{'GOARCH'},$ENV{'GOOS'}
|
// +build $tags
|
||||||
|
|
||||||
package $package
|
package $package
|
||||||
|
|
||||||
|
|
|
@ -23,6 +23,8 @@ package unix
|
||||||
const(
|
const(
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
|
my $offset = 0;
|
||||||
|
|
||||||
sub fmt {
|
sub fmt {
|
||||||
my ($name, $num) = @_;
|
my ($name, $num) = @_;
|
||||||
if($num > 999){
|
if($num > 999){
|
||||||
|
@ -31,15 +33,27 @@ sub fmt {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
$name =~ y/a-z/A-Z/;
|
$name =~ y/a-z/A-Z/;
|
||||||
|
$num = $num + $offset;
|
||||||
print " SYS_$name = $num;\n";
|
print " SYS_$name = $num;\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
my $prev;
|
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>){
|
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
|
# 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]+)/){
|
elsif(/^#define __NR_(\w+)\s+([0-9]+)/){
|
||||||
$prev = $2;
|
$prev = $2;
|
||||||
fmt($1, $2);
|
fmt($1, $2);
|
||||||
|
@ -51,6 +65,12 @@ while(<GCC>){
|
||||||
elsif(/^#define __NR_(\w+)\s+\(\w+\+\s*([0-9]+)\)/){
|
elsif(/^#define __NR_(\w+)\s+\(\w+\+\s*([0-9]+)\)/){
|
||||||
fmt($1, $prev+$2)
|
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;
|
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.
|
// holds a value of type syscall.Errno.
|
||||||
package unix // import "golang.org/x/sys/unix"
|
package unix // import "golang.org/x/sys/unix"
|
||||||
|
|
||||||
import "unsafe"
|
|
||||||
|
|
||||||
// ByteSliceFromString returns a NUL-terminated slice of bytes
|
// ByteSliceFromString returns a NUL-terminated slice of bytes
|
||||||
// containing the text of s. If s contains a NUL byte at any
|
// containing the text of s. If s contains a NUL byte at any
|
||||||
// location, it returns (nil, EINVAL).
|
// 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 }
|
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) {
|
func SysctlArgs(name string, args ...int) (string, error) {
|
||||||
mib, err := sysctlmib(name, args...)
|
buf, err := SysctlRaw(name, args...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
n := len(buf)
|
||||||
// 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
|
|
||||||
}
|
|
||||||
|
|
||||||
// Throw away terminating NUL.
|
// Throw away terminating NUL.
|
||||||
if n > 0 && buf[n-1] == '\x00' {
|
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
|
return buf[0 : n/siz], nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// ParseDirent parses up to max directory entries in buf,
|
func direntIno(buf []byte) (uint64, bool) {
|
||||||
// appending the names to names. It returns the number
|
return readInt(buf, unsafe.Offsetof(Dirent{}.Ino), unsafe.Sizeof(Dirent{}.Ino))
|
||||||
// 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.
|
func direntReclen(buf []byte) (uint64, bool) {
|
||||||
continue
|
return readInt(buf, unsafe.Offsetof(Dirent{}.Reclen), unsafe.Sizeof(Dirent{}.Reclen))
|
||||||
}
|
}
|
||||||
bytes := (*[10000]byte)(unsafe.Pointer(&dirent.Name[0]))
|
|
||||||
var name = string(bytes[0:dirent.Namlen])
|
func direntNamlen(buf []byte) (uint64, bool) {
|
||||||
if name == "." || name == ".." { // Useless names
|
return readInt(buf, unsafe.Offsetof(Dirent{}.Namlen), unsafe.Sizeof(Dirent{}.Namlen))
|
||||||
continue
|
|
||||||
}
|
|
||||||
max--
|
|
||||||
count++
|
|
||||||
names = append(names, name)
|
|
||||||
}
|
|
||||||
return origlen - len(buf), count, names
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//sys ptrace(request int, pid int, addr uintptr, data uintptr) (err error)
|
//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),
|
uintptr(options),
|
||||||
0,
|
0,
|
||||||
)
|
)
|
||||||
use(unsafe.Pointer(_p0))
|
|
||||||
if e1 != 0 {
|
if e1 != 0 {
|
||||||
return nil, e1
|
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))
|
bufsize = unsafe.Sizeof(Statfs_t{}) * uintptr(len(buf))
|
||||||
}
|
}
|
||||||
r0, _, e1 := Syscall(SYS_GETFSSTAT64, uintptr(_p0), bufsize, uintptr(flags))
|
r0, _, e1 := Syscall(SYS_GETFSSTAT64, uintptr(_p0), bufsize, uintptr(flags))
|
||||||
use(unsafe.Pointer(_p0))
|
|
||||||
n = int(r0)
|
n = int(r0)
|
||||||
if e1 != 0 {
|
if e1 != 0 {
|
||||||
err = e1
|
err = e1
|
||||||
|
|
|
@ -56,29 +56,20 @@ func nametomib(name string) (mib []_C_int, err error) {
|
||||||
return buf[0 : n/siz], nil
|
return buf[0 : n/siz], nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// ParseDirent parses up to max directory entries in buf,
|
func direntIno(buf []byte) (uint64, bool) {
|
||||||
// appending the names to names. It returns the number
|
return readInt(buf, unsafe.Offsetof(Dirent{}.Ino), unsafe.Sizeof(Dirent{}.Ino))
|
||||||
// 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])
|
func direntReclen(buf []byte) (uint64, bool) {
|
||||||
if name == "." || name == ".." { // Useless names
|
namlen, ok := direntNamlen(buf)
|
||||||
continue
|
if !ok {
|
||||||
|
return 0, false
|
||||||
}
|
}
|
||||||
max--
|
return (16 + namlen + 1 + 7) & ^7, true
|
||||||
count++
|
|
||||||
names = append(names, name)
|
|
||||||
}
|
}
|
||||||
return origlen - len(buf), count, names
|
|
||||||
|
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)
|
//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))
|
bufsize = unsafe.Sizeof(Statfs_t{}) * uintptr(len(buf))
|
||||||
}
|
}
|
||||||
r0, _, e1 := Syscall(SYS_GETFSSTAT, uintptr(_p0), bufsize, uintptr(flags))
|
r0, _, e1 := Syscall(SYS_GETFSSTAT, uintptr(_p0), bufsize, uintptr(flags))
|
||||||
use(unsafe.Pointer(_p0))
|
|
||||||
n = int(r0)
|
n = int(r0)
|
||||||
if e1 != 0 {
|
if e1 != 0 {
|
||||||
err = e1
|
err = e1
|
||||||
|
|
|
@ -54,32 +54,16 @@ func nametomib(name string) (mib []_C_int, err error) {
|
||||||
return buf[0 : n/siz], nil
|
return buf[0 : n/siz], nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// ParseDirent parses up to max directory entries in buf,
|
func direntIno(buf []byte) (uint64, bool) {
|
||||||
// appending the names to names. It returns the number
|
return readInt(buf, unsafe.Offsetof(Dirent{}.Fileno), unsafe.Sizeof(Dirent{}.Fileno))
|
||||||
// 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.
|
func direntReclen(buf []byte) (uint64, bool) {
|
||||||
continue
|
return readInt(buf, unsafe.Offsetof(Dirent{}.Reclen), unsafe.Sizeof(Dirent{}.Reclen))
|
||||||
}
|
}
|
||||||
bytes := (*[10000]byte)(unsafe.Pointer(&dirent.Name[0]))
|
|
||||||
var name = string(bytes[0:dirent.Namlen])
|
func direntNamlen(buf []byte) (uint64, bool) {
|
||||||
if name == "." || name == ".." { // Useless names
|
return readInt(buf, unsafe.Offsetof(Dirent{}.Namlen), unsafe.Sizeof(Dirent{}.Namlen))
|
||||||
continue
|
|
||||||
}
|
|
||||||
max--
|
|
||||||
count++
|
|
||||||
names = append(names, name)
|
|
||||||
}
|
|
||||||
return origlen - len(buf), count, names
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//sysnb pipe() (r int, w int, err error)
|
//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))
|
bufsize = unsafe.Sizeof(Statfs_t{}) * uintptr(len(buf))
|
||||||
}
|
}
|
||||||
r0, _, e1 := Syscall(SYS_GETFSSTAT, uintptr(_p0), bufsize, uintptr(flags))
|
r0, _, e1 := Syscall(SYS_GETFSSTAT, uintptr(_p0), bufsize, uintptr(flags))
|
||||||
use(unsafe.Pointer(_p0))
|
|
||||||
n = int(r0)
|
n = int(r0)
|
||||||
if e1 != 0 {
|
if e1 != 0 {
|
||||||
err = e1
|
err = e1
|
||||||
|
|
|
@ -7,18 +7,14 @@
|
||||||
package unix_test
|
package unix_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"os"
|
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"golang.org/x/sys/unix"
|
"golang.org/x/sys/unix"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestSysctUint64(t *testing.T) {
|
func TestSysctlUint64(t *testing.T) {
|
||||||
_, err := unix.SysctlUint64("vm.max_kernel_address")
|
_, err := unix.SysctlUint64("security.mac.labeled")
|
||||||
if err != nil {
|
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)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
262
vendor/src/golang.org/x/sys/unix/syscall_linux.go
vendored
262
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)
|
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) {
|
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) {
|
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 {
|
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) {
|
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 {
|
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)
|
//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 utimes(path string, times *[2]Timeval) (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
|
// in 2.6.22, Released, 8 July 2007) then fall back to utimes
|
||||||
var tv [2]Timeval
|
var tv [2]Timeval
|
||||||
for i := 0; i < 2; i++ {
|
for i := 0; i < 2; i++ {
|
||||||
tv[i].Sec = ts[i].Sec
|
tv[i] = NsecToTimeval(TimespecToNsec(ts[i]))
|
||||||
tv[i].Usec = ts[i].Nsec / 1000
|
|
||||||
}
|
}
|
||||||
return utimes(path, (*[2]Timeval)(unsafe.Pointer(&tv[0])))
|
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
|
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) {
|
func anyToSockaddr(rsa *RawSockaddrAny) (Sockaddr, error) {
|
||||||
switch rsa.Addr.Family {
|
switch rsa.Addr.Family {
|
||||||
case AF_NETLINK:
|
case AF_NETLINK:
|
||||||
|
@ -485,6 +642,14 @@ func anyToSockaddr(rsa *RawSockaddrAny) (Sockaddr, error) {
|
||||||
sa.Addr[i] = pp.Addr[i]
|
sa.Addr[i] = pp.Addr[i]
|
||||||
}
|
}
|
||||||
return sa, nil
|
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
|
return nil, EAFNOSUPPORT
|
||||||
}
|
}
|
||||||
|
@ -579,6 +744,13 @@ func GetsockoptUcred(fd, level, opt int) (*Ucred, error) {
|
||||||
return &value, err
|
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) {
|
func SetsockoptIPMreqn(fd, level, opt int, mreq *IPMreqn) (err error) {
|
||||||
return setsockopt(fd, level, opt, unsafe.Pointer(mreq), unsafe.Sizeof(*mreq))
|
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)
|
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) {
|
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
|
// As for ptracePeek, we need to align our accesses to deal
|
||||||
// with the possibility of straddling an invalid page.
|
// 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, "")
|
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) {
|
func ReadDirent(fd int, buf []byte) (n int, err error) {
|
||||||
return Getdents(fd, buf)
|
return Getdents(fd, buf)
|
||||||
}
|
}
|
||||||
|
|
||||||
func ParseDirent(buf []byte, max int, names []string) (consumed int, count int, newnames []string) {
|
func direntIno(buf []byte) (uint64, bool) {
|
||||||
origlen := len(buf)
|
return readInt(buf, unsafe.Offsetof(Dirent{}.Ino), unsafe.Sizeof(Dirent{}.Ino))
|
||||||
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[:])])
|
func direntReclen(buf []byte) (uint64, bool) {
|
||||||
if name == "." || name == ".." { // Useless names
|
return readInt(buf, unsafe.Offsetof(Dirent{}.Reclen), unsafe.Sizeof(Dirent{}.Reclen))
|
||||||
continue
|
|
||||||
}
|
}
|
||||||
max--
|
|
||||||
count++
|
func direntNamlen(buf []byte) (uint64, bool) {
|
||||||
names = append(names, name)
|
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)
|
//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 Getpid() (pid int)
|
||||||
//sysnb Getppid() (ppid int)
|
//sysnb Getppid() (ppid int)
|
||||||
//sys Getpriority(which int, who int) (prio int, err error)
|
//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 Getrusage(who int, rusage *Rusage) (err error)
|
||||||
|
//sysnb Getsid(pid int) (sid int, err error)
|
||||||
//sysnb Gettid() (tid int)
|
//sysnb Gettid() (tid int)
|
||||||
//sys Getxattr(path string, attr string, dest []byte) (sz int, err error)
|
//sys Getxattr(path string, attr string, dest []byte) (sz int, err error)
|
||||||
//sys InotifyAddWatch(fd int, pathname string, mask uint32) (watchdesc 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 Mknodat(dirfd int, path string, mode uint32, dev int) (err error)
|
||||||
//sys Nanosleep(time *Timespec, leftover *Timespec) (err error)
|
//sys Nanosleep(time *Timespec, leftover *Timespec) (err error)
|
||||||
//sys PivotRoot(newroot string, putold string) (err error) = SYS_PIVOT_ROOT
|
//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 Prctl(option int, arg2 uintptr, arg3 uintptr, arg4 uintptr, arg5 uintptr) (err error)
|
||||||
//sys read(fd int, p []byte) (n int, err error)
|
//sys read(fd int, p []byte) (n int, err error)
|
||||||
//sys Removexattr(path string, attr string) (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 Mlockall(flags int) (err error)
|
||||||
//sys Munlockall() (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
|
* Unimplemented
|
||||||
*/
|
*/
|
||||||
|
@ -1109,7 +1292,6 @@ func Munmap(b []byte) (err error) {
|
||||||
// Utimensat
|
// Utimensat
|
||||||
// Vfork
|
// Vfork
|
||||||
// Vhangup
|
// Vhangup
|
||||||
// Vmsplice
|
|
||||||
// Vserver
|
// Vserver
|
||||||
// Waitid
|
// Waitid
|
||||||
// _Sysctl
|
// _Sysctl
|
||||||
|
|
|
@ -6,8 +6,6 @@
|
||||||
|
|
||||||
package unix
|
package unix
|
||||||
|
|
||||||
import "syscall"
|
|
||||||
|
|
||||||
//sys Dup2(oldfd int, newfd int) (err error)
|
//sys Dup2(oldfd int, newfd int) (err error)
|
||||||
//sys EpollWait(epfd int, events []EpollEvent, msec int) (n 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
|
//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 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)
|
//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) {
|
func Gettimeofday(tv *Timeval) (err error) {
|
||||||
errno := gettimeofday(tv)
|
errno := gettimeofday(tv)
|
||||||
if errno != 0 {
|
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
|
package unix
|
||||||
|
|
||||||
const _SYS_dup = SYS_DUP3
|
|
||||||
|
|
||||||
//sys EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error) = SYS_EPOLL_PWAIT
|
//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 Fchown(fd int, uid int, gid int) (err error)
|
||||||
//sys Fstat(fd int, stat *Stat_t) (err error)
|
//sys Fstat(fd int, stat *Stat_t) (err error)
|
||||||
|
|
|
@ -7,13 +7,6 @@
|
||||||
|
|
||||||
package unix
|
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 EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error)
|
||||||
//sys Fchown(fd int, uid int, gid int) (err error)
|
//sys Fchown(fd int, uid int, gid int) (err error)
|
||||||
//sys Fstatfs(fd int, buf *Statfs_t) (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) {
|
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)}
|
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)
|
r0, _, e1 := Syscall(SYS_MMAP, uintptr(unsafe.Pointer(&mmap_args[0])), 0, 0)
|
||||||
use(unsafe.Pointer(&mmap_args[0]))
|
|
||||||
xaddr = uintptr(r0)
|
xaddr = uintptr(r0)
|
||||||
if e1 != 0 {
|
if e1 != 0 {
|
||||||
err = errnoErr(e1)
|
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
|
return mib, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// ParseDirent parses up to max directory entries in buf,
|
func direntIno(buf []byte) (uint64, bool) {
|
||||||
// appending the names to names. It returns the number
|
return readInt(buf, unsafe.Offsetof(Dirent{}.Fileno), unsafe.Sizeof(Dirent{}.Fileno))
|
||||||
// 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.
|
func direntReclen(buf []byte) (uint64, bool) {
|
||||||
continue
|
return readInt(buf, unsafe.Offsetof(Dirent{}.Reclen), unsafe.Sizeof(Dirent{}.Reclen))
|
||||||
}
|
}
|
||||||
bytes := (*[10000]byte)(unsafe.Pointer(&dirent.Name[0]))
|
|
||||||
var name = string(bytes[0:dirent.Namlen])
|
func direntNamlen(buf []byte) (uint64, bool) {
|
||||||
if name == "." || name == ".." { // Useless names
|
return readInt(buf, unsafe.Offsetof(Dirent{}.Namlen), unsafe.Sizeof(Dirent{}.Namlen))
|
||||||
continue
|
|
||||||
}
|
|
||||||
max--
|
|
||||||
count++
|
|
||||||
names = append(names, name)
|
|
||||||
}
|
|
||||||
return origlen - len(buf), count, names
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//sysnb pipe() (fd1 int, fd2 int, err error)
|
//sysnb pipe() (fd1 int, fd2 int, err error)
|
||||||
|
|
|
@ -53,32 +53,16 @@ func nametomib(name string) (mib []_C_int, err error) {
|
||||||
return nil, EINVAL
|
return nil, EINVAL
|
||||||
}
|
}
|
||||||
|
|
||||||
// ParseDirent parses up to max directory entries in buf,
|
func direntIno(buf []byte) (uint64, bool) {
|
||||||
// appending the names to names. It returns the number
|
return readInt(buf, unsafe.Offsetof(Dirent{}.Fileno), unsafe.Sizeof(Dirent{}.Fileno))
|
||||||
// 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.
|
func direntReclen(buf []byte) (uint64, bool) {
|
||||||
continue
|
return readInt(buf, unsafe.Offsetof(Dirent{}.Reclen), unsafe.Sizeof(Dirent{}.Reclen))
|
||||||
}
|
}
|
||||||
bytes := (*[10000]byte)(unsafe.Pointer(&dirent.Name[0]))
|
|
||||||
var name = string(bytes[0:dirent.Namlen])
|
func direntNamlen(buf []byte) (uint64, bool) {
|
||||||
if name == "." || name == ".." { // Useless names
|
return readInt(buf, unsafe.Offsetof(Dirent{}.Namlen), unsafe.Sizeof(Dirent{}.Namlen))
|
||||||
continue
|
|
||||||
}
|
|
||||||
max--
|
|
||||||
count++
|
|
||||||
names = append(names, name)
|
|
||||||
}
|
|
||||||
return origlen - len(buf), count, names
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//sysnb pipe(p *[2]_C_int) (err error)
|
//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))
|
bufsize = unsafe.Sizeof(Statfs_t{}) * uintptr(len(buf))
|
||||||
}
|
}
|
||||||
r0, _, e1 := Syscall(SYS_GETFSSTAT, uintptr(_p0), bufsize, uintptr(flags))
|
r0, _, e1 := Syscall(SYS_GETFSSTAT, uintptr(_p0), bufsize, uintptr(flags))
|
||||||
use(unsafe.Pointer(_p0))
|
|
||||||
n = int(r0)
|
n = int(r0)
|
||||||
if e1 != 0 {
|
if e1 != 0 {
|
||||||
err = e1
|
err = e1
|
||||||
|
|
|
@ -44,46 +44,36 @@ func clen(n []byte) int {
|
||||||
return len(n)
|
return len(n)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ParseDirent parses up to max directory entries in buf,
|
func direntIno(buf []byte) (uint64, bool) {
|
||||||
// appending the names to names. It returns the number
|
return readInt(buf, unsafe.Offsetof(Dirent{}.Ino), unsafe.Sizeof(Dirent{}.Ino))
|
||||||
// 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 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) {
|
func Pipe(p []int) (err error) {
|
||||||
if len(p) != 2 {
|
if len(p) != 2 {
|
||||||
return EINVAL
|
return EINVAL
|
||||||
}
|
}
|
||||||
r0, w0, e1 := pipe()
|
var pp [2]_C_int
|
||||||
if e1 != 0 {
|
n, err := pipe(&pp)
|
||||||
err = syscall.Errno(e1)
|
if n != 0 {
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
p[0], p[1] = int(r0), int(w0)
|
p[0] = int(pp[0])
|
||||||
return
|
p[1] = int(pp[1])
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (sa *SockaddrInet4) sockaddr() (unsafe.Pointer, _Socklen, error) {
|
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 (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) {
|
func Wait4(pid int, wstatus *WaitStatus, options int, rusage *Rusage) (int, error) {
|
||||||
r0, e1 := wait4(uintptr(pid), wstatus, uintptr(options), rusage)
|
var status _C_int
|
||||||
if e1 != 0 {
|
rpid, err := wait4(int32(pid), &status, options, rusage)
|
||||||
err = syscall.Errno(e1)
|
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) {
|
func Gethostname() (name string, err error) {
|
||||||
name, e1 := gethostname()
|
var buf [MaxHostNameLen]byte
|
||||||
if e1 != 0 {
|
n, err := gethostname(buf[:])
|
||||||
err = syscall.Errno(e1)
|
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)
|
//sys utimes(path string, times *[2]Timeval) (err error)
|
||||||
|
|
|
@ -49,11 +49,6 @@ func errnoErr(e syscall.Errno) error {
|
||||||
return e
|
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.
|
// Mmap manager, for use by operating system-specific implementations.
|
||||||
|
|
||||||
type mmapper struct {
|
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 <utime.h>
|
||||||
#include <bluetooth/bluetooth.h>
|
#include <bluetooth/bluetooth.h>
|
||||||
#include <bluetooth/hci.h>
|
#include <bluetooth/hci.h>
|
||||||
|
#include <linux/can.h>
|
||||||
|
#include <linux/if_alg.h>
|
||||||
|
#include <linux/vm_sockets.h>
|
||||||
|
|
||||||
#ifdef TCSETS2
|
#ifdef TCSETS2
|
||||||
// On systems that have "struct termios2" use this as type Termios.
|
// On systems that have "struct termios2" use this as type Termios.
|
||||||
|
@ -105,6 +108,9 @@ typedef struct pt_regs PtraceRegs;
|
||||||
typedef struct user PtraceRegs;
|
typedef struct user PtraceRegs;
|
||||||
#elif defined(__s390x__)
|
#elif defined(__s390x__)
|
||||||
typedef struct _user_regs_struct PtraceRegs;
|
typedef struct _user_regs_struct PtraceRegs;
|
||||||
|
#elif defined(__sparc__)
|
||||||
|
#include <asm/ptrace.h>
|
||||||
|
typedef struct pt_regs PtraceRegs;
|
||||||
#else
|
#else
|
||||||
typedef struct user_regs_struct PtraceRegs;
|
typedef struct user_regs_struct PtraceRegs;
|
||||||
#endif
|
#endif
|
||||||
|
@ -122,11 +128,11 @@ typedef struct {} ptracePer;
|
||||||
// The real epoll_event is a union, and godefs doesn't handle it well.
|
// The real epoll_event is a union, and godefs doesn't handle it well.
|
||||||
struct my_epoll_event {
|
struct my_epoll_event {
|
||||||
uint32_t events;
|
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
|
// padding is not specified in linux/eventpoll.h but added to conform to the
|
||||||
// alignment requirements of EABI
|
// alignment requirements of EABI
|
||||||
int32_t padFd;
|
int32_t padFd;
|
||||||
#elif defined(__powerpc64__) || defined(__s390x__)
|
#elif defined(__powerpc64__) || defined(__s390x__) || defined(__sparc__)
|
||||||
int32_t _padFd;
|
int32_t _padFd;
|
||||||
#endif
|
#endif
|
||||||
int32_t fd;
|
int32_t fd;
|
||||||
|
@ -215,6 +221,12 @@ type RawSockaddrNetlink C.struct_sockaddr_nl
|
||||||
|
|
||||||
type RawSockaddrHCI C.struct_sockaddr_hci
|
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 RawSockaddr C.struct_sockaddr
|
||||||
|
|
||||||
type RawSockaddrAny C.struct_sockaddr_any
|
type RawSockaddrAny C.struct_sockaddr_any
|
||||||
|
@ -255,6 +267,9 @@ const (
|
||||||
SizeofSockaddrLinklayer = C.sizeof_struct_sockaddr_ll
|
SizeofSockaddrLinklayer = C.sizeof_struct_sockaddr_ll
|
||||||
SizeofSockaddrNetlink = C.sizeof_struct_sockaddr_nl
|
SizeofSockaddrNetlink = C.sizeof_struct_sockaddr_nl
|
||||||
SizeofSockaddrHCI = C.sizeof_struct_sockaddr_hci
|
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
|
SizeofLinger = C.sizeof_struct_linger
|
||||||
SizeofIPMreq = C.sizeof_struct_ip_mreq
|
SizeofIPMreq = C.sizeof_struct_ip_mreq
|
||||||
SizeofIPMreqn = C.sizeof_struct_ip_mreqn
|
SizeofIPMreqn = C.sizeof_struct_ip_mreqn
|
||||||
|
@ -445,6 +460,10 @@ const (
|
||||||
|
|
||||||
type Sigset_t C.sigset_t
|
type Sigset_t C.sigset_t
|
||||||
|
|
||||||
|
// sysconf information
|
||||||
|
|
||||||
|
const _SC_PAGESIZE = C._SC_PAGESIZE
|
||||||
|
|
||||||
// Terminal handling
|
// Terminal handling
|
||||||
|
|
||||||
type Termios C.termios_t
|
type Termios C.termios_t
|
||||||
|
|
|
@ -22,6 +22,7 @@ package unix
|
||||||
#define __USE_LEGACY_PROTOTYPES__ // iovec
|
#define __USE_LEGACY_PROTOTYPES__ // iovec
|
||||||
#include <dirent.h>
|
#include <dirent.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
|
#include <netdb.h>
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include <termios.h>
|
#include <termios.h>
|
||||||
|
@ -81,6 +82,7 @@ const (
|
||||||
sizeofLong = C.sizeof_long
|
sizeofLong = C.sizeof_long
|
||||||
sizeofLongLong = C.sizeof_longlong
|
sizeofLongLong = C.sizeof_longlong
|
||||||
PathMax = C.PATH_MAX
|
PathMax = C.PATH_MAX
|
||||||
|
MaxHostNameLen = C.MAXHOSTNAMELEN
|
||||||
)
|
)
|
||||||
|
|
||||||
// Basic types
|
// Basic types
|
||||||
|
|
|
@ -51,8 +51,16 @@ const (
|
||||||
AF_TIPC = 0x1e
|
AF_TIPC = 0x1e
|
||||||
AF_UNIX = 0x1
|
AF_UNIX = 0x1
|
||||||
AF_UNSPEC = 0x0
|
AF_UNSPEC = 0x0
|
||||||
|
AF_VSOCK = 0x28
|
||||||
AF_WANPIPE = 0x19
|
AF_WANPIPE = 0x19
|
||||||
AF_X25 = 0x9
|
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_ADAPT = 0x108
|
||||||
ARPHRD_APPLETLK = 0x8
|
ARPHRD_APPLETLK = 0x8
|
||||||
ARPHRD_ARCNET = 0x7
|
ARPHRD_ARCNET = 0x7
|
||||||
|
@ -145,6 +153,21 @@ const (
|
||||||
B75 = 0x2
|
B75 = 0x2
|
||||||
B921600 = 0x1007
|
B921600 = 0x1007
|
||||||
B9600 = 0xd
|
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
|
BOTHER = 0x1000
|
||||||
BPF_A = 0x10
|
BPF_A = 0x10
|
||||||
BPF_ABS = 0x20
|
BPF_ABS = 0x20
|
||||||
|
@ -190,6 +213,25 @@ const (
|
||||||
BS0 = 0x0
|
BS0 = 0x0
|
||||||
BS1 = 0x2000
|
BS1 = 0x2000
|
||||||
BSDLY = 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
|
CBAUD = 0x100f
|
||||||
CBAUDEX = 0x1000
|
CBAUDEX = 0x1000
|
||||||
CFLUSH = 0xf
|
CFLUSH = 0xf
|
||||||
|
@ -366,6 +408,12 @@ const (
|
||||||
EXTA = 0xe
|
EXTA = 0xe
|
||||||
EXTB = 0xf
|
EXTB = 0xf
|
||||||
EXTPROC = 0x10000
|
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_CLOEXEC = 0x1
|
||||||
FD_SETSIZE = 0x400
|
FD_SETSIZE = 0x400
|
||||||
FF0 = 0x0
|
FF0 = 0x0
|
||||||
|
@ -405,6 +453,8 @@ const (
|
||||||
F_ULOCK = 0x0
|
F_ULOCK = 0x0
|
||||||
F_UNLCK = 0x2
|
F_UNLCK = 0x2
|
||||||
F_WRLCK = 0x1
|
F_WRLCK = 0x1
|
||||||
|
GRND_NONBLOCK = 0x1
|
||||||
|
GRND_RANDOM = 0x2
|
||||||
HUPCL = 0x400
|
HUPCL = 0x400
|
||||||
IBSHIFT = 0x10
|
IBSHIFT = 0x10
|
||||||
ICANON = 0x2
|
ICANON = 0x2
|
||||||
|
@ -789,6 +839,7 @@ const (
|
||||||
NLM_F_ATOMIC = 0x400
|
NLM_F_ATOMIC = 0x400
|
||||||
NLM_F_CREATE = 0x400
|
NLM_F_CREATE = 0x400
|
||||||
NLM_F_DUMP = 0x300
|
NLM_F_DUMP = 0x300
|
||||||
|
NLM_F_DUMP_FILTERED = 0x20
|
||||||
NLM_F_DUMP_INTR = 0x10
|
NLM_F_DUMP_INTR = 0x10
|
||||||
NLM_F_ECHO = 0x8
|
NLM_F_ECHO = 0x8
|
||||||
NLM_F_EXCL = 0x200
|
NLM_F_EXCL = 0x200
|
||||||
|
@ -1228,6 +1279,7 @@ const (
|
||||||
SOL_IP = 0x0
|
SOL_IP = 0x0
|
||||||
SOL_IPV6 = 0x29
|
SOL_IPV6 = 0x29
|
||||||
SOL_IRDA = 0x10a
|
SOL_IRDA = 0x10a
|
||||||
|
SOL_NETLINK = 0x10e
|
||||||
SOL_PACKET = 0x107
|
SOL_PACKET = 0x107
|
||||||
SOL_RAW = 0xff
|
SOL_RAW = 0xff
|
||||||
SOL_SOCKET = 0x1
|
SOL_SOCKET = 0x1
|
||||||
|
@ -1273,6 +1325,17 @@ const (
|
||||||
SO_TIMESTAMPING = 0x25
|
SO_TIMESTAMPING = 0x25
|
||||||
SO_TIMESTAMPNS = 0x23
|
SO_TIMESTAMPNS = 0x23
|
||||||
SO_TYPE = 0x3
|
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_BLKSIZE = 0x200
|
||||||
S_IEXEC = 0x40
|
S_IEXEC = 0x40
|
||||||
S_IFBLK = 0x6000
|
S_IFBLK = 0x6000
|
||||||
|
@ -1445,6 +1508,11 @@ const (
|
||||||
VINTR = 0x0
|
VINTR = 0x0
|
||||||
VKILL = 0x3
|
VKILL = 0x3
|
||||||
VLNEXT = 0xf
|
VLNEXT = 0xf
|
||||||
|
VMADDR_CID_ANY = 0xffffffff
|
||||||
|
VMADDR_CID_HOST = 0x2
|
||||||
|
VMADDR_CID_HYPERVISOR = 0x0
|
||||||
|
VMADDR_CID_RESERVED = 0x1
|
||||||
|
VMADDR_PORT_ANY = 0xffffffff
|
||||||
VMIN = 0x6
|
VMIN = 0x6
|
||||||
VQUIT = 0x1
|
VQUIT = 0x1
|
||||||
VREPRINT = 0xc
|
VREPRINT = 0xc
|
||||||
|
|
|
@ -51,8 +51,16 @@ const (
|
||||||
AF_TIPC = 0x1e
|
AF_TIPC = 0x1e
|
||||||
AF_UNIX = 0x1
|
AF_UNIX = 0x1
|
||||||
AF_UNSPEC = 0x0
|
AF_UNSPEC = 0x0
|
||||||
|
AF_VSOCK = 0x28
|
||||||
AF_WANPIPE = 0x19
|
AF_WANPIPE = 0x19
|
||||||
AF_X25 = 0x9
|
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_ADAPT = 0x108
|
||||||
ARPHRD_APPLETLK = 0x8
|
ARPHRD_APPLETLK = 0x8
|
||||||
ARPHRD_ARCNET = 0x7
|
ARPHRD_ARCNET = 0x7
|
||||||
|
@ -145,6 +153,21 @@ const (
|
||||||
B75 = 0x2
|
B75 = 0x2
|
||||||
B921600 = 0x1007
|
B921600 = 0x1007
|
||||||
B9600 = 0xd
|
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
|
BOTHER = 0x1000
|
||||||
BPF_A = 0x10
|
BPF_A = 0x10
|
||||||
BPF_ABS = 0x20
|
BPF_ABS = 0x20
|
||||||
|
@ -190,6 +213,25 @@ const (
|
||||||
BS0 = 0x0
|
BS0 = 0x0
|
||||||
BS1 = 0x2000
|
BS1 = 0x2000
|
||||||
BSDLY = 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
|
CBAUD = 0x100f
|
||||||
CBAUDEX = 0x1000
|
CBAUDEX = 0x1000
|
||||||
CFLUSH = 0xf
|
CFLUSH = 0xf
|
||||||
|
@ -366,6 +408,12 @@ const (
|
||||||
EXTA = 0xe
|
EXTA = 0xe
|
||||||
EXTB = 0xf
|
EXTB = 0xf
|
||||||
EXTPROC = 0x10000
|
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_CLOEXEC = 0x1
|
||||||
FD_SETSIZE = 0x400
|
FD_SETSIZE = 0x400
|
||||||
FF0 = 0x0
|
FF0 = 0x0
|
||||||
|
@ -405,6 +453,8 @@ const (
|
||||||
F_ULOCK = 0x0
|
F_ULOCK = 0x0
|
||||||
F_UNLCK = 0x2
|
F_UNLCK = 0x2
|
||||||
F_WRLCK = 0x1
|
F_WRLCK = 0x1
|
||||||
|
GRND_NONBLOCK = 0x1
|
||||||
|
GRND_RANDOM = 0x2
|
||||||
HUPCL = 0x400
|
HUPCL = 0x400
|
||||||
IBSHIFT = 0x10
|
IBSHIFT = 0x10
|
||||||
ICANON = 0x2
|
ICANON = 0x2
|
||||||
|
@ -747,6 +797,7 @@ const (
|
||||||
NETLINK_ADD_MEMBERSHIP = 0x1
|
NETLINK_ADD_MEMBERSHIP = 0x1
|
||||||
NETLINK_AUDIT = 0x9
|
NETLINK_AUDIT = 0x9
|
||||||
NETLINK_BROADCAST_ERROR = 0x4
|
NETLINK_BROADCAST_ERROR = 0x4
|
||||||
|
NETLINK_CAP_ACK = 0xa
|
||||||
NETLINK_CONNECTOR = 0xb
|
NETLINK_CONNECTOR = 0xb
|
||||||
NETLINK_CRYPTO = 0x15
|
NETLINK_CRYPTO = 0x15
|
||||||
NETLINK_DNRTMSG = 0xe
|
NETLINK_DNRTMSG = 0xe
|
||||||
|
@ -759,14 +810,19 @@ const (
|
||||||
NETLINK_IP6_FW = 0xd
|
NETLINK_IP6_FW = 0xd
|
||||||
NETLINK_ISCSI = 0x8
|
NETLINK_ISCSI = 0x8
|
||||||
NETLINK_KOBJECT_UEVENT = 0xf
|
NETLINK_KOBJECT_UEVENT = 0xf
|
||||||
|
NETLINK_LISTEN_ALL_NSID = 0x8
|
||||||
|
NETLINK_LIST_MEMBERSHIPS = 0x9
|
||||||
NETLINK_NETFILTER = 0xc
|
NETLINK_NETFILTER = 0xc
|
||||||
NETLINK_NFLOG = 0x5
|
NETLINK_NFLOG = 0x5
|
||||||
NETLINK_NO_ENOBUFS = 0x5
|
NETLINK_NO_ENOBUFS = 0x5
|
||||||
NETLINK_PKTINFO = 0x3
|
NETLINK_PKTINFO = 0x3
|
||||||
NETLINK_RDMA = 0x14
|
NETLINK_RDMA = 0x14
|
||||||
NETLINK_ROUTE = 0x0
|
NETLINK_ROUTE = 0x0
|
||||||
|
NETLINK_RX_RING = 0x6
|
||||||
NETLINK_SCSITRANSPORT = 0x12
|
NETLINK_SCSITRANSPORT = 0x12
|
||||||
NETLINK_SELINUX = 0x7
|
NETLINK_SELINUX = 0x7
|
||||||
|
NETLINK_SOCK_DIAG = 0x4
|
||||||
|
NETLINK_TX_RING = 0x7
|
||||||
NETLINK_UNUSED = 0x1
|
NETLINK_UNUSED = 0x1
|
||||||
NETLINK_USERSOCK = 0x2
|
NETLINK_USERSOCK = 0x2
|
||||||
NETLINK_XFRM = 0x6
|
NETLINK_XFRM = 0x6
|
||||||
|
@ -789,6 +845,7 @@ const (
|
||||||
NLM_F_ATOMIC = 0x400
|
NLM_F_ATOMIC = 0x400
|
||||||
NLM_F_CREATE = 0x400
|
NLM_F_CREATE = 0x400
|
||||||
NLM_F_DUMP = 0x300
|
NLM_F_DUMP = 0x300
|
||||||
|
NLM_F_DUMP_FILTERED = 0x20
|
||||||
NLM_F_DUMP_INTR = 0x10
|
NLM_F_DUMP_INTR = 0x10
|
||||||
NLM_F_ECHO = 0x8
|
NLM_F_ECHO = 0x8
|
||||||
NLM_F_EXCL = 0x200
|
NLM_F_EXCL = 0x200
|
||||||
|
@ -1229,6 +1286,7 @@ const (
|
||||||
SOL_IP = 0x0
|
SOL_IP = 0x0
|
||||||
SOL_IPV6 = 0x29
|
SOL_IPV6 = 0x29
|
||||||
SOL_IRDA = 0x10a
|
SOL_IRDA = 0x10a
|
||||||
|
SOL_NETLINK = 0x10e
|
||||||
SOL_PACKET = 0x107
|
SOL_PACKET = 0x107
|
||||||
SOL_RAW = 0xff
|
SOL_RAW = 0xff
|
||||||
SOL_SOCKET = 0x1
|
SOL_SOCKET = 0x1
|
||||||
|
@ -1274,6 +1332,17 @@ const (
|
||||||
SO_TIMESTAMPING = 0x25
|
SO_TIMESTAMPING = 0x25
|
||||||
SO_TIMESTAMPNS = 0x23
|
SO_TIMESTAMPNS = 0x23
|
||||||
SO_TYPE = 0x3
|
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_BLKSIZE = 0x200
|
||||||
S_IEXEC = 0x40
|
S_IEXEC = 0x40
|
||||||
S_IFBLK = 0x6000
|
S_IFBLK = 0x6000
|
||||||
|
@ -1446,7 +1515,13 @@ const (
|
||||||
VINTR = 0x0
|
VINTR = 0x0
|
||||||
VKILL = 0x3
|
VKILL = 0x3
|
||||||
VLNEXT = 0xf
|
VLNEXT = 0xf
|
||||||
|
VMADDR_CID_ANY = 0xffffffff
|
||||||
|
VMADDR_CID_HOST = 0x2
|
||||||
|
VMADDR_CID_HYPERVISOR = 0x0
|
||||||
|
VMADDR_CID_RESERVED = 0x1
|
||||||
|
VMADDR_PORT_ANY = 0xffffffff
|
||||||
VMIN = 0x6
|
VMIN = 0x6
|
||||||
|
VM_SOCKETS_INVALID_VERSION = 0xffffffff
|
||||||
VQUIT = 0x1
|
VQUIT = 0x1
|
||||||
VREPRINT = 0xc
|
VREPRINT = 0xc
|
||||||
VSTART = 0x8
|
VSTART = 0x8
|
||||||
|
|
|
@ -50,8 +50,16 @@ const (
|
||||||
AF_TIPC = 0x1e
|
AF_TIPC = 0x1e
|
||||||
AF_UNIX = 0x1
|
AF_UNIX = 0x1
|
||||||
AF_UNSPEC = 0x0
|
AF_UNSPEC = 0x0
|
||||||
|
AF_VSOCK = 0x28
|
||||||
AF_WANPIPE = 0x19
|
AF_WANPIPE = 0x19
|
||||||
AF_X25 = 0x9
|
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_ADAPT = 0x108
|
||||||
ARPHRD_APPLETLK = 0x8
|
ARPHRD_APPLETLK = 0x8
|
||||||
ARPHRD_ARCNET = 0x7
|
ARPHRD_ARCNET = 0x7
|
||||||
|
@ -141,6 +149,21 @@ const (
|
||||||
B75 = 0x2
|
B75 = 0x2
|
||||||
B921600 = 0x1007
|
B921600 = 0x1007
|
||||||
B9600 = 0xd
|
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
|
BOTHER = 0x1000
|
||||||
BPF_A = 0x10
|
BPF_A = 0x10
|
||||||
BPF_ABS = 0x20
|
BPF_ABS = 0x20
|
||||||
|
@ -186,6 +209,25 @@ const (
|
||||||
BS0 = 0x0
|
BS0 = 0x0
|
||||||
BS1 = 0x2000
|
BS1 = 0x2000
|
||||||
BSDLY = 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
|
CBAUD = 0x100f
|
||||||
CBAUDEX = 0x1000
|
CBAUDEX = 0x1000
|
||||||
CFLUSH = 0xf
|
CFLUSH = 0xf
|
||||||
|
@ -351,6 +393,12 @@ const (
|
||||||
EXTA = 0xe
|
EXTA = 0xe
|
||||||
EXTB = 0xf
|
EXTB = 0xf
|
||||||
EXTPROC = 0x10000
|
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_CLOEXEC = 0x1
|
||||||
FD_SETSIZE = 0x400
|
FD_SETSIZE = 0x400
|
||||||
FF0 = 0x0
|
FF0 = 0x0
|
||||||
|
@ -390,6 +438,8 @@ const (
|
||||||
F_ULOCK = 0x0
|
F_ULOCK = 0x0
|
||||||
F_UNLCK = 0x2
|
F_UNLCK = 0x2
|
||||||
F_WRLCK = 0x1
|
F_WRLCK = 0x1
|
||||||
|
GRND_NONBLOCK = 0x1
|
||||||
|
GRND_RANDOM = 0x2
|
||||||
HUPCL = 0x400
|
HUPCL = 0x400
|
||||||
IBSHIFT = 0x10
|
IBSHIFT = 0x10
|
||||||
ICANON = 0x2
|
ICANON = 0x2
|
||||||
|
@ -707,6 +757,7 @@ const (
|
||||||
NETLINK_AUDIT = 0x9
|
NETLINK_AUDIT = 0x9
|
||||||
NETLINK_BROADCAST_ERROR = 0x4
|
NETLINK_BROADCAST_ERROR = 0x4
|
||||||
NETLINK_CONNECTOR = 0xb
|
NETLINK_CONNECTOR = 0xb
|
||||||
|
NETLINK_CRYPTO = 0x15
|
||||||
NETLINK_DNRTMSG = 0xe
|
NETLINK_DNRTMSG = 0xe
|
||||||
NETLINK_DROP_MEMBERSHIP = 0x2
|
NETLINK_DROP_MEMBERSHIP = 0x2
|
||||||
NETLINK_ECRYPTFS = 0x13
|
NETLINK_ECRYPTFS = 0x13
|
||||||
|
@ -723,8 +774,11 @@ const (
|
||||||
NETLINK_PKTINFO = 0x3
|
NETLINK_PKTINFO = 0x3
|
||||||
NETLINK_RDMA = 0x14
|
NETLINK_RDMA = 0x14
|
||||||
NETLINK_ROUTE = 0x0
|
NETLINK_ROUTE = 0x0
|
||||||
|
NETLINK_RX_RING = 0x6
|
||||||
NETLINK_SCSITRANSPORT = 0x12
|
NETLINK_SCSITRANSPORT = 0x12
|
||||||
NETLINK_SELINUX = 0x7
|
NETLINK_SELINUX = 0x7
|
||||||
|
NETLINK_SOCK_DIAG = 0x4
|
||||||
|
NETLINK_TX_RING = 0x7
|
||||||
NETLINK_UNUSED = 0x1
|
NETLINK_UNUSED = 0x1
|
||||||
NETLINK_USERSOCK = 0x2
|
NETLINK_USERSOCK = 0x2
|
||||||
NETLINK_XFRM = 0x6
|
NETLINK_XFRM = 0x6
|
||||||
|
@ -747,6 +801,7 @@ const (
|
||||||
NLM_F_ATOMIC = 0x400
|
NLM_F_ATOMIC = 0x400
|
||||||
NLM_F_CREATE = 0x400
|
NLM_F_CREATE = 0x400
|
||||||
NLM_F_DUMP = 0x300
|
NLM_F_DUMP = 0x300
|
||||||
|
NLM_F_DUMP_FILTERED = 0x20
|
||||||
NLM_F_ECHO = 0x8
|
NLM_F_ECHO = 0x8
|
||||||
NLM_F_EXCL = 0x200
|
NLM_F_EXCL = 0x200
|
||||||
NLM_F_MATCH = 0x200
|
NLM_F_MATCH = 0x200
|
||||||
|
@ -1152,6 +1207,7 @@ const (
|
||||||
SOL_IP = 0x0
|
SOL_IP = 0x0
|
||||||
SOL_IPV6 = 0x29
|
SOL_IPV6 = 0x29
|
||||||
SOL_IRDA = 0x10a
|
SOL_IRDA = 0x10a
|
||||||
|
SOL_NETLINK = 0x10e
|
||||||
SOL_PACKET = 0x107
|
SOL_PACKET = 0x107
|
||||||
SOL_RAW = 0xff
|
SOL_RAW = 0xff
|
||||||
SOL_SOCKET = 0x1
|
SOL_SOCKET = 0x1
|
||||||
|
@ -1197,6 +1253,17 @@ const (
|
||||||
SO_TIMESTAMPING = 0x25
|
SO_TIMESTAMPING = 0x25
|
||||||
SO_TIMESTAMPNS = 0x23
|
SO_TIMESTAMPNS = 0x23
|
||||||
SO_TYPE = 0x3
|
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_BLKSIZE = 0x200
|
||||||
S_IEXEC = 0x40
|
S_IEXEC = 0x40
|
||||||
S_IFBLK = 0x6000
|
S_IFBLK = 0x6000
|
||||||
|
@ -1369,6 +1436,11 @@ const (
|
||||||
VINTR = 0x0
|
VINTR = 0x0
|
||||||
VKILL = 0x3
|
VKILL = 0x3
|
||||||
VLNEXT = 0xf
|
VLNEXT = 0xf
|
||||||
|
VMADDR_CID_ANY = 0xffffffff
|
||||||
|
VMADDR_CID_HOST = 0x2
|
||||||
|
VMADDR_CID_HYPERVISOR = 0x0
|
||||||
|
VMADDR_CID_RESERVED = 0x1
|
||||||
|
VMADDR_PORT_ANY = 0xffffffff
|
||||||
VMIN = 0x6
|
VMIN = 0x6
|
||||||
VQUIT = 0x1
|
VQUIT = 0x1
|
||||||
VREPRINT = 0xc
|
VREPRINT = 0xc
|
||||||
|
|
|
@ -54,6 +54,13 @@ const (
|
||||||
AF_VSOCK = 0x28
|
AF_VSOCK = 0x28
|
||||||
AF_WANPIPE = 0x19
|
AF_WANPIPE = 0x19
|
||||||
AF_X25 = 0x9
|
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_ADAPT = 0x108
|
||||||
ARPHRD_APPLETLK = 0x8
|
ARPHRD_APPLETLK = 0x8
|
||||||
ARPHRD_ARCNET = 0x7
|
ARPHRD_ARCNET = 0x7
|
||||||
|
@ -149,6 +156,21 @@ const (
|
||||||
B75 = 0x2
|
B75 = 0x2
|
||||||
B921600 = 0x1007
|
B921600 = 0x1007
|
||||||
B9600 = 0xd
|
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
|
BOTHER = 0x1000
|
||||||
BPF_A = 0x10
|
BPF_A = 0x10
|
||||||
BPF_ABS = 0x20
|
BPF_ABS = 0x20
|
||||||
|
@ -196,6 +218,25 @@ const (
|
||||||
BS0 = 0x0
|
BS0 = 0x0
|
||||||
BS1 = 0x2000
|
BS1 = 0x2000
|
||||||
BSDLY = 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
|
CBAUD = 0x100f
|
||||||
CBAUDEX = 0x1000
|
CBAUDEX = 0x1000
|
||||||
CFLUSH = 0xf
|
CFLUSH = 0xf
|
||||||
|
@ -380,6 +421,12 @@ const (
|
||||||
EXTA = 0xe
|
EXTA = 0xe
|
||||||
EXTB = 0xf
|
EXTB = 0xf
|
||||||
EXTPROC = 0x10000
|
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_CLOEXEC = 0x1
|
||||||
FD_SETSIZE = 0x400
|
FD_SETSIZE = 0x400
|
||||||
FF0 = 0x0
|
FF0 = 0x0
|
||||||
|
@ -419,6 +466,8 @@ const (
|
||||||
F_ULOCK = 0x0
|
F_ULOCK = 0x0
|
||||||
F_UNLCK = 0x2
|
F_UNLCK = 0x2
|
||||||
F_WRLCK = 0x1
|
F_WRLCK = 0x1
|
||||||
|
GRND_NONBLOCK = 0x1
|
||||||
|
GRND_RANDOM = 0x2
|
||||||
HUPCL = 0x400
|
HUPCL = 0x400
|
||||||
IBSHIFT = 0x10
|
IBSHIFT = 0x10
|
||||||
ICANON = 0x2
|
ICANON = 0x2
|
||||||
|
@ -776,6 +825,7 @@ const (
|
||||||
NETLINK_ADD_MEMBERSHIP = 0x1
|
NETLINK_ADD_MEMBERSHIP = 0x1
|
||||||
NETLINK_AUDIT = 0x9
|
NETLINK_AUDIT = 0x9
|
||||||
NETLINK_BROADCAST_ERROR = 0x4
|
NETLINK_BROADCAST_ERROR = 0x4
|
||||||
|
NETLINK_CAP_ACK = 0xa
|
||||||
NETLINK_CONNECTOR = 0xb
|
NETLINK_CONNECTOR = 0xb
|
||||||
NETLINK_CRYPTO = 0x15
|
NETLINK_CRYPTO = 0x15
|
||||||
NETLINK_DNRTMSG = 0xe
|
NETLINK_DNRTMSG = 0xe
|
||||||
|
@ -788,6 +838,8 @@ const (
|
||||||
NETLINK_IP6_FW = 0xd
|
NETLINK_IP6_FW = 0xd
|
||||||
NETLINK_ISCSI = 0x8
|
NETLINK_ISCSI = 0x8
|
||||||
NETLINK_KOBJECT_UEVENT = 0xf
|
NETLINK_KOBJECT_UEVENT = 0xf
|
||||||
|
NETLINK_LISTEN_ALL_NSID = 0x8
|
||||||
|
NETLINK_LIST_MEMBERSHIPS = 0x9
|
||||||
NETLINK_NETFILTER = 0xc
|
NETLINK_NETFILTER = 0xc
|
||||||
NETLINK_NFLOG = 0x5
|
NETLINK_NFLOG = 0x5
|
||||||
NETLINK_NO_ENOBUFS = 0x5
|
NETLINK_NO_ENOBUFS = 0x5
|
||||||
|
@ -821,6 +873,7 @@ const (
|
||||||
NLM_F_ATOMIC = 0x400
|
NLM_F_ATOMIC = 0x400
|
||||||
NLM_F_CREATE = 0x400
|
NLM_F_CREATE = 0x400
|
||||||
NLM_F_DUMP = 0x300
|
NLM_F_DUMP = 0x300
|
||||||
|
NLM_F_DUMP_FILTERED = 0x20
|
||||||
NLM_F_DUMP_INTR = 0x10
|
NLM_F_DUMP_INTR = 0x10
|
||||||
NLM_F_ECHO = 0x8
|
NLM_F_ECHO = 0x8
|
||||||
NLM_F_EXCL = 0x200
|
NLM_F_EXCL = 0x200
|
||||||
|
@ -1275,6 +1328,7 @@ const (
|
||||||
SOL_IP = 0x0
|
SOL_IP = 0x0
|
||||||
SOL_IPV6 = 0x29
|
SOL_IPV6 = 0x29
|
||||||
SOL_IRDA = 0x10a
|
SOL_IRDA = 0x10a
|
||||||
|
SOL_NETLINK = 0x10e
|
||||||
SOL_PACKET = 0x107
|
SOL_PACKET = 0x107
|
||||||
SOL_RAW = 0xff
|
SOL_RAW = 0xff
|
||||||
SOL_SOCKET = 0x1
|
SOL_SOCKET = 0x1
|
||||||
|
@ -1328,7 +1382,18 @@ const (
|
||||||
SO_TIMESTAMPING = 0x25
|
SO_TIMESTAMPING = 0x25
|
||||||
SO_TIMESTAMPNS = 0x23
|
SO_TIMESTAMPNS = 0x23
|
||||||
SO_TYPE = 0x3
|
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
|
||||||
SO_WIFI_STATUS = 0x29
|
SO_WIFI_STATUS = 0x29
|
||||||
|
SPLICE_F_GIFT = 0x8
|
||||||
|
SPLICE_F_MORE = 0x4
|
||||||
|
SPLICE_F_MOVE = 0x1
|
||||||
|
SPLICE_F_NONBLOCK = 0x2
|
||||||
S_BLKSIZE = 0x200
|
S_BLKSIZE = 0x200
|
||||||
S_IEXEC = 0x40
|
S_IEXEC = 0x40
|
||||||
S_IFBLK = 0x6000
|
S_IFBLK = 0x6000
|
||||||
|
@ -1523,6 +1588,11 @@ const (
|
||||||
VINTR = 0x0
|
VINTR = 0x0
|
||||||
VKILL = 0x3
|
VKILL = 0x3
|
||||||
VLNEXT = 0xf
|
VLNEXT = 0xf
|
||||||
|
VMADDR_CID_ANY = 0xffffffff
|
||||||
|
VMADDR_CID_HOST = 0x2
|
||||||
|
VMADDR_CID_HYPERVISOR = 0x0
|
||||||
|
VMADDR_CID_RESERVED = 0x1
|
||||||
|
VMADDR_PORT_ANY = 0xffffffff
|
||||||
VMIN = 0x6
|
VMIN = 0x6
|
||||||
VQUIT = 0x1
|
VQUIT = 0x1
|
||||||
VREPRINT = 0xc
|
VREPRINT = 0xc
|
||||||
|
|
1869
vendor/src/golang.org/x/sys/unix/zerrors_linux_mips.go
vendored
Normal file
1869
vendor/src/golang.org/x/sys/unix/zerrors_linux_mips.go
vendored
Normal file
File diff suppressed because it is too large
Load diff
|
@ -56,6 +56,13 @@ const (
|
||||||
AF_VSOCK = 0x28
|
AF_VSOCK = 0x28
|
||||||
AF_WANPIPE = 0x19
|
AF_WANPIPE = 0x19
|
||||||
AF_X25 = 0x9
|
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_6LOWPAN = 0x339
|
ARPHRD_6LOWPAN = 0x339
|
||||||
ARPHRD_ADAPT = 0x108
|
ARPHRD_ADAPT = 0x108
|
||||||
ARPHRD_APPLETLK = 0x8
|
ARPHRD_APPLETLK = 0x8
|
||||||
|
@ -152,6 +159,21 @@ const (
|
||||||
B75 = 0x2
|
B75 = 0x2
|
||||||
B921600 = 0x1007
|
B921600 = 0x1007
|
||||||
B9600 = 0xd
|
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
|
||||||
BPF_A = 0x10
|
BPF_A = 0x10
|
||||||
BPF_ABS = 0x20
|
BPF_ABS = 0x20
|
||||||
BPF_ADD = 0x0
|
BPF_ADD = 0x0
|
||||||
|
@ -374,6 +396,12 @@ const (
|
||||||
EXTA = 0xe
|
EXTA = 0xe
|
||||||
EXTB = 0xf
|
EXTB = 0xf
|
||||||
EXTPROC = 0x10000
|
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_CLOEXEC = 0x1
|
||||||
FD_SETSIZE = 0x400
|
FD_SETSIZE = 0x400
|
||||||
FLUSHO = 0x2000
|
FLUSHO = 0x2000
|
||||||
|
@ -413,6 +441,8 @@ const (
|
||||||
F_ULOCK = 0x0
|
F_ULOCK = 0x0
|
||||||
F_UNLCK = 0x2
|
F_UNLCK = 0x2
|
||||||
F_WRLCK = 0x1
|
F_WRLCK = 0x1
|
||||||
|
GRND_NONBLOCK = 0x1
|
||||||
|
GRND_RANDOM = 0x2
|
||||||
HUPCL = 0x400
|
HUPCL = 0x400
|
||||||
ICANON = 0x2
|
ICANON = 0x2
|
||||||
ICMPV6_FILTER = 0x1
|
ICMPV6_FILTER = 0x1
|
||||||
|
@ -806,6 +836,7 @@ const (
|
||||||
NLM_F_ATOMIC = 0x400
|
NLM_F_ATOMIC = 0x400
|
||||||
NLM_F_CREATE = 0x400
|
NLM_F_CREATE = 0x400
|
||||||
NLM_F_DUMP = 0x300
|
NLM_F_DUMP = 0x300
|
||||||
|
NLM_F_DUMP_FILTERED = 0x20
|
||||||
NLM_F_DUMP_INTR = 0x10
|
NLM_F_DUMP_INTR = 0x10
|
||||||
NLM_F_ECHO = 0x8
|
NLM_F_ECHO = 0x8
|
||||||
NLM_F_EXCL = 0x200
|
NLM_F_EXCL = 0x200
|
||||||
|
@ -1304,6 +1335,7 @@ const (
|
||||||
SOL_IP = 0x0
|
SOL_IP = 0x0
|
||||||
SOL_IPV6 = 0x29
|
SOL_IPV6 = 0x29
|
||||||
SOL_IRDA = 0x10a
|
SOL_IRDA = 0x10a
|
||||||
|
SOL_NETLINK = 0x10e
|
||||||
SOL_PACKET = 0x107
|
SOL_PACKET = 0x107
|
||||||
SOL_RAW = 0xff
|
SOL_RAW = 0xff
|
||||||
SOL_SOCKET = 0xffff
|
SOL_SOCKET = 0xffff
|
||||||
|
@ -1362,7 +1394,18 @@ const (
|
||||||
SO_TIMESTAMPING = 0x25
|
SO_TIMESTAMPING = 0x25
|
||||||
SO_TIMESTAMPNS = 0x23
|
SO_TIMESTAMPNS = 0x23
|
||||||
SO_TYPE = 0x1008
|
SO_TYPE = 0x1008
|
||||||
|
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
|
||||||
SO_WIFI_STATUS = 0x29
|
SO_WIFI_STATUS = 0x29
|
||||||
|
SPLICE_F_GIFT = 0x8
|
||||||
|
SPLICE_F_MORE = 0x4
|
||||||
|
SPLICE_F_MOVE = 0x1
|
||||||
|
SPLICE_F_NONBLOCK = 0x2
|
||||||
S_BLKSIZE = 0x200
|
S_BLKSIZE = 0x200
|
||||||
S_IEXEC = 0x40
|
S_IEXEC = 0x40
|
||||||
S_IFBLK = 0x6000
|
S_IFBLK = 0x6000
|
||||||
|
@ -1540,6 +1583,11 @@ const (
|
||||||
VINTR = 0x0
|
VINTR = 0x0
|
||||||
VKILL = 0x3
|
VKILL = 0x3
|
||||||
VLNEXT = 0xf
|
VLNEXT = 0xf
|
||||||
|
VMADDR_CID_ANY = 0xffffffff
|
||||||
|
VMADDR_CID_HOST = 0x2
|
||||||
|
VMADDR_CID_HYPERVISOR = 0x0
|
||||||
|
VMADDR_CID_RESERVED = 0x1
|
||||||
|
VMADDR_PORT_ANY = 0xffffffff
|
||||||
VMIN = 0x4
|
VMIN = 0x4
|
||||||
VQUIT = 0x1
|
VQUIT = 0x1
|
||||||
VREPRINT = 0xc
|
VREPRINT = 0xc
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue