4
0
mirror of https://github.com/cwinfo/matterbridge.git synced 2025-06-28 17:19:24 +00:00

Add sshchat dependencies in vendor

This commit is contained in:
Wim
2017-12-03 01:24:05 +01:00
parent 59e55cfbd5
commit ed9118b346
287 changed files with 73450 additions and 25571 deletions

21
vendor/github.com/shazow/ssh-chat/sshd/LICENSE generated vendored Normal file
View File

@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) 2014 Andrey Petrov
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

72
vendor/github.com/shazow/ssh-chat/sshd/auth.go generated vendored Normal file
View File

@ -0,0 +1,72 @@
package sshd
import (
"crypto/sha256"
"encoding/base64"
"errors"
"net"
"golang.org/x/crypto/ssh"
)
// Auth is used to authenticate connections based on public keys.
type Auth interface {
// Whether to allow connections without a public key.
AllowAnonymous() bool
// Given address and public key, return if the connection should be permitted.
Check(net.Addr, ssh.PublicKey) (bool, error)
}
// MakeAuth makes an ssh.ServerConfig which performs authentication against an Auth implementation.
func MakeAuth(auth Auth) *ssh.ServerConfig {
config := ssh.ServerConfig{
NoClientAuth: false,
// Auth-related things should be constant-time to avoid timing attacks.
PublicKeyCallback: func(conn ssh.ConnMetadata, key ssh.PublicKey) (*ssh.Permissions, error) {
ok, err := auth.Check(conn.RemoteAddr(), key)
if !ok {
return nil, err
}
perm := &ssh.Permissions{Extensions: map[string]string{
"pubkey": string(key.Marshal()),
}}
return perm, nil
},
KeyboardInteractiveCallback: func(conn ssh.ConnMetadata, challenge ssh.KeyboardInteractiveChallenge) (*ssh.Permissions, error) {
if !auth.AllowAnonymous() {
return nil, errors.New("public key authentication required")
}
_, err := auth.Check(conn.RemoteAddr(), nil)
return nil, err
},
}
return &config
}
// MakeNoAuth makes a simple ssh.ServerConfig which allows all connections.
// Primarily used for testing.
func MakeNoAuth() *ssh.ServerConfig {
config := ssh.ServerConfig{
NoClientAuth: false,
// Auth-related things should be constant-time to avoid timing attacks.
PublicKeyCallback: func(conn ssh.ConnMetadata, key ssh.PublicKey) (*ssh.Permissions, error) {
perm := &ssh.Permissions{Extensions: map[string]string{
"pubkey": string(key.Marshal()),
}}
return perm, nil
},
KeyboardInteractiveCallback: func(conn ssh.ConnMetadata, challenge ssh.KeyboardInteractiveChallenge) (*ssh.Permissions, error) {
return nil, nil
},
}
return &config
}
// Fingerprint performs a SHA256 BASE64 fingerprint of the PublicKey, similar to OpenSSH.
// See: https://anongit.mindrot.org/openssh.git/commit/?id=56d1c83cdd1ac
func Fingerprint(k ssh.PublicKey) string {
hash := sha256.Sum256(k.Marshal())
return "SHA256:" + base64.StdEncoding.EncodeToString(hash[:])
}

76
vendor/github.com/shazow/ssh-chat/sshd/client.go generated vendored Normal file
View File

