2020-01-08 10:48:53 +00:00
|
|
|
package http
|
|
|
|
|
|
|
|
import (
|
|
|
|
"bufio"
|
|
|
|
"fmt"
|
2020-01-08 15:34:31 +00:00
|
|
|
"git.darknebu.la/maride/pancap/output"
|
2020-01-08 10:48:53 +00:00
|
|
|
"github.com/google/gopacket"
|
|
|
|
"github.com/google/gopacket/tcpassembly"
|
|
|
|
"github.com/google/gopacket/tcpassembly/tcpreader"
|
|
|
|
"io"
|
2020-01-08 15:34:31 +00:00
|
|
|
"io/ioutil"
|
2020-01-08 10:48:53 +00:00
|
|
|
"net/http"
|
|
|
|
)
|
|
|
|
|
|
|
|
var (
|
|
|
|
responseSummaryLines []string
|
|
|
|
)
|
|
|
|
|
|
|
|
type httpResponseFactory struct{}
|
|
|
|
|
|
|
|
type httpResponseStream struct {
|
|
|
|
net, transport gopacket.Flow
|
|
|
|
r tcpreader.ReaderStream
|
|
|
|
}
|
|
|
|
|
|
|
|
// Creates a new HTTPResponseStream for the given packet flow, and analyzes it in a separate thread
|
|
|
|
func (h *httpResponseFactory) New(net, transport gopacket.Flow) tcpassembly.Stream {
|
|
|
|
hstream := &httpResponseStream{
|
|
|
|
net: net,
|
|
|
|
transport: transport,
|
|
|
|
r: tcpreader.NewReaderStream(),
|
|
|
|
}
|
|
|
|
go hstream.run() // Important... we must guarantee that data from the reader stream is read.
|
|
|
|
|
|
|
|
// ReaderStream implements tcpassembly.Stream, so we can return a pointer to it.
|
|
|
|
return &hstream.r
|
|
|
|
}
|
|
|
|
|
|
|
|
// Analyzes the given response
|
|
|
|
func (h *httpResponseStream) run() {
|
|
|
|
iobuf := bufio.NewReader(&h.r)
|
|
|
|
|
|
|
|
for {
|
|
|
|
resp, respErr := http.ReadResponse(iobuf, nil)
|
|
|
|
|
|
|
|
if respErr == io.EOF {
|
|
|
|
// That's ok, we can ignore EOF errors
|
|
|
|
return
|
|
|
|
} else if respErr != nil {
|
|
|
|
// Ignore, because it may be a request
|
|
|
|
} else {
|
|
|
|
// Try to process assembled request
|
2020-01-08 15:34:31 +00:00
|
|
|
fileBytes, _ := ioutil.ReadAll(resp.Body)
|
2020-01-08 10:48:53 +00:00
|
|
|
resp.Body.Close()
|
|
|
|
|
2020-01-08 15:34:31 +00:00
|
|
|
// Register file in filemanager
|
|
|
|
output.RegisterFile("", fileBytes, "HTTP response")
|
|
|
|
|
2020-01-08 10:48:53 +00:00
|
|
|
// Build summary
|
|
|
|
line := fmt.Sprintf("Response %s, Type %s, Size %d bytes", resp.Status, resp.Header.Get("Content-Type"), resp.ContentLength)
|
|
|
|
responseSummaryLines = append(responseSummaryLines, line)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|