Skip to content
This repository has been archived by the owner on Mar 28, 2023. It is now read-only.

Added gencerts command, fixed unreachable code, added missing argument, fixed few golint errors #944

Merged
merged 16 commits into from May 18, 2018
Merged
2 changes: 2 additions & 0 deletions cmd/convert.go
Expand Up @@ -32,12 +32,14 @@ import (
"time"
)

//Convert struct
type Convert struct {
Password string `short:"p" long:"password" description:"the encryption password if the database is encrypted"`
DataDir string `short:"d" long:"datadir" description:"specify the data directory to be used"`
Testnet bool `short:"t" long:"testnet" description:"use the test network"`
}

//Execute convert command
func (x *Convert) Execute(args []string) error {
if len(args) == 0 {
fmt.Fprintf(os.Stderr, "Please specify the cryptocurrency you wish to convert to. Examples:\nopenbazaar-go convert bitcoin\nopenbazaar-go convert bitcoincash\nopenbazaar-go convert zcash /path/to/zcashd\n")
Expand Down
2 changes: 2 additions & 0 deletions cmd/decrypt.go
Expand Up @@ -15,10 +15,12 @@ import (
"golang.org/x/crypto/ssh/terminal"
)

//DecryptDatabase struct
type DecryptDatabase struct {
DataDir string `short:"d" long:"datadir" description:"specify the data directory to be used"`
}

//Execute decryptdatabase command
func (x *DecryptDatabase) Execute(args []string) error {
reader := bufio.NewReader(os.Stdin)

Expand Down
2 changes: 2 additions & 0 deletions cmd/encrypt.go
Expand Up @@ -15,10 +15,12 @@ import (
"golang.org/x/crypto/ssh/terminal"
)

//EncryptDatabase struct
type EncryptDatabase struct {
DataDir string `short:"d" long:"datadir" description:"specify the data directory to be used"`
}

//Execute encryptdatabase command
func (x *EncryptDatabase) Execute(args []string) error {
reader := bufio.NewReader(os.Stdin)
var repoPath string
Expand Down
147 changes: 147 additions & 0 deletions cmd/gencerts.go
@@ -0,0 +1,147 @@
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"
)

//GenerateCertificates struct
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"`
}

//return PublicKey
func publicKey(priv interface{}) interface{} {
switch k := priv.(type) {
case *rsa.PrivateKey:
return &k.PublicKey
default:
return nil
}
}

func pemBlockForKey(priv interface{}) *pem.Block {
switch k := priv.(type) {
case *rsa.PrivateKey:
return &pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(k)}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The preamble "RSA PRIVATE KEY" should probably be a constant.

default:
return nil
}
}

//Execute gencerts command
func (x *GenerateCertificates) Execute(args []string) error {
// Set repo path
repoPath, err := repo.GetRepoPath(x.Testnet)
if err != nil {
return err
}
if x.DataDir != "" {
repoPath = x.DataDir
}

flag.Parse()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this being called early enough? Seems x.Testnet would always be false here.


//Check if host 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)

//Crate 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)
}

template := x509.Certificate{
SerialNumber: serialNumber,
Subject: pkix.Name{
Organization: []string{"OpenBazaar"},
},
NotBefore: notBefore,
NotAfter: notAfter,

KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature,
ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
BasicConstraintsValid: true,
}

//Check if host ip or dns name and count their quantity
hosts := strings.Split(x.Host, ",")
for _, h := range hosts {
if ip := net.ParseIP(h); ip != nil {
template.IPAddresses = append(template.IPAddresses, ip)
} else {
template.DNSNames = append(template.DNSNames, h)
}
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Build your []string for IPAddresses and DNSNames first, then assign it to the struct on L89 all at once.


template.IsCA = true
template.KeyUsage |= x509.KeyUsageCertSign
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why are these floating down here like this? Why not add them to the template declaration on L89?


//Create sertificate
derBytes, err := x509.CreateCertificate(rand.Reader, &template, &template, publicKey(priv), 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("written 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, pemBlockForKey(priv))
keyOut.Close()
log.Noticef("written key.pem\n")

return nil
}
5 changes: 3 additions & 2 deletions cmd/init.go
Expand Up @@ -13,6 +13,7 @@ import (

var log = logging.MustGetLogger("cmd")

//Init struct
type Init struct {
Password string `short:"p" long:"password" description:"the encryption password if the database is to be encrypted"`
DataDir string `short:"d" long:"datadir" description:"specify the data directory to be used"`
Expand All @@ -22,6 +23,7 @@ type Init struct {
WalletCreationDate string `short:"w" long:"walletcreationdate" description:"specify the date the seed was created. if omitted the wallet will sync from the oldest checkpoint."`
}

//Execute init command
func (x *Init) Execute(args []string) error {
// Set repo path
repoPath, err := repo.GetRepoPath(x.Testnet)
Expand Down Expand Up @@ -55,9 +57,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
}
Expand Down
5 changes: 5 additions & 0 deletions cmd/restore.go
Expand Up @@ -47,6 +47,7 @@ import (
"time"
)

//Restore struct
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Adding empty definitions merely to satisfy the linter defeats the purpose of the linter. Let's remove these or replace them w idiomatic go docs. https://blog.golang.org/godoc-documenting-go-code

type Restore struct {
Password string `short:"p" long:"password" description:"the encryption password if the database is encrypted"`
DataDir string `short:"d" long:"datadir" description:"specify the data directory to be used"`
Expand All @@ -57,6 +58,7 @@ type Restore struct {
WalletCreationDate string `short:"w" long:"walletcreationdate" description:"specify the date the seed was created. if omitted the wallet will sync from the oldest checkpoint."`
}

//Execute restore command
func (x *Restore) Execute(args []string) error {
reader := bufio.NewReader(os.Stdin)
if x.Mnemonic == "" {
Expand Down Expand Up @@ -332,6 +334,7 @@ func (x *Restore) Execute(args []string) error {
return nil
}

//RestoreFile restore the file
func RestoreFile(repoPath, peerID, filename string, ctx commands.Context, wg *sync.WaitGroup) {
defer wg.Done()
b, err := ipfs.ResolveThenCat(ctx, ipfspath.FromString(path.Join(peerID, filename)), time.Minute)
Expand All @@ -346,6 +349,7 @@ func RestoreFile(repoPath, peerID, filename string, ctx commands.Context, wg *sy
}
}

//RestoreDirectory restore the directory
func RestoreDirectory(repoPath, directory string, nd *ipfscore.IpfsNode, id *cid.Cid, wg *sync.WaitGroup) {
defer wg.Done()
links, err := nd.DAG.GetLinks(context.Background(), id)
Expand Down Expand Up @@ -375,6 +379,7 @@ func RestoreDirectory(repoPath, directory string, nd *ipfscore.IpfsNode, id *cid

}

//PrintError print error
func PrintError(e string) {
os.Stderr.Write([]byte(e))
}
4 changes: 3 additions & 1 deletion cmd/setapicreds.go
Expand Up @@ -15,11 +15,13 @@ import (
"syscall"
)

//SetAPICreds struct
type SetAPICreds 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"`
}

//Execute setapicreds command
func (x *SetAPICreds) Execute(args []string) error {
// Set repo path
repoPath, err := repo.GetRepoPath(x.Testnet)
Expand Down Expand Up @@ -86,7 +88,7 @@ func (x *SetAPICreds) Execute(args []string) error {
apiCfg.AllowedIPs = []string{}
}

if err := r.SetConfigKey("JSON-API", apiCfg); err != nil {
if r.SetConfigKey("JSON-API", apiCfg); err != nil {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This does not look right. Which err did you mean to check here?

I'm thinking the linter told you that you can't declare an err which has already been declared. But when you remove the : it tells you that err has not be declared inside the block. If this is the case, I've solved this by declaring the err at the top and using = throughout.

return err
}
return nil
Expand Down
20 changes: 15 additions & 5 deletions cmd/start.go
Expand Up @@ -91,10 +91,12 @@ var fileLogFormat = logging.MustStringFormatter(
`%{time:15:04:05.000} [%{shortfunc}] [%{level}] %{message}`,
)

//ErrNoGateways
var (
ErrNoGateways = errors.New("No gateway addresses configured")
)

//Start struct
type Start struct {
Password string `short:"p" long:"password" description:"the encryption password if the database is encrypted"`
Testnet bool `short:"t" long:"testnet" description:"use the test network"`
Expand All @@ -117,6 +119,7 @@ type Start struct {
ZCash string `long:"zcash" description:"use a ZCash wallet in a dedicated data directory. To use this you must pass in the location of the zcashd binary."`
}

//Execute start command
func (x *Start) Execute(args []string) error {
printSplashScreen(x.Verbose)

Expand Down Expand Up @@ -553,7 +556,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
Expand All @@ -565,7 +568,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,
Expand All @@ -590,7 +593,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
Expand All @@ -603,7 +606,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,
Expand Down Expand Up @@ -712,7 +715,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]
Expand Down Expand Up @@ -890,25 +893,30 @@ func printSwarmAddrs(node *ipfscore.IpfsNode) {
}
}

//DummyWriter struct
type DummyWriter struct{}

func (d *DummyWriter) Write(p []byte) (n int, err error) {
return 0, nil
}

//DummyListener struct
type DummyListener struct {
addr net.Addr
}

//Addr return addr
func (d *DummyListener) Addr() net.Addr {
return d.addr
}

//Accept retunr conn
func (d *DummyListener) Accept() (net.Conn, error) {
conn, _ := net.FileConn(nil)
return conn, nil
}

//Close return nil
func (d *DummyListener) Close() error {
return nil
}
Expand Down Expand Up @@ -983,6 +991,7 @@ func newHTTPGateway(node *core.OpenBazaarNode, authCookie http.Cookie, config re
return api.NewGateway(node, authCookie, gwLis.NetListener(), config, ml, opts...)
}

//DHTOption variable
var DHTOption ipfscore.RoutingOption = constructDHTRouting

func constructDHTRouting(ctx context.Context, host p2phost.Host, dstore ipfsrepo.Datastore) (routing.IpfsRouting, error) {
Expand Down Expand Up @@ -1054,6 +1063,7 @@ func serveHTTPApi(cctx *commands.Context) (<-chan error, error) {
return errc, nil
}

//InitializeRepo initialize repo
func InitializeRepo(dataDir, password, mnemonic string, testnet bool, creationDate time.Time) (*db.SQLiteDatastore, error) {
// Database
sqliteDB, err := db.Create(dataDir, password, testnet)
Expand Down