mirror of
https://github.com/bettercap/bettercap
synced 2025-07-12 16:13:48 -07:00
129 lines
2.8 KiB
Go
129 lines
2.8 KiB
Go
package zerogod
|
|
|
|
import (
|
|
"bufio"
|
|
"bytes"
|
|
"fmt"
|
|
"io"
|
|
"net/http"
|
|
"strings"
|
|
"time"
|
|
|
|
"github.com/evilsocket/islazy/tui"
|
|
|
|
"github.com/phin1x/go-ipp"
|
|
)
|
|
|
|
type ClientData struct {
|
|
IP string `json:"ip"`
|
|
UA string `json:"user_agent"`
|
|
}
|
|
|
|
type JobData struct {
|
|
Name string `json:"name"`
|
|
UUID string `json:"uuid"`
|
|
User string `json:"username"`
|
|
}
|
|
|
|
type DocumentData struct {
|
|
Name string `json:"name"`
|
|
Format string `json:"format"`
|
|
Data []byte `json:"data"`
|
|
}
|
|
|
|
type PrintData struct {
|
|
CreatedAt time.Time `json:"created_at"`
|
|
Service string `json:"service"`
|
|
Client ClientData `json:"client"`
|
|
Job JobData `json:"job"`
|
|
Document DocumentData `json:"document"`
|
|
}
|
|
|
|
func ippClientHandler(ctx *HandlerContext) {
|
|
defer ctx.client.Close()
|
|
|
|
clientIP := strings.SplitN(ctx.client.RemoteAddr().String(), ":", 2)[0]
|
|
|
|
buf := make([]byte, 4096)
|
|
|
|
// read raw request
|
|
read, err := ctx.client.Read(buf)
|
|
if err != nil {
|
|
if err == io.EOF {
|
|
ctx.mod.Debug("EOF, client %s disconnected", clientIP)
|
|
return
|
|
}
|
|
ctx.mod.Warning("error while reading from %v: %v", clientIP, err)
|
|
return
|
|
} else if read == 0 {
|
|
ctx.mod.Warning("error while reading from %v: no data", clientIP)
|
|
return
|
|
}
|
|
|
|
raw_req := buf[0:read]
|
|
|
|
ctx.mod.Debug("read %d bytes from %v:\n%s\n", read, clientIP, Dump(raw_req))
|
|
|
|
// parse as http
|
|
reader := bufio.NewReader(bytes.NewReader(raw_req))
|
|
http_req, err := http.ReadRequest(reader)
|
|
if err != nil {
|
|
ctx.mod.Error("error while parsing http request from %v: %v\n%s", clientIP, err, Dump(raw_req))
|
|
return
|
|
}
|
|
|
|
clientUA := http_req.UserAgent()
|
|
ctx.mod.Info("%v -> %s", clientIP, tui.Green(clientUA))
|
|
|
|
ipp_body, err := ippReadRequestBody(ctx, http_req)
|
|
if err != nil {
|
|
ctx.mod.Error("%v", err)
|
|
return
|
|
}
|
|
|
|
// parse as IPP
|
|
ipp_req, err := ipp.NewRequestDecoder(ipp_body).Decode(nil)
|
|
if err != nil {
|
|
ctx.mod.Error("error while parsing ipp request from %v: %v -> %++v", clientIP, err, *http_req)
|
|
return
|
|
}
|
|
|
|
ipp_op_name := fmt.Sprintf("<unknown 0x%x>", ipp_req.Operation)
|
|
if name, found := IPP_REQUEST_NAMES[ipp_req.Operation]; found {
|
|
ipp_op_name = name
|
|
}
|
|
|
|
reqUsername := tui.Dim("<unknown>")
|
|
if value, found := ipp_req.OperationAttributes["requesting-user-name"]; found {
|
|
reqUsername = tui.Blue(value.(string))
|
|
}
|
|
|
|
ctx.mod.Info("%s <- %s@%s (%s) %s",
|
|
tui.Yellow(ctx.service),
|
|
reqUsername,
|
|
clientIP,
|
|
tui.Green(clientUA),
|
|
tui.Bold(ipp_op_name))
|
|
ctx.mod.Debug(" %++v", *ipp_req)
|
|
|
|
switch ipp_req.Operation {
|
|
// Get-Printer-Attributes
|
|
case 0x000B:
|
|
ippOnGetPrinterAttributes(ctx, ipp_req)
|
|
// Validate-Job
|
|
case 0x0004:
|
|
ippOnValidateJob(ctx, ipp_req)
|
|
// Get-Jobs
|
|
case 0x000A:
|
|
ippOnGetJobs(ctx, ipp_req)
|
|
// Print-Job
|
|
case 0x0002:
|
|
ippOnPrintJob(ctx, http_req, ipp_req)
|
|
// Get-Job-Attributes
|
|
case 0x0009:
|
|
ippOnGetJobAttributes(ctx, ipp_req)
|
|
|
|
default:
|
|
ippOnUnhandledRequest(ctx, ipp_req, ipp_op_name)
|
|
}
|
|
}
|