From b5a99751decc43f38c679e7f9309fc7e6c6c6597 Mon Sep 17 00:00:00 2001 From: Felicitas Pojtinger Date: Thu, 2 Dec 2021 12:16:05 +0100 Subject: [PATCH] feat: Allow automatic re-indexing without private key --- cmd/stbak/cmd/archive.go | 60 ++++++++++++++++++--------------- cmd/stbak/cmd/recovery_index.go | 41 ++++++++++++++++------ cmd/stbak/cmd/update.go | 41 ++++++++++++---------- 3 files changed, 88 insertions(+), 54 deletions(-) diff --git a/cmd/stbak/cmd/archive.go b/cmd/stbak/cmd/archive.go index 7e26917..73e2f15 100644 --- a/cmd/stbak/cmd/archive.go +++ b/cmd/stbak/cmd/archive.go @@ -54,6 +54,8 @@ var ( errRecipientNotAccessible = errors.New("recipient/public key not found or accessible") errIdentityNotAccessible = errors.New("identity/private key not found or accessible") + + errMissingTarHeader = errors.New("tar header is missing") ) type flusher interface { @@ -99,10 +101,6 @@ var archiveCmd = &cobra.Command{ if _, err := os.Stat(viper.GetString(recipientFlag)); err != nil { return errRecipientNotAccessible } - - if _, err := os.Stat(viper.GetString(identityFlag)); err != nil { - return errIdentityNotAccessible - } } return nil @@ -130,7 +128,6 @@ var archiveCmd = &cobra.Command{ } pubkey := []byte{} - privkey := []byte{} if viper.GetString(encryptionFlag) != encryptionFormatNoneKey { p, err := ioutil.ReadFile(viper.GetString(recipientFlag)) if err != nil { @@ -138,14 +135,9 @@ var archiveCmd = &cobra.Command{ } pubkey = p - - privkey, err = ioutil.ReadFile(viper.GetString(identityFlag)) - if err != nil { - return err - } } - if err := archive( + hdrs, err := archive( viper.GetString(tapeFlag), viper.GetInt(recordSizeFlag), viper.GetString(srcFlag), @@ -154,7 +146,8 @@ var archiveCmd = &cobra.Command{ viper.GetString(compressionLevelFlag), viper.GetString(encryptionFlag), pubkey, - ); err != nil { + ) + if err != nil { return err } @@ -167,7 +160,17 @@ var archiveCmd = &cobra.Command{ viper.GetBool(overwriteFlag), viper.GetString(compressionFlag), viper.GetString(encryptionFlag), - privkey, + []byte{}, + func(hdr *tar.Header, encryptionFormat string, privkey []byte, i int) error { + if len(hdrs) <= i { + return errMissingTarHeader + } + + *hdr = *hdrs[i] + + return nil + }, + 0, ) }, } @@ -181,67 +184,68 @@ func archive( compressionLevel string, encryptionFormat string, pubkey []byte, -) error { +) ([]*tar.Header, error) { dirty := false tw, isRegular, cleanup, err := openTapeWriter(tape) if err != nil { - return err + return []*tar.Header{}, err } if overwrite { if isRegular { if err := cleanup(&dirty); err != nil { // dirty will always be false here - return err + return []*tar.Header{}, err } f, err := os.OpenFile(tape, os.O_WRONLY|os.O_CREATE, 0600) if err != nil { - return err + return []*tar.Header{}, err } // Clear the file's content if err := f.Truncate(0); err != nil { - return err + return []*tar.Header{}, err } if err := f.Close(); err != nil { - return err + return []*tar.Header{}, err } tw, isRegular, cleanup, err = openTapeWriter(tape) if err != nil { - return err + return []*tar.Header{}, err } } else { if err := cleanup(&dirty); err != nil { // dirty will always be false here - return err + return []*tar.Header{}, err } f, err := os.OpenFile(tape, os.O_WRONLY, os.ModeCharDevice) if err != nil { - return err + return []*tar.Header{}, err } // Seek to the start of the tape if err := controllers.SeekToRecordOnTape(f, 0); err != nil { - return err + return []*tar.Header{}, err } if err := f.Close(); err != nil { - return err + return []*tar.Header{}, err } tw, isRegular, cleanup, err = openTapeWriter(tape) if err != nil { - return err + return []*tar.Header{}, err } } } defer cleanup(&dirty) + headers := []*tar.Header{} first := true - return filepath.Walk(src, func(path string, info fs.FileInfo, err error) error { + return headers, filepath.Walk(src, func(path string, info fs.FileInfo, err error) error { if err != nil { return err } @@ -343,6 +347,9 @@ func archive( return err } + hdrToAppend := *hdr + headers = append(headers, &hdrToAppend) + if err := encryptHeader(hdr, encryptionFormat, pubkey); err != nil { return err } @@ -657,7 +664,6 @@ func init() { archiveCmd.PersistentFlags().BoolP(overwriteFlag, "o", false, "Start writing from the start instead of from the end of the tape or tar file") archiveCmd.PersistentFlags().StringP(compressionLevelFlag, "l", compressionLevelBalanced, fmt.Sprintf("Compression level to use (default %v, available are %v)", compressionLevelBalanced, knownCompressionLevels)) archiveCmd.PersistentFlags().StringP(recipientFlag, "r", "", "Path to public key of recipient to encrypt for") - archiveCmd.PersistentFlags().StringP(identityFlag, "i", "", "Path to private key of recipient that has been encrypted for") viper.AutomaticEnv() diff --git a/cmd/stbak/cmd/recovery_index.go b/cmd/stbak/cmd/recovery_index.go index ce4b08e..1f11a6b 100644 --- a/cmd/stbak/cmd/recovery_index.go +++ b/cmd/stbak/cmd/recovery_index.go @@ -68,6 +68,10 @@ var recoveryIndexCmd = &cobra.Command{ viper.GetString(compressionFlag), viper.GetString(encryptionFlag), privkey, + func(hdr *tar.Header, encryptionFormat string, privkey []byte, i int) error { + return decryptHeader(hdr, encryptionFormat, privkey) + }, + 0, ) }, } @@ -82,6 +86,13 @@ func index( compressionFormat string, encryptionFormat string, privkey []byte, + decryptHeader func( + hdr *tar.Header, + encryptionFormat string, + privkey []byte, + i int, + ) error, + offset int, ) error { if overwrite { f, err := os.OpenFile(metadata, os.O_WRONLY|os.O_CREATE, 0600) @@ -119,6 +130,7 @@ func index( record := int64(record) block := int64(block) + i := 0 for { hdr, err := tr.Next() @@ -169,12 +181,14 @@ func index( break } - if err := decryptHeader(hdr, encryptionFormat, privkey); err != nil { - return err - } + if i >= offset { + if err := decryptHeader(hdr, encryptionFormat, privkey, i-offset); err != nil { + return err + } - if err := indexHeader(record, block, hdr, metadataPersister, compressionFormat, encryptionFormat); err != nil { - return nil + if err := indexHeader(record, block, hdr, metadataPersister, compressionFormat, encryptionFormat); err != nil { + return nil + } } curr, err := f.Seek(0, io.SeekCurrent) @@ -199,6 +213,8 @@ func index( record++ block = 0 } + + i++ } } else { // Seek to record @@ -217,6 +233,7 @@ func index( curr := int64((recordSize * controllers.BlockSize * int(record)) + (int(block) * controllers.BlockSize)) counter := &counters.CounterReader{Reader: br, BytesRead: int(curr)} + i := 0 tr := tar.NewReader(counter) for { @@ -246,12 +263,14 @@ func index( } } - if err := decryptHeader(hdr, encryptionFormat, privkey); err != nil { - return err - } + if i >= offset { + if err := decryptHeader(hdr, encryptionFormat, privkey, i-offset); err != nil { + return err + } - if err := indexHeader(record, block, hdr, metadataPersister, compressionFormat, encryptionFormat); err != nil { - return nil + if err := indexHeader(record, block, hdr, metadataPersister, compressionFormat, encryptionFormat); err != nil { + return nil + } } curr = int64(counter.BytesRead) @@ -270,6 +289,8 @@ func index( record++ block = 0 } + + i++ } } diff --git a/cmd/stbak/cmd/update.go b/cmd/stbak/cmd/update.go index 31148b0..1d1df9f 100644 --- a/cmd/stbak/cmd/update.go +++ b/cmd/stbak/cmd/update.go @@ -39,10 +39,6 @@ var updateCmd = &cobra.Command{ if _, err := os.Stat(viper.GetString(recipientFlag)); err != nil { return errRecipientNotAccessible } - - if _, err := os.Stat(viper.GetString(identityFlag)); err != nil { - return errIdentityNotAccessible - } } return nil @@ -67,7 +63,6 @@ var updateCmd = &cobra.Command{ } pubkey := []byte{} - privkey := []byte{} if viper.GetString(encryptionFlag) != encryptionFormatNoneKey { p, err := ioutil.ReadFile(viper.GetString(recipientFlag)) if err != nil { @@ -75,14 +70,9 @@ var updateCmd = &cobra.Command{ } pubkey = p - - privkey, err = ioutil.ReadFile(viper.GetString(identityFlag)) - if err != nil { - return err - } } - if err := update( + hdrs, err := update( viper.GetString(tapeFlag), viper.GetInt(recordSizeFlag), viper.GetString(srcFlag), @@ -91,7 +81,8 @@ var updateCmd = &cobra.Command{ viper.GetString(compressionLevelFlag), viper.GetString(encryptionFlag), pubkey, - ); err != nil { + ) + if err != nil { return err } @@ -104,7 +95,17 @@ var updateCmd = &cobra.Command{ false, viper.GetString(compressionFlag), viper.GetString(encryptionFlag), - privkey, + []byte{}, + func(hdr *tar.Header, encryptionFormat string, privkey []byte, i int) error { + if len(hdrs) <= i { + return errMissingTarHeader + } + + *hdr = *hdrs[i] + + return nil + }, + 1, ) }, } @@ -118,16 +119,17 @@ func update( compressionLevel string, encryptionFormat string, pubkey []byte, -) error { +) ([]*tar.Header, error) { dirty := false tw, isRegular, cleanup, err := openTapeWriter(tape) if err != nil { - return err + return []*tar.Header{}, err } defer cleanup(&dirty) + headers := []*tar.Header{} first := true - return filepath.Walk(src, func(path string, info fs.FileInfo, err error) error { + return headers, filepath.Walk(src, func(path string, info fs.FileInfo, err error) error { if err != nil { return err } @@ -237,6 +239,9 @@ func update( return err } + hdrToAppend := *hdr + headers = append(headers, &hdrToAppend) + if err := encryptHeader(hdr, encryptionFormat, pubkey); err != nil { return err } @@ -304,6 +309,9 @@ func update( return err } + hdrToAppend := *hdr + headers = append(headers, &hdrToAppend) + if err := encryptHeader(hdr, encryptionFormat, pubkey); err != nil { return err } @@ -325,7 +333,6 @@ func init() { updateCmd.PersistentFlags().BoolP(overwriteFlag, "o", false, "Replace the content on the tape or tar file") updateCmd.PersistentFlags().StringP(compressionLevelFlag, "l", compressionLevelBalanced, fmt.Sprintf("Compression level to use (default %v, available are %v)", compressionLevelBalanced, knownCompressionLevels)) updateCmd.PersistentFlags().StringP(recipientFlag, "r", "", "Path to public key of recipient to encrypt for") - updateCmd.PersistentFlags().StringP(identityFlag, "i", "", "Path to private key of recipient that has been encrypted for") viper.AutomaticEnv()