Skip to content

Commit

Permalink
Add a String() method to channel/request payloads to generate logs
Browse files Browse the repository at this point in the history
This eliminates the need of the hacky conversion to maps and makes it
easier to implement JSON logging in the future.
  • Loading branch information
Kristóf Jakab committed Nov 15, 2016
1 parent daf0c3f commit 9af3800
Show file tree
Hide file tree
Showing 2 changed files with 95 additions and 30 deletions.
31 changes: 21 additions & 10 deletions channel/channel.go
@@ -1,31 +1,41 @@
package channel

import (
"fmt"
log "github.com/Sirupsen/logrus"
"github.com/fatih/structs"
"github.com/jaksi/sshesame/request"
"golang.org/x/crypto/ssh"
"golang.org/x/crypto/ssh/terminal"
"io"
"net"
"strconv"
)

// RFC 4254
type x11 struct {
SourceAddress string
SourcePort uint32
}

func (payload x11) String() string {
return net.JoinHostPort(payload.SourceAddress, strconv.Itoa(int(payload.SourcePort)))
}

type tcpip struct {
DestinationAddress string
DestinationPort uint32
SourceAddress string
SourcePort uint32
}

func (payload tcpip) String() string {
return fmt.Sprintf("%v -> %v",
net.JoinHostPort(payload.SourceAddress, strconv.Itoa(int(payload.SourcePort))),
net.JoinHostPort(payload.DestinationAddress, strconv.Itoa(int(payload.DestinationPort))))
}

