1
0
mirror of https://git.zx2c4.com/wireguard-go synced 2025-09-18 20:57:50 +02:00
wireguard-go/wgcfg/parser.go
David Crawshaw 1ecbb3313c wgcfg: rename Key to PublicKey
A few minor review cleanups while here (e.g. remove unused LessThan).

Signed-off-by: David Crawshaw <crawshaw@tailscale.com>
2020-05-02 00:52:01 +10:00

398 lines
9.0 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/* 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
}