shikigrid/cmd/pwngrid/setup.go

197 lines
4.3 KiB
Go

package main
import (
"os"
"os/signal"
"runtime/pprof"
"time"
"github.com/evilsocket/islazy/fs"
"github.com/evilsocket/islazy/log"
"github.com/andatoshiki/shikigrid/api"
"github.com/andatoshiki/shikigrid/crypto"
"github.com/andatoshiki/shikigrid/mesh"
"github.com/andatoshiki/shikigrid/models"
"github.com/andatoshiki/shikigrid/utils"
"github.com/andatoshiki/shikigrid/version"
"github.com/joho/godotenv"
)
func cleanup() {
if cpuProfile != "" {
log.Info("writing CPU profile to %s ...", cpuProfile)
pprof.StopCPUProfile()
}
if memProfile != "" {
log.Info("writing memory profile to %s ...", memProfile)
f, err := os.Create(memProfile)
if err != nil {
log.Fatal("%v", err)
}
defer func() {
if err := f.Close(); err != nil {
panic(err)
}
}()
if err := pprof.WriteHeapProfile(f); err != nil {
panic(err)
}
}
}
func setupCore() {
c := make(chan os.Signal, 1)
signal.Notify(c, os.Interrupt)
go func() {
for sig := range c {
log.Warning("received signal %v", sig)
cleanup()
os.Exit(0)
}
}()
if cpuProfile != "" {
f, err := os.Create(cpuProfile)
if err != nil {
log.Fatal("%v", err)
}
if err := pprof.StartCPUProfile(f); err != nil {
panic(err)
}
}
if debug {
log.Level = log.DEBUG
} else {
log.Level = log.INFO
}
log.OnFatal = log.ExitOnFatal
}
func waitForKeys() {
privPath := crypto.PrivatePath(keysPath)
for {
if !fs.Exists(privPath) {
log.Debug("waiting for %s ...", privPath)
time.Sleep(1 * time.Second)
} else {
// give it a moment to finish disk sync
time.Sleep(2 * time.Second)
log.Info("%s found", privPath)
break
}
}
}
func setupMesh() {
var err error
if advertise == false {
return //this probably doesnt work
}
peer = mesh.MakeLocalPeer(utils.Hostname(), keys)
if err = peer.StartAdvertising(iface); err != nil {
log.Fatal("error while starting signaling: %v", err)
}
if router, err = mesh.StartRouting(iface, peersPath, peer); err != nil {
log.Fatal("%v", err)
} else {
router.OnNewPeer(func(ident string, peer *mesh.Peer) {
log.Info("detected new peer %s on channel %d", peer.ID(), peer.Channel)
})
router.OnPeerLost(func(ident string, peer *mesh.Peer) {
log.Info("peer %s lost (inactive for %fs)", peer.ID(), peer.InactiveFor())
})
}
log.Info("peer %s signaling is ready", peer.ID())
}
func setupDB() {
if err := godotenv.Load(env); err != nil {
log.Fatal("%v", err)
}
if err := models.Setup(); err != nil {
if nodb {
log.Warning("%v", err)
} else {
log.Fatal("%v", err)
}
}
}
func setupMode() string {
var err error
// in case -inbox was not explicitly passed
if receiver != "" || loop == true || id > 0 {
inbox = true
}
// for inbox actions, set the keys to the default path if empty
if (whoami || inbox) && keysPath == "" {
keysPath = "/etc/pwnagotchi/"
}
// generate keypair
if generate {
if keysPath == "" {
log.Fatal("no -keys path specified")
} else if crypto.KeysExist(keysPath) {
log.Fatal("keypair already exists in %s", keysPath)
}
if _, err = crypto.LoadOrCreate(keysPath, 4096); err != nil {
log.Fatal("error generating RSA keypair: %v", err)
} else {
log.Info("keypair saved to %s", keysPath)
}
os.Exit(0)
}
mode := "peer"
// if keys have been passed explicitly, or one of the inbox actions
// has been specified, we're running on the unit
// if keysPath != "" {
// mode = "peer"
// }
log.Info("shikigrid v%s starting in %s mode ...", version.Version, mode)
if mode == "peer" {
// wait for keys to be generated
if wait {
waitForKeys()
}
// load the keys
if keys, err = crypto.Load(keysPath); err != nil {
log.Fatal("error while loading keys from %s: %v", keysPath, err)
}
// print identity and exit
if whoami {
if Endpoint == "https://grid-api.toshiki.dev/api/v1" {
log.Info("https://toshiki.dev/search/%s", keys.FingerprintHex)
} else {
log.Info("https://pwnagotchi.ai/pwnfile/#!%s", keys.FingerprintHex)
}
os.Exit(0)
}
// only start mesh signaling if this is not an inbox action
if !inbox {
setupMesh()
}
} else if mode == "server" {
// server side we just need to setup the database connection
setupDB()
}
// setup the proper routes for either server or peer mode
err, server = api.Setup(keys, peer, router, Endpoint)
if err != nil {
log.Fatal("%v", err)
}
return mode
}