@ -0,0 +1,76 @@
package sshd
import (
"crypto/rand"
"crypto/rsa"
"io"
"golang.org/x/crypto/ssh"
)
// NewRandomSigner generates a random key of a desired bit length.
func NewRandomSigner(bits int) (ssh.Signer, error) {
key, err := rsa.GenerateKey(rand.Reader, bits)
if err != nil {
return nil, err
}
return ssh.NewSignerFromKey(key)
}
// NewClientConfig creates a barebones ssh.ClientConfig to be used with ssh.Dial.
func NewClientConfig(name string) *ssh.ClientConfig {
return &ssh.ClientConfig{
User: name,
Auth: []ssh.AuthMethod{
ssh.KeyboardInteractive(func(user, instruction string, questions []string, echos []bool) (answers []string, err error) {
return
}),
},
HostKeyCallback: ssh.InsecureIgnoreHostKey(),
}
}
// ConnectShell makes a barebones SSH client session, used for testing.
func ConnectShell(host string, name string, handler func(r io.Reader, w io.WriteCloser) error) error {
config := NewClientConfig(name)
conn, err := ssh.Dial("tcp", host, config)
if err != nil {
return err
}
defer conn.Close()
session, err := conn.NewSession()
if err != nil {
return err
}
defer session.Close()
in, err := session.StdinPipe()
if err != nil {
return err
}
out, err := session.StdoutPipe()
if err != nil {
return err
}
/*
err = session.RequestPty("xterm", 80, 40, ssh.TerminalModes{})
if err != nil {
return err
}
*/
err = session.Shell()
if err != nil {
return err
}
_, err = session.SendRequest("ping", true, nil)
if err != nil {
return err
}
return handler(out, in)
}

34
vendor/github.com/shazow/ssh-chat/sshd/doc.go generated vendored Normal file
View File

@ -0,0 +1,34 @@
package sshd
/*
signer, err := ssh.ParsePrivateKey(privateKey)
config := MakeNoAuth()
config.AddHostKey(signer)
s, err := ListenSSH("0.0.0.0:2022", config)
if err != nil {
// Handle opening socket error
}
defer s.Close()
terminals := s.ServeTerminal()
for term := range terminals {
go func() {
defer term.Close()
term.SetPrompt("...")
term.AutoCompleteCallback = nil // ...
for {
line, err := term.ReadLine()
if err != nil {
break
}
term.Write(...)
}
}()
}
*/

22
vendor/github.com/shazow/ssh-chat/sshd/logger.go generated vendored Normal file
View File

@ -0,0 +1,22 @@
package sshd
import "io"
import stdlog "log"
var logger *stdlog.Logger
func SetLogger(w io.Writer) {
flags := stdlog.Flags()
prefix := "[sshd] "
logger = stdlog.New(w, prefix, flags)
}
type nullWriter struct{}
func (nullWriter) Write(data []byte) (int, error) {
return len(data), nil
}
func init() {
SetLogger(nullWriter{})
}

67
vendor/github.com/shazow/ssh-chat/sshd/net.go generated vendored Normal file
View File

@ -0,0 +1,67 @@
package sshd
import (
"net"
"github.com/shazow/rateio"
"golang.org/x/crypto/ssh"
)
// Container for the connection and ssh-related configuration
type SSHListener struct {
net.Listener
config *ssh.ServerConfig
RateLimit func() rateio.Limiter
HandlerFunc func(term *Terminal)
}
// Make an SSH listener socket
func ListenSSH(laddr string, config *ssh.ServerConfig) (*SSHListener, error) {
socket, err := net.Listen("tcp", laddr)
if err != nil {
return nil, err
}
l := SSHListener{Listener: socket, config: config}
return &l, nil
}
func (l *SSHListener) handleConn(conn net.Conn) (*Terminal, error) {
if l.RateLimit != nil {
// TODO: Configurable Limiter?
conn = ReadLimitConn(conn, l.RateLimit())
}
// Upgrade TCP connection to SSH connection
sshConn, channels, requests, err := ssh.NewServerConn(conn, l.config)
if err != nil {
return nil, err
}
// FIXME: Disconnect if too many faulty requests? (Avoid DoS.)
go ssh.DiscardRequests(requests)
return NewSession(sshConn, channels)
}
// Accept incoming connections as terminal requests and yield them
func (l *SSHListener) Serve() {
defer l.Close()
for {
conn, err := l.Accept()
if err != nil {
logger.Printf("Failed to accept connection: %s", err)
break
}
// Goroutineify to resume accepting sockets early
go func() {
term, err := l.handleConn(conn)
if err != nil {
logger.Printf("[%s] Failed to handshake: %s", conn.RemoteAddr(), err)
return
}
l.HandlerFunc(term)
}()
}
}

