burgerbackup/lib/client/main.go

125 lines
2.8 KiB
Go
Raw Permalink Normal View History

2024-07-12 21:53:59 +01:00
package client
import (
"bytes"
"concord.hectabit.org/Hectabit/burgerbackup/lib/common"
"encoding/base64"
2024-07-12 21:53:59 +01:00
"encoding/json"
"errors"
"golang.org/x/crypto/argon2"
2024-07-12 21:53:59 +01:00
"io"
"log"
"mime/multipart"
2024-07-12 21:53:59 +01:00
"net/http"
"os"
"strconv"
2024-07-12 21:53:59 +01:00
)
func PerformBackup(fileLocation string, backupKey string, cryptoKey string, remoteURL string) (error, int) {
2024-07-12 21:53:59 +01:00
fileContent, err := os.ReadFile(fileLocation)
if err != nil {
log.Println("[CRITICAL] Unknown in PerformBackup() file read:", err)
2024-07-12 21:53:59 +01:00
return err, 0
}
fileInfo, err := os.Stat(fileLocation)
2024-07-12 21:53:59 +01:00
if err != nil {
log.Println("[CRITICAL] Unknown in PerformBackup() file stat:", err)
2024-07-12 21:53:59 +01:00
return err, 1
}
filename := fileInfo.Name()
content := map[string]interface{}{
"filename": filename,
"content": base64.StdEncoding.EncodeToString(fileContent),
}
marshaledContent, err := json.Marshal(content)
if err != nil {
log.Println("[CRITICAL] Unknown in PerformBackup() content marshal:", err)
return err, 2
}
cryptoKeyHashed := argon2.IDKey([]byte(cryptoKey), []byte("burgerbackup"), 1, 64*1024, 4, 32)
encryptedContent, err := common.EncryptAES(cryptoKeyHashed, marshaledContent)
if err != nil {
log.Println("[CRITICAL] Unknown in PerformBackup() content encryption", err)
return err, 3
}
2024-07-12 21:53:59 +01:00
encryptedFile := io.NopCloser(bytes.NewReader(encryptedContent))
err, errCode := SendFileToServer(encryptedFile, backupKey, remoteURL, filename)
2024-07-12 21:53:59 +01:00
if err != nil {
return err, errCode + 4
2024-07-12 21:53:59 +01:00
}
log.Println("[INFO] Backup completed at:")
return nil, -1
}
func SendFileToServer(file io.Reader, backupKey string, remoteURL string, filename string) (error, int) {
sendBody := &bytes.Buffer{}
writer := multipart.NewWriter(sendBody)
part, err := writer.CreateFormFile("file", filename)
2024-07-12 21:53:59 +01:00
if err != nil {
return err, 0
}
_, err = io.Copy(part, file)
if err != nil {
return err, 1
}
err = writer.Close()
if err != nil {
return err, 3
}
req, err := http.NewRequest("POST", remoteURL, sendBody)
if err != nil {
return err, 4
}
2024-07-12 21:53:59 +01:00
salt, err := common.GenSalt(16)
hashedBackupKey, err := common.Hash(backupKey, salt)
if err != nil {
return err, 5
2024-07-12 21:53:59 +01:00
}
req.Header.Set("Authorization", hashedBackupKey)
req.Header.Set("Content-Type", writer.FormDataContentType())
req.Header.Set("Content-Length", strconv.Itoa(sendBody.Len()))
2024-07-12 21:53:59 +01:00
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
return err, 6
2024-07-12 21:53:59 +01:00
}
defer func(Body io.ReadCloser) {
err := Body.Close()
if err != nil {
log.Println("[ERROR] Error in sendFileToServer() response defer:", err)
}
}(resp.Body)
body, err := io.ReadAll(resp.Body)
if err != nil {
return err, 7
2024-07-12 21:53:59 +01:00
}
var response map[string]interface{}
err = json.Unmarshal(body, &response)
if err != nil {
return err, 8
2024-07-12 21:53:59 +01:00
}
if resp.StatusCode != 200 {
err, ok := response["goErr"].(string)
if !ok {
err = "error not sent by server"
}
return errors.New(err), 9
2024-07-12 21:53:59 +01:00
}
return nil, -1
}