Make it possible to set authtoken via ENV

This commit is contained in:
Justin Hawkins 2022-01-16 19:46:29 +10:30
parent 19ef8d65d5
commit 030ebca2c1
4 changed files with 112 additions and 33 deletions

View File

@ -1,5 +1,6 @@
{ {
"cSpell.words": [ "cSpell.words": [
"isatty",
"netgiv", "netgiv",
"pflag" "pflag"
] ]

View File

@ -9,6 +9,7 @@ import (
"io" "io"
"net" "net"
"os" "os"
"time"
log "github.com/sirupsen/logrus" log "github.com/sirupsen/logrus"
@ -22,22 +23,35 @@ type Client struct {
list bool list bool
send bool send bool
receive bool receive bool
authToken string
} }
func (c *Client) Connect() error { func (c *Client) Connect() error {
address := fmt.Sprintf("%s:%d", c.address, c.port) address := fmt.Sprintf("%s:%d", c.address, c.port)
serverAddress, _ := net.ResolveTCPAddr("tcp", address) d := net.Dialer{Timeout: 5 * time.Second}
conn, err := net.DialTCP("tcp", nil, serverAddress) conn, err := d.Dial("tcp", address)
// serverAddress, err := net.ResolveTCPAddr("tcp", address)
// if err != nil {
// return err
// }
// conn, err := d.Dial("tcp", serverAddress)
if err != nil { if err != nil {
return errors.New("problem connecting to server, is it running?\n") return fmt.Errorf("problem connecting to server, is it running?: %v", err)
} }
defer conn.Close() defer conn.Close()
log.Printf("Connection on %s\n", address) log.Printf("Connection on %s\n", address)
sharedKey := secure.Handshake(conn) tcpConn, ok := conn.(*net.TCPConn)
if !ok {
log.Fatal("could not assert")
}
sharedKey := secure.Handshake(tcpConn)
secureConnection := secure.SecureConnection{Conn: conn, SharedKey: sharedKey, Buffer: &bytes.Buffer{}} secureConnection := secure.SecureConnection{Conn: conn, SharedKey: sharedKey, Buffer: &bytes.Buffer{}}
enc := gob.NewEncoder(&secureConnection) enc := gob.NewEncoder(&secureConnection)
@ -46,7 +60,7 @@ func (c *Client) Connect() error {
if c.list { if c.list {
log.Printf("requesting file list") log.Printf("requesting file list")
err := connectToServer(secure.OperationTypeList, enc, dec) err := c.connectToServer(secure.OperationTypeList, enc, dec)
if err != nil { if err != nil {
return fmt.Errorf("could not connect and auth: %v", err) return fmt.Errorf("could not connect and auth: %v", err)
} }
@ -69,7 +83,7 @@ func (c *Client) Connect() error {
} else if c.receive { } else if c.receive {
log.Printf("receiving a file") log.Printf("receiving a file")
err := connectToServer(secure.OperationTypeReceive, enc, dec) err := c.connectToServer(secure.OperationTypeReceive, enc, dec)
if err != nil { if err != nil {
return fmt.Errorf("could not connect and auth: %v", err) return fmt.Errorf("could not connect and auth: %v", err)
} }
@ -111,7 +125,7 @@ func (c *Client) Connect() error {
} else if c.send { } else if c.send {
// send mode // send mode
err := connectToServer(secure.OperationTypeSend, enc, dec) err := c.connectToServer(secure.OperationTypeSend, enc, dec)
if err != nil { if err != nil {
return fmt.Errorf("could not connect and auth: %v", err) return fmt.Errorf("could not connect and auth: %v", err)
} }
@ -167,14 +181,14 @@ func (c *Client) Connect() error {
} }
func connectToServer(op secure.OperationTypeEnum, enc *gob.Encoder, dec *gob.Decoder) error { func (c *Client) connectToServer(op secure.OperationTypeEnum, enc *gob.Encoder, dec *gob.Decoder) error {
// list mode // list mode
startPacket := secure.PacketStartRequest{ startPacket := secure.PacketStartRequest{
OperationType: op, OperationType: op,
ClientName: "", ClientName: "",
ProtocolVersion: "1.0", ProtocolVersion: "1.0",
AuthToken: "dummy", AuthToken: c.authToken,
} }
err := enc.Encode(startPacket) err := enc.Encode(startPacket)
if err != nil { if err != nil {

93
main.go
View File

@ -14,29 +14,95 @@ import (
func main() { func main() {
// log.SetFlags(log.Lshortfile) // log.SetFlags(log.Lshortfile)
flag.Int("port", 4912, "Port to run server/client on.") // flag.Int("port", 4912, "Port to run server/client on.")
addr := flag.String("a", "127.0.0.1", "address to connect to.") // addr := flag.String("a", "127.0.0.1", "address to connect to.")
isServer := flag.Bool("s", false, "Set if running the server.") isServer := flag.Bool("s", false, "Run netgiv in server mode")
// client mode flags
isList := flag.Bool("l", false, "Set if requesting a list") isList := flag.Bool("l", false, "Set if requesting a list")
isSend := flag.Bool("c", false, "Set if sending a file (copy)") isSend := flag.Bool("c", false, "sending stdin to netgiv server (copy)")
isReceive := flag.Bool("p", false, "Set if receiving a file (paste)") isReceive := flag.Bool("p", false, "receive file from netgiv server to stdout (paste)")
flag.String("address", "", "IP address/hostname of the netgiv server")
helpConfig := flag.Bool("help-config", false, "Show help on netgiv configuration")
// common flags
flag.String("authtoken", "", "Authentication token")
flag.Int("port", 0, "Port")
flag.Parse() flag.Parse()
viper.AddConfigPath("$HOME/.netgiv/") // call multiple times to add many search paths
viper.SetConfigType("yaml")
viper.SetDefault("port", 4512) viper.SetDefault("port", 4512)
if err := viper.ReadInConfig(); err != nil {
if _, ok := err.(viper.ConfigFileNotFoundError); ok {
// no config file maybe that's ok
panic(err)
} else {
// Config file was found but another error was produced
log.Fatal(err)
}
}
pflag.CommandLine.AddGoFlagSet(flag.CommandLine) pflag.CommandLine.AddGoFlagSet(flag.CommandLine)
pflag.Parse() pflag.Parse()
viper.BindPFlags(pflag.CommandLine) viper.BindPFlags(pflag.CommandLine)
viper.SetEnvPrefix("NETGIV")
viper.BindEnv("authtoken")
// pull the various things into local variables
port := viper.GetInt("port") // retrieve value from viper port := viper.GetInt("port") // retrieve value from viper
authtoken := viper.GetString("authtoken")
if authtoken == "" {
log.Fatal("authtoken must be set")
}
address := viper.GetString("address")
if !*isServer && address == "" {
log.Fatal("an address must be provided on the command line, or configuration")
}
flag.Usage = func() {
fmt.Fprintf(flag.CommandLine.Output(), "Usage of %s:\n", os.Args[0])
flag.PrintDefaults()
fmt.Printf("\nIf stdin or stdout is a pipe, %s will automatically choose an appropriate\n", os.Args[0])
fmt.Printf("copy (-c) or paste (-p) mode\n")
}
if *helpConfig {
fmt.Print(
`netgiv can be configured by command line parameters (see --help) but it will
often be convenient to create a config file. The config file is in yaml format,
and should be stored in $HOME/.netgiv/config.yaml.
For both client and server, you will want to set the 'authtoken' key (they must
match). You'll want to also set the 'port' key if you would like to run netgiv
on a non-standard port (the default is 4512).
On the client you will probably want to set the 'address' key, so that your client
knows where to find the netgiv server. This key is ignored when running in server
mode.
Example:
port: 5412
authtoken: verysecretvaluehere
address: 10.1.12.20
`)
os.Exit(1)
}
if *isServer { if *isServer {
s := Server{port: port, authToken: authtoken}
log.Printf("Server running on %d\n", port)
s := Server{port: port}
s.Run() s.Run()
} else { } else {
if !*isList && !*isSend && !*isReceive { if !*isList && !*isSend && !*isReceive {
// try to work out the intent based on whether or not stdin/stdout // try to work out the intent based on whether or not stdin/stdout
// are ttys // are ttys
@ -45,21 +111,18 @@ func main() {
if stdinTTY && !stdoutTTY { if stdinTTY && !stdoutTTY {
*isReceive = true *isReceive = true
} else if !stdinTTY && stdoutTTY { } else if !stdinTTY && stdoutTTY {
*isSend = true *isSend = true
} else if !stdinTTY && !stdoutTTY { } else if !stdinTTY && !stdoutTTY {
log.Fatal("I can't cope with both stdin and stdout being pipes") log.Fatal("I can't cope with both stdin and stdout being pipes")
} else {
flag.Usage()
os.Exit(1)
} }
} }
if !*isList && !*isSend && !*isReceive { c := Client{port: port, address: address, list: *isList, send: *isSend, receive: *isReceive, authToken: authtoken}
// could default to list?
*isList = true
}
c := Client{port: port, address: *addr, list: *isList, send: *isSend, receive: *isReceive}
err := c.Connect() err := c.Connect()
if err != nil { if err != nil {
fmt.Print(err) fmt.Print(err)

View File

@ -21,6 +21,7 @@ import (
type Server struct { type Server struct {
port int port int
authToken string
} }
// An NGF is a Netgiv File // An NGF is a Netgiv File
@ -71,11 +72,11 @@ func (s *Server) Run() {
fmt.Print(err) fmt.Print(err)
} }
go handleConnection(conn) go s.handleConnection(conn)
} }
} }
func handleConnection(conn *net.TCPConn) { func (s *Server) handleConnection(conn *net.TCPConn) {
defer conn.Close() defer conn.Close()
conn.SetDeadline(time.Now().Add(time.Second * 5)) conn.SetDeadline(time.Now().Add(time.Second * 5))
@ -113,7 +114,7 @@ func handleConnection(conn *net.TCPConn) {
return return
} }
if start.AuthToken != "dummy2" { if start.AuthToken != s.authToken {
log.Print("bad authtoken") log.Print("bad authtoken")
startResponse.Response = secure.PacketStartResponseEnumBadAuthToken startResponse.Response = secure.PacketStartResponseEnumBadAuthToken
enc.Encode(startResponse) enc.Encode(startResponse)