mirror of
https://github.com/FlipsideCrypto/dcrd.git
synced 2026-02-06 10:56:47 +00:00
146 lines
3.8 KiB
Go
146 lines
3.8 KiB
Go
// Copyright (c) 2013-2014 The btcsuite developers
|
|
// Copyright (c) 2015-2016 The Decred developers
|
|
// Use of this source code is governed by an ISC
|
|
// license that can be found in the LICENSE file.
|
|
|
|
package main
|
|
|
|
import (
|
|
"crypto/elliptic"
|
|
"fmt"
|
|
"io/ioutil"
|
|
"os"
|
|
"os/user"
|
|
"path/filepath"
|
|
"runtime"
|
|
"strings"
|
|
"time"
|
|
|
|
"github.com/decred/dcrd/certgen"
|
|
flags "github.com/jessevdk/go-flags"
|
|
)
|
|
|
|
type config struct {
|
|
Directory string `short:"d" long:"directory" description:"Directory to write certificate pair"`
|
|
Years int `short:"y" long:"years" description:"How many years a certificate is valid for"`
|
|
Organization string `short:"o" long:"org" description:"Organization in certificate"`
|
|
ExtraHosts []string `short:"H" long:"host" description:"Additional hosts/IPs to create certificate for"`
|
|
Force bool `short:"f" long:"force" description:"Force overwriting of any old certs and keys"`
|
|
}
|
|
|
|
func main() {
|
|
cfg := config{
|
|
Years: 10,
|
|
Organization: "gencerts",
|
|
}
|
|
parser := flags.NewParser(&cfg, flags.Default)
|
|
_, err := parser.Parse()
|
|
if err != nil {
|
|
if e, ok := err.(*flags.Error); !ok || e.Type != flags.ErrHelp {
|
|
parser.WriteHelp(os.Stderr)
|
|
}
|
|
return
|
|
}
|
|
|
|
if cfg.Directory == "" {
|
|
var err error
|
|
cfg.Directory, err = os.Getwd()
|
|
if err != nil {
|
|
fmt.Fprintf(os.Stderr, "no directory specified and cannot get working directory\n")
|
|
os.Exit(1)
|
|
}
|
|
}
|
|
cfg.Directory = cleanAndExpandPath(cfg.Directory)
|
|
certFile := filepath.Join(cfg.Directory, "rpc.cert")
|
|
keyFile := filepath.Join(cfg.Directory, "rpc.key")
|
|
|
|
if !cfg.Force {
|
|
if fileExists(certFile) || fileExists(keyFile) {
|
|
fmt.Fprintf(os.Stderr, "%v: certificate and/or key files exist; use -f to force\n", cfg.Directory)
|
|
os.Exit(1)
|
|
}
|
|
}
|
|
|
|
validUntil := time.Now().Add(time.Duration(cfg.Years) * 365 * 24 * time.Hour)
|
|
cert, key, err := certgen.NewTLSCertPair(elliptic.P521(), cfg.Organization, validUntil, cfg.ExtraHosts)
|
|
if err != nil {
|
|
fmt.Fprintf(os.Stderr, "cannot generate certificate pair: %v\n", err)
|
|
os.Exit(1)
|
|
}
|
|
|
|
// Write cert and key files.
|
|
if err = ioutil.WriteFile(certFile, cert, 0644); err != nil {
|
|
fmt.Fprintf(os.Stderr, "cannot write cert: %v\n", err)
|
|
os.Exit(1)
|
|
}
|
|
if err = ioutil.WriteFile(keyFile, key, 0600); err != nil {
|
|
os.Remove(certFile)
|
|
fmt.Fprintf(os.Stderr, "cannot write key: %v\n", err)
|
|
os.Exit(1)
|
|
}
|
|
}
|
|
|
|
// cleanAndExpandPath expands environment variables and leading ~ in the
|
|
// passed path, cleans the result, and returns it.
|
|
func cleanAndExpandPath(path string) string {
|
|
// Nothing to do when no path is given.
|
|
if path == "" {
|
|
return path
|
|
}
|
|
|
|
// NOTE: The os.ExpandEnv doesn't work with Windows cmd.exe-style
|
|
// %VARIABLE%, but the variables can still be expanded via POSIX-style
|
|
// $VARIABLE.
|
|
path = os.ExpandEnv(path)
|
|
|
|
if !strings.HasPrefix(path, "~") {
|
|
return filepath.Clean(path)
|
|
}
|
|
|
|
// Expand initial ~ to the current user's home directory, or ~otheruser
|
|
// to otheruser's home directory. On Windows, both forward and backward
|
|
// slashes can be used.
|
|
path = path[1:]
|
|
|
|
var pathSeparators string
|
|
if runtime.GOOS == "windows" {
|
|
pathSeparators = string(os.PathSeparator) + "/"
|
|
} else {
|
|
pathSeparators = string(os.PathSeparator)
|
|
}
|
|
|
|
userName := ""
|
|
if i := strings.IndexAny(path, pathSeparators); i != -1 {
|
|
userName = path[:i]
|
|
path = path[i:]
|
|
}
|
|
|
|
homeDir := ""
|
|
var u *user.User
|
|
var err error
|
|
if userName == "" {
|
|
u, err = user.Current()
|
|
} else {
|
|
u, err = user.Lookup(userName)
|
|
}
|
|
if err == nil {
|
|
homeDir = u.HomeDir
|
|
}
|
|
// Fallback to CWD if user lookup fails or user has no home directory.
|
|
if homeDir == "" {
|
|
homeDir = "."
|
|
}
|
|
|
|
return filepath.Join(homeDir, path)
|
|
}
|
|
|
|
// fileExists reports whether the named file or directory exists.
|
|
func fileExists(name string) bool {
|
|
if _, err := os.Stat(name); err != nil {
|
|
if os.IsNotExist(err) {
|
|
return false
|
|
}
|
|
}
|
|
return true
|
|
}
|