Skip to content

Commit

Permalink
Merge pull request #79 from xxxserxxx/user-keys-master
Browse files Browse the repository at this point in the history
User keys master
  • Loading branch information
naggie authored Aug 3, 2024
2 parents ac2ff11 + 76306e9 commit baf0beb
Show file tree
Hide file tree
Showing 3 changed files with 63 additions and 11 deletions.
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 @@ -40,19 +43,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

0 comments on commit baf0beb

Please sign in to comment.