+
+/*
+ * In the context of jcr, flush any remaining data from the cipher context,
+ * writing it to bfd.
+ * Return value is true on success, false on failure.
+ */
+bool flush_cipher(JCR *jcr, BFILE *bfd, uint64_t *addr, int flags,
+ RESTORE_CIPHER_CTX *cipher_ctx)
+{
+ uint32_t decrypted_len = 0;
+ char *wbuf; /* write buffer */
+ uint32_t wsize; /* write size */
+ char ec1[50]; /* Buffer printing huge values */
+ bool second_pass = false;
+
+again:
+ /* Write out the remaining block and free the cipher context */
+ cipher_ctx->buf = check_pool_memory_size(cipher_ctx->buf, cipher_ctx->buf_len +
+ cipher_ctx->block_size);
+
+ if (!crypto_cipher_finalize(cipher_ctx->cipher, (uint8_t *)&cipher_ctx->buf[cipher_ctx->buf_len],
+ &decrypted_len)) {
+ /* Writing out the final, buffered block failed. Shouldn't happen. */
+ Jmsg3(jcr, M_ERROR, 0, _("Decryption error. buf_len=%d decrypt_len=%d on file %s\n"),
+ cipher_ctx->buf_len, decrypted_len, jcr->last_fname);
+ }
+
+ Dmsg2(30, "Flush decrypt len=%d buf_len=%d\n", decrypted_len, cipher_ctx->buf_len);
+ /* If nothing new was decrypted, and our output buffer is empty, return */
+ if (decrypted_len == 0 && cipher_ctx->buf_len == 0) {
+ return true;
+ }
+
+ cipher_ctx->buf_len += decrypted_len;
+
+ unser_crypto_packet_len(cipher_ctx);
+ Dmsg1(500, "Crypto unser block size=%d\n", cipher_ctx->packet_len - CRYPTO_LEN_SIZE);
+ wsize = cipher_ctx->packet_len - CRYPTO_LEN_SIZE;
+ wbuf = &cipher_ctx->buf[CRYPTO_LEN_SIZE]; /* Decrypted, possibly decompressed output here. */
+ cipher_ctx->buf_len -= cipher_ctx->packet_len;
+ Dmsg2(30, "Encryption writing full block, %u bytes, remaining %u bytes in buffer\n", wsize, cipher_ctx->buf_len);
+
+ if (flags & FO_SPARSE) {
+ if (!sparse_data(jcr, bfd, addr, &wbuf, &wsize)) {
+ return false;
+ }
+ }
+
+ if (flags & FO_GZIP) {
+ if (!decompress_data(jcr, &wbuf, &wsize)) {
+ return false;
+ }
+ }
+
+ Dmsg0(30, "Call store_data\n");
+ if (!store_data(jcr, bfd, wbuf, wsize, (flags & FO_WIN32DECOMP) != 0)) {
+ return false;
+ }
+ jcr->JobBytes += wsize;
+ Dmsg2(30, "Flush write %u bytes, JobBytes=%s\n", wsize, edit_uint64(jcr->JobBytes, ec1));
+
+ /* Move any remaining data to start of buffer */
+ if (cipher_ctx->buf_len > 0) {
+ Dmsg1(30, "Moving %u buffered bytes to start of buffer\n", cipher_ctx->buf_len);
+ memmove(cipher_ctx->buf, &cipher_ctx->buf[cipher_ctx->packet_len],
+ cipher_ctx->buf_len);
+ }
+ /* The packet was successfully written, reset the length so that the next
+ * packet length may be re-read by unser_crypto_packet_len() */
+ cipher_ctx->packet_len = 0;
+
+ if (cipher_ctx->buf_len >0 && !second_pass) {
+ second_pass = true;
+ goto again;
+ }
+
+ /* Stop decryption */
+ cipher_ctx->buf_len = 0;
+ cipher_ctx->packet_len = 0;
+
+ return true;
+}
+
+static void deallocate_cipher(r_ctx &rctx)
+{
+ /* Flush and deallocate previous stream's cipher context */
+ if (rctx.cipher_ctx.cipher) {
+ flush_cipher(rctx.jcr, &rctx.bfd, &rctx.fileAddr, rctx.flags, &rctx.cipher_ctx);
+ crypto_cipher_free(rctx.cipher_ctx.cipher);
+ rctx.cipher_ctx.cipher = NULL;
+ }
+}
+
+static void deallocate_fork_cipher(r_ctx &rctx)
+{
+
+ /* Flush and deallocate previous stream's fork cipher context */
+ if (rctx.fork_cipher_ctx.cipher) {
+ flush_cipher(rctx.jcr, &rctx.forkbfd, &rctx.fork_addr, rctx.fork_flags, &rctx.fork_cipher_ctx);
+ crypto_cipher_free(rctx.fork_cipher_ctx.cipher);
+ rctx.fork_cipher_ctx.cipher = NULL;
+ }
+}
+
+static void free_signature(r_ctx &rctx)
+{
+ if (rctx.sig) {
+ crypto_sign_free(rctx.sig);
+ rctx.sig = NULL;
+ }
+}
+
+static void free_session(r_ctx &rctx)
+{
+ if (rctx.cs) {
+ crypto_session_free(rctx.cs);
+ rctx.cs = NULL;
+ }
+}
+
+
+/* This code if implemented goes above */
+#ifdef stbernard_implemented
+/ #if defined(HAVE_WIN32)
+ bool bResumeOfmOnExit = FALSE;
+ if (isOpenFileManagerRunning()) {
+ if ( pauseOpenFileManager() ) {
+ Jmsg(jcr, M_INFO, 0, _("Open File Manager paused\n") );
+ bResumeOfmOnExit = TRUE;
+ }
+ else {
+ Jmsg(jcr, M_ERROR, 0, _("FAILED to pause Open File Manager\n") );
+ }
+ }
+ {
+ char username[UNLEN+1];
+ DWORD usize = sizeof(username);
+ int privs = enable_backup_privileges(NULL, 1);
+ if (GetUserName(username, &usize)) {
+ Jmsg2(jcr, M_INFO, 0, _("Running as '%s'. Privmask=%#08x\n"), username,
+ } else {
+ Jmsg(jcr, M_WARNING, 0, _("Failed to retrieve current UserName\n"));
+ }
+ }
+#endif