diff --git a/config.go b/config.go index 5887cb0..8b86627 100644 --- a/config.go +++ b/config.go @@ -26,7 +26,7 @@ func NewConfig(actionType string, actionData string) *Config { return &Config{ActionType: actionType, ActionData: actionData} } -func (config *Config) Validate() { +func (config *Config) Validate() { if config.ActionType == "url" { // Parse URL in config urlParser, err := url.Parse(config.ActionData) @@ -52,15 +52,21 @@ func (config *Config) CreateFile(dir string) { log.Logger = log.Output(zerolog.ConsoleWriter{Out: os.Stderr}).Hook(FatalHook{}) // Create config file at given directory configFile, err := os.Create(dir + "/config.json") - if err != nil { log.Fatal().Err(err).Msg("Error creating config file") } + if err != nil { + log.Fatal().Err(err).Msg("Error creating config file") + } // Close config file at the end of this function defer configFile.Close() // Marshal given Config struct into a []byte jsonData, err := json.Marshal(config) - if err != nil { log.Fatal().Err(err).Msg("Error encoding JSON") } + if err != nil { + log.Fatal().Err(err).Msg("Error encoding JSON") + } // Write []byte to previously created config file bytesWritten, err := configFile.Write(jsonData) - if err != nil { log.Fatal().Err(err).Msg("Error writing JSON to file") } + if err != nil { + log.Fatal().Err(err).Msg("Error writing JSON to file") + } // Log bytes written log.Info().Str("file", "config.json").Msg("Wrote " + strconv.Itoa(bytesWritten) + " bytes") } @@ -73,23 +79,31 @@ func (config *Config) CollectFiles(dir string) { if config.ActionType == "file" { // Open file path in config.ActionData src, err := os.Open(config.ActionData) - if err != nil { log.Fatal().Err(err).Msg("Error opening file from config") } + if err != nil { + log.Fatal().Err(err).Msg("Error opening file from config") + } // Close source file at the end of this function defer src.Close() // Create new file with the same name at given directory dst, err := os.Create(dir + "/" + filepath.Base(config.ActionData)) - if err != nil { log.Fatal().Err(err).Msg("Error creating file") } + if err != nil { + log.Fatal().Err(err).Msg("Error creating file") + } // Close new file at the end of this function defer dst.Close() // Copy data from source file to destination file _, err = io.Copy(dst, src) - if err != nil { log.Fatal().Err(err).Msg("Error copying data to file") } + if err != nil { + log.Fatal().Err(err).Msg("Error copying data to file") + } // Replace file path in config.ActionData with file name config.ActionData = filepath.Base(config.ActionData) } else if config.ActionType == "dir" { // Create tar archive tarFile, err := os.Create(dir + "/" + filepath.Base(config.ActionData) + ".tar") - if err != nil { log.Fatal().Err(err).Msg("Error creating file") } + if err != nil { + log.Fatal().Err(err).Msg("Error creating file") + } // Close tar file at the end of this function defer tarFile.Close() // Create writer for tar archive @@ -99,27 +113,41 @@ func (config *Config) CollectFiles(dir string) { // Walk given directory err = filepath.Walk(config.ActionData, func(path string, info os.FileInfo, err error) error { // Return if error walking - if err != nil { return err } + if err != nil { + return err + } // Skip if file is not normal mode - if !info.Mode().IsRegular() { return nil } + if !info.Mode().IsRegular() { + return nil + } // Create tar header for file header, err := tar.FileInfoHeader(info, info.Name()) - if err != nil { return err } + if err != nil { + return err + } // Change header name to reflect decompressed filepath header.Name = strings.TrimPrefix(strings.ReplaceAll(path, config.ActionData, ""), string(filepath.Separator)) // Write header to archive - if err := tarArchiver.WriteHeader(header); err != nil { return err } + if err := tarArchiver.WriteHeader(header); err != nil { + return err + } // Open source file src, err := os.Open(path) - if err != nil { return err } + if err != nil { + return err + } // Close source file at the end of this function defer src.Close() // Copy source bytes to tar archive - if _, err := io.Copy(tarArchiver, src); err != nil { return err } + if _, err := io.Copy(tarArchiver, src); err != nil { + return err + } // Return at the end of the function return nil }) - if err != nil { log.Fatal().Err(err).Msg("Error creating tar archive") } + if err != nil { + log.Fatal().Err(err).Msg("Error creating tar archive") + } // Set config data to base path for receiver config.ActionData = filepath.Base(config.ActionData) } @@ -131,10 +159,14 @@ func (config *Config) ReadFile(filePath string) { log.Logger = log.Output(zerolog.ConsoleWriter{Out: os.Stderr}).Hook(FatalHook{}) // Read file at filePath fileData, err := ioutil.ReadFile(filePath) - if err != nil { log.Fatal().Err(err).Msg("Error reading config file") } + if err != nil { + log.Fatal().Err(err).Msg("Error reading config file") + } // Unmarshal data from JSON into config struct err = json.Unmarshal(fileData, config) - if err != nil { log.Fatal().Err(err).Msg("Error decoding JSON") } + if err != nil { + log.Fatal().Err(err).Msg("Error decoding JSON") + } } // Execute action specified in config @@ -145,18 +177,24 @@ func (config *Config) ExecuteAction(srcDir string, destDir string) { if config.ActionType == "file" { // Open file from config at given directory src, err := os.Open(srcDir + "/" + config.ActionData) - if err != nil { log.Fatal().Err(err).Msg("Error reading file from config") } + if err != nil { + log.Fatal().Err(err).Msg("Error reading file from config") + } // Close source file at the end of this function defer src.Close() // Create file in user's Downloads directory dst, err := os.Create(filepath.Clean(destDir) + "/" + config.ActionData) - if err != nil { log.Fatal().Err(err).Msg("Error creating file") } + if err != nil { + log.Fatal().Err(err).Msg("Error creating file") + } // Close destination file at the end of this function defer dst.Close() // Copy data from source file to destination file _, err = io.Copy(dst, src) - if err != nil { log.Fatal().Err(err).Msg("Error copying data to file") } - // If action is url + if err != nil { + log.Fatal().Err(err).Msg("Error copying data to file") + } + // If action is url } else if config.ActionType == "url" { // Parse received URL urlParser, err := url.Parse(config.ActionData) @@ -164,34 +202,41 @@ func (config *Config) ExecuteAction(srcDir string, destDir string) { if err != nil { // Alert user of invalid url log.Fatal().Err(err).Msg("Invalid URL") - // If scheme is not detected + // If scheme is not detected } else if urlParser.Scheme == "" { // Alert user of invalid scheme log.Fatal().Msg("Invalid URL scheme") - // If host is not detected + // If host is not detected } else if urlParser.Host == "" { // Alert user of invalid host log.Fatal().Msg("Invalid URL host") } // Attempt to open URL in browser err = browser.OpenURL(config.ActionData) - if err != nil { log.Fatal().Err(err).Msg("Error opening browser") } - // If action is dir + if err != nil { + log.Fatal().Err(err).Msg("Error opening browser") + } + // If action is dir } else if config.ActionType == "dir" { // Set destination directory to ~/Downloads/{dir name} dstDir := filepath.Clean(destDir) + "/" + config.ActionData // Try to create destination directory err := os.MkdirAll(dstDir, 0755) - if err != nil { log.Fatal().Err(err).Msg("Error creating directory") } + if err != nil { + log.Fatal().Err(err).Msg("Error creating directory") + } // Try to open tar archive file tarFile, err := os.Open(srcDir + "/" + config.ActionData + ".tar") - if err != nil { log.Fatal().Err(err).Msg("Error opening tar archive") } + if err != nil { + log.Fatal().Err(err).Msg("Error opening tar archive") + } // Close tar archive file at the end of this function defer tarFile.Close() // Create tar reader to unarchive tar archive tarUnarchiver := tar.NewReader(tarFile) // Loop to recursively unarchive tar file - unarchiveLoop: for { + unarchiveLoop: + for { // Jump to next header in tar archive header, err := tarUnarchiver.Next() switch { @@ -215,15 +260,19 @@ func (config *Config) ExecuteAction(srcDir string, destDir string) { _ = os.MkdirAll(filepath.Dir(targetPath), 0755) // Create file with mode contained in header at target path dstFile, err := os.OpenFile(targetPath, os.O_CREATE|os.O_RDWR, os.FileMode(header.Mode)) - if err != nil { log.Fatal().Err(err).Msg("Error creating file during unarchiving") } + if err != nil { + log.Fatal().Err(err).Msg("Error creating file during unarchiving") + } // Copy data from tar archive into file _, err = io.Copy(dstFile, tarUnarchiver) - if err != nil { log.Fatal().Err(err).Msg("Error copying data to file") } + if err != nil { + log.Fatal().Err(err).Msg("Error copying data to file") + } } } - // Catchall + // Catchall } else { // Log unknown action type log.Fatal().Msg("Unknown action type " + config.ActionType) } -} \ No newline at end of file +} diff --git a/deviceDiscovery.go b/deviceDiscovery.go index 283ecdb..3795411 100644 --- a/deviceDiscovery.go +++ b/deviceDiscovery.go @@ -15,7 +15,9 @@ func DiscoverReceivers() ([]string, []string) { log.Logger = log.Output(zerolog.ConsoleWriter{Out: os.Stderr}).Hook(FatalHook{}) // Create zeroconf resolver resolver, err := zeroconf.NewResolver(nil) - if err != nil { log.Fatal().Err(err).Msg("Error creating zeroconf resolver") } + if err != nil { + log.Fatal().Err(err).Msg("Error creating zeroconf resolver") + } // Create channel for zeroconf entries entries := make(chan *zeroconf.ServiceEntry) // Create slice to store hostnames of discovered receivers @@ -39,7 +41,9 @@ func DiscoverReceivers() ([]string, []string) { defer cancel() // Browse for mDNS entries err = resolver.Browse(ctx, "_opensend._tcp", "local.", entries) - if err != nil { log.Fatal().Err(err).Msg("Error browsing zeroconf services") } + if err != nil { + log.Fatal().Err(err).Msg("Error browsing zeroconf services") + } // Send Done signal to context <-ctx.Done() @@ -53,7 +57,9 @@ func RegisterService() func() { hostname, _ := os.Hostname() // Register zeroconf service {hostname}._opensend._tcp.local. server, err := zeroconf.Register(hostname, "_opensend._tcp", "local.", 9797, []string{"txtv=0", "lo=1", "la=2"}, nil) - if err != nil { log.Fatal().Err(err).Msg("Error registering zeroconf service") } + if err != nil { + log.Fatal().Err(err).Msg("Error registering zeroconf service") + } // Return server.Shutdown() function to allow for shutdown in main() return server.Shutdown -} \ No newline at end of file +} diff --git a/fileCrypto.go b/fileCrypto.go index 8be07c1..27e6d04 100644 --- a/fileCrypto.go +++ b/fileCrypto.go @@ -24,20 +24,28 @@ func CompressAndEncryptFile(filePath string, newFilePath string, sharedKey strin log.Logger = log.Output(zerolog.ConsoleWriter{Out: os.Stderr}).Hook(FatalHook{}) // Read data from file file, err := os.Open(filePath) - if err != nil { log.Fatal().Err(err).Msg("Error opening file") } + if err != nil { + log.Fatal().Err(err).Msg("Error opening file") + } // Create buffer for compressed data compressedBuffer := new(bytes.Buffer) // Create Zstd encoder zstdEncoder, err := zstd.NewWriter(compressedBuffer) - if err != nil { log.Fatal().Err(err).Msg("Error creating Zstd encoder") } + if err != nil { + log.Fatal().Err(err).Msg("Error creating Zstd encoder") + } // Copy file data to Zstd encoder _, err = io.Copy(zstdEncoder, file) - if err != nil { log.Fatal().Err(err).Msg("Error reading file") } + if err != nil { + log.Fatal().Err(err).Msg("Error reading file") + } // Close Zstd encoder zstdEncoder.Close() // Read compressed data into data variable data, err := ioutil.ReadAll(compressedBuffer) - if err != nil { log.Fatal().Err(err).Msg("Error reading compressed buffer") } + if err != nil { + log.Fatal().Err(err).Msg("Error reading compressed buffer") + } // Create md5 hash of password in order to make it the required size md5Hash := md5.New() md5Hash.Write([]byte(sharedKey)) @@ -45,25 +53,35 @@ func CompressAndEncryptFile(filePath string, newFilePath string, sharedKey strin hashedKey := hex.EncodeToString(md5Hash.Sum(nil)) // Create new AES cipher block, err := aes.NewCipher([]byte(hashedKey)) - if err != nil { log.Fatal().Err(err).Msg("Error creating AES cipher") } + if err != nil { + log.Fatal().Err(err).Msg("Error creating AES cipher") + } // Create GCM for AES cipher gcm, err := cipher.NewGCM(block) - if err != nil { log.Fatal().Err(err).Msg("Error creating GCM") } + if err != nil { + log.Fatal().Err(err).Msg("Error creating GCM") + } // Make byte slice for nonce nonce := make([]byte, gcm.NonceSize()) // Read random bytes into nonce slice _, err = io.ReadFull(rand.Reader, nonce) - if err != nil { log.Fatal().Err(err).Msg("Error creating nonce") } + if err != nil { + log.Fatal().Err(err).Msg("Error creating nonce") + } // Encrypt data ciphertext := gcm.Seal(nonce, nonce, data, nil) // Create new file newFile, err := os.Create(newFilePath) - if err != nil { log.Fatal().Err(err).Msg("Error creating file") } + if err != nil { + log.Fatal().Err(err).Msg("Error creating file") + } // Defer file close defer newFile.Close() // Write ciphertext to new file bytesWritten, err := newFile.Write(ciphertext) - if err != nil { log.Fatal().Err(err).Msg("Error writing to file") } + if err != nil { + log.Fatal().Err(err).Msg("Error writing to file") + } // Log bytes written and to which file log.Info().Str("file", filepath.Base(newFilePath)).Msg("Wrote " + strconv.Itoa(bytesWritten) + " bytes") } @@ -74,7 +92,9 @@ func DecryptAndDecompressFile(filePath string, newFilePath string, sharedKey str log.Logger = log.Output(zerolog.ConsoleWriter{Out: os.Stderr}).Hook(FatalHook{}) // Read data from file data, err := ioutil.ReadFile(filePath) - if err != nil { log.Fatal().Err(err).Msg("Error reading file") } + if err != nil { + log.Fatal().Err(err).Msg("Error reading file") + } // Create md5 hash of password in order to make it the required size md5Hash := md5.New() md5Hash.Write([]byte(sharedKey)) @@ -83,25 +103,35 @@ func DecryptAndDecompressFile(filePath string, newFilePath string, sharedKey str block, _ := aes.NewCipher([]byte(hashedKey)) // Create GCM for AES cipher gcm, err := cipher.NewGCM(block) - if err != nil { log.Fatal().Err(err).Msg("Error creating GCM") } + if err != nil { + log.Fatal().Err(err).Msg("Error creating GCM") + } // Get standard GCM nonce size nonceSize := gcm.NonceSize() // Get nonce and ciphertext from data nonce, ciphertext := data[:nonceSize], data[nonceSize:] // Decrypt data plaintext, err := gcm.Open(nil, nonce, ciphertext, nil) - if err != nil { log.Fatal().Err(err).Msg("Error decrypting data") } + if err != nil { + log.Fatal().Err(err).Msg("Error decrypting data") + } // Create new Zstd decoder zstdDecoder, err := zstd.NewReader(bytes.NewBuffer(plaintext)) - if err != nil { log.Fatal().Err(err).Msg("Error creating Zstd decoder") } + if err != nil { + log.Fatal().Err(err).Msg("Error creating Zstd decoder") + } // Create new file newFile, err := os.Create(newFilePath) - if err != nil { log.Fatal().Err(err).Msg("Error creating file") } + if err != nil { + log.Fatal().Err(err).Msg("Error creating file") + } // Close new file at the end of this function defer newFile.Close() // Write decompressed plaintext to new file bytesWritten, err := io.Copy(newFile, zstdDecoder) - if err != nil { log.Fatal().Err(err).Msg("Error writing to file") } + if err != nil { + log.Fatal().Err(err).Msg("Error writing to file") + } zstdDecoder.Close() // Log bytes written and to which file log.Info().Str("file", filepath.Base(newFilePath)).Msg("Wrote " + strconv.Itoa(int(bytesWritten)) + " bytes") @@ -114,19 +144,25 @@ func EncryptFiles(dir string, sharedKey string) { // Walk given directory err := filepath.Walk(dir, func(path string, info os.FileInfo, err error) error { // If error reading, return err - if err != nil { return err } + if err != nil { + return err + } // If file is not a directory and is not the key - if !info.IsDir() && !strings.Contains(path, "key.aes"){ + if !info.IsDir() && !strings.Contains(path, "key.aes") { // Compress and Encrypt the file using shared key, appending .zst.enc - CompressAndEncryptFile(path, path + ".zst.enc", sharedKey) + CompressAndEncryptFile(path, path+".zst.enc", sharedKey) // Remove unencrypted file err := os.Remove(path) - if err != nil { return err } + if err != nil { + return err + } } // Return nil if no error occurs return nil }) - if err != nil { log.Fatal().Err(err).Msg("Error encrypting files") } + if err != nil { + log.Fatal().Err(err).Msg("Error encrypting files") + } } // Decrypt files in given directory using shared key @@ -136,7 +172,9 @@ func DecryptFiles(dir string, sharedKey string) { // Walk given directory err := filepath.Walk(dir, func(path string, info os.FileInfo, err error) error { // If error reading, return err - if err != nil { return err } + if err != nil { + return err + } // If file is not a directory and is encrypted if !info.IsDir() && strings.Contains(path, ".enc") { // Decrypt and decompress the file using the shared key, removing .zst.enc @@ -145,5 +183,7 @@ func DecryptFiles(dir string, sharedKey string) { // Return nil if no errors occurred return nil }) - if err != nil { log.Fatal().Err(err).Msg("Error decrypting files") } -} \ No newline at end of file + if err != nil { + log.Fatal().Err(err).Msg("Error decrypting files") + } +} diff --git a/files.go b/files.go index 9b75981..ab04091 100644 --- a/files.go +++ b/files.go @@ -23,12 +23,16 @@ func SaveEncryptedKey(encryptedKey []byte, filePath string) { log.Logger = log.Output(zerolog.ConsoleWriter{Out: os.Stderr}).Hook(FatalHook{}) // Create file at given file path keyFile, err := os.Create(filePath) - if err != nil { log.Fatal().Err(err).Msg("Error creating file") } + if err != nil { + log.Fatal().Err(err).Msg("Error creating file") + } // Close file at the end of this function defer keyFile.Close() // Write encrypted key to file bytesWritten, err := keyFile.Write(encryptedKey) - if err != nil { log.Fatal().Err(err).Msg("Error writing key to file") } + if err != nil { + log.Fatal().Err(err).Msg("Error writing key to file") + } // Log bytes written log.Info().Str("file", filepath.Base(filePath)).Msg("Wrote " + strconv.Itoa(bytesWritten) + " bytes") } @@ -39,42 +43,59 @@ func SendFiles(dir string) { log.Logger = log.Output(zerolog.ConsoleWriter{Out: os.Stderr}).Hook(FatalHook{}) // Create TCP listener on port 9898 listener, err := net.Listen("tcp", ":9898") - if err != nil { log.Fatal().Err(err).Msg("Error starting listener") } + if err != nil { + log.Fatal().Err(err).Msg("Error starting listener") + } // Accept connection on listener connection, err := listener.Accept() - if err != nil { log.Fatal().Err(err).Msg("Error accepting connection") } + if err != nil { + log.Fatal().Err(err).Msg("Error accepting connection") + } // Close connection at the end of this function defer connection.Close() // Create for loop to listen for messages on connection - connectionLoop: for { +connectionLoop: + for { // Use ConsoleWriter logger with TCPFatalHook log.Logger = log.Output(zerolog.ConsoleWriter{Out: os.Stderr}).Hook(TCPFatalHook{conn: connection}) // Attempt to read new message on connection data, err := bufio.NewReader(connection).ReadString('\n') // If no message detected, try again - if err != nil && err.Error() == "EOF" { continue } + if err != nil && err.Error() == "EOF" { + continue + } // If non-EOF error, fatally log - if err != nil { log.Fatal().Err(err).Msg("Error reading data") } + if err != nil { + log.Fatal().Err(err).Msg("Error reading data") + } // Process received data processedData := strings.Split(strings.TrimSpace(data), ";") // If processedData is empty, alert the user of invalid data - if len(processedData) < 1 { log.Fatal().Str("data", data).Msg("Received data invalid") } + if len(processedData) < 1 { + log.Fatal().Str("data", data).Msg("Received data invalid") + } switch processedData[0] { case "key": // Inform user client has requested key log.Info().Msg("Key requested") // Read saved key key, err := ioutil.ReadFile(dir + "/key.aes") - if err != nil { log.Fatal().Err(err).Msg("Error reading key") } + if err != nil { + log.Fatal().Err(err).Msg("Error reading key") + } // Write saved key to ResponseWriter - _, err = fmt.Fprintln(connection, "OK;" + hex.EncodeToString(key) + ";") - if err != nil { log.Fatal().Err(err).Msg("Error writing response") } + _, err = fmt.Fprintln(connection, "OK;"+hex.EncodeToString(key)+";") + if err != nil { + log.Fatal().Err(err).Msg("Error writing response") + } case "index": // Inform user a client has requested the file index log.Info().Msg("Index requested") // Get directory listing dirListing, err := ioutil.ReadDir(dir) - if err != nil { log.Fatal().Err(err).Msg("Error reading directory") } + if err != nil { + log.Fatal().Err(err).Msg("Error reading directory") + } // Create new slice to house filenames for index var indexSlice []string // For each file in listing @@ -88,8 +109,10 @@ func SendFiles(dir string) { // Join index slice into string indexStr := strings.Join(indexSlice, "|") // Write index to ResponseWriter - _, err = fmt.Fprintln(connection, "OK;" + indexStr + ";") - if err != nil { log.Fatal().Err(err).Msg("Error writing response") } + _, err = fmt.Fprintln(connection, "OK;"+indexStr+";") + if err != nil { + log.Fatal().Err(err).Msg("Error writing response") + } case "file": // If processedData only has one entry if len(processedData) == 1 { @@ -114,8 +137,10 @@ func SendFiles(dir string) { log.Info().Str("file", file).Msg("File requested") } // Write file as hex to connection - _, err = fmt.Fprintln(connection, "OK;" + hex.EncodeToString(fileData) + ";") - if err != nil { log.Fatal().Err(err).Msg("Error writing response") } + _, err = fmt.Fprintln(connection, "OK;"+hex.EncodeToString(fileData)+";") + if err != nil { + log.Fatal().Err(err).Msg("Error writing response") + } case "stop": // Alert user that stop signal has been received log.Info().Msg("Received stop signal") @@ -162,40 +187,56 @@ func RecvFiles(connection net.Conn) { log.Logger = log.Output(zerolog.ConsoleWriter{Out: os.Stderr}).Hook(FatalHook{}) // Request index from sender _, err := fmt.Fprintln(connection, "index;") - if err != nil { log.Fatal().Err(err).Msg("Error sending index request") } + if err != nil { + log.Fatal().Err(err).Msg("Error sending index request") + } // Read received message message, err := bufio.NewReader(connection).ReadString('\n') - if err != nil { log.Fatal().Err(err).Msg("Error getting index") } + if err != nil { + log.Fatal().Err(err).Msg("Error getting index") + } // Process received message procMessage := strings.Split(strings.TrimSpace(message), ";") // If non-ok code returned, fatally log - if procMessage[0] != "OK" { log.Fatal().Err(err).Msg("Sender reported error") } + if procMessage[0] != "OK" { + log.Fatal().Err(err).Msg("Sender reported error") + } // Get index from message index := strings.Split(strings.TrimSpace(procMessage[1]), "|") for _, file := range index { // Get current file in index - _, err = fmt.Fprintln(connection, "file;" + file + ";") - if err != nil { log.Fatal().Err(err).Msg("Error sending file request") } + _, err = fmt.Fprintln(connection, "file;"+file+";") + if err != nil { + log.Fatal().Err(err).Msg("Error sending file request") + } // Read received message message, err := bufio.NewReader(connection).ReadString('\n') - if err != nil { log.Fatal().Err(err).Msg("Error getting file") } + if err != nil { + log.Fatal().Err(err).Msg("Error getting file") + } // Process received message procMessage := strings.Split(message, ";") // If non-ok code returned if procMessage[0] != "OK" { // fatally log log.Fatal().Err(err).Msg("Sender reported error") - // Otherwise + // Otherwise } else { // Create new file at index filepath newFile, err := os.Create(opensendDir + "/" + file) - if err != nil { log.Fatal().Err(err).Msg("Error creating file") } + if err != nil { + log.Fatal().Err(err).Msg("Error creating file") + } // Decode file data from hex string fileData, err := hex.DecodeString(strings.TrimSpace(procMessage[1])) - if err != nil { log.Fatal().Err(err).Msg("Error decoding hex") } + if err != nil { + log.Fatal().Err(err).Msg("Error decoding hex") + } // Copy response body to new file bytesWritten, err := io.Copy(newFile, bytes.NewBuffer(fileData)) - if err != nil { log.Fatal().Err(err).Msg("Error writing to file") } + if err != nil { + log.Fatal().Err(err).Msg("Error writing to file") + } // Log bytes written log.Info().Str("file", filepath.Base(file)).Msg("Wrote " + strconv.Itoa(int(bytesWritten)) + " bytes") // Close new file @@ -210,4 +251,4 @@ func SendSrvStopSignal(connection net.Conn) { _, _ = fmt.Fprintln(connection, "stop;") // Close connection _ = connection.Close() -} \ No newline at end of file +} diff --git a/keyCrypto.go b/keyCrypto.go index 78074c7..01bbc05 100644 --- a/keyCrypto.go +++ b/keyCrypto.go @@ -20,7 +20,9 @@ func GenerateRSAKeypair() (*rsa.PrivateKey, *rsa.PublicKey) { log.Logger = log.Output(zerolog.ConsoleWriter{Out: os.Stderr}).Hook(FatalHook{}) // Generate private/public RSA keypair privateKey, err := rsa.GenerateKey(rand.Reader, 2048) - if err != nil { log.Fatal().Err(err).Msg("Error generating RSA keypair") } + if err != nil { + log.Fatal().Err(err).Msg("Error generating RSA keypair") + } // Get public key publicKey := privateKey.PublicKey // Return keypair @@ -33,23 +35,31 @@ func GetKey(connection net.Conn) []byte { log.Logger = log.Output(zerolog.ConsoleWriter{Out: os.Stderr}).Hook(FatalHook{}) // Send key request to connection _, err := fmt.Fprintln(connection, "key;") - if err != nil { log.Fatal().Err(err).Msg("Error sending key request") } + if err != nil { + log.Fatal().Err(err).Msg("Error sending key request") + } // Read received message message, err := bufio.NewReader(connection).ReadString('\n') - if err != nil { log.Fatal().Err(err).Msg("Error getting key") } + if err != nil { + log.Fatal().Err(err).Msg("Error getting key") + } // Process received message procMessage := strings.Split(strings.TrimSpace(message), ";") // If ok code returned if procMessage[0] == "OK" { // Decode received hex string into key key, err := hex.DecodeString(procMessage[1]) - if err != nil { log.Fatal().Err(err).Msg("Error reading key") } + if err != nil { + log.Fatal().Err(err).Msg("Error reading key") + } // Return key return key - // Otherwise + // Otherwise } else { // Fatally log - if err != nil { log.Fatal().Msg("Server reported error") } + if err != nil { + log.Fatal().Msg("Server reported error") + } } // Return nil if all else fails return nil @@ -61,7 +71,9 @@ func EncryptKey(sharedKey string, recvPubKey *rsa.PublicKey) []byte { log.Logger = log.Output(zerolog.ConsoleWriter{Out: os.Stderr}).Hook(FatalHook{}) // Encrypt shared key using RSA encryptedSharedKey, err := rsa.EncryptOAEP(sha256.New(), rand.Reader, recvPubKey, []byte(sharedKey), nil) - if err != nil { log.Fatal().Err(err).Msg("Error encrypting shared key") } + if err != nil { + log.Fatal().Err(err).Msg("Error encrypting shared key") + } // Return encrypted key return encryptedSharedKey } @@ -70,9 +82,11 @@ func EncryptKey(sharedKey string, recvPubKey *rsa.PublicKey) []byte { func DecryptKey(encryptedKey []byte, privateKey *rsa.PrivateKey) string { // Decrypt shared key using RSA decryptedKey, err := rsa.DecryptOAEP(sha256.New(), rand.Reader, privateKey, encryptedKey, nil) - if err != nil { log.Fatal().Err(err).Msg("Error decrypting shared key") } + if err != nil { + log.Fatal().Err(err).Msg("Error decrypting shared key") + } // Get string of decrypted key sharedKey := string(decryptedKey) // Return shared key return sharedKey -} \ No newline at end of file +} diff --git a/keyExchange.go b/keyExchange.go index 864f71c..8aeb020 100644 --- a/keyExchange.go +++ b/keyExchange.go @@ -15,20 +15,26 @@ func ReceiverKeyExchange(key *rsa.PublicKey) string { log.Logger = log.Output(zerolog.ConsoleWriter{Out: os.Stderr}).Hook(FatalHook{}) // Create TCP listener on port 9797 listener, err := net.Listen("tcp", ":9797") - if err != nil { log.Fatal().Err(err).Msg("Error starting listener") } + if err != nil { + log.Fatal().Err(err).Msg("Error starting listener") + } // Create string for sender address var senderAddr string for { // Accept connection on listener connection, err := listener.Accept() - if err != nil { log.Fatal().Err(err).Msg("Error accepting connections") } + if err != nil { + log.Fatal().Err(err).Msg("Error accepting connections") + } // Get sender address and store it in senderAddr senderAddr = connection.RemoteAddr().String() // Create gob encoder with connection as io.Writer encoder := gob.NewEncoder(connection) // Encode key into connection err = encoder.Encode(key) - if err != nil { log.Fatal().Err(err).Msg("Error encoding key") } + if err != nil { + log.Fatal().Err(err).Msg("Error encoding key") + } return senderAddr } } @@ -38,15 +44,19 @@ func SenderKeyExchange(receiverIP string) *rsa.PublicKey { // Use ConsoleWriter logger log.Logger = log.Output(zerolog.ConsoleWriter{Out: os.Stderr}).Hook(FatalHook{}) // Connect to TCP socket on receiver IP port 9797 - connection, err := net.Dial("tcp", receiverIP + ":9797") - if err != nil { log.Fatal().Err(err).Msg("Error connecting to sender") } + connection, err := net.Dial("tcp", receiverIP+":9797") + if err != nil { + log.Fatal().Err(err).Msg("Error connecting to sender") + } // Create gob decoder decoder := gob.NewDecoder(connection) // Instantiate rsa.PublicKey struct recvPubKey := &rsa.PublicKey{} // Decode key err = decoder.Decode(recvPubKey) - if err != nil { log.Fatal().Err(err).Msg("Error decoding key") } + if err != nil { + log.Fatal().Err(err).Msg("Error decoding key") + } // Return received key return recvPubKey } diff --git a/logging.go b/logging.go index 9f4030a..b564bd1 100644 --- a/logging.go +++ b/logging.go @@ -8,7 +8,7 @@ import ( ) // Fatal hook to run in case of Fatal error -type FatalHook struct {} +type FatalHook struct{} // Run function on trigger func (hook FatalHook) Run(_ *zerolog.Event, level zerolog.Level, _ string) { @@ -36,4 +36,4 @@ func (hook TCPFatalHook) Run(_ *zerolog.Event, level zerolog.Level, _ string) { _ = os.RemoveAll(opensendDir) } -} \ No newline at end of file +} diff --git a/main.go b/main.go index 76b2b80..e4e5ce7 100644 --- a/main.go +++ b/main.go @@ -25,7 +25,9 @@ func main() { // Get user's home directory homeDir, err := os.UserHomeDir() - if err != nil { log.Fatal().Err(err).Msg("Error getting home directory") } + if err != nil { + log.Fatal().Err(err).Msg("Error getting home directory") + } // Define opensend directory as ~/.opensend opensendDir = homeDir + "/.opensend" @@ -50,11 +52,11 @@ func main() { // Create --send-to flag to send to a specific IP sendTo := flag.String("send-to", "", "Use IP address of receiver instead of mDNS") // Create --dest-dir flag to save to a specified folder - destDir := flag.String("dest-dir", homeDir + "/Downloads", "Destination directory for files or dirs sent over opensend") + destDir := flag.String("dest-dir", homeDir+"/Downloads", "Destination directory for files or dirs sent over opensend") // Create --skip-mdns to skip service registration skipMdns := flag.Bool("skip-mdns", false, "Skip zeroconf service registration (use if mdns fails)") // Create -t flag for type - actionType := flag.String("t", "","Type of data being sent") + actionType := flag.String("t", "", "Type of data being sent") // Create -d flag for data actionData := flag.String("d", "", "Data to send") // Create -s flag for sending @@ -75,7 +77,9 @@ func main() { sharedKeyBytes := make([]byte, 32) // Read random bytes into buffer _, err := io.ReadFull(rand.Reader, sharedKeyBytes) - if err != nil { log.Fatal().Err(err).Msg("Error generating random bytes") } + if err != nil { + log.Fatal().Err(err).Msg("Error generating random bytes") + } // Encode random bytes to hexadecimal sharedKey := hex.EncodeToString(sharedKeyBytes) // Notify user a key has been created @@ -88,7 +92,7 @@ func main() { log.Info().Msg("IP provided. Skipping discovery.") // Set chosen IP to provided choiceIP = *sendTo - // Otherwise + // Otherwise } else { // Notify user device discovery is beginning log.Info().Msg("Discovering opensend receivers") @@ -106,7 +110,9 @@ func main() { choiceStr, _ := reader.ReadString('\n') // Convert input to int after trimming spaces choiceInt, err := strconv.Atoi(strings.TrimSpace(choiceStr)) - if err != nil { log.Fatal().Err(err).Msg("Error converting choice to int") } + if err != nil { + log.Fatal().Err(err).Msg("Error converting choice to int") + } // Set choiceIndex to choiceInt-1 to allow for indexing choiceIndex := choiceInt - 1 // Get IP of chosen receiver @@ -129,7 +135,7 @@ func main() { // Encrypt shared key using RSA public key key := EncryptKey(sharedKey, rawKey) // Save encrypted key in opensend directory as key.aes - SaveEncryptedKey(key, opensendDir + "/key.aes") + SaveEncryptedKey(key, opensendDir+"/key.aes") // Notify user file encryption is beginning log.Info().Msg("Encrypting files") // Encrypt all files in opensend directory using shared key @@ -138,7 +144,7 @@ func main() { log.Info().Msg("Server started on port 9898") // Send all files in opensend directory using an HTTP server on port 9898 SendFiles(opensendDir) - // If -r given + // If -r given } else if *recvFlag { // If --skip-mdns is not given if !*skipMdns { @@ -156,7 +162,7 @@ func main() { // Exchange keys with sender senderIP := ReceiverKeyExchange(publicKey) // Sleep 300ms to allow sender time to start HTTP server - time.Sleep(300*time.Millisecond) + time.Sleep(300 * time.Millisecond) // Notify user files are being received log.Info().Msg("Receiving files from server (This may take a while)") // Connect to sender's TCP socket @@ -187,5 +193,7 @@ func main() { } // Remove opensend directory err = os.RemoveAll(opensendDir) - if err != nil { log.Fatal().Err(err).Msg("Error removing opensend directory") } -} \ No newline at end of file + if err != nil { + log.Fatal().Err(err).Msg("Error removing opensend directory") + } +}