This is a fork of: https://github.com/roglew/puppy
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

2177 lines
49 KiB

7 years ago
package puppy
7 years ago
import (
"bufio"
"bytes"
"crypto/tls"
7 years ago
"encoding/base64"
"encoding/json"
"errors"
"fmt"
"io"
"log"
"net"
"sort"
"strconv"
"strings"
"sync"
"time"
"github.com/gorilla/websocket"
)
7 years ago
// Creates a MessageListener that implements the default puppy handlers. See the message docs for more info
7 years ago
func NewProxyMessageListener(logger *log.Logger, iproxy *InterceptingProxy) *MessageListener {
l := NewMessageListener(logger, iproxy)
l.AddHandler("ping", pingHandler)
l.AddHandler("submit", submitHandler)
l.AddHandler("savenew", saveNewHandler)
l.AddHandler("storagequery", storageQueryHandler)
l.AddHandler("validatequery", validateQueryHandler)
7 years ago
l.AddHandler("checkrequest", checkRequestHandler)
7 years ago
l.AddHandler("setscope", setScopeHandler)
l.AddHandler("viewscope", viewScopeHandler)
l.AddHandler("addtag", addTagHandler)
l.AddHandler("removetag", removeTagHandler)
l.AddHandler("cleartag", clearTagHandler)
l.AddHandler("intercept", interceptHandler)
l.AddHandler("allsavedqueries", allSavedQueriesHandler)
l.AddHandler("savequery", saveQueryHandler)
l.AddHandler("loadquery", loadQueryHandler)
l.AddHandler("deletequery", deleteQueryHandler)
l.AddHandler("addlistener", addListenerHandler)
l.AddHandler("removelistener", removeListenerHandler)
l.AddHandler("getlisteners", getListenersHandler)
l.AddHandler("loadcerts", loadCertificatesHandler)
l.AddHandler("setcerts", setCertificatesHandler)
7 years ago
l.AddHandler("clearcerts", clearCertificatesHandler)
l.AddHandler("gencerts", generateCertificatesHandler)
l.AddHandler("genpemcerts", generatePEMCertificatesHandler)
l.AddHandler("addsqlitestorage", addSQLiteStorageHandler)
l.AddHandler("addinmemorystorage", addInMemoryStorageHandler)
l.AddHandler("closestorage", closeStorageHandler)
l.AddHandler("setproxystorage", setProxyStorageHandler)
l.AddHandler("liststorage", listProxyStorageHandler)
l.AddHandler("setproxy", setProxyHandler)
6 years ago
l.AddHandler("watchstorage", watchStorageHandler)
6 years ago
l.AddHandler("setpluginvalue", setPluginValueHandler)
l.AddHandler("getpluginvalue", getPluginValueHandler)
7 years ago
return l
}
7 years ago
// JSON data representing a ProxyRequest
7 years ago
type RequestJSON struct {
DestHost string
DestPort int
UseTLS bool
Method string
Path string
7 years ago
ProtoMajor int
ProtoMinor int
Headers map[string][]string
Body string
Tags []string
7 years ago
StartTime int64 `json:"StartTime,omitempty"`
EndTime int64 `json:"EndTime,omitempty"`
7 years ago
Unmangled *RequestJSON `json:"Unmangled,omitempty"`
Response *ResponseJSON `json:"Response,omitempty"`
7 years ago
WSMessages []*WSMessageJSON `json:"WSMessages,omitempty"`
DbId string `json:"DbId,omitempty"`
7 years ago
}
7 years ago
// JSON data representing a ProxyResponse
7 years ago
type ResponseJSON struct {
ProtoMajor int
ProtoMinor int
StatusCode int
Reason string
7 years ago
Headers map[string][]string
Body string
7 years ago
Unmangled *ResponseJSON `json:"Unmangled,omitempty"`
DbId string
7 years ago
}
7 years ago
// JSON data representing a ProxyWSMessage
7 years ago
type WSMessageJSON struct {
Message string
IsBinary bool
ToServer bool
7 years ago
Timestamp int64
Unmangled *WSMessageJSON `json:"Unmangled,omitempty"`
DbId string
7 years ago
}
7 years ago
// Check that the RequestJSON contains valid data
7 years ago
func (reqd *RequestJSON) Validate() error {
if reqd.DestHost == "" {
return errors.New("request is missing target host")
}
if reqd.DestPort == 0 {
return errors.New("request is missing target port")
}
return nil
}
7 years ago
// Convert RequestJSON into a ProxyRequest
7 years ago
func (reqd *RequestJSON) Parse() (*ProxyRequest, error) {
if err := reqd.Validate(); err != nil {
return nil, err
}
dataBuf := new(bytes.Buffer)
statusLine := fmt.Sprintf("%s %s HTTP/%d.%d", reqd.Method, reqd.Path, reqd.ProtoMajor, reqd.ProtoMinor)
dataBuf.Write([]byte(statusLine))
dataBuf.Write([]byte("\r\n"))
for k, vs := range reqd.Headers {
for _, v := range vs {
if strings.ToLower(k) != "content-length" {
dataBuf.Write([]byte(k))
dataBuf.Write([]byte(": "))
dataBuf.Write([]byte(v))
dataBuf.Write([]byte("\r\n"))
}
}
}
body, err := base64.StdEncoding.DecodeString(reqd.Body)
if err != nil {
return nil, err
}
dataBuf.Write([]byte("Content-Length"))
dataBuf.Write([]byte(": "))
dataBuf.Write([]byte(strconv.Itoa(len(body))))
dataBuf.Write([]byte("\r\n\r\n"))
dataBuf.Write(body)
req, err := ProxyRequestFromBytes(dataBuf.Bytes(), reqd.DestHost, reqd.DestPort, reqd.UseTLS)
if err != nil {
return nil, err
}
if req.Host == "" {
req.Host = reqd.DestHost
}
if reqd.StartTime > 0 {
req.StartDatetime = time.Unix(0, reqd.StartTime)
}
if reqd.EndTime > 0 {
req.EndDatetime = time.Unix(0, reqd.EndTime)
}
for _, tag := range reqd.Tags {
7 years ago
req.AddTag(tag)
}
if reqd.Response != nil {
rsp, err := reqd.Response.Parse()
if err != nil {
return nil, err
}
req.ServerResponse = rsp
}
for _, wsmd := range reqd.WSMessages {
wsm, err := wsmd.Parse()
if err != nil {
return nil, err
}
req.WSMessages = append(req.WSMessages, wsm)
}
sort.Sort(WSSort(req.WSMessages))
return req, nil
}
7 years ago
// Convert a ProxyRequest into JSON data. If headersOnly is true, the JSON data will only contain the headers and metadata of the message
func NewRequestJSON(req *ProxyRequest, headersOnly bool) *RequestJSON {
7 years ago
newHeaders := make(map[string][]string)
for k, vs := range req.Header {
for _, v := range vs {
l, ok := newHeaders[k]
if ok {
newHeaders[k] = append(l, v)
} else {
newHeaders[k] = make([]string, 1)
newHeaders[k][0] = v
}
}
}
var unmangled *RequestJSON = nil
if req.Unmangled != nil {
unmangled = NewRequestJSON(req.Unmangled, headersOnly)
}
var rsp *ResponseJSON = nil
if req.ServerResponse != nil {
rsp = NewResponseJSON(req.ServerResponse, headersOnly)
}
wsms := make([]*WSMessageJSON, 0)
for _, wsm := range req.WSMessages {
wsms = append(wsms, NewWSMessageJSON(wsm))
}
ret := &RequestJSON{
DestHost: req.DestHost,
DestPort: req.DestPort,
UseTLS: req.DestUseTLS,
Method: req.Method,
Path: req.HTTPPath(),
7 years ago
ProtoMajor: req.ProtoMajor,
ProtoMinor: req.ProtoMinor,
Headers: newHeaders,
Tags: req.Tags(),
7 years ago
StartTime: req.StartDatetime.UnixNano(),
EndTime: req.EndDatetime.UnixNano(),
7 years ago
Unmangled: unmangled,
Response: rsp,
7 years ago
WSMessages: wsms,
DbId: req.DbId,
7 years ago
}
if !headersOnly {
ret.Body = base64.StdEncoding.EncodeToString(req.BodyBytes())
}
return ret
}
7 years ago
// Ensure that response JSON data is valid
7 years ago
func (rspd *ResponseJSON) Validate() error {
return nil
}
7 years ago
// Convert response JSON data into a ProxyResponse
7 years ago
func (rspd *ResponseJSON) Parse() (*ProxyResponse, error) {
if err := rspd.Validate(); err != nil {
return nil, err
}
dataBuf := new(bytes.Buffer)
statusLine := fmt.Sprintf("HTTP/%d.%d %03d %s", rspd.ProtoMajor, rspd.ProtoMinor, rspd.StatusCode, rspd.Reason)
dataBuf.Write([]byte(statusLine))
dataBuf.Write([]byte("\r\n"))
for k, vs := range rspd.Headers {
for _, v := range vs {
if strings.ToLower(k) != "content-length" {
dataBuf.Write([]byte(k))
dataBuf.Write([]byte(": "))
dataBuf.Write([]byte(v))
dataBuf.Write([]byte("\r\n"))
}
}
}
body, err := base64.StdEncoding.DecodeString(rspd.Body)
if err != nil {
return nil, err
}
dataBuf.Write([]byte("Content-Length"))
dataBuf.Write([]byte(": "))
dataBuf.Write([]byte(strconv.Itoa(len(rspd.Body))))
dataBuf.Write([]byte("\r\n\r\n"))
dataBuf.Write(body)
rsp, err := ProxyResponseFromBytes(dataBuf.Bytes())
if err != nil {
return nil, err
}
if rspd.Unmangled != nil {
ursp, err := rspd.Unmangled.Parse()
if err != nil {
return nil, err
}
rsp.Unmangled = ursp
}
return rsp, nil
}
7 years ago
// Serialize a ProxyResponse into JSON data. If headersOnly is true, the JSON data will only contain the headers and metadata of the message
func NewResponseJSON(rsp *ProxyResponse, headersOnly bool) *ResponseJSON {
7 years ago
newHeaders := make(map[string][]string)
for k, vs := range rsp.Header {
for _, v := range vs {
l, ok := newHeaders[k]
if ok {
newHeaders[k] = append(l, v)
} else {
newHeaders[k] = make([]string, 1)
newHeaders[k][0] = v
}
}
}
var unmangled *ResponseJSON = nil
if rsp.Unmangled != nil {
unmangled = NewResponseJSON(rsp.Unmangled, headersOnly)
}
ret := &ResponseJSON{
ProtoMajor: rsp.ProtoMajor,
ProtoMinor: rsp.ProtoMinor,
StatusCode: rsp.StatusCode,
Reason: rsp.HTTPStatus(),
Headers: newHeaders,
DbId: rsp.DbId,
Unmangled: unmangled,
7 years ago
}
if !headersOnly {
ret.Body = base64.StdEncoding.EncodeToString(rsp.BodyBytes())
}
return ret
}
7 years ago
// Parse websocket message JSON data into a ProxyWSMEssage
7 years ago
func (wsmd *WSMessageJSON) Parse() (*ProxyWSMessage, error) {
var Direction int
if wsmd.ToServer {
Direction = ToServer
} else {
Direction = ToClient
}
var mtype int
if wsmd.IsBinary {
mtype = websocket.BinaryMessage
} else {
mtype = websocket.TextMessage
}
message, err := base64.StdEncoding.DecodeString(wsmd.Message)
if err != nil {
return nil, err
}
var unmangled *ProxyWSMessage
if wsmd.Unmangled != nil {
unmangled, err = wsmd.Unmangled.Parse()
if err != nil {
return nil, err
}
}
retData := &ProxyWSMessage{
Message: message,
Type: mtype,
7 years ago
Direction: Direction,
Timestamp: time.Unix(0, wsmd.Timestamp),
Unmangled: unmangled,
DbId: wsmd.DbId,
7 years ago
}
return retData, nil
}
7 years ago
// Serialize a websocket message into JSON data
func NewWSMessageJSON(wsm *ProxyWSMessage) *WSMessageJSON {
7 years ago
isBinary := false
if wsm.Type == websocket.BinaryMessage {
isBinary = true
}
7 years ago
toServer := false
if wsm.Direction == ToServer {
toServer = true
}
var unmangled *WSMessageJSON
if wsm.Unmangled != nil {
unmangled = NewWSMessageJSON(wsm.Unmangled)
}
ret := &WSMessageJSON{
Message: base64.StdEncoding.EncodeToString(wsm.Message),
IsBinary: isBinary,
ToServer: toServer,
7 years ago
Timestamp: wsm.Timestamp.UnixNano(),
Unmangled: unmangled,
DbId: wsm.DbId,
7 years ago
}
return ret
}
7 years ago
// Clears metadata (start/end time, DbId) and dependent message data (response, websocket messages, and unmangled versions) from the RequestJSON
7 years ago
func CleanReqJSON(req *RequestJSON) {
req.StartTime = 0
req.EndTime = 0
req.Unmangled = nil
req.Response = nil
req.WSMessages = nil
req.DbId = ""
}
7 years ago
// Clears metadata (DbId) and dependent message data (unmangled version) from the ResponseJSON
7 years ago
func CleanRspJSON(rsp *ResponseJSON) {
rsp.Unmangled = nil
rsp.DbId = ""
}
7 years ago
// Clears metadata (timestamp, DbId) and dependent message data (unmangled version) from the WSMessageJSON
7 years ago
func CleanWSJSON(wsm *WSMessageJSON) {
wsm.Timestamp = 0
wsm.Unmangled = nil
wsm.DbId = ""
}
type successResult struct {
Success bool
}
/*
Ping
*/
type pingMessage struct{}
7 years ago
type pingResponse struct {
Success bool
Ping string
7 years ago
}
func pingHandler(b []byte, c net.Conn, logger *log.Logger, iproxy *InterceptingProxy) {
rsp := pingResponse{Success: true, Ping: "Pong"}
MessageResponse(c, rsp)
}
/*
Submit
*/
type submitMessage struct {
Request *RequestJSON
Storage int
}
type submitResponse struct {
Success bool
7 years ago
SubmittedRequest *RequestJSON
}
func submitHandler(b []byte, c net.Conn, logger *log.Logger, iproxy *InterceptingProxy) {
mreq := submitMessage{}
if err := json.Unmarshal(b, &mreq); err != nil {
ErrorResponse(c, fmt.Sprintf("error parsing submit message: %s", err.Error()))
return
}
req, err := mreq.Request.Parse()
if err != nil {
ErrorResponse(c, fmt.Sprintf("error parsing http request: %s", err.Error()))
return
}
if mreq.Storage > 0 {
storage, _ := iproxy.GetMessageStorage(mreq.Storage)
if storage == nil {
ErrorResponse(c, fmt.Sprintf("storage with id %d does not exist", mreq.Storage))
return
}
SaveNewRequest(storage, req)
}
logger.Println("Submitting request to", req.FullURL(), "...")
if err := iproxy.SubmitRequest(req); err != nil {
7 years ago
ErrorResponse(c, err.Error())
return
}
if mreq.Storage > 0 {
storage, _ := iproxy.GetMessageStorage(mreq.Storage)
if storage == nil {
ErrorResponse(c, fmt.Sprintf("storage with id %d does not exist", mreq.Storage))
return
}
UpdateRequest(storage, req)
}
result := NewRequestJSON(req, false)
response := submitResponse{Success: true, SubmittedRequest: result}
MessageResponse(c, response)
}
/*
SaveNew
*/
type saveNewMessage struct {
7 years ago
Request *RequestJSON
7 years ago
Storage int
}
type saveNewResponse struct {
Success bool
DbId string
7 years ago
}
func saveNewHandler(b []byte, c net.Conn, logger *log.Logger, iproxy *InterceptingProxy) {
mreq := submitMessage{}
if err := json.Unmarshal(b, &mreq); err != nil {
ErrorResponse(c, fmt.Sprintf("error parsing submit message: %s", err.Error()))
return
}
if mreq.Storage == 0 {
ErrorResponse(c, "storage is required")
return
}
req, err := mreq.Request.Parse()
if err != nil {
ErrorResponse(c, fmt.Sprintf("error parsing http request: %s", err.Error()))
return
}
storage, _ := iproxy.GetMessageStorage(mreq.Storage)
if storage == nil {
ErrorResponse(c, fmt.Sprintf("storage with id %d does not exist", mreq.Storage))
return
}
err = SaveNewRequest(storage, req)
if err != nil {
ErrorResponse(c, fmt.Sprintf("error saving http request: %s", err.Error()))
return
}
response := &saveNewResponse{
Success: true,
DbId: req.DbId,
7 years ago
}
MessageResponse(c, response)
}
/*
QueryRequests
*/
type storageQueryMessage struct {
Query StrMessageQuery
7 years ago
HeadersOnly bool
MaxResults int64
Storage int
7 years ago
}
type storageQueryResult struct {
Success bool
Results []*RequestJSON
}
func storageQueryHandler(b []byte, c net.Conn, logger *log.Logger, iproxy *InterceptingProxy) {
mreq := storageQueryMessage{
Query: nil,
7 years ago
HeadersOnly: false,
MaxResults: 0,
7 years ago
}
if err := json.Unmarshal(b, &mreq); err != nil {
ErrorResponse(c, "error parsing query message")
return
}
if mreq.Query == nil {
ErrorResponse(c, "query is required")
return
}
if mreq.Storage == 0 {
ErrorResponse(c, "storage is required")
return
}
storage, _ := iproxy.GetMessageStorage(mreq.Storage)
if storage == nil {
ErrorResponse(c, fmt.Sprintf("storage with id %d does not exist", mreq.Storage))
return
}
var searchResults []*ProxyRequest
if len(mreq.Query) == 1 && len(mreq.Query[0]) == 1 {
args, err := CheckArgsStrToGo(mreq.Query[0][0])
if err != nil {
ErrorResponse(c, err.Error())
return
}
logger.Println("Search query is one phrase, sending directly to storage...")
searchResults, err = storage.Search(mreq.MaxResults, args...)
if err != nil {
ErrorResponse(c, err.Error())
return
}
} else {
logger.Println("Search query is multple sets of arguments, creating checker and checking naively...")
7 years ago
goQuery, err := StrQueryToMsgQuery(mreq.Query)
7 years ago
if err != nil {
ErrorResponse(c, err.Error())
return
}
checker, err := CheckerFromMessageQuery(goQuery)
if err != nil {
ErrorResponse(c, err.Error())
return
}
searchResults, err = storage.CheckRequests(mreq.MaxResults, checker)
if err != nil {
ErrorResponse(c, err.Error())
return
}
}
var result storageQueryResult
reqResults := make([]*RequestJSON, len(searchResults))
for i, req := range searchResults {
reqResults[i] = NewRequestJSON(req, mreq.HeadersOnly)
}
result.Success = true
result.Results = reqResults
MessageResponse(c, &result)
}
/*
ValidateQuery
*/
type validateQueryMessage struct {
Query StrMessageQuery
}
func validateQueryHandler(b []byte, c net.Conn, logger *log.Logger, iproxy *InterceptingProxy) {
mreq := validateQueryMessage{}
if err := json.Unmarshal(b, &mreq); err != nil {
ErrorResponse(c, "error parsing query message")
return
}
7 years ago
goQuery, err := StrQueryToMsgQuery(mreq.Query)
7 years ago
if err != nil {
ErrorResponse(c, err.Error())
return
}
_, err = CheckerFromMessageQuery(goQuery)
if err != nil {
ErrorResponse(c, err.Error())
return
}
MessageResponse(c, &successResult{Success: true})
7 years ago
}
7 years ago
/*
CheckRequest
*/
type checkRequestMessage struct {
6 years ago
Query StrMessageQuery
Request *RequestJSON
DbId string
StorageId int
7 years ago
}
type checkRequestResponse struct {
Result bool
Success bool
}
func checkRequestHandler(b []byte, c net.Conn, logger *log.Logger, iproxy *InterceptingProxy) {
mreq := checkRequestMessage{}
if err := json.Unmarshal(b, &mreq); err != nil {
ErrorResponse(c, "error parsing query message")
return
}
6 years ago
var req *ProxyRequest
var err error
if mreq.DbId != "" {
storage, _ := iproxy.GetMessageStorage(mreq.StorageId)
if storage == nil {
ErrorResponse(c, fmt.Sprintf("storage with id %d does not exist", mreq.StorageId))
return
}
searchResults, err := storage.Search(1, FieldId, StrIs, mreq.DbId)
if err != nil {
ErrorResponse(c, err.Error())
return
}
if len(searchResults) == 0 {
ErrorResponse(c, fmt.Sprintf("message with id=%s does not exist", mreq.DbId))
return
}
req = searchResults[0]
} else {
req, err = mreq.Request.Parse()
if err != nil {
ErrorResponse(c, fmt.Sprintf("error parsing http request: %s", err.Error()))
return
}
7 years ago
}
goQuery, err := StrQueryToMsgQuery(mreq.Query)
if err != nil {
ErrorResponse(c, err.Error())
return
}
checker, err := CheckerFromMessageQuery(goQuery)
if err != nil {
ErrorResponse(c, err.Error())
return
}
result := &checkRequestResponse{
Success: true,
Result: checker(req),
}
MessageResponse(c, result)
}
7 years ago
/*
SetScope
*/
type setScopeMessage struct {
Query StrMessageQuery
}
func setScopeHandler(b []byte, c net.Conn, logger *log.Logger, iproxy *InterceptingProxy) {
mreq := setScopeMessage{}
7 years ago
if err := json.Unmarshal(b, &mreq); err != nil {
ErrorResponse(c, "error parsing query message")
return
}
7 years ago
goQuery, err := StrQueryToMsgQuery(mreq.Query)
7 years ago
if err != nil {
ErrorResponse(c, err.Error())
return
}
err = iproxy.SetScopeQuery(goQuery)
if err != nil {
ErrorResponse(c, err.Error())
return
}
MessageResponse(c, &successResult{Success: true})
7 years ago
}
/*
ViewScope
*/
type viewScopeMessage struct {
}
type viewScopeResult struct {
Success bool
7 years ago
IsCustom bool
Query StrMessageQuery
7 years ago
}
func viewScopeHandler(b []byte, c net.Conn, logger *log.Logger, iproxy *InterceptingProxy) {
scopeQuery := iproxy.GetScopeQuery()
scopeChecker := iproxy.GetScopeChecker()
if scopeQuery == nil && scopeChecker != nil {
MessageResponse(c, &viewScopeResult{
Success: true,
7 years ago
IsCustom: true,
})
return
}
var err error
7 years ago
strQuery, err := MsgQueryToStrQuery(scopeQuery)
7 years ago
if err != nil {
ErrorResponse(c, err.Error())
return
}
MessageResponse(c, &viewScopeResult{
Success: true,
7 years ago
IsCustom: false,
Query: strQuery,
7 years ago
})
}
/*
Tag messages
*/
type addTagMessage struct {
ReqId string
Tag string
7 years ago
Storage int
}
func addTagHandler(b []byte, c net.Conn, logger *log.Logger, iproxy *InterceptingProxy) {
mreq := addTagMessage{}
if err := json.Unmarshal(b, &mreq); err != nil {
ErrorResponse(c, fmt.Sprintf("error parsing message: %s", err.Error()))
return
}
if mreq.Storage == 0 {
ErrorResponse(c, "storage is required")
return
}
storage, _ := iproxy.GetMessageStorage(mreq.Storage)
if storage == nil {
ErrorResponse(c, fmt.Sprintf("storage with id %d does not exist", mreq.Storage))
return
}
if mreq.ReqId == "" || mreq.Tag == "" {
ErrorResponse(c, "both request id and tag are required")
return
}
7 years ago
req, err := storage.LoadRequest(mreq.ReqId)
if err != nil {
ErrorResponse(c, fmt.Sprintf("error loading request: %s", err.Error()))
return
}
req.AddTag(mreq.Tag)
err = UpdateRequest(storage, req)
if err != nil {
ErrorResponse(c, fmt.Sprintf("error saving request: %s", err.Error()))
return
}
MessageResponse(c, &successResult{Success: true})
7 years ago
}
type removeTagMessage struct {
ReqId string
Tag string
7 years ago
Storage int
}
func removeTagHandler(b []byte, c net.Conn, logger *log.Logger, iproxy *InterceptingProxy) {
mreq := removeTagMessage{}
if err := json.Unmarshal(b, &mreq); err != nil {
ErrorResponse(c, fmt.Sprintf("error parsing message: %s", err.Error()))
return
}
if mreq.Storage == 0 {
ErrorResponse(c, "storage is required")
return
}
storage, _ := iproxy.GetMessageStorage(mreq.Storage)
if storage == nil {
ErrorResponse(c, fmt.Sprintf("storage with id %d does not exist", mreq.Storage))
return
}
if mreq.ReqId == "" || mreq.Tag == "" {
ErrorResponse(c, "both request id and tag are required")
return
}
7 years ago
req, err := storage.LoadRequest(mreq.ReqId)
if err != nil {
ErrorResponse(c, fmt.Sprintf("error loading request: %s", err.Error()))
return
}
req.RemoveTag(mreq.Tag)
err = UpdateRequest(storage, req)
if err != nil {
ErrorResponse(c, fmt.Sprintf("error saving request: %s", err.Error()))
return
}
MessageResponse(c, &successResult{Success: true})
7 years ago
}
type clearTagsMessage struct {
ReqId string
7 years ago
Storage int
}
func clearTagHandler(b []byte, c net.Conn, logger *log.Logger, iproxy *InterceptingProxy) {
mreq := clearTagsMessage{}
if err := json.Unmarshal(b, &mreq); err != nil {
ErrorResponse(c, fmt.Sprintf("error parsing message: %s", err.Error()))
return
}
if mreq.Storage == 0 {
ErrorResponse(c, "storage is required")
return
}
storage, _ := iproxy.GetMessageStorage(mreq.Storage)
if storage == nil {
ErrorResponse(c, fmt.Sprintf("storage with id %d does not exist", mreq.Storage))
return
}
req, err := storage.LoadRequest(mreq.ReqId)
if err != nil {
ErrorResponse(c, fmt.Sprintf("error loading request: %s", err.Error()))
return
}
req.ClearTags()
err = UpdateRequest(storage, req)
if err != nil {
ErrorResponse(c, fmt.Sprintf("error saving request: %s", err.Error()))
return
}
MessageResponse(c, &successResult{Success: true})
7 years ago
}
/*
Intercept
*/
type interceptMessage struct {
InterceptRequests bool
7 years ago
InterceptResponses bool
InterceptWS bool
7 years ago
UseQuery bool
Query MessageQuery
7 years ago
}
type intHandshakeResult struct {
Success bool
}
// id func
var getNextIntId = IdCounter()
type intRequest struct {
// A request to have a message mangled
Id int
Type string
7 years ago
Success bool
Result chan *intResponse `json:"-"`
Request *RequestJSON `json:"Request,omitempty"`
Response *ResponseJSON `json:"Response,omitempty"`
7 years ago
WSMessage *WSMessageJSON `json:"WSMessage,omitempty"`
}
type intResponse struct {
// response from the client with a mangled http request
Id int
7 years ago
Dropped bool
Request *RequestJSON `json:"Request,omitempty"`
Response *ResponseJSON `json:"Response,omitempty"`
7 years ago
WSMessage *WSMessageJSON `json:"WSMessage,omitempty"`
}
type intErrorMessage struct {
// a message template for sending an error to client if there is an error
// with the mangled message they sent
Id int
7 years ago
Success bool
Reason string
7 years ago
}
func intErrorResponse(id int, conn net.Conn, reason string) {
m := &intErrorMessage{
Id: id,
7 years ago
Success: false,
Reason: reason,
7 years ago
}
MessageResponse(conn, m)
}
func interceptHandler(b []byte, c net.Conn, logger *log.Logger, iproxy *InterceptingProxy) {
mreq := interceptMessage{
InterceptRequests: false,
7 years ago
InterceptResponses: false,
InterceptWS: false,
UseQuery: false,
7 years ago
}
if err := json.Unmarshal(b, &mreq); err != nil {
ErrorResponse(c, fmt.Sprintf("error parsing message: %s", err.Error()))
return
}
if !mreq.InterceptRequests && !mreq.InterceptResponses && !mreq.InterceptWS {
ErrorResponse(c, "must intercept at least one message type")
return
}
pendingRequests := make(map[int]*intRequest)
var pendingRequestsMtx sync.Mutex
// helper functions for managing pending requests
getPendingRequest := func(id int) (*intRequest, error) {
pendingRequestsMtx.Lock()
defer pendingRequestsMtx.Unlock()
ret, ok := pendingRequests[id]
if !ok {
return nil, fmt.Errorf("pending request with id %d does not exist", id)
}
return ret, nil
}
addPendingRequest := func(pendingReq *intRequest) {
pendingRequestsMtx.Lock()
defer pendingRequestsMtx.Unlock()
pendingRequests[pendingReq.Id] = pendingReq
}
removePendingRequest := func(pendingReq *intRequest) {
pendingRequestsMtx.Lock()
defer pendingRequestsMtx.Unlock()
delete(pendingRequests, pendingReq.Id)
}
// parse the checker
var checker RequestChecker = nil
if mreq.UseQuery {
var err error
checker, err = CheckerFromMessageQuery(mreq.Query)
if err != nil {
ErrorResponse(c, fmt.Sprintf("error with message query: %s", err.Error()))
return
}
}
MessageResponse(c, &intHandshakeResult{Success: true})
// hook the request interceptor
var reqSub *ReqIntSub = nil
if mreq.InterceptRequests {
logger.Println("Adding request interceptor...")
// Create a function that sends requests to client and wait for the client to respond
reqIntFunc := func(req *ProxyRequest) (*ProxyRequest, error) {
// if it doesn't pass the query, return the request unmodified
if checker != nil && !checker(req) {
return req, nil
}
// JSON serialize the request
reqData := NewRequestJSON(req, false)
CleanReqJSON(reqData)
// convert request data to an intRequest
intReq := &intRequest{
Id: getNextIntId(),
Type: "httprequest",
Result: make(chan *intResponse),
7 years ago
Success: true,
Request: reqData,
}
// add bookkeeping for results, defer cleanup
addPendingRequest(intReq)
defer removePendingRequest(intReq)
// submit the request
MessageResponse(c, intReq)
// wait for result
intRsp, ok := <-intReq.Result
if !ok {
// if it closed, just pass the request along
return req, nil
}
if intRsp.Dropped {
// if it's dropped, return nil
return nil, nil
}
newReq := intRsp.Request
CleanReqJSON(newReq)
ret, err := newReq.Parse()
if err != nil {
return nil, err
}
return ret, nil
}
7 years ago
reqSub = iproxy.AddReqInterceptor(reqIntFunc)
7 years ago
}
var rspSub *RspIntSub = nil
if mreq.InterceptResponses {
logger.Println("Adding response interceptor...")
rspIntFunc := func(req *ProxyRequest, rsp *ProxyResponse) (*ProxyResponse, error) {
logger.Println("Intercepted response!")
// if it doesn't pass the query, return the request unmodified
if checker != nil && !checker(req) {
return rsp, nil
}
reqData := NewRequestJSON(req, false)
CleanReqJSON(reqData)
7 years ago
rspData := NewResponseJSON(rsp, false)
CleanRspJSON(rspData)
intReq := &intRequest{
Id: getNextIntId(),
Type: "httpresponse",
Result: make(chan *intResponse),
7 years ago
Success: true,
Request: reqData,
7 years ago
Response: rspData,
}
// add bookkeeping for results, defer cleanup
addPendingRequest(intReq)
defer removePendingRequest(intReq)
// submit the request
MessageResponse(c, intReq)
// wait for result
intRsp, ok := <-intReq.Result
if !ok {
// it closed, pass response along unmodified
return rsp, nil
}
if intRsp.Dropped {
// if it's dropped, return nil
return nil, nil
}
newRsp := intRsp.Response
CleanRspJSON(newRsp)
ret, err := newRsp.Parse()
if err != nil {
return nil, err
}
return ret, nil
}
7 years ago
rspSub = iproxy.AddRspInterceptor(rspIntFunc)
7 years ago
}
var wsSub *WSIntSub = nil
if mreq.InterceptWS {
logger.Println("Adding websocket interceptor...")
wsIntFunc := func(req *ProxyRequest, rsp *ProxyResponse, wsm *ProxyWSMessage) (*ProxyWSMessage, error) {
// if it doesn't pass the query, return the request unmodified
if checker != nil && !checker(req) {
return wsm, nil
}
wsData := NewWSMessageJSON(wsm)
var msgType string
if wsData.ToServer {
msgType = "wstoserver"
} else {
msgType = "wstoclient"
}
CleanWSJSON(wsData)
reqData := NewRequestJSON(req, false)
CleanReqJSON(reqData)
7 years ago
rspData := NewResponseJSON(rsp, false)
CleanRspJSON(rspData)
intReq := &intRequest{
Id: getNextIntId(),
Type: msgType,
Result: make(chan *intResponse),
7 years ago
Success: true,
Request: reqData,
Response: rspData,
7 years ago
WSMessage: wsData,
}
// add bookkeeping for results, defer cleanup
addPendingRequest(intReq)
defer removePendingRequest(intReq)
// submit the request
MessageResponse(c, intReq)
// wait for result
intRsp, ok := <-intReq.Result
if !ok {
// it closed, pass message along unmodified
return wsm, nil
}
if intRsp.Dropped {
// if it's dropped, return nil
return nil, nil
}
newWsm := intRsp.WSMessage
CleanWSJSON(newWsm)
ret, err := newWsm.Parse()
if err != nil {
return nil, err
}
return ret, nil
}
7 years ago
wsSub = iproxy.AddWSInterceptor(wsIntFunc)
7 years ago
}
closeAll := func() {
if reqSub != nil {
// close req sub
7 years ago
iproxy.RemoveReqInterceptor(reqSub)
7 years ago
}
if rspSub != nil {
// close rsp sub
7 years ago
iproxy.RemoveRspInterceptor(rspSub)
7 years ago
}
if wsSub != nil {
// close websocket sub
7 years ago
iproxy.RemoveWSInterceptor(wsSub)
7 years ago
}
// Close all pending requests
pendingRequestsMtx.Lock()
defer pendingRequestsMtx.Unlock()
for _, req := range pendingRequests {
close(req.Result)
}
}
defer closeAll()
// Read from the connection and process mangled requests
reader := bufio.NewReader(c)
for {
// read line from conn
logger.Println("Waiting on next message...")
m, err := ReadMessage(reader)
if err != nil {
if err != io.EOF {
logger.Println("Error reading message:", err.Error())
intErrorResponse(0, c, "error reading message")
continue
}
logger.Println("Connection closed")
return
}
// convert line to appropriate struct
var intRsp intResponse
if err := json.Unmarshal(m, &intRsp); err != nil {
intErrorResponse(0, c, fmt.Sprintf("error parsing message: %s", err.Error()))
continue
}
// get the pending request
pendingReq, err := getPendingRequest(intRsp.Id)
if err != nil {
intErrorResponse(intRsp.Id, c, err.Error())
continue
}
// Validate the data contained in the response
switch pendingReq.Type {
case "httprequest":
if intRsp.Request == nil {
intErrorResponse(intRsp.Id, c, "missing request")
continue
}
case "httpresponse":
if intRsp.Response == nil {
intErrorResponse(intRsp.Id, c, "missing response")
continue
}
case "wstoserver", "wstoclient":
if intRsp.WSMessage == nil {
intErrorResponse(intRsp.Id, c, "missing websocket message")
continue
}
intRsp.WSMessage.ToServer = (pendingReq.Type == "wstoserver")
default:
intErrorResponse(intRsp.Id, c, "internal error, stored message has invalid type")
continue
}
// pass along message
removePendingRequest(pendingReq)
pendingReq.Result <- &intRsp
}
}
/*
Query management
*/
type allSavedQueriesMessage struct {
Storage int
}
type allSavedQueriesResponse struct {
Success bool
Queries []*StrSavedQuery
}
type StrSavedQuery struct {
Name string
Query StrMessageQuery
}
func allSavedQueriesHandler(b []byte, c net.Conn, logger *log.Logger, iproxy *InterceptingProxy) {
mreq := allSavedQueriesMessage{}
if err := json.Unmarshal(b, &mreq); err != nil {
ErrorResponse(c, fmt.Sprintf("error parsing message: %s", err.Error()))
return
}
if mreq.Storage == 0 {
ErrorResponse(c, "storage is required")
return
}
storage, _ := iproxy.GetMessageStorage(mreq.Storage)
if storage == nil {
ErrorResponse(c, fmt.Sprintf("storage with id %d does not exist", mreq.Storage))
return
}
goQueries, err := storage.AllSavedQueries()
if err != nil {
ErrorResponse(c, err.Error())
return
}
savedQueries := make([]*StrSavedQuery, 0)
for _, q := range goQueries {
strSavedQuery := &StrSavedQuery{
Name: q.Name,
7 years ago
Query: nil,
}
7 years ago
sq, err := MsgQueryToStrQuery(q.Query)
7 years ago
if err == nil {
strSavedQuery.Query = sq
savedQueries = append(savedQueries, strSavedQuery)
}
}
MessageResponse(c, &allSavedQueriesResponse{
Success: true,
Queries: savedQueries,
})
}
type saveQueryMessage struct {
Name string
Query StrMessageQuery
7 years ago
Storage int
}
func saveQueryHandler(b []byte, c net.Conn, logger *log.Logger, iproxy *InterceptingProxy) {
mreq := saveQueryMessage{}
7 years ago
if err := json.Unmarshal(b, &mreq); err != nil {
ErrorResponse(c, "error parsing message")
return
}
if mreq.Storage == 0 {
ErrorResponse(c, "storage is required")
return
}
storage, _ := iproxy.GetMessageStorage(mreq.Storage)
if storage == nil {
ErrorResponse(c, fmt.Sprintf("storage with id %d does not exist", mreq.Storage))
return
}
if mreq.Name == "" || mreq.Query == nil {
ErrorResponse(c, "name and query are required")
return
}
7 years ago
goQuery, err := StrQueryToMsgQuery(mreq.Query)
7 years ago
if err != nil {
ErrorResponse(c, err.Error())
return
}
_, err = CheckerFromMessageQuery(goQuery)
if err != nil {
ErrorResponse(c, err.Error())
return
}
err = storage.SaveQuery(mreq.Name, goQuery)
if err != nil {
ErrorResponse(c, err.Error())
return
}
MessageResponse(c, &successResult{Success: true})
7 years ago
}
type loadQueryMessage struct {
Name string
7 years ago
Storage int
}
type loadQueryResult struct {
Success bool
Query StrMessageQuery
7 years ago
}
func loadQueryHandler(b []byte, c net.Conn, logger *log.Logger, iproxy *InterceptingProxy) {
mreq := loadQueryMessage{}
if err := json.Unmarshal(b, &mreq); err != nil {
ErrorResponse(c, "error parsing message")
return
}
if mreq.Name == "" {
ErrorResponse(c, "name is required")
return
}
if mreq.Storage == 0 {
ErrorResponse(c, "storage is required")
return
}
storage, _ := iproxy.GetMessageStorage(mreq.Storage)
if storage == nil {
ErrorResponse(c, fmt.Sprintf("storage with id %d does not exist", mreq.Storage))
return
}
query, err := storage.LoadQuery(mreq.Name)
if err != nil {
ErrorResponse(c, err.Error())
return
}
7 years ago
strQuery, err := MsgQueryToStrQuery(query)
7 years ago
if err != nil {
ErrorResponse(c, err.Error())
return
}
result := &loadQueryResult{
Success: true,
Query: strQuery,
7 years ago
}
MessageResponse(c, result)
}
type deleteQueryMessage struct {
Name string
7 years ago
Storage int
}
func deleteQueryHandler(b []byte, c net.Conn, logger *log.Logger, iproxy *InterceptingProxy) {
mreq := deleteQueryMessage{}
if err := json.Unmarshal(b, &mreq); err != nil {
ErrorResponse(c, "error parsing message")
return
}
if mreq.Storage == 0 {
ErrorResponse(c, "storage is required")
return
}
storage, _ := iproxy.GetMessageStorage(mreq.Storage)
if storage == nil {
ErrorResponse(c, fmt.Sprintf("storage with id %d does not exist", mreq.Storage))
return
}
err := storage.DeleteQuery(mreq.Name)
if err != nil {
ErrorResponse(c, err.Error())
return
}
MessageResponse(c, &successResult{Success: true})
7 years ago
}
/*
Listener management
*/
type activeListener struct {
Id int
7 years ago
Listener net.Listener `json:"-"`
Type string
Addr string
7 years ago
}
type addListenerMessage struct {
Type string
Addr string
7 years ago
TransparentMode bool
DestHost string
DestPort int
DestUseTLS bool
7 years ago
}
type addListenerResult struct {
Success bool
Id int
7 years ago
}
var getNextMsgListenerId = IdCounter()
// may want to move these into the iproxy to avoid globals since this assumes exactly one iproxy
var msgActiveListenersMtx sync.Mutex
var msgActiveListeners map[int]*activeListener = make(map[int]*activeListener)
func addListenerHandler(b []byte, c net.Conn, logger *log.Logger, iproxy *InterceptingProxy) {
mreq := addListenerMessage{}
if err := json.Unmarshal(b, &mreq); err != nil {
ErrorResponse(c, "error parsing message")
return
}
if mreq.Type == "" || mreq.Addr == "" {
ErrorResponse(c, "type and addr are required")
return
}
// why did I add support to listen on unix sockets? I have no idea but I'm gonna leave it
if !(mreq.Type == "tcp" ||
mreq.Type == "unix") {
ErrorResponse(c, "type must be \"tcp\" or \"unix\"")
return
}
listener, err := net.Listen(mreq.Type, mreq.Addr)
if err != nil {
ErrorResponse(c, err.Error())
return
}
7 years ago
if mreq.TransparentMode {
iproxy.AddTransparentListener(listener, mreq.DestHost,
mreq.DestPort, mreq.DestUseTLS)
} else {
iproxy.AddListener(listener)
}
7 years ago
alistener := &activeListener{
Id: getNextMsgListenerId(),
7 years ago
Listener: listener,
Type: mreq.Type,
Addr: mreq.Addr,
7 years ago
}
msgActiveListenersMtx.Lock()
defer msgActiveListenersMtx.Unlock()
msgActiveListeners[alistener.Id] = alistener
result := &addListenerResult{
Success: true,
Id: alistener.Id,
7 years ago
}
MessageResponse(c, result)
}
type removeListenerMessage struct {
Id int
}
func removeListenerHandler(b []byte, c net.Conn, logger *log.Logger, iproxy *InterceptingProxy) {
mreq := removeListenerMessage{}
if err := json.Unmarshal(b, &mreq); err != nil {
ErrorResponse(c, "error parsing message")
return
}
msgActiveListenersMtx.Lock()
defer msgActiveListenersMtx.Unlock()
alistener, ok := msgActiveListeners[mreq.Id]
if !ok {
ErrorResponse(c, "listener does not exist")
return
}
iproxy.RemoveListener(alistener.Listener)
delete(msgActiveListeners, alistener.Id)
MessageResponse(c, &successResult{Success: true})
7 years ago
}
type getListenersMessage struct{}
7 years ago
type getListenersResult struct {
Success bool
Results []*activeListener
}
func getListenersHandler(b []byte, c net.Conn, logger *log.Logger, iproxy *InterceptingProxy) {
result := &getListenersResult{
Success: true,
Results: make([]*activeListener, 0),
}
msgActiveListenersMtx.Lock()
defer msgActiveListenersMtx.Unlock()
for _, alistener := range msgActiveListeners {
result.Results = append(result.Results, alistener)
}
MessageResponse(c, result)
}
/*
Certificate Management
*/
type loadCertificatesMessage struct {
KeyFile string
7 years ago
CertificateFile string
}
func loadCertificatesHandler(b []byte, c net.Conn, logger *log.Logger, iproxy *InterceptingProxy) {
mreq := loadCertificatesMessage{}
if err := json.Unmarshal(b, &mreq); err != nil {
ErrorResponse(c, "error parsing message")
return
}
if mreq.KeyFile == "" || mreq.CertificateFile == "" {
ErrorResponse(c, "both KeyFile and CertificateFile are required")
return
}
7 years ago
err := iproxy.LoadCACertificates(mreq.CertificateFile, mreq.KeyFile)
7 years ago
if err != nil {
ErrorResponse(c, err.Error())
return
}
MessageResponse(c, &successResult{Success: true})
7 years ago
}
type setCertificatesMessage struct {
KeyPEMData []byte
7 years ago
CertificatePEMData []byte
}
func setCertificatesHandler(b []byte, c net.Conn, logger *log.Logger, iproxy *InterceptingProxy) {
mreq := setCertificatesMessage{}
if err := json.Unmarshal(b, &mreq); err != nil {
ErrorResponse(c, "error parsing message")
return
}
if len(mreq.KeyPEMData) == 0 || len(mreq.CertificatePEMData) == 0 {
ErrorResponse(c, "both KeyPEMData and CertificatePEMData are required")
return
}
caCert, err := tls.X509KeyPair(mreq.CertificatePEMData, mreq.KeyPEMData)
7 years ago
if err != nil {
ErrorResponse(c, err.Error())
return
}
iproxy.SetCACertificate(&caCert)
MessageResponse(c, &successResult{Success: true})
7 years ago
}
func clearCertificatesHandler(b []byte, c net.Conn, logger *log.Logger, iproxy *InterceptingProxy) {
iproxy.SetCACertificate(nil)
MessageResponse(c, &successResult{Success: true})
7 years ago
}
type generateCertificatesMessage struct {
KeyFile string
7 years ago
CertFile string
}
func generateCertificatesHandler(b []byte, c net.Conn, logger *log.Logger, iproxy *InterceptingProxy) {
mreq := generateCertificatesMessage{}
if err := json.Unmarshal(b, &mreq); err != nil {
ErrorResponse(c, "error parsing message")
return
}
_, err := GenerateCACertsToDisk(mreq.CertFile, mreq.KeyFile)
7 years ago
if err != nil {
ErrorResponse(c, err.Error())
return
}
MessageResponse(c, &successResult{Success: true})
7 years ago
}
type generatePEMCertificatesResult struct {
Success bool
KeyPEMData []byte
7 years ago
CertificatePEMData []byte
}
func generatePEMCertificatesHandler(b []byte, c net.Conn, logger *log.Logger, iproxy *InterceptingProxy) {
mreq := generateCertificatesMessage{}
if err := json.Unmarshal(b, &mreq); err != nil {
ErrorResponse(c, "error parsing message")
return
}
pair, err := GenerateCACerts()
if err != nil {
ErrorResponse(c, "error generating certificates: "+err.Error())
7 years ago
return
}
result := &generatePEMCertificatesResult{
Success: true,
KeyPEMData: pair.PrivateKeyPEM(),
7 years ago
CertificatePEMData: pair.CACertPEM(),
}
MessageResponse(c, result)
}
/*
Storage functions
*/
type addSQLiteStorageMessage struct {
Path string
7 years ago
Description string
}
type addSQLiteStorageResult struct {
Success bool
7 years ago
StorageId int
}
func addSQLiteStorageHandler(b []byte, c net.Conn, logger *log.Logger, iproxy *InterceptingProxy) {
mreq := addSQLiteStorageMessage{}
if err := json.Unmarshal(b, &mreq); err != nil {
ErrorResponse(c, "error parsing message")
return
}
if mreq.Path == "" {
ErrorResponse(c, "file path is required")
return
}
storage, err := OpenSQLiteStorage(mreq.Path, logger)
if err != nil {
ErrorResponse(c, "error opening SQLite databae: "+err.Error())
7 years ago
return
}
sid := iproxy.AddMessageStorage(storage, mreq.Description)
result := &addSQLiteStorageResult{
Success: true,
7 years ago
StorageId: sid,
}
MessageResponse(c, result)
}
type addInMemoryStorageMessage struct {
Description string
}
type addInMemoryStorageResult struct {
Success bool
7 years ago
StorageId int
}
func addInMemoryStorageHandler(b []byte, c net.Conn, logger *log.Logger, iproxy *InterceptingProxy) {
mreq := addInMemoryStorageMessage{}
if err := json.Unmarshal(b, &mreq); err != nil {
ErrorResponse(c, "error parsing message")
return
}
storage, err := InMemoryStorage(logger)
if err != nil {
ErrorResponse(c, "error creating in memory storage: "+err.Error())
7 years ago
return
}
sid := iproxy.AddMessageStorage(storage, mreq.Description)
result := &addInMemoryStorageResult{
Success: true,
7 years ago
StorageId: sid,
}
MessageResponse(c, result)
}
type closeStorageMessage struct {
StorageId int
}
type closeStorageResult struct {
Success bool
}
func closeStorageHandler(b []byte, c net.Conn, logger *log.Logger, iproxy *InterceptingProxy) {
mreq := closeStorageMessage{}
if err := json.Unmarshal(b, &mreq); err != nil {
ErrorResponse(c, "error parsing message")
return
}
if mreq.StorageId == 0 {
ErrorResponse(c, "StorageId is required")
return
}
iproxy.CloseMessageStorage(mreq.StorageId)
MessageResponse(c, &successResult{Success: true})
7 years ago
}
type setProxyStorageMessage struct {
StorageId int
}
func setProxyStorageHandler(b []byte, c net.Conn, logger *log.Logger, iproxy *InterceptingProxy) {
mreq := setProxyStorageMessage{}
if err := json.Unmarshal(b, &mreq); err != nil {
ErrorResponse(c, "error parsing message")
return
}
if mreq.StorageId == 0 {
ErrorResponse(c, "StorageId is required")
return
}
err := iproxy.SetProxyStorage(mreq.StorageId)
if err != nil {
ErrorResponse(c, err.Error())
return
}
MessageResponse(c, &successResult{Success: true})
7 years ago
}
type savedStorageJSON struct {
Id int
7 years ago
Description string
}
type listProxyStorageResult struct {
Storages []*savedStorageJSON
Success bool
7 years ago
}
func listProxyStorageHandler(b []byte, c net.Conn, logger *log.Logger, iproxy *InterceptingProxy) {
storages := iproxy.ListMessageStorage()
storagesJSON := make([]*savedStorageJSON, len(storages))
for i, ss := range storages {
storagesJSON[i] = &savedStorageJSON{ss.Id, ss.Description}
}
result := &listProxyStorageResult{
Storages: storagesJSON,
Success: true,
7 years ago
}
MessageResponse(c, result)
}
/*
SetProxy
*/
type setProxyMessage struct {
UseProxy bool
ProxyHost string
ProxyPort int
ProxyIsSOCKS bool
UseCredentials bool
Username string
Password string
}
func setProxyHandler(b []byte, c net.Conn, logger *log.Logger, iproxy *InterceptingProxy) {
mreq := setProxyMessage{}
if err := json.Unmarshal(b, &mreq); err != nil {
ErrorResponse(c, "error parsing message")
return
}
var creds *ProxyCredentials = nil
if mreq.UseCredentials {
creds = &ProxyCredentials{
Username: mreq.Username,
Password: mreq.Password,
}
}
if !mreq.UseProxy {
iproxy.ClearUpstreamProxy()
} else {
if mreq.ProxyIsSOCKS {
iproxy.SetUpstreamSOCKSProxy(mreq.ProxyHost, mreq.ProxyPort, creds)
} else {
iproxy.SetUpstreamProxy(mreq.ProxyHost, mreq.ProxyPort, creds)
}
}
MessageResponse(c, &successResult{Success: true})
}
6 years ago
/*
WatchStorage
*/
type watchStorageMessage struct {
HeadersOnly bool
}
type proxyMsgStorageWatcher struct {
connMtx sync.Mutex
headersOnly bool
conn net.Conn
}
type storageUpdateResponse struct {
StorageId int
Action string
MessageId string
Request *RequestJSON
Response *ResponseJSON
WSMessage *WSMessageJSON
}
// Implement watcher
6 years ago
func (sw *proxyMsgStorageWatcher) NewRequestSaved(storageId int, ms MessageStorage, req *ProxyRequest) {
sw.connMtx.Lock()
defer sw.connMtx.Unlock()
msgRsp := &storageUpdateResponse{}
6 years ago
msgRsp.Request = NewRequestJSON(req, sw.headersOnly)
msgRsp.Action = "NewRequest"
6 years ago
msgRsp.StorageId = storageId
6 years ago
MessageResponse(sw.conn, msgRsp)
}
6 years ago
func (sw *proxyMsgStorageWatcher) RequestUpdated(storageId int, ms MessageStorage, req *ProxyRequest) {
sw.connMtx.Lock()
defer sw.connMtx.Unlock()
msgRsp := &storageUpdateResponse{}
6 years ago
msgRsp.Request = NewRequestJSON(req, sw.headersOnly)
msgRsp.Action = "RequestUpdated"
6 years ago
msgRsp.StorageId = storageId
6 years ago
MessageResponse(sw.conn, msgRsp)
}
6 years ago
func (sw *proxyMsgStorageWatcher) RequestDeleted(storageId int, ms MessageStorage, DbId string) {
sw.connMtx.Lock()
defer sw.connMtx.Unlock()
msgRsp := &storageUpdateResponse{}
6 years ago
msgRsp.Action = "RequestDeleted"
msgRsp.MessageId = DbId
6 years ago
msgRsp.StorageId = storageId
6 years ago
MessageResponse(sw.conn, msgRsp)
}
6 years ago
func (sw *proxyMsgStorageWatcher) NewResponseSaved(storageId int, ms MessageStorage, rsp *ProxyResponse) {
sw.connMtx.Lock()
defer sw.connMtx.Unlock()
msgRsp := &storageUpdateResponse{}
6 years ago
msgRsp.Response = NewResponseJSON(rsp, sw.headersOnly)
msgRsp.Action = "NewResponse"
6 years ago
msgRsp.StorageId = storageId
6 years ago
MessageResponse(sw.conn, msgRsp)
}
6 years ago
func (sw *proxyMsgStorageWatcher) ResponseUpdated(storageId int, ms MessageStorage, rsp *ProxyResponse) {
sw.connMtx.Lock()
defer sw.connMtx.Unlock()
msgRsp := &storageUpdateResponse{}
6 years ago
msgRsp.Response = NewResponseJSON(rsp, sw.headersOnly)
msgRsp.Action = "ResponseUpdated"
6 years ago
msgRsp.StorageId = storageId
6 years ago
MessageResponse(sw.conn, msgRsp)
}
6 years ago
func (sw *proxyMsgStorageWatcher) ResponseDeleted(storageId int, ms MessageStorage, DbId string) {
sw.connMtx.Lock()
defer sw.connMtx.Unlock()
msgRsp := &storageUpdateResponse{}
6 years ago
msgRsp.Action = "ResponseDeleted"
msgRsp.MessageId = DbId
6 years ago
msgRsp.StorageId = storageId
6 years ago
MessageResponse(sw.conn, msgRsp)
}
6 years ago
func (sw *proxyMsgStorageWatcher) NewWSMessageSaved(storageId int, ms MessageStorage, req *ProxyRequest, wsm *ProxyWSMessage) {
sw.connMtx.Lock()
defer sw.connMtx.Unlock()
msgRsp := &storageUpdateResponse{}
6 years ago
msgRsp.Request = NewRequestJSON(req, sw.headersOnly)
msgRsp.WSMessage = NewWSMessageJSON(wsm)
msgRsp.Action = "NewWSMessage"
6 years ago
msgRsp.StorageId = storageId
6 years ago
MessageResponse(sw.conn, msgRsp)
}
6 years ago
func (sw *proxyMsgStorageWatcher) WSMessageUpdated(storageId int, ms MessageStorage, req *ProxyRequest, wsm *ProxyWSMessage) {
sw.connMtx.Lock()
defer sw.connMtx.Unlock()
msgRsp := &storageUpdateResponse{}
6 years ago
msgRsp.Request = NewRequestJSON(req, sw.headersOnly)
msgRsp.WSMessage = NewWSMessageJSON(wsm)
msgRsp.Action = "WSMessageUpdated"
6 years ago
msgRsp.StorageId = storageId
6 years ago
MessageResponse(sw.conn, msgRsp)
}
6 years ago
func (sw *proxyMsgStorageWatcher) WSMessageDeleted(storageId int, ms MessageStorage, DbId string) {
sw.connMtx.Lock()
defer sw.connMtx.Unlock()
6 years ago
var msgRsp storageUpdateResponse
msgRsp.Action = "WSMessageDeleted"
msgRsp.MessageId = DbId
6 years ago
msgRsp.StorageId = storageId
6 years ago
MessageResponse(sw.conn, msgRsp)
}
// Actual handler
func watchStorageHandler(b []byte, c net.Conn, logger *log.Logger, iproxy *InterceptingProxy) {
mreq := watchStorageMessage{}
if err := json.Unmarshal(b, &mreq); err != nil {
ErrorResponse(c, "error parsing message")
return
}
6 years ago
// add global watcher
watcher := &proxyMsgStorageWatcher{
headersOnly: mreq.HeadersOnly,
conn: c,
6 years ago
}
6 years ago
iproxy.GlobalStorageWatch(watcher)
defer iproxy.GlobalStorageEndWatch(watcher)
6 years ago
// Keep the connection open
MessageResponse(c, &successResult{Success: true})
6 years ago
tmpbuf := make([]byte, 1)
6 years ago
var err error = nil
for err == nil {
_, err = c.Read(tmpbuf)
}
}
6 years ago
/*
SetPluginValue and GetPluginValue
*/
type setPluginValueMessage struct {
Key string
Value string
Storage int
}
func setPluginValueHandler(b []byte, c net.Conn, logger *log.Logger, iproxy *InterceptingProxy) {
mreq := setPluginValueMessage{}
if err := json.Unmarshal(b, &mreq); err != nil {
ErrorResponse(c, "error parsing message")
return
}
if mreq.Storage == 0 {
ErrorResponse(c, "storage is required")
return
}
storage, _ := iproxy.GetMessageStorage(mreq.Storage)
if storage == nil {
ErrorResponse(c, fmt.Sprintf("storage with id %d does not exist", mreq.Storage))
return
}
if mreq.Key == "" {
ErrorResponse(c, "key value is required")
return
}
err := storage.SetPluginValue(mreq.Key, mreq.Value)
if err != nil {
ErrorResponse(c, fmt.Sprintf("error saving value: %s", err.Error()))
return
}
MessageResponse(c, &successResult{Success: true})
}
type getPluginValueMessage struct {
Key string
Storage int
}
type getPluginValueResponse struct {
Value string
Success bool
}
func getPluginValueHandler(b []byte, c net.Conn, logger *log.Logger, iproxy *InterceptingProxy) {
mreq := getPluginValueMessage{}
if err := json.Unmarshal(b, &mreq); err != nil {
ErrorResponse(c, "error parsing message")
return
}
if mreq.Storage == 0 {
ErrorResponse(c, "storage is required")
return
}
storage, _ := iproxy.GetMessageStorage(mreq.Storage)
if storage == nil {
ErrorResponse(c, fmt.Sprintf("storage with id %d does not exist", mreq.Storage))
return
}
if mreq.Key == "" {
ErrorResponse(c, "key value is required")
return
}
value, err := storage.GetPluginValue(mreq.Key)
if err != nil {
ErrorResponse(c, fmt.Sprintf("error getting value: %s", err.Error()))
return
}
MessageResponse(c, &getPluginValueResponse{Value: value, Success: true})
}