feature: Gets signing server and client infrastructure working.
This commit is contained in:
parent
a5e479cc0c
commit
e527413faf
13 changed files with 865 additions and 62 deletions
312
main.go
312
main.go
|
@ -3,6 +3,7 @@ package main
|
|||
import (
|
||||
"context"
|
||||
_ "embed"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"net"
|
||||
"os"
|
||||
|
@ -11,6 +12,8 @@ import (
|
|||
"git.greysoh.dev/imterah/bismuthd/client"
|
||||
core "git.greysoh.dev/imterah/bismuthd/commons"
|
||||
"git.greysoh.dev/imterah/bismuthd/server"
|
||||
"git.greysoh.dev/imterah/bismuthd/signingclient"
|
||||
"git.greysoh.dev/imterah/bismuthd/signingserver"
|
||||
"github.com/charmbracelet/log"
|
||||
"github.com/urfave/cli/v2"
|
||||
"tailscale.com/net/socks5"
|
||||
|
@ -19,7 +22,7 @@ import (
|
|||
//go:embed ascii.txt
|
||||
var asciiArt string
|
||||
|
||||
func bismuthClientEntrypoint(cCtx *cli.Context) error {
|
||||
func clientEntrypoint(cCtx *cli.Context) error {
|
||||
pubKeyFile, err := os.ReadFile(cCtx.String("pubkey"))
|
||||
|
||||
if err != nil {
|
||||
|
@ -37,6 +40,8 @@ func bismuthClientEntrypoint(cCtx *cli.Context) error {
|
|||
|
||||
bismuth, err := client.New(pubKey, privKey)
|
||||
|
||||
log.Debugf("My key fingerprint is: %s", bismuth.PublicKey.GetFingerprint())
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -82,13 +87,15 @@ func bismuthClientEntrypoint(cCtx *cli.Context) error {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
conn, err = bismuth.Conn(conn)
|
||||
conn, returnData, err := bismuth.Conn(conn)
|
||||
|
||||
if err != nil && err.Error() != "EOF" {
|
||||
log.Errorf("failed to initialize bismuth connection to '%s:%s': '%s'", ip, port, err.Error())
|
||||
return nil, err
|
||||
}
|
||||
|
||||
log.Debugf("Server key fingerprint for '%s' is: %s", addr, returnData.ServerPublicKey.GetFingerprint())
|
||||
|
||||
return conn, err
|
||||
} else {
|
||||
conn, err := net.Dial(network, addr)
|
||||
|
@ -110,8 +117,8 @@ func bismuthClientEntrypoint(cCtx *cli.Context) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func bismuthServerEntrypoint(cCtx *cli.Context) error {
|
||||
relayServers := []string{}
|
||||
func serverEntrypoint(cCtx *cli.Context) error {
|
||||
signingServers := []string{}
|
||||
|
||||
pubKeyFile, err := os.ReadFile(cCtx.String("pubkey"))
|
||||
|
||||
|
@ -130,7 +137,8 @@ func bismuthServerEntrypoint(cCtx *cli.Context) error {
|
|||
|
||||
network := fmt.Sprintf("%s:%s", cCtx.String("source-ip"), cCtx.String("source-port"))
|
||||
|
||||
bismuth, err := server.NewBismuthServer(pubKey, privKey, relayServers, core.XChaCha20Poly1305, func(connBismuth net.Conn) error {
|
||||
bismuth, err := server.NewBismuthServer(pubKey, privKey, signingServers, core.XChaCha20Poly1305)
|
||||
bismuth.HandleConnection = func(connBismuth net.Conn, _ *server.ClientMetadata) error {
|
||||
connDialed, err := net.Dial("tcp", network)
|
||||
|
||||
if err != nil {
|
||||
|
@ -183,7 +191,7 @@ func bismuthServerEntrypoint(cCtx *cli.Context) error {
|
|||
}()
|
||||
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -201,23 +209,197 @@ func bismuthServerEntrypoint(cCtx *cli.Context) error {
|
|||
|
||||
for {
|
||||
conn, err := listener.Accept()
|
||||
|
||||
if err != nil {
|
||||
log.Warnf("failed to accept connection: '%s'", err.Error())
|
||||
continue
|
||||
}
|
||||
|
||||
log.Debugf("Recieved connection from '%s'", conn.RemoteAddr().String())
|
||||
|
||||
go func() {
|
||||
err := bismuth.HandleProxy(conn)
|
||||
|
||||
if err != nil && err.Error() != "EOF" {
|
||||
log.Warnf("connection crashed/dropped during proxy handling: '%s'", err.Error())
|
||||
}
|
||||
}()
|
||||
}
|
||||
}
|
||||
|
||||
func signingServerEntrypoint(cCtx *cli.Context) error {
|
||||
log.Warn("Using the built-in bismuth signing server in production is a horrible idea as it has no validation!")
|
||||
log.Warn("Consider writing using a custom solution that's based on the signing server code, rather than the default implementation.")
|
||||
|
||||
signServers := []string{}
|
||||
|
||||
pubKeyFile, err := os.ReadFile(cCtx.String("pubkey"))
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
privKeyFile, err := os.ReadFile(cCtx.String("privkey"))
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
pubKey := string(pubKeyFile)
|
||||
privKey := string(privKeyFile)
|
||||
|
||||
listener, err := net.Listen("tcp", fmt.Sprintf("%s:%s", cCtx.String("ip"), cCtx.String("port")))
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
bismuthServer, err := server.NewBismuthServer(pubKey, privKey, signServers, core.XChaCha20Poly1305)
|
||||
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
// I'd like to use the SigningServer struct, but I can't really do that
|
||||
_, err = signingserver.New(bismuthServer)
|
||||
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
defer listener.Close()
|
||||
|
||||
log.Info("Bismuth signing server is listening...")
|
||||
|
||||
for {
|
||||
conn, err := listener.Accept()
|
||||
|
||||
if err != nil {
|
||||
log.Warn(err.Error())
|
||||
continue
|
||||
}
|
||||
|
||||
log.Debugf("Recieved connection from '%s'", conn.RemoteAddr().String())
|
||||
|
||||
go func() {
|
||||
err := bismuth.HandleProxy(conn)
|
||||
err = bismuthServer.HandleProxy(conn)
|
||||
|
||||
if err != nil && err.Error() != "EOF" {
|
||||
log.Warnf("Connection crashed/dropped during proxy handling: '%s'", err.Error())
|
||||
log.Warnf("connection crashed/dropped during proxy handling: '%s'", err.Error())
|
||||
return
|
||||
}
|
||||
}()
|
||||
}
|
||||
}
|
||||
|
||||
func verifyCert(cCtx *cli.Context) error {
|
||||
domainList := strings.Split(cCtx.String("domain-names"), ":")
|
||||
pubKeyFile, err := os.ReadFile(cCtx.String("pubkey"))
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
privKeyFile, err := os.ReadFile(cCtx.String("privkey"))
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
pubKey := string(pubKeyFile)
|
||||
privKey := string(privKeyFile)
|
||||
|
||||
bismuthClient, err := client.New(pubKey, privKey)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
dialedConn, err := net.Dial("tcp", cCtx.String("signing-server"))
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
conn, certResults, err := bismuthClient.Conn(dialedConn)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if certResults.OverallTrustScore < 50 {
|
||||
return fmt.Errorf("overall trust score is below 50% for certificate")
|
||||
}
|
||||
|
||||
fmt.Println("Sending signing request to sign server...")
|
||||
|
||||
hasBeenTrusted, err := signingclient.RequestDomainToBeTrusted(conn, domainList, "")
|
||||
|
||||
if hasBeenTrusted {
|
||||
fmt.Println("Server has been successfully signed.")
|
||||
} else {
|
||||
fmt.Println("Server has not been successfully signed.")
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func signCert(cCtx *cli.Context) error {
|
||||
domainList := strings.Split(cCtx.String("domain-names"), ":")
|
||||
keyFingerprint, err := hex.DecodeString(cCtx.String("key-fingerprint"))
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
pubKeyFile, err := os.ReadFile(cCtx.String("pubkey"))
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
privKeyFile, err := os.ReadFile(cCtx.String("privkey"))
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
pubKey := string(pubKeyFile)
|
||||
privKey := string(privKeyFile)
|
||||
|
||||
bismuthClient, err := client.New(pubKey, privKey)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
dialedConn, err := net.Dial("tcp", cCtx.String("signing-server"))
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
conn, certResults, err := bismuthClient.Conn(dialedConn)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if certResults.OverallTrustScore < 50 {
|
||||
return fmt.Errorf("overall trust score is below 50% for certificate")
|
||||
}
|
||||
|
||||
isTrusted, err := signingclient.IsDomainTrusted(conn, keyFingerprint, domainList)
|
||||
fmt.Printf("is certificate trusted: %t\n", isTrusted)
|
||||
|
||||
if !isTrusted {
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func main() {
|
||||
fmt.Println(asciiArt)
|
||||
fmt.Print("Implementation of the Bismuth protocol\n\n")
|
||||
|
@ -282,7 +464,7 @@ func main() {
|
|||
},
|
||||
},
|
||||
Usage: "client for the Bismuth protocol",
|
||||
Action: bismuthClientEntrypoint,
|
||||
Action: clientEntrypoint,
|
||||
},
|
||||
{
|
||||
Name: "server",
|
||||
|
@ -308,6 +490,14 @@ func main() {
|
|||
Usage: "port to connect to",
|
||||
Required: true,
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "signing-servers",
|
||||
Usage: "servers trusting/\"signing\" the public key. seperated using colons",
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "domain-names",
|
||||
Usage: "domain names the key is authorized to use. seperated using colons",
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "dest-ip",
|
||||
Usage: "IP to listen on",
|
||||
|
@ -320,7 +510,109 @@ func main() {
|
|||
},
|
||||
},
|
||||
Usage: "server for the Bismuth protocol",
|
||||
Action: bismuthServerEntrypoint,
|
||||
Action: serverEntrypoint,
|
||||
},
|
||||
{
|
||||
Name: "test-sign-server",
|
||||
Aliases: []string{"tss"},
|
||||
Flags: []cli.Flag{
|
||||
&cli.StringFlag{
|
||||
Name: "pubkey",
|
||||
Usage: "path to PGP public key",
|
||||
Required: true,
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "privkey",
|
||||
Usage: "path to PGP private key",
|
||||
Required: true,
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "ip",
|
||||
Usage: "IP to listen on",
|
||||
Value: "0.0.0.0",
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "port",
|
||||
Usage: "port to listen on",
|
||||
Value: "9090",
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "domain-names",
|
||||
Usage: "domain names the key is authorized to use. seperated using colons",
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "signing-server",
|
||||
Usage: "domain names the key is authorized to use. seperated using colons",
|
||||
},
|
||||
},
|
||||
Usage: "test signing server for the Bismuth protocol",
|
||||
Action: signingServerEntrypoint,
|
||||
},
|
||||
{
|
||||
Name: "sign-tool",
|
||||
Aliases: []string{"st"},
|
||||
Subcommands: []*cli.Command{
|
||||
{
|
||||
Name: "is-verified",
|
||||
Aliases: []string{"i", "iv", "cv"},
|
||||
Flags: []cli.Flag{
|
||||
&cli.StringFlag{
|
||||
Name: "key-fingerprint",
|
||||
Usage: "fingerprint of key",
|
||||
Required: true,
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "pubkey",
|
||||
Usage: "path to PGP public key",
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "privkey",
|
||||
Usage: "path to PGP private key",
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "domain-names",
|
||||
Usage: "domain names the key is authorized to use. seperated using colons",
|
||||
Required: true,
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "signing-server",
|
||||
Usage: "signing server to use",
|
||||
Required: true,
|
||||
},
|
||||
},
|
||||
Usage: "check if a certificate is verified for Bismuth",
|
||||
Action: signCert,
|
||||
},
|
||||
{
|
||||
Name: "verify-cert",
|
||||
Aliases: []string{"v", "vc"},
|
||||
Flags: []cli.Flag{
|
||||
&cli.StringFlag{
|
||||
Name: "pubkey",
|
||||
Usage: "path to PGP public key",
|
||||
Required: true,
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "privkey",
|
||||
Usage: "path to PGP private key",
|
||||
Required: true,
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "domain-names",
|
||||
Usage: "domain names the key is authorized to use. seperated using colons",
|
||||
Required: true,
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "signing-server",
|
||||
Usage: "signing server to use",
|
||||
Required: true,
|
||||
},
|
||||
},
|
||||
Usage: "verifies certificate for Bismuth",
|
||||
Action: verifyCert,
|
||||
},
|
||||
},
|
||||
Usage: "signing tool for Bismuth",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue