Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

User keys master #79

Open
wants to merge 7 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
12 changes: 9 additions & 3 deletions cmd/cli/add.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,18 @@ import (
)

// Add prompts for the required information and creates a new peer
func Add(hostname, owner, description string, confirm bool) {
// TODO accept existing pubkey
func Add(hostname string, privKey, pubKey bool, owner, description string, confirm bool) {
config, err := LoadConfigFile()
check(err, "failed to load configuration file")
server := GetServer(config)

var private, public string
if privKey {
private = MustPromptString("private key", true)
}
if pubKey {
public = MustPromptString("public key", true)
}
if owner == "" {
owner = MustPromptString("owner", true)
}
Expand All @@ -30,7 +36,7 @@ func Add(hostname, owner, description string, confirm bool) {
// newline (not on stdout) to separate config
fmt.Fprintln(os.Stderr)

peer, err := lib.NewPeer(server, owner, hostname, description)
peer, err := lib.NewPeer(server, private, public, owner, hostname, description)
check(err, "failed to get new peer")

// TODO Some kind of recovery here would be nice, to avoid
Expand Down
13 changes: 10 additions & 3 deletions cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,8 +67,8 @@ var (
}

addCmd = &cobra.Command{
Use: "add [hostname]",
Short: "Add a new peer + sync",
Use: "add <hostname>",
Short: "Add a new peer + sync, optionally using a provided WireGuard private key",
PreRunE: func(cmd *cobra.Command, args []string) error {
// Make sure we have the hostname
if len(args) != 1 {
Expand All @@ -77,7 +77,12 @@ var (
return nil
},
Run: func(cmd *cobra.Command, args []string) {
cli.Add(args[0], owner, description, confirm)
privKey, err := cmd.PersistentFlags().GetBool("private-key")
pubKey, err := cmd.PersistentFlags().GetBool("public-key")
if err != nil {
cli.ExitFail("%w - error processing key flag", err)
}
cli.Add(args[0], privKey, pubKey, owner, description, confirm)
},
}

Expand Down Expand Up @@ -142,6 +147,8 @@ func init() {
addCmd.Flags().StringVar(&owner, "owner", "", "owner of the new peer")
addCmd.Flags().StringVar(&description, "description", "", "description of the new peer")
addCmd.Flags().BoolVar(&confirm, "confirm", false, "confirm")
addCmd.PersistentFlags().BoolP("private-key", "r", false, "Accept user-supplied private key. If supplied, dsnet will generate a public key.")
addCmd.PersistentFlags().BoolP("public-key", "u", false, "Accept user-supplied public key. If supplied, the user must add the private key to the generated config (or provide it with --private-key).")
removeCmd.Flags().BoolVar(&confirm, "confirm", false, "confirm")
regenerateCmd.Flags().BoolVar(&confirm, "confirm", false, "confirm")

Expand Down
49 changes: 44 additions & 5 deletions lib/peer.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,10 @@ import (
"errors"
"fmt"
"net"
"strings"
"time"

"golang.zx2c4.com/wireguard/wgctrl/wgtypes"
)

// PeerType is what configuration to use when generating
Expand Down Expand Up @@ -37,19 +40,55 @@ type Peer struct {
PersistentKeepalive int
}

func NewPeer(server *Server, owner string, hostname string, description string) (Peer, error) {
// NewPeer generates a peer from the supplied arguments and generates keys if needed.
// - server is required and provides network information
// - private is a base64-encoded private key; if the empty string, a new key will be generated
// - public is a base64-encoded public key. If empty, it will be generated from the private key.
// If **not** empty, the private key will be included IFF a private key was provided.
// - owner is the owner name (required)
// - hostname is the name of the peer (required)
// - description is the annotation for the peer
func NewPeer(server *Server, private, public, owner, hostname, description string) (Peer, error) {
if owner == "" {
return Peer{}, errors.New("missing owner")
}
if hostname == "" {
return Peer{}, errors.New("missing hostname")
}

privateKey, err := GenerateJSONPrivateKey()
if err != nil {
return Peer{}, fmt.Errorf("failed to generate private key: %s", err)
var privateKey JSONKey
if private != "" {
userKey := &JSONKey{}
userKey.UnmarshalJSON([]byte(private))
privateKey = *userKey
} else {
var err error
privateKey, err = GenerateJSONPrivateKey()
if err != nil {
return Peer{}, fmt.Errorf("failed to generate private key: %s", err)
}
}

var publicKey JSONKey
if public != "" {
b64Key := strings.Trim(string(public), "\"")
key, err := wgtypes.ParseKey(b64Key)
if err != nil {
return Peer{}, err
}
publicKey = JSONKey{Key: key}
if private == "" {
privateKey = JSONKey{Key: wgtypes.Key([wgtypes.KeyLen]byte{})}
} else {
pubK := privateKey.PublicKey()
ascK := pubK.Key.String()
if ascK != public {
return Peer{}, fmt.Errorf("user-supplied private and public keys are not related")
}
}
} else {
publicKey = privateKey.PublicKey()
}
publicKey := privateKey.PublicKey()

presharedKey, err := GenerateJSONKey()
if err != nil {
Expand Down