Skip to content

Commit

Permalink
Add templating option for RDP files
Browse files Browse the repository at this point in the history
  • Loading branch information
bolkedebruin committed May 15, 2023
1 parent 769abae commit cdc497f
Show file tree
Hide file tree
Showing 10 changed files with 425 additions and 267 deletions.
11 changes: 5 additions & 6 deletions cmd/rdpgw/config/configuration.go
Original file line number Diff line number Diff line change
Expand Up @@ -89,12 +89,11 @@ type SecurityConfig struct {
}

type ClientConfig struct {
NetworkAutoDetect int `koanf:"networkautodetect"`
BandwidthAutoDetect int `koanf:"bandwidthautodetect"`
ConnectionType int `koanf:"connectiontype"`
UsernameTemplate string `koanf:"usernametemplate"`
SplitUserDomain bool `koanf:"splituserdomain"`
DefaultDomain string `koanf:"defaultdomain"`
Defaults string `koanf:"defaults"`
// kept for backwards compatibility
UsernameTemplate string `koanf:"usernametemplate"`
SplitUserDomain bool `koanf:"splituserdomain"`
DefaultDomain string `koanf:"defaultdomain"`
}

func ToCamel(s string) string {
Expand Down
83 changes: 83 additions & 0 deletions cmd/rdpgw/config/parsers/rdp.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
package parsers

import (
"bufio"
"bytes"
"fmt"
"sort"
"strconv"
"strings"
)

type RDP struct{}

func Parser() *RDP {
return &RDP{}
}

func (p *RDP) Unmarshal(b []byte) (map[string]interface{}, error) {
r := bytes.NewReader(b)
scanner := bufio.NewScanner(r)
mp := make(map[string]interface{})

c := 0
for scanner.Scan() {
c++
line := strings.TrimSpace(scanner.Text())
if line == "" || strings.HasPrefix(line, "#") {
continue
}
fields := strings.SplitN(line, ":", 3)
if len(fields) != 3 {
return nil, fmt.Errorf("malformed line %d: %q", c, line)
}

key := strings.TrimSpace(fields[0])
t := strings.TrimSpace(fields[1])
val := strings.TrimSpace(fields[2])

switch t {
case "i":
intValue, err := strconv.Atoi(val)
if err != nil {
return nil, fmt.Errorf("cannot parse integer at line %d: %s", c, line)
}
mp[key] = intValue
case "s":
mp[key] = val
default:
return nil, fmt.Errorf("malformed line %d: %s", c, line)
}
}
return mp, nil
}

func (p *RDP) Marshal(o map[string]interface{}) ([]byte, error) {
var b bytes.Buffer

keys := make([]string, 0, len(o))
for k := range o {
keys = append(keys, k)
}
sort.Strings(keys)

for _, key := range keys {
v := o[key]
switch v.(type) {
case bool:
if v == true {
fmt.Fprintf(&b, "%s:i:1", key)
} else {
fmt.Fprintf(&b, "%s:i:0", key)
}
case int:
fmt.Fprintf(&b, "%s:i:%d", key, v)
case string:
fmt.Fprintf(&b, "%s:s:%s", key, v)
default:
return nil, fmt.Errorf("error marshalling")
}
fmt.Fprint(&b, "\r\n")
}
return b.Bytes(), nil
}
85 changes: 85 additions & 0 deletions cmd/rdpgw/config/parsers/rdp_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
package parsers

import (
"github.com/stretchr/testify/assert"
"testing"
)

func TestUnmarshalRDPFile(t *testing.T) {
rdp := Parser()

testCases := []struct {
name string
cfg []byte
expOutput map[string]interface{}
err error
}{
{
name: "empty",
expOutput: map[string]interface{}{},
},
{
name: "string",
cfg: []byte(`username:s:user1`),
expOutput: map[string]interface{}{
"username": "user1",
},
},
{
name: "integer",
cfg: []byte(`session bpp:i:32`),
expOutput: map[string]interface{}{
"session bpp": 32,
},
},
{
name: "multi",
cfg: []byte("compression:i:1\r\nusername:s:user2\r\n"),
expOutput: map[string]interface{}{
"compression": 1,
"username": "user2",
},
},
}

for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
outMap, err := rdp.Unmarshal(tc.cfg)
assert.Equal(t, tc.err, err)
assert.Equal(t, tc.expOutput, outMap)
})
}
}

func TestRDP_Marshal(t *testing.T) {
testCases := []struct {
name string
input map[string]interface{}
output []byte
err error
}{
{
name: "Empty RDP",
input: map[string]interface{}{},
output: []byte(nil),
},
{
name: "Valid RDP all types",
input: map[string]interface{}{
"compression": 1,
"session bpp": 32,
"username": "user1",
},
output: []byte("compression:i:1\r\nsession bpp:i:32\r\nusername:s:user1\r\n"),
},
}

rdp := Parser()
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
out, err := rdp.Marshal(tc.input)
assert.Equal(t, tc.output, out)
assert.Equal(t, tc.err, err)
})
}
}
10 changes: 4 additions & 6 deletions cmd/rdpgw/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -108,14 +108,12 @@ func main() {
Hosts: conf.Server.Hosts,
HostSelection: conf.Server.HostSelection,
RdpOpts: web.RdpOpts{
UsernameTemplate: conf.Client.UsernameTemplate,
SplitUserDomain: conf.Client.SplitUserDomain,
DefaultDomain: conf.Client.DefaultDomain,
NetworkAutoDetect: conf.Client.NetworkAutoDetect,
BandwidthAutoDetect: conf.Client.BandwidthAutoDetect,
ConnectionType: conf.Client.ConnectionType,
UsernameTemplate: conf.Client.UsernameTemplate,
SplitUserDomain: conf.Client.SplitUserDomain,
DefaultDomain: conf.Client.DefaultDomain,
},
GatewayAddress: url,
TemplateFile: conf.Client.Defaults,
}

if conf.Caps.TokenAuth {
Expand Down
Loading

0 comments on commit cdc497f

Please sign in to comment.