diff --git a/client.go b/client.go index 715fd0c..136b2ca 100644 --- a/client.go +++ b/client.go @@ -1,11 +1,11 @@ package main import ( - "bufio" + "encoding/gob" "errors" "fmt" + "log" "net" - "os" "github.com/tardisx/netgiv/secure" ) @@ -20,7 +20,7 @@ func (c *Client) Connect() error { conn, err := net.DialTCP("tcp", nil, serverAddress) if err != nil { - return errors.New("Problem connecting to server, is it running?\n") + return errors.New("problem connecting to server, is it running?\n") } defer conn.Close() @@ -29,26 +29,46 @@ func (c *Client) Connect() error { sharedKey := secure.Handshake(conn) secureConnection := secure.SecureConnection{Conn: conn, SharedKey: sharedKey} - reader := bufio.NewReader(os.Stdin) + // reader := bufio.NewReader(os.Stdin) + enc := gob.NewEncoder(&secureConnection) for { - fmt.Print("> ") - // Read up to the newline character - msg, _ := reader.ReadBytes(0xA) - // Kill the newline char - msg = msg[:len(msg)-1] - _, err := secureConnection.Write(msg) - - response := make([]byte, 1024) - - _, err = secureConnection.Read(response) - if err != nil { - fmt.Print("Connection to the server was closed.\n") - break + msg := secure.PacketStart{ + OperationType: secure.OperationTypeSend, + ClientName: "Justin Hawkins", + ProtocolVersion: "v1.0", + AuthToken: "abc123", } - fmt.Printf("%s\n", response) + // gob.Register(secure.PacketSendStart{}) + err := enc.Encode(msg) + if err != nil { + panic(err) + } + + data := secure.PacketSendDataStart{ + Filename: "foobar", + TotalSize: 3, + Data: []byte{0x20, 0x21, 0x22}, + } + err = enc.Encode(data) + if err != nil { + panic(err) + } + log.Print("done that") + conn.Close() + + break + // response := make([]byte, 1024) + + // _, err = secureConnection.Read(response) + // if err != nil { + // fmt.Print("Connection to the server was closed.\n") + // break + // } + + // fmt.Printf("%s\n", response) } return nil diff --git a/main.go b/main.go index 54867f0..63adf09 100644 --- a/main.go +++ b/main.go @@ -3,9 +3,11 @@ package main import ( "flag" "fmt" + "log" ) func main() { + log.SetFlags(log.Lshortfile) port := flag.Int("p", 9000, "Port to run server/client on.") isServer := flag.Bool("s", false, "Set if running the server.") flag.Parse() diff --git a/secure/secure.go b/secure/secure.go index 0cb05b7..3985da7 100644 --- a/secure/secure.go +++ b/secure/secure.go @@ -3,7 +3,10 @@ package secure import ( "bytes" "crypto/rand" + "encoding/binary" "errors" + "io" + "log" "net" "golang.org/x/crypto/nacl/box" @@ -11,63 +14,126 @@ import ( type SecureMessage struct { Msg []byte + Size uint16 Nonce [24]byte } func (s *SecureMessage) toByteArray() []byte { - return append(s.Nonce[:], s.Msg[:]...) + length := []byte{0x0, 0x0} + binary.BigEndian.PutUint16(length, uint16(len(s.Msg))) + out := append(s.Nonce[:], length...) + out = append(out, s.Msg[:]...) + return out +} + +func DeterminePacketSize(data []byte) uint16 { + // first 24 bytes are the nonce, then the size + if len(data) < 26 { + log.Printf("packet is too small to be complete - %d bytes", len(data)) + return 0 + } + size := binary.BigEndian.Uint16(data[24:26]) + size += 26 // add the length header and the nonce + log.Printf("size of packet inside the %d bytes is %d bytes", len(data), size) + return size } func ConstructSecureMessage(sm []byte) SecureMessage { var nonce [24]byte nonceArray := sm[:24] + size := binary.BigEndian.Uint16(sm[24:26]) copy(nonce[:], nonceArray) // Trim out all unnecessary bytes - msg := bytes.Trim(sm[24:], "\x00") + // msg := bytes.Trim(sm[24:], "\x00") - return SecureMessage{Msg: msg, Nonce: nonce} + return SecureMessage{Msg: sm[26 : 26+size], Size: size, Nonce: nonce} } type SecureConnection struct { Conn *net.TCPConn SharedKey *[32]byte + Buffer *bytes.Buffer } func (s *SecureConnection) Read(p []byte) (int, error) { - message := make([]byte, 2048) + message := make([]byte, 20408) // Read the message from the buffer + eof := false + + log.Printf("READ: Start, buffer contains %d bytes", s.Buffer.Len()) + n, err := s.Conn.Read(message) - secureMessage := ConstructSecureMessage(message) + if err != nil && err != io.EOF { + log.Printf("read: error in connection read %v", err) + return 0, err + } + if err == io.EOF { + eof = true + } + + // log.Printf("read: got %d bytes on the wire, error is %v", n, err) + // log.Printf("looks like %v", message[:n]) + if eof { + log.Printf("eof is true - this is our final read!") + } + + s.Buffer.Write(message[:n]) + // log.Printf("read: appended them to the buffer which is now %d bytes", len(s.Buffer.Bytes())) + + actualPacketEnd := DeterminePacketSize(s.Buffer.Bytes()) + if actualPacketEnd == 0 { + log.Printf("packet too small?") + // panic("small") + return 0, io.EOF + } + + secureMessage := ConstructSecureMessage(s.Buffer.Bytes()[:actualPacketEnd]) + // log.Printf("Secure message from wire bytes: \n nonce: %v\n msg: %v\n size: %d\n", secureMessage.Nonce, secureMessage.Msg, secureMessage.Size) decryptedMessage, ok := box.OpenAfterPrecomputation(nil, secureMessage.Msg, &secureMessage.Nonce, s.SharedKey) if !ok { - return 0, errors.New("Problem decrypting the message.\n") + return 0, errors.New("problem decrypting the message") } - // Actually copy it to the destination byte array - n = copy(p, decryptedMessage) + copy(p, decryptedMessage) - return n, err + // trim what we used off the buffer + newBuffer := s.Buffer.Bytes()[actualPacketEnd:] + s.Buffer = bytes.NewBuffer(newBuffer) + + if eof && s.Buffer.Len() == 0 { + log.Printf("returning the final packet") + return len(decryptedMessage), io.EOF + } + + log.Printf("successfully read %d bytes", len(decryptedMessage)) + return len(decryptedMessage), nil } func (s *SecureConnection) Write(p []byte) (int, error) { + // func (s *SecureConnection) Write(o encoding.BinaryMarshaler) (int, error) { var nonce [24]byte + log.Printf("clear bytes: %v", p) + // Create a new nonce for each message sent rand.Read(nonce[:]) - + log.Printf("before encryption it is %d bytes", len(p)) encryptedMessage := box.SealAfterPrecomputation(nil, p, &nonce, s.SharedKey) sm := SecureMessage{Msg: encryptedMessage, Nonce: nonce} // Write it to the connection - return s.Conn.Write(sm.toByteArray()) + wireBytes := sm.toByteArray() + log.Printf("putting %d bytes on the wire\n nonce: %v\n bytes: %v", len(wireBytes), nonce, wireBytes) + return s.Conn.Write(wireBytes) } func Handshake(conn *net.TCPConn) *[32]byte { var peerKey, sharedKey [32]byte + log.Print("starting handshake") publicKey, privateKey, _ := box.GenerateKey(rand.Reader) conn.Write(publicKey[:]) @@ -78,5 +144,33 @@ func Handshake(conn *net.TCPConn) *[32]byte { box.Precompute(&sharedKey, &peerKey, privateKey) + log.Printf("ending handshake, sk: %v", sharedKey) + return &sharedKey } + +type OperationTypeEnum byte + +const ( + OperationTypeSend OperationTypeEnum = iota +) + +// PacketStart is sent from the client to the server at the beginning +// to authenticate and annonce the requested particular operation +type PacketStart struct { + OperationType OperationTypeEnum + ClientName string + ProtocolVersion string + AuthToken string +} + +type PacketSendDataStart struct { + Filename string + TotalSize uint32 + Data []byte +} + +type PacketSendDataNext struct { + Size uint16 + Data []byte +} diff --git a/server.go b/server.go index 5a8ebaf..4f5a2ef 100644 --- a/server.go +++ b/server.go @@ -1,9 +1,14 @@ package main import ( + "bytes" + "encoding/gob" "fmt" + "io" + "log" "net" "os" + "time" "github.com/tardisx/netgiv/secure" ) @@ -35,17 +40,46 @@ func (s *Server) Run() { func handleConnection(conn *net.TCPConn) { defer conn.Close() + + conn.SetDeadline(time.Now().Add(time.Second)) + sharedKey := secure.Handshake(conn) - secureConnection := secure.SecureConnection{Conn: conn, SharedKey: sharedKey} + secureConnection := secure.SecureConnection{Conn: conn, SharedKey: sharedKey, Buffer: &bytes.Buffer{}} + gob.Register(secure.PacketStart{}) + gob.Register(secure.PacketSendDataStart{}) + + dec := gob.NewDecoder(&secureConnection) + + // At this point we are in for { - msg := make([]byte, 1024) - _, err := secureConnection.Read(msg) + p1 := secure.PacketStart{} + + log.Print("trying to decode something from wire") + err := dec.Decode(&p1) + if err == io.EOF { + log.Printf("connection has been closed") + return + } if err != nil { - break + panic(err) } - secureConnection.Write(msg) + log.Printf("Decoded packet:\n%#v", p1) + + p2 := secure.PacketSendDataStart{} + + err = dec.Decode(&p2) + if err == io.EOF { + log.Printf("connection has been closed") + return + } + if err != nil { + panic(err) + } + + log.Printf("Decoded packet:\n%#v", p2) + } }