From caaea3b8af43dead41771d83aa6f78217b735970 Mon Sep 17 00:00:00 2001 From: Russel Van Tuyl Date: Thu, 14 Dec 2023 08:44:32 -0500 Subject: [PATCH] Fixes #148 --- .github/workflows/go_dev.yml | 2 +- .github/workflows/go_main.yml | 2 +- docs/CHANGELOG.MD | 6 ++++++ pkg/merlin.go | 2 +- pkg/services/rpc/rpc.go | 28 +++++++++++++++++++++------- 5 files changed, 30 insertions(+), 10 deletions(-) diff --git a/.github/workflows/go_dev.yml b/.github/workflows/go_dev.yml index 2c4e7da4..031d5818 100644 --- a/.github/workflows/go_dev.yml +++ b/.github/workflows/go_dev.yml @@ -1,7 +1,7 @@ # This workflow will build a golang project # For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-go -name: "Merlin Server - Scan, Build, & Test: Development Work" +name: "Scan, Build, & Test: Development Work" on: push: diff --git a/.github/workflows/go_main.yml b/.github/workflows/go_main.yml index 47203b53..a9ece5a2 100644 --- a/.github/workflows/go_main.yml +++ b/.github/workflows/go_main.yml @@ -1,7 +1,7 @@ # This workflow will build a golang project # For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-go -name: "Merlin Server - Scan, Build, & Test: Main" +name: "Scan, Build, & Test: Main" on: push: diff --git a/docs/CHANGELOG.MD b/docs/CHANGELOG.MD index 5381e104..9624f397 100644 --- a/docs/CHANGELOG.MD +++ b/docs/CHANGELOG.MD @@ -4,6 +4,12 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html). +## 2.1.0 - 2023-12-14 + +### Fixed + +- [Issue 148](https://github.com/Ne0nd0g/merlin/issues/148) - Validate & encode gRPC messages to UTF-8 + ## 2.0.0 - 2023-11-05 ### Added diff --git a/pkg/merlin.go b/pkg/merlin.go index af6b97ae..01353254 100644 --- a/pkg/merlin.go +++ b/pkg/merlin.go @@ -21,7 +21,7 @@ along with Merlin. If not, see . package merlin // Version is a constant variable containing the version number for the Merlin package -const Version = "2.0.0" +const Version = "2.1.0" // Build is a hash off the git commit and is stamped it at compile time var Build = "nonRelease" diff --git a/pkg/services/rpc/rpc.go b/pkg/services/rpc/rpc.go index 16dd000b..1d10beef 100644 --- a/pkg/services/rpc/rpc.go +++ b/pkg/services/rpc/rpc.go @@ -37,6 +37,7 @@ import ( "os" "strings" "time" + "unicode/utf8" // 3rd Party "github.com/google/uuid" @@ -367,7 +368,7 @@ func (s *Service) SendClientMessage(msg *message.Message) { func NewPBErrorMessage(err error) *pb.Message { return &pb.Message{ Level: pb.MessageLevel_WARN, - Message: err.Error(), + Message: validUTF8(err.Error()), Timestamp: time.Now().UTC().Format(time.RFC3339), Error: true, } @@ -377,7 +378,7 @@ func NewPBErrorMessage(err error) *pb.Message { func NewPBSuccessMessage(msg string) *pb.Message { return &pb.Message{ Level: pb.MessageLevel_SUCCESS, - Message: msg, + Message: validUTF8(msg), Timestamp: time.Now().UTC().Format(time.RFC3339), } } @@ -386,7 +387,7 @@ func NewPBSuccessMessage(msg string) *pb.Message { func NewPBNoteMessage(msg string) *pb.Message { return &pb.Message{ Level: pb.MessageLevel_NOTE, - Message: msg, + Message: validUTF8(msg), Timestamp: time.Now().UTC().Format(time.RFC3339), } } @@ -395,7 +396,7 @@ func NewPBNoteMessage(msg string) *pb.Message { func NewPBInfoMessage(msg string) *pb.Message { return &pb.Message{ Level: pb.MessageLevel_INFO, - Message: msg, + Message: validUTF8(msg), Timestamp: time.Now().UTC().Format(time.RFC3339), } } @@ -404,7 +405,7 @@ func NewPBInfoMessage(msg string) *pb.Message { func NewPBPlainMessage(msg string) *pb.Message { return &pb.Message{ Level: pb.MessageLevel_PLAIN, - Message: msg, + Message: validUTF8(msg), Timestamp: time.Now().UTC().Format(time.RFC3339), } } @@ -413,7 +414,7 @@ func NewPBPlainMessage(msg string) *pb.Message { func NewPBWarnMessage(msg string) *pb.Message { return &pb.Message{ Level: pb.MessageLevel_WARN, - Message: msg, + Message: validUTF8(msg), Timestamp: time.Now().UTC().Format(time.RFC3339), } } @@ -439,12 +440,25 @@ func NewPBMessageFromMessage(msg *message.Message) *pb.Message { } return &pb.Message{ Level: level, - Message: msg.Message(), + Message: validUTF8(msg.Message()), Timestamp: msg.Time().UTC().Format(time.RFC3339), Error: msg.Error(), } } +// validUTF8 ensures the string contains valid UTF-8 and replaces invalid characters with the '�' character +// gRPC messages must be valid UTF-8 +func validUTF8(s string) string { + // Ensure the message is a valid UTF-8 string + if utf8.ValidString(s) { + return s + } + return fmt.Sprintf( + "\n*** The message contained invalid UTF-8 that was replaced with the '�' character ***\n\n%s", + strings.ToValidUTF8(s, "�"), + ) +} + // getTLSConfig creates a new TLS configuration for the RPC service func getTLSConfig(secure bool, tlsKey, tlsCert, tlsCA string) (*tls.Config, error) { slog.Debug("entering into function", "secure", secure, "tlsKey", tlsKey, "tlsCert", tlsCert)