summaryrefslogtreecommitdiff
path: root/helper/args.go
blob: 7a67269601f47f02a2c38368ae38fc3b8f2ff44d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
package main

import (
	"log"
	"net"
	"os"
	"regexp"
	"strconv"
)

const (
	// TODO: this is the nameserver for tcp, but for udp is 10.42.0.1
	//       the nameserver pick up should be dependent on the proto being used
	nameserver = "10.41.0.1"
)

var (
	fixedArgs = []string{
		"--nobind",
		"--client",
		"--dev", "tun",
		"--tls-client",
		"--remote-cert-tls", "server",
		"--dhcp-option", "DNS", nameserver,
		"--log", logFolder + "openvpn.log",
	}

	allowendArgs = map[string][]string{
		"--remote":            []string{"IP", "NUMBER", "PROTO"},
		"--tls-cipher":        []string{"CIPHER"},
		"--cipher":            []string{"CIPHER"},
		"--auth":              []string{"CIPHER"},
		"--management-client": []string{},
		"--management":        []string{"IP", "NUMBER"},
		"--cert":              []string{"FILE"},
		"--key":               []string{"FILE"},
		"--ca":                []string{"FILE"},
		"--fragment":          []string{"NUMBER"},
		"--keepalive":         []string{"NUMBER", "NUMBER"},
		"--verb":              []string{"NUMBER"},
		"--tun-ipv6":          []string{},
	}

	cipher  = regexp.MustCompile("^[A-Z0-9-]+$")
	formats = map[string]func(s string) bool{
		"NUMBER": isNumber,
		"PROTO":  isProto,
		"IP":     isIP,
		"CIPHER": cipher.MatchString,
		"FILE":   isFile,
	}
)

func parseOpenvpnArgs(args []string) []string {
	newArgs := fixedArgs
	newArgs = append(newArgs, platformOpenvpnFlags...)
	for i := 0; i < len(args); i++ {
		params, ok := allowendArgs[args[i]]
		if !ok {
			log.Printf("Invalid openvpn arg: %s", args[i])
			continue
		}
		for j, arg := range args[i+1 : i+len(params)+1] {
			if !formats[params[j]](arg) {
				ok = false
				break
			}
		}
		if ok {
			newArgs = append(newArgs, args[i:i+len(params)+1]...)
			i = i + len(params)
		} else {
			log.Printf("Invalid openvpn arg params: %v", args[i:i+len(params)+1])
		}
	}
	return newArgs
}

func isNumber(s string) bool {
	_, err := strconv.Atoi(s)
	return err == nil
}

func isProto(s string) bool {
	for _, proto := range []string{"tcp", "udp", "tcp4", "udp4", "tcp6", "udp6"} {
		if s == proto {
			return true
		}
	}
	return false
}

func isIP(s string) bool {
	return net.ParseIP(s) != nil
}

func isFile(s string) bool {
	info, err := os.Stat(s)
	if err != nil {
		return false
	}
	return !info.IsDir()
}