func Handle(remoteAddr net.Addr, newChannel ssh.NewChannel) {
payload := map[string]interface{}{
"data": newChannel.ExtraData(),
}
var payload interface{} = newChannel.ExtraData()
switch newChannel.ChannelType() {
case "x11":
parsedPayload := x11{}
Expand All @@ -34,7 +44,7 @@ func Handle(remoteAddr net.Addr, newChannel ssh.NewChannel) {
log.Warning("Failed to parse payload:", err.Error())
break
}
payload = structs.Map(parsedPayload)
payload = parsedPayload
case "forwarded-tcpip":
// Server initiated forwarding
fallthrough
Expand All @@ -46,12 +56,13 @@ func Handle(remoteAddr net.Addr, newChannel ssh.NewChannel) {
log.Warning("Failed to parse payload:", err.Error())
break
}
payload = structs.Map(parsedPayload)
payload = parsedPayload
}
logData := payload
logData["client"] = remoteAddr
logData["channel"] = newChannel.ChannelType()
log.WithFields(logData).Info("Channel requested")
log.WithFields(log.Fields{
"client": remoteAddr,
"channel": newChannel.ChannelType(),
"payload": payload,
}).Info("Channel requested")
channel, channelRequests, err := newChannel.Accept()
if err != nil {
log.Warning("Failed to accept channel:", err.Error())
Expand Down
94 changes: 74 additions & 20 deletions request/request.go
@@ -1,58 +1,113 @@
package request

import (
"fmt"
log "github.com/Sirupsen/logrus"
"github.com/fatih/structs"
"golang.org/x/crypto/ssh"
"net"
"strconv"
)

// RFC 4254
type tcpipForward struct {
BindAddress string
BindPort uint32
}

func (payload tcpipForward) String() string {
return net.JoinHostPort(payload.BindAddress, strconv.Itoa(int(payload.BindPort)))
}

type pty struct {
Term string
Width, Height uint32
PixelWidth, PixelHeight uint32
Modes []byte
}

func (payload pty) String() string {
return fmt.Sprintf("%v, %vx%v (%vx%v pixels)", payload.Term, payload.Width, payload.Height, payload.PixelWidth, payload.PixelHeight)
}

type x11 struct {
SingleConnection bool
AuthenticationProtocol string
AuthenticationCookie string
Screen uint32
}

func (payload x11) String() string {
return fmt.Sprintf("Single connection: %v, protocol: %v, cookie: %v, screen: %v", payload.SingleConnection, payload.AuthenticationProtocol, payload.AuthenticationCookie, payload.Screen)
}

type env struct {
Name, Value string
}

func (payload env) String() string {
return fmt.Sprintf("%v=%v", payload.Name, payload.Value)
}

type exec struct {
Command string
}

func (payload exec) String() string {
return payload.Command
}

type subsystem struct {
Name string
}

func (payload subsystem) String() string {
return payload.Name
}

type windowChange struct {
Width, Height uint32
PixelWidth, PixelHeight uint32
}

func (payload windowChange) String() string {
return fmt.Sprintf("%vx%v (%vx%v pixels)", payload.Width, payload.Height, payload.PixelWidth, payload.PixelHeight)
}

type flowControl struct {
CanDo bool
}

func (payload flowControl) String() string {
return strconv.FormatBool(payload.CanDo)
}

type signal struct {
Name string
}

func (payload signal) String() string {
return payload.Name
}

type exitStatus struct {
Status uint32
}

func (payload exitStatus) String() string {
return strconv.Itoa(int(payload.Status))
}

type exitSignal struct {
Name string
CoreDumped bool
ErrorMessage string
Language string
}

func (payload exitSignal) String() string {
return fmt.Sprintf("%v, core dumped: %v, error message: %v, language: %v", payload.Name, payload.CoreDumped, payload.ErrorMessage, payload.Language)
}

func SendExitStatus(channel ssh.Channel) {
_, err := channel.SendRequest("exit-status", false, ssh.Marshal(exitStatus{0}))
if err != nil {
Expand All @@ -62,9 +117,7 @@ func SendExitStatus(channel ssh.Channel) {

func Handle(remoteAddr net.Addr, channel string, requests <-chan *ssh.Request) {
for request := range requests {
payload := map[string]interface{}{
"data": request.Payload,
}
var payload interface{} = request.Payload
switch request.Type {
case "tcpip-forward":
fallthrough
Expand All @@ -75,93 +128,94 @@ func Handle(remoteAddr net.Addr, channel string, requests <-chan *ssh.Request) {
log.Warning("Failed to parse payload:", err.Error())
break
}
payload = structs.Map(parsedPayload)
payload = parsedPayload
case "pty-req":
parsedPayload := pty{}
err := ssh.Unmarshal(request.Payload, &parsedPayload)
if err != nil {
log.Warning("Failed to parse payload:", err.Error())
break
}
payload = structs.Map(parsedPayload)
payload = parsedPayload
case "x11-req":
parsedPayload := x11{}
err := ssh.Unmarshal(request.Payload, &parsedPayload)
if err != nil {
log.Warning("Failed to parse payload:", err.Error())
break
}
payload = structs.Map(parsedPayload)
payload = parsedPayload
case "env":
parsedPayload := env{}
err := ssh.Unmarshal(request.Payload, &parsedPayload)
if err != nil {
log.Warning("Failed to parse payload:", err.Error())
break
}
payload = structs.Map(parsedPayload)
payload = parsedPayload
case "exec":
parsedPayload := exec{}
err := ssh.Unmarshal(request.Payload, &parsedPayload)
if err != nil {
log.Warning("Failed to parse payload:", err.Error())
break
}
payload = structs.Map(parsedPayload)
payload = parsedPayload
case "subsystem":
parsedPayload := subsystem{}
err := ssh.Unmarshal(request.Payload, &parsedPayload)
if err != nil {
log.Warning("Failed to parse payload:", err.Error())
break
}
payload = structs.Map(parsedPayload)
payload = parsedPayload
case "window-change":
parsedPayload := windowChange{}
err := ssh.Unmarshal(request.Payload, &parsedPayload)
if err != nil {
log.Warning("Failed to parse payload:", err.Error())
break
}
payload = structs.Map(parsedPayload)
payload = parsedPayload
case "xon-xoff":
parsedPayload := flowControl{}
err := ssh.Unmarshal(request.Payload, &parsedPayload)
if err != nil {
log.Warning("Failed to parse payload:", err.Error())
break
}
payload = structs.Map(parsedPayload)
payload = parsedPayload
case "signal":
parsedPayload := signal{}
err := ssh.Unmarshal(request.Payload, &parsedPayload)
if err != nil {
log.Warning("Failed to parse payload:", err.Error())
break
}
payload = structs.Map(parsedPayload)
payload = parsedPayload
case "exit-status":
parsedPayload := exitStatus{}
err := ssh.Unmarshal(request.Payload, &parsedPayload)
if err != nil {
log.Warning("Failed to parse payload:", err.Error())
break
}
payload = structs.Map(parsedPayload)
payload = parsedPayload
case "exit-signal":
parsedPayload := exitSignal{}
err := ssh.Unmarshal(request.Payload, &parsedPayload)
if err != nil {
log.Warning("Failed to parse payload:", err.Error())
break
}
payload = structs.Map(parsedPayload)
payload = parsedPayload
}
logData := payload
logData["client"] = remoteAddr
logData["channel"] = channel
logData["request"] = request.Type
log.WithFields(logData).Info("Request received")
log.WithFields(log.Fields{
"client": remoteAddr,
"channel": channel,
"request": request.Type,
"payload": payload,
}).Info("Request received")
if request.WantReply {
err := request.Reply(true, nil)
if err != nil {
Expand Down

0 comments on commit 9af3800

Please sign in to comment.