diff --git a/cmd/gencerts.go b/cmd/gencerts.go new file mode 100644 index 0000000000..5b53c76cf1 --- /dev/null +++ b/cmd/gencerts.go @@ -0,0 +1,128 @@ +package cmd + +import ( + "crypto/rand" + "crypto/rsa" + "crypto/x509" + "crypto/x509/pkix" + "encoding/pem" + "flag" + "math/big" + "net" + "os" + "path" + "strings" + "time" + + "github.com/OpenBazaar/openbazaar-go/repo" +) + +type GenerateCertificates struct { + DataDir string `short:"d" long:"datadir" description:"specify the data directory to be used"` + Testnet bool `short:"t" long:"testnet" description:"config file is for testnet node"` + Host string `short:"h" long:"host" description:"comma-separated hostnames and IPs to generate a certificate for"` + ValidFor time.Duration `long:"duration" description:"duration that certificate is valid for"` +} + +func (x *GenerateCertificates) Execute(args []string) error { + + flag.Parse() + + // Set repo path + repoPath, err := repo.GetRepoPath(x.Testnet) + if err != nil { + return err + } + if x.DataDir != "" { + repoPath = x.DataDir + } + + // Check if host was entered + if len(x.Host) == 0 { + log.Fatalf("Missing required --host parameter") + } + + // Set default duration + if x.ValidFor == 0 { + x.ValidFor = 365 * 24 * time.Hour + } + + var priv interface{} + + // Generate key + priv, err = rsa.GenerateKey(rand.Reader, 2048) + if err != nil { + log.Fatalf("failed to generate private key: %s", err) + } + + // Set creation date + var notBefore = time.Now() + notAfter := notBefore.Add(x.ValidFor) + + // Create serial nmuber + serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128) + serialNumber, err := rand.Int(rand.Reader, serialNumberLimit) + if err != nil { + log.Fatalf("failed to generate serial number: %s", err) + } + + // Check if host ip or dns name and count their quantity + ipAddresses := []net.IP{} + dnsNames := []string{} + hosts := strings.Split(x.Host, ",") + for _, h := range hosts { + if ip := net.ParseIP(h); ip != nil { + ipAddresses = append(ipAddresses, ip) + } else { + dnsNames = append(dnsNames, h) + } + } + + template := x509.Certificate{ + SerialNumber: serialNumber, + IPAddresses: ipAddresses, + DNSNames: dnsNames, + Subject: pkix.Name{ + Organization: []string{"OpenBazaar"}, + }, + NotBefore: notBefore, + NotAfter: notAfter, + KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature | x509.KeyUsageCertSign, + ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth}, + BasicConstraintsValid: true, + IsCA: true, + } + + // Create certificate + derBytes, err := x509.CreateCertificate(rand.Reader, &template, &template, &priv.(*rsa.PrivateKey).PublicKey, priv) + if err != nil { + log.Fatalf("Failed to create certificate: %s", err) + } + + // Create ssl directory + err = os.MkdirAll(path.Join(repoPath, "ssl"), os.ModePerm) + if err != nil { + log.Fatalf("Failed to create ssl directory: %s", err) + } + + // Create and write cert.pem + certOut, err := os.Create(path.Join(repoPath, "ssl", "cert.pem")) + if err != nil { + log.Fatalf("failed to open cert.pem for writing: %s", err) + } + pem.Encode(certOut, &pem.Block{Type: "CERTIFICATE", Bytes: derBytes}) + certOut.Close() + log.Noticef("wrote cert.pem\n") + + // Create and write key.pem + keyOut, err := os.OpenFile(path.Join(repoPath, "ssl", "key.pem"), os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600) + if err != nil { + log.Noticef("failed to open key.pem for writing:", err) + return err + } + pem.Encode(keyOut, &pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(priv.(*rsa.PrivateKey))}) + keyOut.Close() + log.Noticef("wrote key.pem\n") + + return nil +} diff --git a/cmd/init.go b/cmd/init.go index 98d0068ce5..0674e17f17 100644 --- a/cmd/init.go +++ b/cmd/init.go @@ -55,9 +55,8 @@ func (x *Init) Execute(args []string) error { } fmt.Printf("OpenBazaar repo initialized at %s\n", repoPath) return nil - } else { - return nil } + return nil } else if err != nil { return err } diff --git a/cmd/setapicreds.go b/cmd/setapicreds.go index 0f82cfe216..efb2761c25 100644 --- a/cmd/setapicreds.go +++ b/cmd/setapicreds.go @@ -86,8 +86,10 @@ func (x *SetAPICreds) Execute(args []string) error { apiCfg.AllowedIPs = []string{} } - if err := r.SetConfigKey("JSON-API", apiCfg); err != nil { + err = r.SetConfigKey("JSON-API", apiCfg) + if err != nil { return err } + return nil } diff --git a/cmd/start.go b/cmd/start.go index 8c0a32cb44..c958623f88 100644 --- a/cmd/start.go +++ b/cmd/start.go @@ -553,7 +553,7 @@ func (x *Start) Execute(args []string) error { return err } } - feeApi, err := url.Parse(walletCfg.FeeAPI) + feeAPI, err := url.Parse(walletCfg.FeeAPI) if err != nil { log.Error(err) return err @@ -565,7 +565,7 @@ func (x *Start) Execute(args []string) error { LowFee: uint64(walletCfg.LowFeeDefault), MediumFee: uint64(walletCfg.MediumFeeDefault), HighFee: uint64(walletCfg.HighFeeDefault), - FeeAPI: *feeApi, + FeeAPI: *feeAPI, RepoPath: repoPath, CreationDate: creationDate, DB: sqliteDB, @@ -590,7 +590,7 @@ func (x *Start) Execute(args []string) error { return err } } - feeApi, err := url.Parse(walletCfg.FeeAPI) + feeAPI, err := url.Parse(walletCfg.FeeAPI) if err != nil { log.Error(err) return err @@ -603,7 +603,7 @@ func (x *Start) Execute(args []string) error { LowFee: uint64(walletCfg.LowFeeDefault), MediumFee: uint64(walletCfg.MediumFeeDefault), HighFee: uint64(walletCfg.HighFeeDefault), - FeeAPI: *feeApi, + FeeAPI: *feeAPI, RepoPath: repoPath, CreationDate: creationDate, DB: sqliteDB, @@ -712,7 +712,7 @@ func (x *Start) Execute(args []string) error { f.Close() } else { if string(cookie)[:len(cookiePrefix)] != cookiePrefix { - return errors.New("Invalid authentication cookie. Delete it to generate a new one.") + return errors.New("Invalid authentication cookie. Delete it to generate a new one") } split := strings.SplitAfter(string(cookie), cookiePrefix) authCookie.Value = split[1] diff --git a/cmd/status.go b/cmd/status.go index f2ae08af63..884dbd580d 100644 --- a/cmd/status.go +++ b/cmd/status.go @@ -31,7 +31,6 @@ func (x *Status) Execute(args []string) error { if fsrepo.IsInitialized(repoPath) { sqliteDB, err := db.Create(repoPath, "", x.Testnet) if err != nil { - return err os.Exit(1) } defer sqliteDB.Close() diff --git a/core/net.go b/core/net.go index 5c819346cb..97c2ae8592 100644 --- a/core/net.go +++ b/core/net.go @@ -402,7 +402,6 @@ func (n *OpenBazaarNode) SendDisputeClose(peerId string, k *libp2p.PubKey, resol Payload: a, } return n.sendMessage(peerId, k, m) - return nil } func (n *OpenBazaarNode) SendChat(peerId string, chatMessage *pb.Chat) error { diff --git a/dummy/main.go b/dummy/main.go index 8fd0432b68..09902a8890 100644 --- a/dummy/main.go +++ b/dummy/main.go @@ -248,7 +248,7 @@ func newNode(repoPath string, db *db.SQLiteDatastore) (*core.OpenBazaarNode, err val, ok := ival.([]byte) if !ok { log.Fatal("Key value is not a []byte.") - return nil, errors.New("Key value is not a []byte.") + return nil, errors.New("Key value is not a []byte") } dhtrec := new(recpb.Record) proto.Unmarshal(val, dhtrec) diff --git a/net/retriever/retriever.go b/net/retriever/retriever.go index 6c8db9d3cb..7cf3ca5817 100644 --- a/net/retriever/retriever.go +++ b/net/retriever/retriever.go @@ -388,7 +388,7 @@ func (m *MessageRetriever) handleMessage(env pb.Envelope, addr string, id *peer. log.Errorf("Error saving offline message %s to database: %s", addr, err.Error()) } } else { - log.Errorf("Error serializing offline message %s for storage") + log.Errorf("Error serializing offline message %s for storage", addr) } } else if env.Message.MessageType == pb.Message_ORDER && resp != nil { log.Errorf("Error processing ORDER message: %s, sending ERROR response", err.Error()) diff --git a/openbazaard.go b/openbazaard.go index 16855bd611..074f41e79f 100644 --- a/openbazaard.go +++ b/openbazaard.go @@ -17,7 +17,9 @@ var log = logging.MustGetLogger("main") type Opts struct { Version bool `short:"v" long:"version" description:"Print the version number and exit"` } + type Stop struct{} + type Restart struct{} var stopServer Stop @@ -50,6 +52,11 @@ func main() { os.Exit(1) } }() + + parser.AddCommand("gencerts", + "Generate certificates", + "Generate self-singned certificates", + &cmd.GenerateCertificates{}) parser.AddCommand("init", "initialize a new repo and exit", "Initializes a new repo without starting the server",