aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Crawshaw <crawshaw@tailscale.com>2020-05-02 14:55:34 +1000
committerDavid Crawshaw <crawshaw@tailscale.com>2020-05-02 14:55:35 +1000
commiteb897a7dd8427b87553a2e634b305ff6a40a995c (patch)
tree55f70b085a13a2997c75c453c07ecd32af22d568
parent3636c2ec1261545768095a1e2b98e250d8ae0751 (diff)
downloadwireguard-go-eb897a7dd8427b87553a2e634b305ff6a40a995c.tar.gz
wireguard-go-eb897a7dd8427b87553a2e634b305ff6a40a995c.zip
wgcfg: remove for now
Going to develop this on a branch and bring it in all at once. Signed-off-by: David Crawshaw <crawshaw@tailscale.com>
-rw-r--r--wgcfg/config.go78
-rw-r--r--wgcfg/ip.go152
-rw-r--r--wgcfg/ip_test.go106
-rw-r--r--wgcfg/key.go182
-rw-r--r--wgcfg/key_test.go33
-rw-r--r--wgcfg/name.go49
-rw-r--r--wgcfg/parser.go397
-rw-r--r--wgcfg/parser_test.go127
-rw-r--r--wgcfg/writer.go73
9 files changed, 0 insertions, 1197 deletions
diff --git a/wgcfg/config.go b/wgcfg/config.go
deleted file mode 100644
index ffb7556..0000000
--- a/wgcfg/config.go
+++ /dev/null
@@ -1,78 +0,0 @@
-/* SPDX-License-Identifier: MIT
- *
- * Copyright (C) 2019 WireGuard LLC. All Rights Reserved.
- */
-
-// Package wgcfg has types and a parser for representing WireGuard config.
-package wgcfg
-
-import (
- "fmt"
- "strings"
-)
-
-// Config is a wireguard configuration.
-type Config struct {
- Name string
- PrivateKey PrivateKey
- Addresses []CIDR
- ListenPort uint16
- MTU uint16
- DNS []IP
- Peers []Peer
-}
-
-type Peer struct {
- PublicKey PublicKey
- PresharedKey SymmetricKey
- AllowedIPs []CIDR
- Endpoints []Endpoint
- PersistentKeepalive uint16
-}
-
-type Endpoint struct {
- Host string
- Port uint16
-}
-
-func (e *Endpoint) String() string {
- if strings.IndexByte(e.Host, ':') > 0 {
- return fmt.Sprintf("[%s]:%d", e.Host, e.Port)
- }
- return fmt.Sprintf("%s:%d", e.Host, e.Port)
-}
-
-func (e *Endpoint) IsEmpty() bool {
- return len(e.Host) == 0
-}
-
-// Copy makes a deep copy of Config.
-// The result aliases no memory with the original.
-func (cfg Config) Copy() Config {
- res := cfg
- if res.Addresses != nil {
- res.Addresses = append([]CIDR{}, res.Addresses...)
- }
- if res.DNS != nil {
- res.DNS = append([]IP{}, res.DNS...)
- }
- peers := make([]Peer, 0, len(res.Peers))
- for _, peer := range res.Peers {
- peers = append(peers, peer.Copy())
- }
- res.Peers = peers
- return res
-}
-
-// Copy makes a deep copy of Peer.
-// The result aliases no memory with the original.
-func (peer Peer) Copy() Peer {
- res := peer
- if res.AllowedIPs != nil {
- res.AllowedIPs = append([]CIDR{}, res.AllowedIPs...)
- }
- if res.Endpoints != nil {
- res.Endpoints = append([]Endpoint{}, res.Endpoints...)
- }
- return res
-}
diff --git a/wgcfg/ip.go b/wgcfg/ip.go
deleted file mode 100644
index 47fa91c..0000000
--- a/wgcfg/ip.go
+++ /dev/null
@@ -1,152 +0,0 @@
-package wgcfg
-
-import (
- "fmt"
- "math"
- "net"
-)
-
-// IP is an IPv4 or an IPv6 address.
-//
-// Internally the address is always represented in its IPv6 form.
-// IPv4 addresses use the IPv4-in-IPv6 syntax.
-type IP struct {
- Addr [16]byte
-}
-
-func (ip IP) String() string { return net.IP(ip.Addr[:]).String() }
-
-// IP converts ip into a standard library net.IP.
-func (ip IP) IP() net.IP { return net.IP(ip.Addr[:]) }
-
-// Is6 reports whether ip is an IPv6 address.
-func (ip IP) Is6() bool { return !ip.Is4() }
-
-// Is4 reports whether ip is an IPv4 address.
-func (ip IP) Is4() bool {
- return ip.Addr[0] == 0 && ip.Addr[1] == 0 &&
- ip.Addr[2] == 0 && ip.Addr[3] == 0 &&
- ip.Addr[4] == 0 && ip.Addr[5] == 0 &&
- ip.Addr[6] == 0 && ip.Addr[7] == 0 &&
- ip.Addr[8] == 0 && ip.Addr[9] == 0 &&
- ip.Addr[10] == 0xff && ip.Addr[11] == 0xff
-}
-
-// To4 returns either a 4 byte slice for an IPv4 address, or nil if
-// it's not IPv4.
-func (ip IP) To4() []byte {
- if ip.Is4() {
- return ip.Addr[12:16]
- } else {
- return nil
- }
-}
-
-// Equal reports whether ip == x.
-func (ip IP) Equal(x IP) bool {
- return ip == x
-}
-
-func (ip IP) MarshalText() ([]byte, error) {
- return []byte(ip.String()), nil
-}
-
-func (ip *IP) UnmarshalText(text []byte) error {
- parsedIP, ok := ParseIP(string(text))
- if !ok {
- return fmt.Errorf("wgcfg.IP: UnmarshalText: bad IP address %q", text)
- }
- *ip = parsedIP
- return nil
-}
-
-func IPv4(b0, b1, b2, b3 byte) (ip IP) {
- ip.Addr[10], ip.Addr[11] = 0xff, 0xff // IPv4-in-IPv6 prefix
- ip.Addr[12] = b0
- ip.Addr[13] = b1
- ip.Addr[14] = b2
- ip.Addr[15] = b3
- return ip
-}
-
-// ParseIP parses the string representation of an address into an IP.
-//
-// It accepts IPv4 notation such as "1.2.3.4" and IPv6 notation like ""::0".
-// The ok result reports whether s was a valid IP and ip is valid.
-func ParseIP(s string) (ip IP, ok bool) {
- netIP := net.ParseIP(s)
- if netIP == nil {
- return IP{}, false
- }
- copy(ip.Addr[:], netIP.To16())
- return ip, true
-}
-
-// CIDR is a compact IP address and subnet mask.
-type CIDR struct {
- IP IP
- Mask uint8 // 0-32 for IsIPv4, 4-128 for IsIPv6
-}
-
-// ParseCIDR parses CIDR notation into a CIDR type.
-// Typical CIDR strings look like "192.168.1.0/24".
-func ParseCIDR(s string) (CIDR, error) {
- netIP, netAddr, err := net.ParseCIDR(s)
- if err != nil {
- return CIDR{}, err
- }
- var cidr CIDR
- copy(cidr.IP.Addr[:], netIP.To16())
- ones, _ := netAddr.Mask.Size()
- cidr.Mask = uint8(ones)
-
- return cidr, nil
-}
-
-func (r CIDR) String() string { return r.IPNet().String() }
-
-func (r CIDR) IPNet() *net.IPNet {
- bits := 128
- if r.IP.Is4() {
- bits = 32
- }
- return &net.IPNet{IP: r.IP.IP(), Mask: net.CIDRMask(int(r.Mask), bits)}
-}
-
-func (r CIDR) Contains(ip IP) bool {
- c := int8(r.Mask)
- i := 0
- if r.IP.Is4() {
- i = 12
- if ip.Is6() {
- return false
- }
- }
- for ; i < 16 && c > 0; i++ {
- var x uint8
- if c < 8 {
- x = 8 - uint8(c)
- }
- m := uint8(math.MaxUint8) >> x << x
- a := r.IP.Addr[i] & m
- b := ip.Addr[i] & m
- if a != b {
- return false
- }
- c -= 8
- }
- return true
-}
-
-func (r CIDR) MarshalText() ([]byte, error) {
- return []byte(r.String()), nil
-}
-
-func (r *CIDR) UnmarshalText(text []byte) error {
- cidr, err := ParseCIDR(string(text))
- if err != nil {
- return fmt.Errorf("wgcfg.CIDR: UnmarshalText: %v", err)
- }
- *r = cidr
- return nil
-}
diff --git a/wgcfg/ip_test.go b/wgcfg/ip_test.go
deleted file mode 100644
index 6cd41d3..0000000
--- a/wgcfg/ip_test.go
+++ /dev/null
@@ -1,106 +0,0 @@
-/* SPDX-License-Identifier: MIT
- *
- * Copyright (C) 2019 WireGuard LLC. All Rights Reserved.
- */
-
-package wgcfg_test
-
-import (
- "testing"
-
- "golang.zx2c4.com/wireguard/wgcfg"
-)
-
-func parseIP(t testing.TB, ipStr string) wgcfg.IP {
- t.Helper()
- ip, ok := wgcfg.ParseIP(ipStr)
- if !ok {
- t.Fatalf("failed to parse IP: %q", ipStr)
- }
- return ip
-}
-
-func TestCIDRContains(t *testing.T) {
- t.Run("home router test", func(t *testing.T) {
- r, err := wgcfg.ParseCIDR("192.168.0.0/24")
- if err != nil {
- t.Fatal(err)
- }
- ip := parseIP(t, "192.168.0.1")
- if !r.Contains(ip) {
- t.Fatalf("%q should contain %q", r, ip)
- }
- })
-
- t.Run("IPv4 outside network", func(t *testing.T) {
- r, err := wgcfg.ParseCIDR("192.168.0.0/30")
- if err != nil {
- t.Fatal(err)
- }
- ip := parseIP(t, "192.168.0.4")
- if r.Contains(ip) {
- t.Fatalf("%q should not contain %q", r, ip)
- }
- })
-
- t.Run("IPv4 does not contain IPv6", func(t *testing.T) {
- r, err := wgcfg.ParseCIDR("192.168.0.0/24")
- if err != nil {
- t.Fatal(err)
- }
- ip := parseIP(t, "2001:db8:85a3:0:0:8a2e:370:7334")
- if r.Contains(ip) {
- t.Fatalf("%q should not contain %q", r, ip)
- }
- })
-
- t.Run("IPv6 inside network", func(t *testing.T) {
- r, err := wgcfg.ParseCIDR("2001:db8:1234::/48")
- if err != nil {
- t.Fatal(err)
- }
- ip := parseIP(t, "2001:db8:1234:0000:0000:0000:0000:0001")
- if !r.Contains(ip) {
- t.Fatalf("%q should not contain %q", r, ip)
- }
- })
-
- t.Run("IPv6 outside network", func(t *testing.T) {
- r, err := wgcfg.ParseCIDR("2001:db8:1234:0:190b:0:1982::/126")
- if err != nil {
- t.Fatal(err)
- }
- ip := parseIP(t, "2001:db8:1234:0:190b:0:1982:4")
- if r.Contains(ip) {
- t.Fatalf("%q should not contain %q", r, ip)
- }
- })
-}
-
-func BenchmarkCIDRContainsIPv4(b *testing.B) {
- b.Run("IPv4", func(b *testing.B) {
- r, err := wgcfg.ParseCIDR("192.168.1.0/24")
- if err != nil {
- b.Fatal(err)
- }
- ip := parseIP(b, "1.2.3.4")
- b.ResetTimer()
-
- for i := 0; i < b.N; i++ {
- r.Contains(ip)
- }
- })
-
- b.Run("IPv6", func(b *testing.B) {
- r, err := wgcfg.ParseCIDR("2001:db8:1234::/48")
- if err != nil {
- b.Fatal(err)
- }
- ip := parseIP(b, "2001:db8:1234:0000:0000:0000:0000:0001")
- b.ResetTimer()
-
- for i := 0; i < b.N; i++ {
- r.Contains(ip)
- }
- })
-}
diff --git a/wgcfg/key.go b/wgcfg/key.go
deleted file mode 100644
index d75f0d9..0000000
--- a/wgcfg/key.go
+++ /dev/null
@@ -1,182 +0,0 @@
-package wgcfg
-
-import (
- "bytes"
- cryptorand "crypto/rand"
- "crypto/subtle"
- "encoding/base64"
- "encoding/hex"
- "errors"
- "fmt"
- "strings"
-
- "golang.org/x/crypto/chacha20poly1305"
- "golang.org/x/crypto/curve25519"
-)
-
-const KeySize = 32
-
-// PublicKey is curve25519 key.
-// It is used by WireGuard to represent public and preshared keys.
-type PublicKey [KeySize]byte
-
-func ParseKey(b64 string) (*PublicKey, error) { return parseKeyBase64(base64.StdEncoding, b64) }
-
-func ParseHexKey(s string) (PublicKey, error) {
- b, err := hex.DecodeString(s)
- if err != nil {
- return PublicKey{}, &ParseError{"invalid hex key: " + err.Error(), s}
- }
- if len(b) != KeySize {
- return PublicKey{}, &ParseError{fmt.Sprintf("invalid hex key length: %d", len(b)), s}
- }
-
- var key PublicKey
- copy(key[:], b)
- return key, nil
-}
-
-func ParsePrivateHexKey(v string) (PrivateKey, error) {
- k, err := ParseHexKey(v)
- if err != nil {
- return PrivateKey{}, err
- }
- pk := PrivateKey(k)
- if pk.IsZero() {
- // Do not clamp a zero key, pass the zero through
- // (much like NaN propagation) so that IsZero reports
- // a useful result.
- return pk, nil
- }
- pk.clamp()
- return pk, nil
-}
-
-func (k PublicKey) Base64() string { return base64.StdEncoding.EncodeToString(k[:]) }
-func (k PublicKey) String() string { return k.ShortString() }
-func (k PublicKey) HexString() string { return hex.EncodeToString(k[:]) }
-func (k PublicKey) Equal(k2 PublicKey) bool { return subtle.ConstantTimeCompare(k[:], k2[:]) == 1 }
-
-func (k *PublicKey) ShortString() string {
- long := k.Base64()
- return "[" + long[0:5] + "]"
-}
-
-func (k PublicKey) IsZero() bool {
- var zeros PublicKey
- return subtle.ConstantTimeCompare(zeros[:], k[:]) == 1
-}
-
-// PrivateKey is curve25519 key.
-// It is used by WireGuard to represent private keys.
-type PrivateKey [KeySize]byte
-
-// NewPrivateKey generates a new curve25519 secret key.
-// It conforms to the format described on https://cr.yp.to/ecdh.html.
-func NewPrivateKey() (pk PrivateKey, err error) {
- _, err = cryptorand.Read(pk[:])
- if err != nil {
- return PrivateKey{}, err
- }
- pk.clamp()
- return pk, nil
-}
-
-func ParsePrivateKey(b64 string) (*PrivateKey, error) {
- k, err := parseKeyBase64(base64.StdEncoding, b64)
- return (*PrivateKey)(k), err
-}
-
-func (k *PrivateKey) String() string { return base64.StdEncoding.EncodeToString(k[:]) }
-func (k *PrivateKey) HexString() string { return hex.EncodeToString(k[:]) }
-func (k *PrivateKey) Equal(k2 PrivateKey) bool { return subtle.ConstantTimeCompare(k[:], k2[:]) == 1 }
-
-func (k PrivateKey) IsZero() bool {
- var zeros PrivateKey
- return subtle.ConstantTimeCompare(zeros[:], k[:]) == 1
-}
-
-func (k *PrivateKey) clamp() {
- k[0] &= 248
- k[31] = (k[31] & 127) | 64
-}
-
-// Public computes the public key matching this curve25519 secret key.
-func (k PrivateKey) Public() PublicKey {
- if k.IsZero() {
- panic("wgcfg: tried to generate public key for a zero key")
- }
- var p [KeySize]byte
- curve25519.ScalarBaseMult(&p, (*[KeySize]byte)(&k))
- return (PublicKey)(p)
-}
-
-func (k PrivateKey) MarshalText() ([]byte, error) {
- buf := new(bytes.Buffer)
- fmt.Fprintf(buf, `privkey:%x`, k[:])
- return buf.Bytes(), nil
-}
-
-func (k *PrivateKey) UnmarshalText(b []byte) error {
- s := string(b)
- if !strings.HasPrefix(s, `privkey:`) {
- return errors.New("wgcfg.PrivateKey: UnmarshalText not given a private-key string")
- }
- s = strings.TrimPrefix(s, `privkey:`)
- key, err := ParseHexKey(s)
- if err != nil {
- return fmt.Errorf("wgcfg.PrivateKey: UnmarshalText: %v", err)
- }
- copy(k[:], key[:])
- return nil
-}
-
-func (k PrivateKey) SharedSecret(pub PublicKey) (ss [KeySize]byte) {
- apk := (*[KeySize]byte)(&pub)
- ask := (*[KeySize]byte)(&k)
- curve25519.ScalarMult(&ss, ask, apk)
- return ss
-}
-
-func parseKeyBase64(enc *base64.Encoding, s string) (*PublicKey, error) {
- k, err := enc.DecodeString(s)
- if err != nil {
- return nil, &ParseError{"Invalid key: " + err.Error(), s}
- }
- if len(k) != KeySize {
- return nil, &ParseError{"Keys must decode to exactly 32 bytes", s}
- }
- var key PublicKey
- copy(key[:], k)
- return &key, nil
-}
-
-func ParseSymmetricKey(b64 string) (SymmetricKey, error) {
- k, err := parseKeyBase64(base64.StdEncoding, b64)
- if err != nil {
- return SymmetricKey{}, err
- }
- return SymmetricKey(*k), nil
-}
-
-func ParseSymmetricHexKey(s string) (SymmetricKey, error) {
- b, err := hex.DecodeString(s)
- if err != nil {
- return SymmetricKey{}, &ParseError{"invalid symmetric hex key: " + err.Error(), s}
- }
- if len(b) != chacha20poly1305.KeySize {
- return SymmetricKey{}, &ParseError{fmt.Sprintf("invalid symmetric hex key length: %d", len(b)), s}
- }
- var key SymmetricKey
- copy(key[:], b)
- return key, nil
-}
-
-// SymmetricKey is a 32-byte value used as a pre-shared key.
-type SymmetricKey [chacha20poly1305.KeySize]byte
-
-func (k SymmetricKey) Base64() string { return base64.StdEncoding.EncodeToString(k[:]) }
-func (k SymmetricKey) String() string { return "sym:" + k.Base64()[:8] }
-func (k SymmetricKey) HexString() string { return hex.EncodeToString(k[:]) }
-func (k SymmetricKey) IsZero() bool { return k.Equal(SymmetricKey{}) }
-func (k SymmetricKey) Equal(k2 SymmetricKey) bool { return subtle.ConstantTimeCompare(k[:], k2[:]) == 1 }
diff --git a/wgcfg/key_test.go b/wgcfg/key_test.go
deleted file mode 100644
index f4640d4..0000000
--- a/wgcfg/key_test.go
+++ /dev/null
@@ -1,33 +0,0 @@
-package wgcfg
-
-import (
- "bytes"
- "testing"
-)
-
-func TestKeyBasics(t *testing.T) {
- pk1, err := NewPrivateKey()
- if err != nil {
- t.Fatal(err)
- }
- k1 := pk1.Public()
-
- t.Run("second key", func(t *testing.T) {
- // Different keys should be different.
- pk2, err := NewPrivateKey()
- if err != nil {
- t.Fatal(err)
- }
- k2 := pk2.Public()
- if bytes.Equal(k1[:], k2[:]) {
- t.Fatalf("k1 %v == k2 %v", k1[:], k2[:])
- }
- // Check for obvious comparables to make sure we are not generating bad strings somewhere.
- if b1, b2 := k1.String(), k2.String(); b1 == b2 {
- t.Fatalf("base64-encoded keys match: %s, %s", b1, b2)
- }
- if pub1, pub2 := pk1.Public().String(), pk2.Public().String(); pub1 == pub2 {
- t.Fatalf("base64-encoded public keys match: %s, %s", pub1, pub2)
- }
- })
-}
diff --git a/wgcfg/name.go b/wgcfg/name.go
deleted file mode 100644
index 28bc0f0..0000000
--- a/wgcfg/name.go
+++ /dev/null
@@ -1,49 +0,0 @@
-/* SPDX-License-Identifier: MIT
- *
- * Copyright (C) 2019 WireGuard LLC. All Rights Reserved.
- */
-
-package wgcfg
-
-import (
- "regexp"
- "strings"
-)
-
-var reservedNames = []string{
- "CON", "PRN", "AUX", "NUL",
- "COM1", "COM2", "COM3", "COM4", "COM5", "COM6", "COM7", "COM8", "COM9",
- "LPT1", "LPT2", "LPT3", "LPT4", "LPT5", "LPT6", "LPT7", "LPT8", "LPT9",
-}
-
-const specialChars = "/\\<>:\"|?*\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f\x00"
-
-var allowedNameFormat *regexp.Regexp
-
-func init() {
- allowedNameFormat = regexp.MustCompile("^[a-zA-Z0-9_=+.-]{1,32}$")
-}
-
-func isReserved(name string) bool {
- if len(name) == 0 {
- return false
- }
- for _, reserved := range reservedNames {
- if strings.EqualFold(name, reserved) {
- return true
- }
- }
- return false
-}
-
-func hasSpecialChars(name string) bool {
- return strings.ContainsAny(name, specialChars)
-}
-
-func TunnelNameIsValid(name string) bool {
- // Aside from our own restrictions, let's impose the Windows restrictions first
- if isReserved(name) || hasSpecialChars(name) {
- return false
- }
- return allowedNameFormat.MatchString(name)
-}
diff --git a/wgcfg/parser.go b/wgcfg/parser.go
deleted file mode 100644
index 8db18f3..0000000
--- a/wgcfg/parser.go
+++ /dev/null
@@ -1,397 +0,0 @@
-/* SPDX-License-Identifier: MIT
- *
- * Copyright (C) 2019 WireGuard LLC. All Rights Reserved.
- */
-
-package wgcfg
-
-import (
- "encoding/hex"
- "fmt"
- "net"
- "strconv"
- "strings"
-)
-
-type ParseError struct {
- why string
- offender string
-}
-
-func (e *ParseError) Error() string {
- return fmt.Sprintf("%s: ā€˜%sā€™", e.why, e.offender)
-}
-
-func parseEndpoints(s string) ([]Endpoint, error) {
- var eps []Endpoint
- vals := strings.Split(s, ",")
- for _, val := range vals {
- e, err := parseEndpoint(val)
- if err != nil {
- return nil, err
- }
- eps = append(eps, *e)
- }
- return eps, nil
-}
-
-func parseEndpoint(s string) (*Endpoint, error) {
- i := strings.LastIndexByte(s, ':')
- if i < 0 {
- return nil, &ParseError{"Missing port from endpoint", s}
- }
- host, portStr := s[:i], s[i+1:]
- if len(host) < 1 {
- return nil, &ParseError{"Invalid endpoint host", host}
- }
- port, err := parsePort(portStr)
- if err != nil {
- return nil, err
- }
- hostColon := strings.IndexByte(host, ':')
- if host[0] == '[' || host[len(host)-1] == ']' || hostColon > 0 {
- err := &ParseError{"Brackets must contain an IPv6 address", host}
- if len(host) > 3 && host[0] == '[' && host[len(host)-1] == ']' && hostColon > 0 {
- maybeV6 := net.ParseIP(host[1 : len(host)-1])
- if maybeV6 == nil || len(maybeV6) != net.IPv6len {
- return nil, err
- }
- } else {
- return nil, err
- }
- host = host[1 : len(host)-1]
- }
- return &Endpoint{host, uint16(port)}, nil
-}
-
-func parseMTU(s string) (uint16, error) {
- m, err := strconv.Atoi(s)
- if err != nil {
- return 0, err
- }
- if m < 576 || m > 65535 {
- return 0, &ParseError{"Invalid MTU", s}
- }
- return uint16(m), nil
-}
-
-func parsePort(s string) (uint16, error) {
- m, err := strconv.Atoi(s)
- if err != nil {
- return 0, err
- }
- if m < 0 || m > 65535 {
- return 0, &ParseError{"Invalid port", s}
- }
- return uint16(m), nil
-}
-
-func parsePersistentKeepalive(s string) (uint16, error) {
- if s == "off" {
- return 0, nil
- }
- m, err := strconv.Atoi(s)
- if err != nil {
- return 0, err
- }
- if m < 0 || m > 65535 {
- return 0, &ParseError{"Invalid persistent keepalive", s}
- }
- return uint16(m), nil
-}
-
-func parseKeyHex(s string) (*PublicKey, error) {
- k, err := hex.DecodeString(s)
- if err != nil {
- return nil, &ParseError{"Invalid key: " + err.Error(), s}
- }
- if len(k) != KeySize {
- return nil, &ParseError{"Keys must decode to exactly 32 bytes", s}
- }
- var key PublicKey
- copy(key[:], k)
- return &key, nil
-}
-
-func parseBytesOrStamp(s string) (uint64, error) {
- b, err := strconv.ParseUint(s, 10, 64)
- if err != nil {
- return 0, &ParseError{"Number must be a number between 0 and 2^64-1: " + err.Error(), s}
- }
- return b, nil
-}
-
-func splitList(s string) ([]string, error) {
- var out []string
- for _, split := range strings.Split(s, ",") {
- trim := strings.TrimSpace(split)
- if len(trim) == 0 {
- return nil, &ParseError{"Two commas in a row", s}
- }
- out = append(out, trim)
- }
- return out, nil
-}
-
-type parserState int
-
-const (
- inInterfaceSection parserState = iota
- inPeerSection
- notInASection
-)
-
-func (c *Config) maybeAddPeer(p *Peer) {
- if p != nil {
- c.Peers = append(c.Peers, *p)
- }
-}
-
-func FromWgQuick(s string, name string) (*Config, error) {
- if !TunnelNameIsValid(name) {
- return nil, &ParseError{"Tunnel name is not valid", name}
- }
- lines := strings.Split(s, "\n")
- parserState := notInASection
- conf := Config{Name: name}
- sawPrivateKey := false
- var peer *Peer
- for _, line := range lines {
- pound := strings.IndexByte(line, '#')
- if pound >= 0 {
- line = line[:pound]
- }
- line = strings.TrimSpace(line)
- lineLower := strings.ToLower(line)
- if len(line) == 0 {
- continue
- }
- if lineLower == "[interface]" {
- conf.maybeAddPeer(peer)
- parserState = inInterfaceSection
- continue
- }
- if lineLower == "[peer]" {
- conf.maybeAddPeer(peer)
- peer = &Peer{}
- parserState = inPeerSection
- continue
- }
- if parserState == notInASection {
- return nil, &ParseError{"Line must occur in a section", line}
- }
- equals := strings.IndexByte(line, '=')
- if equals < 0 {
- return nil, &ParseError{"Invalid config key is missing an equals separator", line}
- }
- key, val := strings.TrimSpace(lineLower[:equals]), strings.TrimSpace(line[equals+1:])
- if len(val) == 0 {
- return nil, &ParseError{"Key must have a value", line}
- }
- if parserState == inInterfaceSection {
- switch key {
- case "privatekey":
- k, err := ParseKey(val)
- if err != nil {
- return nil, err
- }
- conf.PrivateKey = PrivateKey(*k)
- sawPrivateKey = true
- case "listenport":
- p, err := parsePort(val)
- if err != nil {
- return nil, err
- }
- conf.ListenPort = p
- case "mtu":
- m, err := parseMTU(val)
- if err != nil {
- return nil, err
- }
- conf.MTU = m
- case "address":
- addresses, err := splitList(val)
- if err != nil {
- return nil, err
- }
- for _, address := range addresses {
- a, err := ParseCIDR(address)
- if err != nil {
- return nil, err
- }
- conf.Addresses = append(conf.Addresses, a)
- }
- case "dns":
- addresses, err := splitList(val)
- if err != nil {
- return nil, err
- }
- for _, address := range addresses {
- a, ok := ParseIP(address)
- if !ok {
- return nil, &ParseError{"Invalid IP address", address}
- }
- conf.DNS = append(conf.DNS, a)
- }
- default:
- return nil, &ParseError{"Invalid key for [Interface] section", key}
- }
- } else if parserState == inPeerSection {
- switch key {
- case "publickey":
- k, err := ParseKey(val)
- if err != nil {
- return nil, err
- }
- peer.PublicKey = *k
- case "presharedkey":
- k, err := ParseKey(val)
- if err != nil {
- return nil, err
- }
- peer.PresharedKey = SymmetricKey(*k)
- case "allowedips":
- addresses, err := splitList(val)
- if err != nil {
- return nil, err
- }
- for _, address := range addresses {
- a, err := ParseCIDR(address)
- if err != nil {
- return nil, err
- }
- peer.AllowedIPs = append(peer.AllowedIPs, a)
- }
- case "persistentkeepalive":
- p, err := parsePersistentKeepalive(val)
- if err != nil {
- return nil, err
- }
- peer.PersistentKeepalive = p
- case "endpoint":
- eps, err := parseEndpoints(val)
- if err != nil {
- return nil, err
- }
- peer.Endpoints = eps
- default:
- return nil, &ParseError{"Invalid key for [Peer] section", key}
- }
- }
- }
- conf.maybeAddPeer(peer)
-
- if !sawPrivateKey {
- return nil, &ParseError{"An interface must have a private key", "[none specified]"}
- }
- for _, p := range conf.Peers {
- if p.PublicKey.IsZero() {
- return nil, &ParseError{"All peers must have public keys", "[none specified]"}
- }
- }
-
- return &conf, nil
-}
-
-// TODO(apenwarr): This is incompatibe with current Device.IpcSetOperation.
-// It duplicates all the parser stuff in there, but is missing some
-// keywords. Nothing useful seems to need it anymore.
-func Broken_FromUAPI(s string, existingConfig *Config) (*Config, error) {
- lines := strings.Split(s, "\n")
- parserState := inInterfaceSection
- conf := Config{
- Name: existingConfig.Name,
- Addresses: existingConfig.Addresses,
- DNS: existingConfig.DNS,
- MTU: existingConfig.MTU,
- }
- var peer *Peer
- for _, line := range lines {
- if len(line) == 0 {
- continue
- }
- equals := strings.IndexByte(line, '=')
- if equals < 0 {
- return nil, &ParseError{"Invalid config key is missing an equals separator", line}
- }
- key, val := line[:equals], line[equals+1:]
- if len(val) == 0 {
- return nil, &ParseError{"Key must have a value", line}
- }
- switch key {
- case "public_key":
- conf.maybeAddPeer(peer)
- peer = &Peer{}
- parserState = inPeerSection
- case "errno":
- if val == "0" {
- continue
- } else {
- return nil, &ParseError{"Error in getting configuration", val}
- }
- }
- if parserState == inInterfaceSection {
- switch key {
- case "private_key":
- k, err := parseKeyHex(val)
- if err != nil {
- return nil, err
- }
- conf.PrivateKey = PrivateKey(*k)
- case "listen_port":
- p, err := parsePort(val)
- if err != nil {
- return nil, err
- }
- conf.ListenPort = p
- case "fwmark":
- // Ignored for now.
-
- default:
- return nil, &ParseError{"Invalid key for interface section", key}
- }
- } else if parserState == inPeerSection {
- switch key {
- case "public_key":
- k, err := parseKeyHex(val)
- if err != nil {
- return nil, err
- }
- peer.PublicKey = *k
- case "preshared_key":
- k, err := parseKeyHex(val)
- if err != nil {
- return nil, err
- }
- peer.PresharedKey = SymmetricKey(*k)
- case "protocol_version":
- if val != "1" {
- return nil, &ParseError{"Protocol version must be 1", val}
- }
- case "allowed_ip":
- a, err := ParseCIDR(val)
- if err != nil {
- return nil, err
- }
- peer.AllowedIPs = append(peer.AllowedIPs, a)
- case "persistent_keepalive_interval":
- p, err := parsePersistentKeepalive(val)
- if err != nil {
- return nil, err
- }
- peer.PersistentKeepalive = p
- case "endpoint":
- eps, err := parseEndpoints(val)
- if err != nil {
- return nil, err
- }
- peer.Endpoints = eps
- default:
- return nil, &ParseError{"Invalid key for peer section", key}
- }
- }
- }
- conf.maybeAddPeer(peer)
-
- return &conf, nil
-}
diff --git a/wgcfg/parser_test.go b/wgcfg/parser_test.go
deleted file mode 100644
index d0df537..0000000
--- a/wgcfg/parser_test.go
+++ /dev/null
@@ -1,127 +0,0 @@
-/* SPDX-License-Identifier: MIT
- *
- * Copyright (C) 2019 WireGuard LLC. All Rights Reserved.
- */
-
-package wgcfg
-
-import (
- "reflect"
- "runtime"
- "testing"
-)
-
-const testInput = `
-[Interface]
-Address = 10.192.122.1/24
-Address = 10.10.0.1/16
-PrivateKey = yAnz5TF+lXXJte14tji3zlMNq+hd2rYUIgJBgB3fBmk=
-ListenPort = 51820 #comments don't matter
-
-[Peer]
-PublicKey = xTIBA5rboUvnH4htodjb6e697QjLERt1NAB4mZqp8Dg=
-Endpoint = 192.95.5.67:1234
-AllowedIPs = 10.192.122.3/32, 10.192.124.1/24
-
-[Peer]
-PublicKey = TrMvSoP4jYQlY6RIzBgbssQqY3vxI2Pi+y71lOWWXX0=
-Endpoint = [2607:5300:60:6b0::c05f:543]:2468
-AllowedIPs = 10.192.122.4/32, 192.168.0.0/16
-PersistentKeepalive = 100
-
-[Peer]
-PublicKey = gN65BkIKy1eCE9pP1wdc8ROUtkHLF2PfAqYdyYBz6EA=
-PresharedKey = TrMvSoP4jYQlY6RIzBgbssQqY3vxI2Pi+y71lOWWXX0=
-Endpoint = test.wireguard.com:18981
-AllowedIPs = 10.10.10.230/32`
-
-func noError(t *testing.T, err error) bool {
- if err == nil {
- return true
- }
- _, fn, line, _ := runtime.Caller(1)
- t.Errorf("Error at %s:%d: %#v", fn, line, err)
- return false
-}
-
-func equal(t *testing.T, expected, actual interface{}) bool {
- if reflect.DeepEqual(expected, actual) {
- return true
- }
- _, fn, line, _ := runtime.Caller(1)
- t.Errorf("Failed equals at %s:%d\nactual %#v\nexpected %#v", fn, line, actual, expected)
- return false
-}
-func lenTest(t *testing.T, actualO interface{}, expected int) bool {
- actual := reflect.ValueOf(actualO).Len()
- if reflect.DeepEqual(expected, actual) {
- return true
- }
- _, fn, line, _ := runtime.Caller(1)
- t.Errorf("Wrong length at %s:%d\nactual %#v\nexpected %#v", fn, line, actual, expected)
- return false
-}
-func contains(t *testing.T, list, element interface{}) bool {
- listValue := reflect.ValueOf(list)
- for i := 0; i < listValue.Len(); i++ {
- if reflect.DeepEqual(listValue.Index(i).Interface(), element) {
- return true
- }
- }
- _, fn, line, _ := runtime.Caller(1)
- t.Errorf("Error %s:%d\nelement not found: %#v", fn, line, element)
- return false
-}
-
-func TestFromWgQuick(t *testing.T) {
- conf, err := FromWgQuick(testInput, "test")
- if noError(t, err) {
-
- lenTest(t, conf.Addresses, 2)
- contains(t, conf.Addresses, CIDR{IPv4(10, 10, 0, 1), 16})
- contains(t, conf.Addresses, CIDR{IPv4(10, 192, 122, 1), 24})
- equal(t, "yAnz5TF+lXXJte14tji3zlMNq+hd2rYUIgJBgB3fBmk=", conf.PrivateKey.String())
- equal(t, uint16(51820), conf.ListenPort)
-
- lenTest(t, conf.Peers, 3)
- lenTest(t, conf.Peers[0].AllowedIPs, 2)
- equal(t, Endpoint{Host: "192.95.5.67", Port: 1234}, conf.Peers[0].Endpoints[0])
- equal(t, "xTIBA5rboUvnH4htodjb6e697QjLERt1NAB4mZqp8Dg=", conf.Peers[0].PublicKey.Base64())
-
- lenTest(t, conf.Peers[1].AllowedIPs, 2)
- equal(t, Endpoint{Host: "2607:5300:60:6b0::c05f:543", Port: 2468}, conf.Peers[1].Endpoints[0])
- equal(t, "TrMvSoP4jYQlY6RIzBgbssQqY3vxI2Pi+y71lOWWXX0=", conf.Peers[1].PublicKey.Base64())
- equal(t, uint16(100), conf.Peers[1].PersistentKeepalive)
-
- lenTest(t, conf.Peers[2].AllowedIPs, 1)
- equal(t, Endpoint{Host: "test.wireguard.com", Port: 18981}, conf.Peers[2].Endpoints[0])
- equal(t, "gN65BkIKy1eCE9pP1wdc8ROUtkHLF2PfAqYdyYBz6EA=", conf.Peers[2].PublicKey.Base64())
- equal(t, "TrMvSoP4jYQlY6RIzBgbssQqY3vxI2Pi+y71lOWWXX0=", conf.Peers[2].PresharedKey.Base64())
- }
-}
-
-func TestParseEndpoint(t *testing.T) {
- _, err := parseEndpoint("[192.168.42.0:]:51880")
- if err == nil {
- t.Error("Error was expected")
- }
- e, err := parseEndpoint("192.168.42.0:51880")
- if noError(t, err) {
- equal(t, "192.168.42.0", e.Host)
- equal(t, uint16(51880), e.Port)
- }
- e, err = parseEndpoint("test.wireguard.com:18981")
- if noError(t, err) {
- equal(t, "test.wireguard.com", e.Host)
- equal(t, uint16(18981), e.Port)
- }
- e, err = parseEndpoint("[2607:5300:60:6b0::c05f:543]:2468")
- if noError(t, err) {
- equal(t, "2607:5300:60:6b0::c05f:543", e.Host)
- equal(t, uint16(2468), e.Port)
- }
- _, err = parseEndpoint("[::::::invalid:18981")
- if err == nil {
- t.Error("Error was expected")
- }
-}
diff --git a/wgcfg/writer.go b/wgcfg/writer.go
deleted file mode 100644
index 246a57d..0000000
--- a/wgcfg/writer.go
+++ /dev/null
@@ -1,73 +0,0 @@
-/* SPDX-License-Identifier: MIT
- *
- * Copyright (C) 2019 WireGuard LLC. All Rights Reserved.
- */
-
-package wgcfg
-
-import (
- "fmt"
- "net"
- "strings"
-)
-
-func (conf *Config) ToUAPI() (string, error) {
- output := new(strings.Builder)
- fmt.Fprintf(output, "private_key=%s\n", conf.PrivateKey.HexString())
-
- if conf.ListenPort > 0 {
- fmt.Fprintf(output, "listen_port=%d\n", conf.ListenPort)
- }
-
- output.WriteString("replace_peers=true\n")
-
- for _, peer := range conf.Peers {
- fmt.Fprintf(output, "public_key=%s\n", peer.PublicKey.HexString())
- fmt.Fprintf(output, "protocol_version=1\n")
- fmt.Fprintf(output, "replace_allowed_ips=true\n")
-
- if !peer.PresharedKey.IsZero() {
- fmt.Fprintf(output, "preshared_key = %s\n", peer.PresharedKey.String())
- }
-
- if len(peer.AllowedIPs) > 0 {
- for _, address := range peer.AllowedIPs {
- fmt.Fprintf(output, "allowed_ip=%s\n", address.String())
- }
- }
-
- if len(peer.Endpoints) > 0 {
- var reps []string
- for _, ep := range peer.Endpoints {
- ips, err := net.LookupIP(ep.Host)
- if err != nil {
- return "", err
- }
- var ip net.IP
- for _, iterip := range ips {
- if ip4 := iterip.To4(); ip4 != nil {
- ip = ip4
- break
- }
- if ip == nil {
- ip = iterip
- }
- }
- if ip == nil {
- return "", fmt.Errorf("unable to resolve IP address of endpoint %q (%v)", ep.Host, ips)
- }
- resolvedEndpoint := Endpoint{ip.String(), ep.Port}
- reps = append(reps, resolvedEndpoint.String())
- }
- fmt.Fprintf(output, "endpoint=%s\n", strings.Join(reps, ","))
- } else {
- fmt.Fprint(output, "endpoint=\n")
- }
-
- // Note: this needs to come *after* endpoint definitions,
- // because setting it will trigger a handshake to all
- // already-defined endpoints.
- fmt.Fprintf(output, "persistent_keepalive_interval=%d\n", peer.PersistentKeepalive)
- }
- return output.String(), nil
-}