mirror of
https://github.com/wader/fq.git
synced 2024-12-29 00:22:38 +03:00
9852f56b74
What it can do: - Decodes records and most standard messages and extensions. - Decryptes records and reassemples application data stream if a keylog is provided and the cipher suite is supported. - Supports most recommended and used ciphers and a bunch of older ones. What it can't do: - SSL v3 maybe supported, is similar to TLS 1.0, not tested. - Decryption and renegotiation/cipher change. - Record defragmentation not supported, seems rare over TCP. - TLS 1.3 - SSL v2 but v2 compat header is supported. - Some key exchange messages not decoded yet Decryption code is heavly based on golang crypto/tls and zmap/zcrypto. Will be base for decoding http2 and other TLS based on protocols. Fixes #587
91 lines
1.9 KiB
Go
91 lines
1.9 KiB
Go
// Package rezlib wraps a zlib reader and makes it possible to read
|
|
// until the last current input flush boundary by reading until EOF.
|
|
//
|
|
// Inspiration from https://github.com/golang/go/issues/48877
|
|
//
|
|
// TODO: force deflate only?
|
|
//
|
|
// This is used by TLS deflate (seems be zlib?) where a flush is done
|
|
// between each record
|
|
package rezlib
|
|
|
|
import (
|
|
"bytes"
|
|
"compress/zlib"
|
|
"errors"
|
|
"fmt"
|
|
"io"
|
|
)
|
|
|
|
// max deflate dictionary size
|
|
const maxDictSize = 1 << 15 // 32KiB
|
|
|
|
type Reader struct {
|
|
r io.Reader
|
|
fr io.Reader
|
|
res zlib.Resetter
|
|
currentDict bytes.Buffer
|
|
zlibHeader [2]byte
|
|
hadUnexpectedEOF bool
|
|
}
|
|
|
|
func NewReader(r io.Reader) (*Reader, error) {
|
|
var zlibHeader [2]byte
|
|
if _, err := io.ReadFull(r, zlibHeader[:]); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
zr, zrErr := zlib.NewReader(io.MultiReader(
|
|
bytes.NewBuffer(zlibHeader[:]),
|
|
r,
|
|
))
|
|
if zrErr != nil {
|
|
return nil, zrErr
|
|
}
|
|
|
|
res, resOk := zr.(zlib.Resetter)
|
|
if !resOk {
|
|
panic("zlib reader not a Resetter")
|
|
}
|
|
|
|
return &Reader{
|
|
r: r,
|
|
fr: zr,
|
|
res: res,
|
|
zlibHeader: zlibHeader,
|
|
}, nil
|
|
}
|
|
|
|
func (r *Reader) Read(b []byte) (int, error) {
|
|
if r.hadUnexpectedEOF {
|
|
r.hadUnexpectedEOF = false
|
|
// inject zlib header again
|
|
mr := io.MultiReader(
|
|
bytes.NewReader(r.zlibHeader[:]),
|
|
r.r,
|
|
)
|
|
if err := r.res.Reset(mr, r.currentDict.Bytes()); err != nil {
|
|
panic(fmt.Sprintf("zlib reader could not reset %s", err))
|
|
}
|
|
}
|
|
|
|
n, err := r.fr.Read(b)
|
|
|
|
r.currentDict.Write(b[:n])
|
|
l := r.currentDict.Len()
|
|
if l > maxDictSize {
|
|
r.currentDict.Next(l - maxDictSize)
|
|
}
|
|
|
|
// TODO: currently we assume ErrUnexpectedEOF means we have read
|
|
// until a flush boundary. To get read of the error reset with
|
|
// current dictionary
|
|
// some better way?
|
|
if errors.Is(err, io.ErrUnexpectedEOF) {
|
|
r.hadUnexpectedEOF = true
|
|
err = io.EOF
|
|
}
|
|
|
|
return n, err
|
|
}
|