70
vendor/github.com/shazow/ssh-chat/sshd/pty.go generated vendored Normal file
View File

@ -0,0 +1,70 @@
package sshd
import "encoding/binary"
// Helpers below are borrowed from go.crypto circa 2011:
// parsePtyRequest parses the payload of the pty-req message and extracts the
// dimensions of the terminal. See RFC 4254, section 6.2.
func parsePtyRequest(s []byte) (width, height int, ok bool) {
_, s, ok = parseString(s)
if !ok {
return
}
width32, s, ok := parseUint32(s)
if !ok {
return
}
height32, _, ok := parseUint32(s)
width = int(width32)
height = int(height32)
if width < 1 {
ok = false
}
if height < 1 {
ok = false
}
return
}
func parseWinchRequest(s []byte) (width, height int, ok bool) {
width32, _, ok := parseUint32(s)
if !ok {
return
}
height32, _, ok := parseUint32(s)
if !ok {
return
}
width = int(width32)
height = int(height32)
if width < 1 {
ok = false
}
if height < 1 {
ok = false
}
return
}
func parseString(in []byte) (out string, rest []byte, ok bool) {
if len(in) < 4 {
return
}
length := binary.BigEndian.Uint32(in)
if uint32(len(in)) < 4+length {
return
}
out = string(in[4 : 4+length])
rest = in[4+length:]
ok = true
return
}
func parseUint32(in []byte) (uint32, []byte, bool) {
if len(in) < 4 {
return 0, nil, false
}
return binary.BigEndian.Uint32(in), in[4:], true
}

71
vendor/github.com/shazow/ssh-chat/sshd/ratelimit.go generated vendored Normal file
View File

@ -0,0 +1,71 @@
package sshd
import (
"io"
"net"
"time"
"github.com/shazow/rateio"
)
type limitedConn struct {
net.Conn
io.Reader // Our rate-limited io.Reader for net.Conn
}
func (r *limitedConn) Read(p []byte) (n int, err error) {
return r.Reader.Read(p)
}
// ReadLimitConn returns a net.Conn whose io.Reader interface is rate-limited by limiter.
func ReadLimitConn(conn net.Conn, limiter rateio.Limiter) net.Conn {
return &limitedConn{
Conn: conn,
Reader: rateio.NewReader(conn, limiter),
}
}
// Count each read as 1 unless it exceeds some number of bytes.
type inputLimiter struct {
// TODO: Could do all kinds of fancy things here, like be more forgiving of
// connections that have been around for a while.
Amount int
Frequency time.Duration
remaining int
readCap int
numRead int
timeRead time.Time
}
// NewInputLimiter returns a rateio.Limiter with sensible defaults for
// differentiating between humans typing and bots spamming.
func NewInputLimiter() rateio.Limiter {
grace := time.Second * 3
return &inputLimiter{
Amount: 2 << 14, // ~16kb, should be plenty for a high typing rate/copypasta/large key handshakes.
Frequency: time.Minute * 1,
readCap: 128, // Allow up to 128 bytes per read (anecdotally, 1 character = 52 bytes over ssh)
numRead: -1024 * 1024, // Start with a 1mb grace
timeRead: time.Now().Add(grace),
}
}
// Count applies 1 if n<readCap, else n
func (limit *inputLimiter) Count(n int) error {
now := time.Now()
if now.After(limit.timeRead) {
limit.numRead = 0
limit.timeRead = now.Add(limit.Frequency)
}
if n <= limit.readCap {
limit.numRead += 1
} else {
limit.numRead += n
}
if limit.numRead > limit.Amount {
return rateio.ErrRateExceeded
}
return nil
}

