diff --git a/cmd/keygen.go b/cmd/keygen.go index bf7d1d1..82e2e22 100644 --- a/cmd/keygen.go +++ b/cmd/keygen.go @@ -24,17 +24,18 @@ func NewKeygenCommand() cli.Command { Action: keygenAction, Flags: []cli.Flag{ cli.StringFlag{ - Name: "email", - Usage: "Your email address (ex. something@mail.i2p)", + Name: "signer", + Usage: "Your SU3 signing ID (your email address)", }, }, } } func keygenAction(c *cli.Context) { - signer := c.String("email") - if signer == "" { - log.Fatalln("You must specify an email address (ex. --email=something@mail.i2p)") + signerId := c.String("signer") + if signerId == "" { + fmt.Println("--signer is required") + return } serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128) @@ -46,7 +47,7 @@ func keygenAction(c *cli.Context) { template := &x509.Certificate{ BasicConstraintsValid: true, IsCA: true, - SubjectKeyId: []byte(signer), + SubjectKeyId: []byte(signerId), SerialNumber: serialNumber, Subject: pkix.Name{ Organization: []string{"I2P Anonymous Network"}, @@ -54,7 +55,7 @@ func keygenAction(c *cli.Context) { Locality: []string{"XX"}, StreetAddress: []string{"XX"}, Country: []string{"XX"}, - CommonName: signer, + CommonName: signerId, }, NotBefore: time.Now(), NotAfter: time.Now().AddDate(10, 0, 0), @@ -91,7 +92,7 @@ func keygenAction(c *cli.Context) { fmt.Println("private key saved to reseed_private.pem") // save cert - filename := reseed.SignerFilename(signer) + filename := reseed.SignerFilename(signerId) certOut, err := os.Create(filename) if err != nil { log.Fatalf("failed to open %s for writing: %s", filename, err) diff --git a/cmd/reseeder.go b/cmd/reseeder.go index c69e837..26d8de6 100644 --- a/cmd/reseeder.go +++ b/cmd/reseeder.go @@ -3,6 +3,7 @@ package cmd import ( "fmt" "log" + "net" "runtime" "time" @@ -18,14 +19,23 @@ func NewReseedCommand() cli.Command { Action: reseedAction, Flags: []cli.Flag{ cli.StringFlag{ - Name: "addr", - Value: "127.0.0.1:9090", - Usage: "IP and port to listen on", + Name: "signer", + Usage: "Your SU3 signing ID (your email address)", }, cli.StringFlag{ Name: "netdb", Usage: "Path to NetDB directory containing routerInfos", }, + cli.StringFlag{ + Name: "ip", + Value: "0.0.0.0", + Usage: "IP address to listen on", + }, + cli.StringFlag{ + Name: "port", + Value: "9090", + Usage: "Port to listen on", + }, cli.StringFlag{ Name: "tlscert", Value: "cert.pem", @@ -36,10 +46,6 @@ func NewReseedCommand() cli.Command { Value: "key.pem", Usage: "Path to tls key", }, - cli.StringFlag{ - Name: "signer", - Usage: "Your email address or su3 signing ID", - }, cli.StringFlag{ Name: "keyfile", Value: "reseed_private.pem", @@ -66,12 +72,25 @@ func reseedAction(c *cli.Context) { return } + signerId := c.String("signer") + if signerId == "" { + fmt.Println("--signer is required") + return + } + + reloadIntvl, err := time.ParseDuration(c.String("interval")) + if nil != err { + log.Fatalf("'%s' is not a valid time interval.\n", reloadIntvl) + } + + // use at most half of the cores cpus := runtime.NumCPU() if cpus >= 4 { runtime.GOMAXPROCS(cpus / 2) } // load our signing privKey + // @todo: generate a new signing key if one doesn't exist privKey, err := loadPrivateKey(c.String("keyfile")) if nil != err { log.Fatalln(err) @@ -81,24 +100,19 @@ func reseedAction(c *cli.Context) { netdb := reseed.NewLocalNetDb(netdbDir) // create a reseeder - intr, err := time.ParseDuration(c.String("interval")) - if nil != err { - log.Fatalf("'%s' is not a valid time duration\n", intr) - } - reseeder := reseed.NewReseeder(netdb) reseeder.SigningKey = privKey - reseeder.SignerId = []byte(c.String("signer")) + reseeder.SignerId = []byte(signerId) reseeder.NumRi = c.Int("numRI") - reseeder.RebuildInterval = intr + reseeder.RebuildInterval = reloadIntvl reseeder.Start() // create a server server := reseed.NewServer() server.Reseeder = reseeder - server.Addr = c.String("addr") + server.Addr = net.JoinHostPort(c.String("ip"), c.String("port")) - // @todo generate self-signed keys if they don't exist + // @todo check if tls cert exists, prompt to generate a new one if not log.Printf("Server listening on %s\n", server.Addr) server.ListenAndServeTLS(c.String("tlscert"), c.String("tlskey")) diff --git a/cmd/su3tools.go b/cmd/su3tools.go index 82db29e..f95e82c 100644 --- a/cmd/su3tools.go +++ b/cmd/su3tools.go @@ -1,6 +1,7 @@ package cmd import ( + "fmt" "io/ioutil" "log" @@ -16,12 +17,12 @@ func NewSu3Command() cli.Command { Action: su3Action, Flags: []cli.Flag{ cli.StringFlag{ - Name: "netdb", - Usage: "Path to NetDB directory containing routerInfos", + Name: "signer", + Usage: "Your SU3 signing ID (your email address)", }, cli.StringFlag{ - Name: "signer", - Usage: "Your email address or su3 signing ID", + Name: "netdb", + Usage: "Path to NetDB directory containing routerInfos", }, cli.StringFlag{ Name: "keyfile", @@ -33,20 +34,31 @@ func NewSu3Command() cli.Command { } func su3Action(c *cli.Context) { + netdbDir := c.String("netdb") + if netdbDir == "" { + fmt.Println("--netdb is required") + return + } + + signerId := c.String("signer") + if signerId == "" { + fmt.Println("--signer is required") + return + } + // load our signing privKey privKey, err := loadPrivateKey(c.String("keyfile")) if nil != err { log.Fatalln(err) } - netdb := reseed.NewLocalNetDb(c.String("netdb")) + netdb := reseed.NewLocalNetDb(netdbDir) reseeder := reseed.NewReseeder(netdb) - reseeder.SignerId = []byte(c.String("signer")) + reseeder.SignerId = []byte(signerId) reseeder.SigningKey = privKey // make a fake peer - peer := reseed.Peer("127.0.0.1") - seeds, err := reseeder.Seeds(peer) + seeds, err := reseeder.Seeds(reseed.Peer("127.0.0.1")) if nil != err { log.Fatalln(err) return diff --git a/cmd/utils.go b/cmd/utils.go index 84fbc4e..90a3989 100644 --- a/cmd/utils.go +++ b/cmd/utils.go @@ -12,6 +12,7 @@ func loadPrivateKey(path string) (*rsa.PrivateKey, error) { if nil != err { return nil, err } + privDer, _ := pem.Decode(privPem) privKey, err := x509.ParsePKCS1PrivateKey(privDer.Bytes) if nil != err { diff --git a/cmd/verify_public.go b/cmd/verify_public.go index ec342ad..70fab4c 100644 --- a/cmd/verify_public.go +++ b/cmd/verify_public.go @@ -14,7 +14,7 @@ import ( func NewSu3VerifyPublicCommand() cli.Command { return cli.Command{ - Name: "vp", + Name: "check_all", Usage: "Verify all publicly listed reseed servers", Description: "Verify all publicly listed reseed servers", Action: su3VerifyPublicAction, @@ -38,16 +38,16 @@ func su3VerifyPublicAction(c *cli.Context) { "https://ieb9oopo.mooo.com/", } - pipe := make(chan *http.Response) + responses := make(chan *http.Response) // Kick off goroutines to download the URLs - go download(pipe, public_servers) + go download(responses, public_servers) // Process them serially - validate(pipe) + validate(responses) } -func download(out chan *http.Response, urls []string) { +func download(responses chan *http.Response, urls []string) { tr := &http.Transport{ TLSClientConfig: &tls.Config{InsecureSkipVerify: true}, } @@ -68,18 +68,19 @@ func download(out chan *http.Response, urls []string) { log.Fatalln(err) } - out <- resp + responses <- resp }(url) } + // wait for all the responses to be handled wg.Wait() - close(out) + close(responses) } -func validate(in chan *http.Response) { +func validate(responses chan *http.Response) { ks := reseed.KeyStore{Path: "./certificates"} - for resp := range in { + for resp := range responses { fmt.Printf("Validating: %s\n", resp.Request.URL) if resp.StatusCode != 200 { diff --git a/su3/su3.go b/su3/su3.go index 98d4e6d..b8bc02b 100644 --- a/su3/su3.go +++ b/su3/su3.go @@ -147,9 +147,10 @@ func (s *Su3File) BodyBytes() []byte { func (s *Su3File) Bytes() []byte { buf := new(bytes.Buffer) - buf.Write(s.BodyBytes()) - // xx+ Signature, length specified in header, covers everything starting at byte 0 + // write the body + buf.Write(s.BodyBytes()) + // append the signature binary.Write(buf, binary.BigEndian, s.Signature) return buf.Bytes()