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": [
"isatty",
"netgiv",
"pflag"
]

View File

@ -9,6 +9,7 @@ import (
"io"
"net"
"os"
"time"
log "github.com/sirupsen/logrus"
@ -17,27 +18,40 @@ import (
)
type Client struct {
address string
port int
list bool
send bool
receive bool
address string
port int
list bool
send bool
receive bool
authToken string
}
func (c *Client) Connect() error {
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 {
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()
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{}}
enc := gob.NewEncoder(&secureConnection)
@ -46,7 +60,7 @@ func (c *Client) Connect() error {
if c.list {
log.Printf("requesting file list")
err := connectToServer(secure.OperationTypeList, enc, dec)
err := c.connectToServer(secure.OperationTypeList, enc, dec)
if err != nil {
return fmt.Errorf("could not connect and auth: %v", err)
}
@ -69,7 +83,7 @@ func (c *Client) Connect() error {
} else if c.receive {
log.Printf("receiving a file")
err := connectToServer(secure.OperationTypeReceive, enc, dec)
err := c.connectToServer(secure.OperationTypeReceive, enc, dec)
if err != nil {
return fmt.Errorf("could not connect and auth: %v", err)
}
@ -111,7 +125,7 @@ func (c *Client) Connect() error {
} else if c.send {
// send mode
err := connectToServer(secure.OperationTypeSend, enc, dec)
err := c.connectToServer(secure.OperationTypeSend, enc, dec)
if err != nil {
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
startPacket := secure.PacketStartRequest{
OperationType: op,
ClientName: "",
ProtocolVersion: "1.0",
AuthToken: "dummy",
AuthToken: c.authToken,
}
err := enc.Encode(startPacket)
if err != nil {

93
main.go
View File

@ -14,29 +14,95 @@ import (
func main() {
// log.SetFlags(log.Lshortfile)
flag.Int("port", 4912, "Port to run server/client on.")
addr := flag.String("a", "127.0.0.1", "address to connect to.")
isServer := flag.Bool("s", false, "Set if running the server.")
// flag.Int("port", 4912, "Port to run server/client on.")
// addr := flag.String("a", "127.0.0.1", "address to connect to.")
isServer := flag.Bool("s", false, "Run netgiv in server mode")
// client mode flags
isList := flag.Bool("l", false, "Set if requesting a list")
isSend := flag.Bool("c", false, "Set if sending a file (copy)")
isReceive := flag.Bool("p", false, "Set if receiving a file (paste)")
isSend := flag.Bool("c", false, "sending stdin to netgiv server (copy)")
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()
viper.AddConfigPath("$HOME/.netgiv/") // call multiple times to add many search paths
viper.SetConfigType("yaml")
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.Parse()
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
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 {
log.Printf("Server running on %d\n", port)
s := Server{port: port}
s := Server{port: port, authToken: authtoken}
s.Run()
} else {
if !*isList && !*isSend && !*isReceive {
// try to work out the intent based on whether or not stdin/stdout
// are ttys
@ -45,21 +111,18 @@ func main() {
if stdinTTY && !stdoutTTY {
*isReceive = true
} else if !stdinTTY && stdoutTTY {
*isSend = true
} else if !stdinTTY && !stdoutTTY {
log.Fatal("I can't cope with both stdin and stdout being pipes")
} else {
flag.Usage()
os.Exit(1)
}
}
if !*isList && !*isSend && !*isReceive {
// could default to list?
*isList = true
}
c := Client{port: port, address: *addr, list: *isList, send: *isSend, receive: *isReceive}
c := Client{port: port, address: address, list: *isList, send: *isSend, receive: *isReceive, authToken: authtoken}
err := c.Connect()
if err != nil {
fmt.Print(err)

View File

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