167
vendor/github.com/shazow/ssh-chat/sshd/terminal.go generated vendored Normal file
View File

@ -0,0 +1,167 @@
package sshd
import (
"errors"
"fmt"
"net"
"sync"
"time"
"golang.org/x/crypto/ssh"
"golang.org/x/crypto/ssh/terminal"
)
var keepaliveInterval = time.Second * 30
var keepaliveRequest = "keepalive@ssh-chat"
var ErrNoSessionChannel = errors.New("no session channel")
var ErrNotSessionChannel = errors.New("terminal requires session channel")
// Connection is an interface with fields necessary to operate an sshd host.
type Connection interface {
PublicKey() ssh.PublicKey
RemoteAddr() net.Addr
Name() string
ClientVersion() []byte
Close() error
}
type sshConn struct {
*ssh.ServerConn
}
func (c sshConn) PublicKey() ssh.PublicKey {
if c.Permissions == nil {
return nil
}
s, ok := c.Permissions.Extensions["pubkey"]
if !ok {
return nil
}
key, err := ssh.ParsePublicKey([]byte(s))
if err != nil {
return nil
}
return key
}
func (c sshConn) Name() string {
return c.User()
}
// Extending ssh/terminal to include a closer interface
type Terminal struct {
terminal.Terminal
Conn Connection
Channel ssh.Channel
done chan struct{}
closeOnce sync.Once
}
// Make new terminal from a session channel
func NewTerminal(conn *ssh.ServerConn, ch ssh.NewChannel) (*Terminal, error) {
if ch.ChannelType() != "session" {
return nil, ErrNotSessionChannel
}
channel, requests, err := ch.Accept()
if err != nil {
return nil, err
}
term := Terminal{
Terminal: *terminal.NewTerminal(channel, "Connecting..."),
Conn: sshConn{conn},
Channel: channel,
done: make(chan struct{}),
}
go term.listen(requests)
go func() {
// Keep-Alive Ticker
ticker := time.Tick(keepaliveInterval)
for {
select {
case <-ticker:
_, err := channel.SendRequest(keepaliveRequest, true, nil)
if err != nil {
// Connection is gone
logger.Printf("[%s] Keepalive failed, closing terminal: %s", term.Conn.RemoteAddr(), err)
term.Close()
return
}
case <-term.done:
return
}
}
}()
return &term, nil
}
// Find session channel and make a Terminal from it
func NewSession(conn *ssh.ServerConn, channels <-chan ssh.NewChannel) (*Terminal, error) {
// Make a terminal from the first session found
for ch := range channels {
if t := ch.ChannelType(); t != "session" {
logger.Printf("[%s] Ignored channel type: %s", conn.RemoteAddr(), t)
ch.Reject(ssh.UnknownChannelType, fmt.Sprintf("unknown channel type: %s", t))
continue
}
return NewTerminal(conn, ch)
}
return nil, ErrNoSessionChannel
}
// Close terminal and ssh connection
func (t *Terminal) Close() error {
var err error
t.closeOnce.Do(func() {
close(t.done)
t.Channel.Close()
err = t.Conn.Close()
})
return err
}
// Negotiate terminal type and settings
func (t *Terminal) listen(requests <-chan *ssh.Request) {
hasShell := false
for req := range requests {
var width, height int
var ok bool
switch req.Type {
case "shell":
if !hasShell {
ok = true
hasShell = true
}
case "pty-req":
width, height, ok = parsePtyRequest(req.Payload)
if ok {
// TODO: Hardcode width to 100000?
err := t.SetSize(width, height)
ok = err == nil
}
case "window-change":
width, height, ok = parseWinchRequest(req.Payload)
if ok {
// TODO: Hardcode width to 100000?
err := t.SetSize(width, height)
ok = err == nil
}
}
if req.WantReply {
req.Reply(ok, nil)
}
}
}