merge majestrate's changes from years ago

This commit is contained in:
idk
2021-04-19 20:51:15 -04:00
28 changed files with 333 additions and 37 deletions

1
.gitignore vendored
View File

@ -5,3 +5,4 @@
*.coverprofile *.coverprofile
*exportable-fuzz.zip *exportable-fuzz.zip
go-i2p go-i2p
*.exe

25
Makefile Normal file
View File

@ -0,0 +1,25 @@
REPO := $(shell dirname $(realpath $(lastword $(MAKEFILE_LIST))))
ifdef GOROOT
GO = $(GOROOT)/bin/go
endif
GO ?= $(shell which go)
ifeq ($(GOOS),windows)
EXE := $(REPO)/go-i2p.exe
else
EXE := $(REPO)/go-i2p
endif
build: clean $(EXE)
$(EXE):
$(GO) build -v -o $(EXE)
test:
$(GO) test ./...
clean:
$(GO) clean -v

View File

@ -56,7 +56,7 @@ func (certificate Certificate) Type() (cert_type int, err error) {
cert_len := len(certificate) cert_len := len(certificate)
if cert_len < CERT_MIN_SIZE { if cert_len < CERT_MIN_SIZE {
log.WithFields(log.Fields{ log.WithFields(log.Fields{
"at": "(Certificate) Type", "at": "(Certificate) Type",
"certificate_bytes_length": cert_len, "certificate_bytes_length": cert_len,
"reason": "too short (len < CERT_MIN_SIZE)", "reason": "too short (len < CERT_MIN_SIZE)",
}).Error("invalid certificate") }).Error("invalid certificate")
@ -82,7 +82,7 @@ func (certificate Certificate) Length() (length int, err error) {
inferred_len := length + CERT_MIN_SIZE inferred_len := length + CERT_MIN_SIZE
if inferred_len > cert_len { if inferred_len > cert_len {
log.WithFields(log.Fields{ log.WithFields(log.Fields{
"at": "(Certificate) Length", "at": "(Certificate) Length",
"certificate_bytes_length": cert_len, "certificate_bytes_length": cert_len,
"certificate_length_field": length, "certificate_length_field": length,
"expected_bytes_length": inferred_len, "expected_bytes_length": inferred_len,
@ -91,7 +91,7 @@ func (certificate Certificate) Length() (length int, err error) {
err = errors.New("certificate parsing warning: certificate data is shorter than specified by length") err = errors.New("certificate parsing warning: certificate data is shorter than specified by length")
} else if cert_len > inferred_len { } else if cert_len > inferred_len {
log.WithFields(log.Fields{ log.WithFields(log.Fields{
"at": "(Certificate) Length", "at": "(Certificate) Length",
"certificate_bytes_length": cert_len, "certificate_bytes_length": cert_len,
"certificate_length_field": length, "certificate_length_field": length,
"expected_bytes_length": inferred_len, "expected_bytes_length": inferred_len,

View File

@ -28,8 +28,8 @@ payload :: data
import ( import (
"errors" "errors"
log "github.com/sirupsen/logrus"
"github.com/go-i2p/go-i2p/lib/crypto" "github.com/go-i2p/go-i2p/lib/crypto"
log "github.com/sirupsen/logrus"
) )
// Key Certificate Signing Key Types // Key Certificate Signing Key Types
@ -90,6 +90,10 @@ func (key_certificate KeyCertificate) Data() ([]byte, error) {
func (key_certificate KeyCertificate) SigningPublicKeyType() (signing_pubkey_type int, err error) { func (key_certificate KeyCertificate) SigningPublicKeyType() (signing_pubkey_type int, err error) {
data, err := key_certificate.Data() data, err := key_certificate.Data()
if err != nil { if err != nil {
log.WithFields(log.Fields{
"at": "(KeyCertificate) SigningPublicKeyType",
"reason": err.Error(),
}).Error("error getting signing public key")
return return
} }
data_len := len(data) data_len := len(data)
@ -231,6 +235,11 @@ func (key_certificate KeyCertificate) SignatureSize() (size int) {
} }
key_type, err := key_certificate.SigningPublicKeyType() key_type, err := key_certificate.SigningPublicKeyType()
if err != nil { if err != nil {
log.WithFields(log.Fields{
"at": "(KeyCertificate) SignatureSize",
"key_type": key_type,
"reason": "failed to read signing public key type",
}).Error("error getting signature size")
return 0 return 0
} }
return sizes[int(key_type)] return sizes[int(key_type)]

View File

@ -47,8 +47,8 @@ total length: 387+ bytes
import ( import (
"errors" "errors"
log "github.com/sirupsen/logrus"
"github.com/go-i2p/go-i2p/lib/crypto" "github.com/go-i2p/go-i2p/lib/crypto"
log "github.com/sirupsen/logrus"
) )
// Sizes of various KeysAndCert structures and requirements // Sizes of various KeysAndCert structures and requirements

View File

@ -82,8 +82,8 @@ signature :: Signature
import ( import (
"errors" "errors"
log "github.com/sirupsen/logrus"
"github.com/go-i2p/go-i2p/lib/crypto" "github.com/go-i2p/go-i2p/lib/crypto"
log "github.com/sirupsen/logrus"
) )
// Sizes of various structures in an I2P LeaseSet // Sizes of various structures in an I2P LeaseSet

View File

@ -51,7 +51,7 @@ func (mapping Mapping) Values() (map_values MappingValues, errs []error) {
mapping_len := len(mapping) mapping_len := len(mapping)
if mapping_len > inferred_length { if mapping_len > inferred_length {
log.WithFields(log.Fields{ log.WithFields(log.Fields{
"at": "(Mapping) Values", "at": "(Mapping) Values",
"mappnig_bytes_length": mapping_len, "mappnig_bytes_length": mapping_len,
"mapping_length_field": length, "mapping_length_field": length,
"expected_bytes_length": inferred_length, "expected_bytes_length": inferred_length,
@ -60,7 +60,7 @@ func (mapping Mapping) Values() (map_values MappingValues, errs []error) {
errs = append(errs, errors.New("warning parsing mapping: data exists beyond length of mapping")) errs = append(errs, errors.New("warning parsing mapping: data exists beyond length of mapping"))
} else if inferred_length > mapping_len { } else if inferred_length > mapping_len {
log.WithFields(log.Fields{ log.WithFields(log.Fields{
"at": "(Mapping) Values", "at": "(Mapping) Values",
"mappnig_bytes_length": mapping_len, "mappnig_bytes_length": mapping_len,
"mapping_length_field": length, "mapping_length_field": length,
"expected_bytes_length": inferred_length, "expected_bytes_length": inferred_length,

View File

@ -204,13 +204,15 @@ func (router_info RouterInfo) Options() (mapping Mapping) {
} }
// //
// Return the 40 bytes that follow the Mapping in the RouterInfo. // Return the signature of this router info
// //
func (router_info RouterInfo) Signature() (signature Signature) { func (router_info RouterInfo) Signature() (signature Signature) {
head := router_info.optionsLocation() head := router_info.optionsLocation()
size := head + router_info.optionsSize() size := head + router_info.optionsSize()
// TODO: signature is not always 40 bytes, is 40 bytes for DSA only ident, _ := router_info.RouterIdentity()
signature = Signature(router_info[size : size+40]) keyCert := KeyCertificate(ident)
sigSize := keyCert.SignatureSize()
signature = Signature(router_info[size : size+sigSize])
return return
} }

View File

@ -36,7 +36,7 @@ func (str String) Length() (length int, err error) {
str_len := len(str) str_len := len(str)
if inferred_len > str_len { if inferred_len > str_len {
log.WithFields(log.Fields{ log.WithFields(log.Fields{
"at": "(String) Length", "at": "(String) Length",
"string_bytes_length": str_len, "string_bytes_length": str_len,
"string_length_field": length, "string_length_field": length,
"expected_bytes_length": inferred_len, "expected_bytes_length": inferred_len,
@ -45,7 +45,7 @@ func (str String) Length() (length int, err error) {
err = errors.New("string parsing warning: string data is shorter than specified by length") err = errors.New("string parsing warning: string data is shorter than specified by length")
} else if str_len > inferred_len { } else if str_len > inferred_len {
log.WithFields(log.Fields{ log.WithFields(log.Fields{
"at": "(String) Length", "at": "(String) Length",
"string_bytes_length": str_len, "string_bytes_length": str_len,
"string_length_field": length, "string_length_field": length,
"expected_bytes_length": inferred_len, "expected_bytes_length": inferred_len,

View File

@ -2,8 +2,8 @@ package config
import ( import (
"errors" "errors"
log "github.com/sirupsen/logrus"
"github.com/go-i2p/go-i2p/lib/common" "github.com/go-i2p/go-i2p/lib/common"
log "github.com/sirupsen/logrus"
"strings" "strings"
"unicode/utf8" "unicode/utf8"
) )
@ -41,14 +41,14 @@ var SU3_CONTENT_TYPE_NEWS_FEED = "news_feed"
var SU3_CONTENT_TYPE_BLOCKLIST_FEED = "blocklist_feed" var SU3_CONTENT_TYPE_BLOCKLIST_FEED = "blocklist_feed"
var SU3_SIGNATURE_TYPE_MAP = map[[SU3_SIGNATURE_TYPE_LEN]byte]string{ var SU3_SIGNATURE_TYPE_MAP = map[[SU3_SIGNATURE_TYPE_LEN]byte]string{
[SU3_SIGNATURE_TYPE_LEN]byte{0x00, 0x00}: SU3_SIGNATURE_TYPE_DSA_SHA1, {0x00, 0x00}: SU3_SIGNATURE_TYPE_DSA_SHA1,
[SU3_SIGNATURE_TYPE_LEN]byte{0x00, 0x01}: SU3_SIGNATURE_TYPE_ECDSA_SHA256_P256, {0x00, 0x01}: SU3_SIGNATURE_TYPE_ECDSA_SHA256_P256,
[SU3_SIGNATURE_TYPE_LEN]byte{0x00, 0x02}: SU3_SIGNATURE_TYPE_ECDSA_SHA384_P384, {0x00, 0x02}: SU3_SIGNATURE_TYPE_ECDSA_SHA384_P384,
[SU3_SIGNATURE_TYPE_LEN]byte{0x00, 0x03}: SU3_SIGNATURE_TYPE_ECDSA_SHA512_P521, {0x00, 0x03}: SU3_SIGNATURE_TYPE_ECDSA_SHA512_P521,
[SU3_SIGNATURE_TYPE_LEN]byte{0x00, 0x04}: SU3_SIGNATURE_TYPE_RSA_SHA256_2048, {0x00, 0x04}: SU3_SIGNATURE_TYPE_RSA_SHA256_2048,
[SU3_SIGNATURE_TYPE_LEN]byte{0x00, 0x05}: SU3_SIGNATURE_TYPE_RSA_SHA384_3072, {0x00, 0x05}: SU3_SIGNATURE_TYPE_RSA_SHA384_3072,
[SU3_SIGNATURE_TYPE_LEN]byte{0x00, 0x06}: SU3_SIGNATURE_TYPE_RSA_SHA512_4096, {0x00, 0x06}: SU3_SIGNATURE_TYPE_RSA_SHA512_4096,
[SU3_SIGNATURE_TYPE_LEN]byte{0x00, 0x08}: SU3_SIGNATURE_TYPE_EdDSA_SHA512_Ed25519ph, {0x00, 0x08}: SU3_SIGNATURE_TYPE_EdDSA_SHA512_Ed25519ph,
} }
var SU3_FILE_TYPE_MAP = map[byte]string{ var SU3_FILE_TYPE_MAP = map[byte]string{
@ -242,7 +242,7 @@ func getFileFormatVersion(data []byte) (int, error) {
if file_format_version_byte := data[SU3_MAGIC_BYTE_LEN+1]; file_format_version_byte != 0x00 { if file_format_version_byte := data[SU3_MAGIC_BYTE_LEN+1]; file_format_version_byte != 0x00 {
log.WithFields(log.Fields{ log.WithFields(log.Fields{
"at": "config.getSignatureType", "at": "config.getSignatureType",
"file_format_version_byte": file_format_version_byte, "file_format_version_byte": file_format_version_byte,
}).Debug(ERR_SU3_FILE_FORMAT_VERSION_UNKNOWN) }).Debug(ERR_SU3_FILE_FORMAT_VERSION_UNKNOWN)
return int(file_format_version_byte), ERR_SU3_FILE_FORMAT_VERSION_UNKNOWN return int(file_format_version_byte), ERR_SU3_FILE_FORMAT_VERSION_UNKNOWN

View File

@ -14,7 +14,7 @@ func TestDSA(t *testing.T) {
sk, err = sk.Generate() sk, err = sk.Generate()
if err == nil { if err == nil {
zeros := 0 zeros := 0
for b, _ := range sk { for b := range sk {
if b == 0 { if b == 0 {
zeros++ zeros++
} }

View File

@ -9,11 +9,11 @@ import (
// XXX: IMPLEMENT THIS // XXX: IMPLEMENT THIS
func Test_I2PHMAC(t *testing.T) { func Test_I2PHMAC(t *testing.T) {
data := make([]byte, 64) data := make([]byte, 64)
for idx, _ := range data { for idx := range data {
data[idx] = 1 data[idx] = 1
} }
var k HMACKey var k HMACKey
for idx, _ := range k[:] { for idx := range k[:] {
k[idx] = 1 k[idx] = 1
} }
d := I2PHMAC(data, k) d := I2PHMAC(data, k)

View File

@ -2,9 +2,9 @@ package i2np
import ( import (
"errors" "errors"
log "github.com/sirupsen/logrus"
"github.com/go-i2p/go-i2p/lib/common" "github.com/go-i2p/go-i2p/lib/common"
"github.com/go-i2p/go-i2p/lib/tunnel" "github.com/go-i2p/go-i2p/lib/tunnel"
log "github.com/sirupsen/logrus"
"time" "time"
) )

View File

@ -2,8 +2,8 @@ package i2np
import ( import (
"errors" "errors"
log "github.com/sirupsen/logrus"
"github.com/go-i2p/go-i2p/lib/common" "github.com/go-i2p/go-i2p/lib/common"
log "github.com/sirupsen/logrus"
"time" "time"
) )

View File

@ -30,6 +30,9 @@ type NetworkDatabase interface {
// return how many router infos we have // return how many router infos we have
Size() int Size() int
// Recaculate size of netdb from backend
RecalculateSize() error
// ensure underlying resources exist , i.e. directories, files, configs // ensure underlying resources exist , i.e. directories, files, configs
Ensure() error Ensure() error
} }

View File

@ -3,13 +3,17 @@ package netdb
import ( import (
"bytes" "bytes"
"fmt" "fmt"
log "github.com/sirupsen/logrus"
"github.com/go-i2p/go-i2p/lib/bootstrap" "github.com/go-i2p/go-i2p/lib/bootstrap"
"github.com/go-i2p/go-i2p/lib/common" "github.com/go-i2p/go-i2p/lib/common"
"github.com/go-i2p/go-i2p/lib/common/base64" "github.com/go-i2p/go-i2p/lib/common/base64"
"github.com/go-i2p/go-i2p/lib/util"
log "github.com/sirupsen/logrus"
"io" "io"
"io/ioutil"
"os" "os"
"path/filepath" "path/filepath"
"strconv"
"strings"
) )
// standard network database implementation using local filesystem skiplist // standard network database implementation using local filesystem skiplist
@ -45,6 +49,60 @@ func (db StdNetDB) Path() string {
// return how many routers we know about in our network database // return how many routers we know about in our network database
// //
func (db StdNetDB) Size() (routers int) { func (db StdNetDB) Size() (routers int) {
// TODO: implement this
var err error
var data []byte
if !util.CheckFileExists(db.cacheFilePath()) {
// regenerate
err = db.RecalculateSize()
if err != nil {
// TODO : what now? let's panic for now
util.Panicf("could not recalculate netdb size: %s", err)
}
}
data, err = ioutil.ReadFile(db.cacheFilePath())
if err == nil {
routers, err = strconv.Atoi(string(data))
}
return
}
// name of file to hold precomputed size of netdb
const CacheFileName = "sizecache.txt"
// get filepath for storing netdb info cache
func (db StdNetDB) cacheFilePath() string {
return filepath.Join(db.Path(), CacheFileName)
}
func (db StdNetDB) CheckFilePathValid(fpath string) bool {
// TODO: make this better
return strings.HasSuffix(fpath, ".dat")
}
// recalculateSize recalculates cached size of netdb
func (db StdNetDB) RecalculateSize() (err error) {
fpath := db.cacheFilePath()
count := 0
err = filepath.Walk(fpath, func(fname string, info os.FileInfo, err error) error {
if info.IsDir() {
return err
}
if db.CheckFilePathValid(fname) {
// TODO: make sure it's in a skiplist directory
count++
}
return err
})
if err == nil {
str := fmt.Sprintf("%d", count)
var f *os.File
f, err = os.OpenFile(fpath, os.O_CREATE|os.O_WRONLY, 0600)
if err == nil {
_, err = io.WriteString(f, str)
f.Close()
}
}
return return
} }

View File

@ -3,12 +3,16 @@ package router
import ( import (
"github.com/go-i2p/go-i2p/lib/config" "github.com/go-i2p/go-i2p/lib/config"
"github.com/go-i2p/go-i2p/lib/netdb" "github.com/go-i2p/go-i2p/lib/netdb"
log "github.com/sirupsen/logrus"
"time"
) )
// i2p router type // i2p router type
type Router struct { type Router struct {
cfg *config.RouterConfig cfg *config.RouterConfig
ndb netdb.StdNetDB ndb netdb.StdNetDB
closeChnl chan bool
running bool
} }
// create router with default configuration // create router with default configuration
@ -22,15 +26,58 @@ func CreateRouter() (r *Router, err error) {
func FromConfig(c *config.RouterConfig) (r *Router, err error) { func FromConfig(c *config.RouterConfig) (r *Router, err error) {
r = new(Router) r = new(Router)
r.cfg = c r.cfg = c
r.closeChnl = make(chan bool)
return return
} }
// Wait blocks until router is fully stopped
func (r *Router) Wait() {
<-r.closeChnl
}
// Stop starts stopping internal state of router
func (r *Router) Stop() {
r.closeChnl <- true
r.running = false
}
// Close closes any internal state and finallizes router resources so that nothing can start up again
func (r *Router) Close() error {
return nil
}
// Start starts router mainloop
func (r *Router) Start() {
if r.running {
log.WithFields(log.Fields{
"at": "(Router) Start",
"reason": "router is already running",
}).Error("Error Starting router")
return
}
r.running = true
go r.mainloop()
}
// run i2p router mainloop // run i2p router mainloop
func (r *Router) Run() { func (r *Router) mainloop() {
r.ndb = netdb.StdNetDB(r.cfg.NetDb.Path) r.ndb = netdb.StdNetDB(r.cfg.NetDb.Path)
// make sure the netdb is ready // make sure the netdb is ready
err := r.ndb.Ensure() err := r.ndb.Ensure()
if err == nil { if err == nil {
// netdb ready // netdb ready
log.WithFields(log.Fields{
"at": "(Router) mainloop",
}).Info("Router ready")
for err == nil {
time.Sleep(time.Second)
}
} else {
// netdb failed
log.WithFields(log.Fields{
"at": "(Router) mainloop",
"reason": err.Error(),
}).Error("Netdb Startup failed")
r.Stop()
} }
} }

View File

@ -0,0 +1,6 @@
package ntcp
// Session implements TransportSession
// An established transport session
type Session struct {
}

View File

@ -0,0 +1,5 @@
package ntcp
// Transport is an ntcp transport implementing transport.Transport interface
type Transport struct {
}

View File

@ -3,8 +3,8 @@ package tunnel
import ( import (
"encoding/binary" "encoding/binary"
"errors" "errors"
log "github.com/sirupsen/logrus"
"github.com/go-i2p/go-i2p/lib/common" "github.com/go-i2p/go-i2p/lib/common"
log "github.com/sirupsen/logrus"
) )
/* /*

View File

@ -2,8 +2,8 @@ package tunnel
import ( import (
"encoding/binary" "encoding/binary"
log "github.com/sirupsen/logrus"
"github.com/go-i2p/go-i2p/lib/crypto" "github.com/go-i2p/go-i2p/lib/crypto"
log "github.com/sirupsen/logrus"
) )
/* /*

12
lib/util/checkfile.go Normal file
View File

@ -0,0 +1,12 @@
package util
import (
"os"
)
// Check if a file exists and is readable etc
// returns false if not
func CheckFileExists(fpath string) bool {
_, e := os.Stat(fpath)
return e == nil
}

16
lib/util/closeables.go Normal file
View File

@ -0,0 +1,16 @@
package util
import "io"
var closeOnExit []io.Closer
func RegisterCloser(c io.Closer) {
closeOnExit = append(closeOnExit, c)
}
func CloseAll() {
for idx := range closeOnExit {
closeOnExit[idx].Close()
}
closeOnExit = nil
}

11
lib/util/panicf.go Normal file
View File

@ -0,0 +1,11 @@
package util
import (
"fmt"
)
// Panicf allows passing formated string to panic()
func Panicf(format string, args ...interface{}) {
s := fmt.Sprintf(format, args...)
panic(s)
}

View File

@ -0,0 +1,33 @@
package signals
import (
"os"
)
var sigChan = make(chan os.Signal)
type Handler func()
var reloaders []Handler
func RegisterReloadHandler(f Handler) {
reloaders = append(reloaders, f)
}
func handleReload() {
for idx := range reloaders {
reloaders[idx]()
}
}
var interrupters []Handler
func RegisterInterruptHandler(f Handler) {
interrupters = append(interrupters, f)
}
func handleInterrupted() {
for idx := range interrupters {
interrupters[idx]()
}
}

30
lib/util/signals/unix.go Normal file
View File

@ -0,0 +1,30 @@
// +build !windows
package signals
import (
"os/signal"
"syscall"
)
func init() {
signal.Notify(sigChan, syscall.SIGINT, syscall.SIGTERM, syscall.SIGHUP)
}
func Handle() {
for {
sig, ok := <-sigChan
if !ok {
// closed channel
return
}
if sig == syscall.SIGHUP {
handleReload()
} else if sig == syscall.SIGINT || sig == syscall.SIGTERM {
handleInterrupted()
} else {
// wtf?
}
}
}

View File

@ -0,0 +1,28 @@
// +build windows
package signals
import (
"os"
"os/signal"
)
func init() {
signal.Notify(sigChan, os.Interrupt)
}
func Handle() {
for {
sig, ok := <-sigChan
if !ok {
// closed channel
return
}
if sig == os.Interrupt {
handleInterrupted()
} else {
// wtf?
}
}
}

16
main.go
View File

@ -1,18 +1,28 @@
package main package main
import ( import (
log "github.com/sirupsen/logrus"
"github.com/go-i2p/go-i2p/lib/router" "github.com/go-i2p/go-i2p/lib/router"
"github.com/go-i2p/go-i2p/lib/util/signals"
log "github.com/sirupsen/logrus"
) )
func main() { func main() {
go signals.Handle()
log.Info("parsing i2p router configuration") log.Info("parsing i2p router configuration")
log.Info("starting up i2p router") log.Info("starting up i2p router")
r, err := router.CreateRouter() r, err := router.CreateRouter()
if err == nil { if err == nil {
r.Run() signals.RegisterReloadHandler(func() {
// TODO: reload config
})
signals.RegisterInterruptHandler(func() {
// TODO: graceful shutdown
r.Stop()
})
r.Start()
r.Wait()
r.Close()
} else { } else {
log.Errorf("failed to create i2p router: %s", err) log.Errorf("failed to create i2p router: %s", err)
} }