mirror of
https://github.com/bettercap/bettercap
synced 2025-07-30 03:29:57 -07:00
adding vendor folder
This commit is contained in:
parent
49c65021ea
commit
c304ca4696
1145 changed files with 369961 additions and 2 deletions
434
vendor/github.com/inconshreveable/go-vhost/tls.go
generated
vendored
Normal file
434
vendor/github.com/inconshreveable/go-vhost/tls.go
generated
vendored
Normal file
|
@ -0,0 +1,434 @@
|
|||
// Portions of the TLS code are:
|
||||
// Copyright 2010 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.
|
||||
|
||||
// TLS virtual hosting
|
||||
|
||||
package vhost
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"io"
|
||||
"net"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
const (
|
||||
maxPlaintext = 16384 // maximum plaintext payload length
|
||||
maxCiphertext = 16384 + 2048 // maximum ciphertext payload length
|
||||
recordHeaderLen = 5 // record header length
|
||||
maxHandshake = 65536 // maximum handshake we support (protocol max is 16 MB)
|
||||
)
|
||||
|
||||
type alert uint8
|
||||
|
||||
const (
|
||||
alertUnexpectedMessage alert = 10
|
||||
alertRecordOverflow alert = 22
|
||||
alertInternalError alert = 80
|
||||
)
|
||||
|
||||
var alertText = map[alert]string{
|
||||
alertUnexpectedMessage: "unexpected message",
|
||||
alertRecordOverflow: "record overflow",
|
||||
alertInternalError: "internal error",
|
||||
}
|
||||
|
||||
func (e alert) String() string {
|
||||
s, ok := alertText[e]
|
||||
if ok {
|
||||
return s
|
||||
}
|
||||
return "alert(" + strconv.Itoa(int(e)) + ")"
|
||||
}
|
||||
|
||||
func (e alert) Error() string {
|
||||
return e.String()
|
||||
}
|
||||
|
||||
// TLS record types.
|
||||
type recordType uint8
|
||||
|
||||
const (
|
||||
recordTypeHandshake recordType = 22
|
||||
)
|
||||
|
||||
// TLS handshake message types.
|
||||
const (
|
||||
typeClientHello uint8 = 1
|
||||
)
|
||||
|
||||
// TLS extension numbers
|
||||
var (
|
||||
extensionServerName uint16 = 0
|
||||
extensionStatusRequest uint16 = 5
|
||||
extensionSupportedCurves uint16 = 10
|
||||
extensionSupportedPoints uint16 = 11
|
||||
extensionSessionTicket uint16 = 35
|
||||
extensionNextProtoNeg uint16 = 13172 // not IANA assigned
|
||||
)
|
||||
|
||||
// TLS CertificateStatusType (RFC 3546)
|
||||
const (
|
||||
statusTypeOCSP uint8 = 1
|
||||
)
|
||||
|
||||
// A Conn represents a secured connection.
|
||||
// It implements the net.Conn interface.
|
||||
type TLSConn struct {
|
||||
*sharedConn
|
||||
ClientHelloMsg *ClientHelloMsg
|
||||
}
|
||||
|
||||
// TLS parses the ClientHello message on conn and returns
|
||||
// a new, unread connection with metadata for virtual host muxing
|
||||
func TLS(conn net.Conn) (tlsConn *TLSConn, err error) {
|
||||
c, rd := newShared(conn)
|
||||
|
||||
tlsConn = &TLSConn{sharedConn: c}
|
||||
if tlsConn.ClientHelloMsg, err = readClientHello(rd); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func (c *TLSConn) Host() string {
|
||||
if c.ClientHelloMsg == nil {
|
||||
return ""
|
||||
}
|
||||
return c.ClientHelloMsg.ServerName
|
||||
}
|
||||
|
||||
func (c *TLSConn) Free() {
|
||||
c.ClientHelloMsg = nil
|
||||
}
|
||||
|
||||
// A block is a simple data buffer.
|
||||
type block struct {
|
||||
data []byte
|
||||
off int // index for Read
|
||||
}
|
||||
|
||||
// resize resizes block to be n bytes, growing if necessary.
|
||||
func (b *block) resize(n int) {
|
||||
if n > cap(b.data) {
|
||||
b.reserve(n)
|
||||
}
|
||||
b.data = b.data[0:n]
|
||||
}
|
||||
|
||||
// reserve makes sure that block contains a capacity of at least n bytes.
|
||||
func (b *block) reserve(n int) {
|
||||
if cap(b.data) >= n {
|
||||
return
|
||||
}
|
||||
m := cap(b.data)
|
||||
if m == 0 {
|
||||
m = 1024
|
||||
}
|
||||
for m < n {
|
||||
m *= 2
|
||||
}
|
||||
data := make([]byte, len(b.data), m)
|
||||
copy(data, b.data)
|
||||
b.data = data
|
||||
}
|
||||
|
||||
// readFromUntil reads from r into b until b contains at least n bytes
|
||||
// or else returns an error.
|
||||
func (b *block) readFromUntil(r io.Reader, n int) error {
|
||||
// quick case
|
||||
if len(b.data) >= n {
|
||||
return nil
|
||||
}
|
||||
|
||||
// read until have enough.
|
||||
b.reserve(n)
|
||||
for {
|
||||
m, err := r.Read(b.data[len(b.data):cap(b.data)])
|
||||
b.data = b.data[0 : len(b.data)+m]
|
||||
if len(b.data) >= n {
|
||||
break
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (b *block) Read(p []byte) (n int, err error) {
|
||||
n = copy(p, b.data[b.off:])
|
||||
b.off += n
|
||||
return
|
||||
}
|
||||
|
||||
// newBlock allocates a new block
|
||||
func newBlock() *block {
|
||||
return new(block)
|
||||
}
|
||||
|
||||
// splitBlock splits a block after the first n bytes,
|
||||
// returning a block with those n bytes and a
|
||||
// block with the remainder. the latter may be nil.
|
||||
func splitBlock(b *block, n int) (*block, *block) {
|
||||
if len(b.data) <= n {
|
||||
return b, nil
|
||||
}
|
||||
bb := newBlock()
|
||||
bb.resize(len(b.data) - n)
|
||||
copy(bb.data, b.data[n:])
|
||||
b.data = b.data[0:n]
|
||||
return b, bb
|
||||
}
|
||||
|
||||
// readHandshake reads the next handshake message from
|
||||
// the record layer.
|
||||
func readClientHello(rd io.Reader) (*ClientHelloMsg, error) {
|
||||
var nextBlock *block // raw input, right off the wire
|
||||
var hand bytes.Buffer // handshake data waiting to be read
|
||||
|
||||
// readRecord reads the next TLS record from the connection
|
||||
// and updates the record layer state.
|
||||
readRecord := func() error {
|
||||
// Caller must be in sync with connection:
|
||||
// handshake data if handshake not yet completed,
|
||||
// else application data. (We don't support renegotiation.)
|
||||
if nextBlock == nil {
|
||||
nextBlock = newBlock()
|
||||
}
|
||||
b := nextBlock
|
||||
|
||||
// Read header, payload.
|
||||
if err := b.readFromUntil(rd, recordHeaderLen); err != nil {
|
||||
return err
|
||||
}
|
||||
typ := recordType(b.data[0])
|
||||
|
||||
// No valid TLS record has a type of 0x80, however SSLv2 handshakes
|
||||
// start with a uint16 length where the MSB is set and the first record
|
||||
// is always < 256 bytes long. Therefore typ == 0x80 strongly suggests
|
||||
// an SSLv2 client.
|
||||
if typ == 0x80 {
|
||||
return errors.New("tls: unsupported SSLv2 handshake received")
|
||||
}
|
||||
|
||||
vers := uint16(b.data[1])<<8 | uint16(b.data[2])
|
||||
n := int(b.data[3])<<8 | int(b.data[4])
|
||||
if n > maxCiphertext {
|
||||
return alertRecordOverflow
|
||||
}
|
||||
|
||||
// First message, be extra suspicious:
|
||||
// this might not be a TLS client.
|
||||
// Bail out before reading a full 'body', if possible.
|
||||
// The current max version is 3.1.
|
||||
// If the version is >= 16.0, it's probably not real.
|
||||
// Similarly, a clientHello message encodes in
|
||||
// well under a kilobyte. If the length is >= 12 kB,
|
||||
// it's probably not real.
|
||||
if (typ != recordTypeHandshake) || vers >= 0x1000 || n >= 0x3000 {
|
||||
return alertUnexpectedMessage
|
||||
}
|
||||
|
||||
if err := b.readFromUntil(rd, recordHeaderLen+n); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Process message.
|
||||
b, nextBlock = splitBlock(b, recordHeaderLen+n)
|
||||
b.off = recordHeaderLen
|
||||
data := b.data[b.off:]
|
||||
if len(data) > maxPlaintext {
|
||||
return alertRecordOverflow
|
||||
}
|
||||
|
||||
hand.Write(data)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
if err := readRecord(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
data := hand.Bytes()
|
||||
n := int(data[1])<<16 | int(data[2])<<8 | int(data[3])
|
||||
if n > maxHandshake {
|
||||
return nil, alertInternalError
|
||||
}
|
||||
for hand.Len() < 4+n {
|
||||
if err := readRecord(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
data = hand.Next(4 + n)
|
||||
if data[0] != typeClientHello {
|
||||
return nil, alertUnexpectedMessage
|
||||
}
|
||||
|
||||
msg := new(ClientHelloMsg)
|
||||
if !msg.unmarshal(data) {
|
||||
return nil, alertUnexpectedMessage
|
||||
}
|
||||
|
||||
return msg, nil
|
||||
}
|
||||
|
||||
type ClientHelloMsg struct {
|
||||
Raw []byte
|
||||
Vers uint16
|
||||
Random []byte
|
||||
SessionId []byte
|
||||
CipherSuites []uint16
|
||||
CompressionMethods []uint8
|
||||
NextProtoNeg bool
|
||||
ServerName string
|
||||
OcspStapling bool
|
||||
SupportedCurves []uint16
|
||||
SupportedPoints []uint8
|
||||
TicketSupported bool
|
||||
SessionTicket []uint8
|
||||
}
|
||||
|
||||
func (m *ClientHelloMsg) unmarshal(data []byte) bool {
|
||||
if len(data) < 42 {
|
||||
return false
|
||||
}
|
||||
m.Raw = data
|
||||
m.Vers = uint16(data[4])<<8 | uint16(data[5])
|
||||
m.Random = data[6:38]
|
||||
sessionIdLen := int(data[38])
|
||||
if sessionIdLen > 32 || len(data) < 39+sessionIdLen {
|
||||
return false
|
||||
}
|
||||
m.SessionId = data[39 : 39+sessionIdLen]
|
||||
data = data[39+sessionIdLen:]
|
||||
if len(data) < 2 {
|
||||
return false
|
||||
}
|
||||
// cipherSuiteLen is the number of bytes of cipher suite numbers. Since
|
||||
// they are uint16s, the number must be even.
|
||||
cipherSuiteLen := int(data[0])<<8 | int(data[1])
|
||||
if cipherSuiteLen%2 == 1 || len(data) < 2+cipherSuiteLen {
|
||||
return false
|
||||
}
|
||||
numCipherSuites := cipherSuiteLen / 2
|
||||
m.CipherSuites = make([]uint16, numCipherSuites)
|
||||
for i := 0; i < numCipherSuites; i++ {
|
||||
m.CipherSuites[i] = uint16(data[2+2*i])<<8 | uint16(data[3+2*i])
|
||||
}
|
||||
data = data[2+cipherSuiteLen:]
|
||||
if len(data) < 1 {
|
||||
return false
|
||||
}
|
||||
compressionMethodsLen := int(data[0])
|
||||
if len(data) < 1+compressionMethodsLen {
|
||||
return false
|
||||
}
|
||||
m.CompressionMethods = data[1 : 1+compressionMethodsLen]
|
||||
|
||||
data = data[1+compressionMethodsLen:]
|
||||
|
||||
m.NextProtoNeg = false
|
||||
m.ServerName = ""
|
||||
m.OcspStapling = false
|
||||
m.TicketSupported = false
|
||||
m.SessionTicket = nil
|
||||
|
||||
if len(data) == 0 {
|
||||
// ClientHello is optionally followed by extension data
|
||||
return true
|
||||
}
|
||||
if len(data) < 2 {
|
||||
return false
|
||||
}
|
||||
|
||||
extensionsLength := int(data[0])<<8 | int(data[1])
|
||||
data = data[2:]
|
||||
if extensionsLength != len(data) {
|
||||
return false
|
||||
}
|
||||
|
||||
for len(data) != 0 {
|
||||
if len(data) < 4 {
|
||||
return false
|
||||
}
|
||||
extension := uint16(data[0])<<8 | uint16(data[1])
|
||||
length := int(data[2])<<8 | int(data[3])
|
||||
data = data[4:]
|
||||
if len(data) < length {
|
||||
return false
|
||||
}
|
||||
|
||||
switch extension {
|
||||
case extensionServerName:
|
||||
if length < 2 {
|
||||
return false
|
||||
}
|
||||
numNames := int(data[0])<<8 | int(data[1])
|
||||
d := data[2:]
|
||||
for i := 0; i < numNames; i++ {
|
||||
if len(d) < 3 {
|
||||
return false
|
||||
}
|
||||
nameType := d[0]
|
||||
nameLen := int(d[1])<<8 | int(d[2])
|
||||
d = d[3:]
|
||||
if len(d) < nameLen {
|
||||
return false
|
||||
}
|
||||
if nameType == 0 {
|
||||
m.ServerName = string(d[0:nameLen])
|
||||
break
|
||||
}
|
||||
d = d[nameLen:]
|
||||
}
|
||||
case extensionNextProtoNeg:
|
||||
if length > 0 {
|
||||
return false
|
||||
}
|
||||
m.NextProtoNeg = true
|
||||
case extensionStatusRequest:
|
||||
m.OcspStapling = length > 0 && data[0] == statusTypeOCSP
|
||||
case extensionSupportedCurves:
|
||||
// http://tools.ietf.org/html/rfc4492#section-5.5.1
|
||||
if length < 2 {
|
||||
return false
|
||||
}
|
||||
l := int(data[0])<<8 | int(data[1])
|
||||
if l%2 == 1 || length != l+2 {
|
||||
return false
|
||||
}
|
||||
numCurves := l / 2
|
||||
m.SupportedCurves = make([]uint16, numCurves)
|
||||
d := data[2:]
|
||||
for i := 0; i < numCurves; i++ {
|
||||
m.SupportedCurves[i] = uint16(d[0])<<8 | uint16(d[1])
|
||||
d = d[2:]
|
||||
}
|
||||
case extensionSupportedPoints:
|
||||
// http://tools.ietf.org/html/rfc4492#section-5.5.2
|
||||
if length < 1 {
|
||||
return false
|
||||
}
|
||||
l := int(data[0])
|
||||
if length != l+1 {
|
||||
return false
|
||||
}
|
||||
m.SupportedPoints = make([]uint8, l)
|
||||
copy(m.SupportedPoints, data[1:])
|
||||
case extensionSessionTicket:
|
||||
// http://tools.ietf.org/html/rfc5077#section-3.2
|
||||
m.TicketSupported = true
|
||||
m.SessionTicket = data[:length]
|
||||
}
|
||||
data = data[length:]
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue