Commit 1a3812e0 authored by Victor Kotlyar's avatar Victor Kotlyar
Browse files

Ported commits from castor/master for Encryption:

6b6374d6c2e209c98c0d4d7aa665e1df83d71aaa
  CASTOR-5350: Introduce encryption SCSI commands in tape drive
  backend

  Implementation of two methods:
    * setEncryptionKey(key): Sets encryption params to drive.
    * clearEncryptionKey: Clears encryption params from drive.

3cf91d48f5c7b0cb563c3037aee69ec769f5ab94
  Added support for an interface script that will setup drive
  encryption per tape

e9ca601687508de20fab7154e63bb0dbd1b25a8a
  Migrate TapeWriteSingleThread::TapeCleaning::~TapeCleaning() body to
  .cpp

266b02d8175b5cfc0b688135cbdc335e93060b
  CASTOR-5350: Refactor support for only external key management script

789b26a0bc69053ff1ab792a02676a7753f093ed
  Merge branch 'encryption_backend' into 'master'

  CASTOR-5350: Encryption backend

  ## Description
    The aim of this merge request is to incorporate encryption support
    into CASTOR.
    The proposed changes are to be used in conjunction with the
    operators'
    [ExternalEncryptionKeyScript](https://gitlab.cern.ch/slaskari/castor-get-encryption-key).

    The **aim** is to enable encryption in specific tape pools of
    CASTOR.
  ## Changes
    * Introduce encryption SCSI backend to DriveGeneric.
    * Introduce encryption control wrapper
    * (`castor/tape/tapeserver/daemon/EncryptionControl`) for
    * abstracting the two sub-components of:
      * Calling the `ExternalEncryptionKeyScript`,
      * Calling the equivalent DriveGeneric function for
      * passing/clearing the encryption parameters to/from the drive.
    * Add new configuration option in `castor.conf` for the external key
    * management script.
    * Create a Subprocess wrapper for executing external commands as
    * CASTOR children (`castor/server/Subprocess.{h,c}pp`).
    * Incorporate encryption handling in the:
      * DataTransferSession
      * LabelSession
      * CleanerSession
    * Add encryption control timer in the task Watchdog.
  See merge request !1

fa550707c42d80466bbd448e355aaf9be5ea8e04
  Clear encryption key only when encryption enabled
  Changes include:
    - Making EncryptionControl stateful
    - Calling clearEncryptionKey on the drive only when encryption is
      on.
  Also includes a minor duplicate code fix on DriveGeneric.
cf4eb9f3ae36c9cfc9c40349d69ab6642020e81e
  Merge branch 'encryption_changes' into 'master'
  Clear encryption key only when encryption enabled
  ## Description
    Changes include:
    - Making EncryptionControl stateful
    - Calling `clearEncryptionKey()` on the drive only when encryption
      is on.
    Also includes a minor duplicate code fix on **DriveGeneric.cpp**.
  See merge request !2

40366d963ee33ca081df6c991189b21369e461fd
  Check if the drive has encryption capability enabled:
    * Add isEncryptionCapEnabled() vendor-specific function
    * Check isEncryptionCapEnabled() before passing encryption params
    * Check isEncryptionCapEnabled() before clearing encryption params
    * Clear encryption key before unencrypted I/O

4ccc661d01eccfc3fdfb9ee2578d15a147a0c55a
  Merge branch 'encryption_capability_enabled' into 'master'
  Drive encryption capabilities inclusion
  ## Description
    The aim of this merge request is to address issues related to
    encryption on drive without the encryption capability enabled.
    More specifically:
      * It introduces a vendor-specific way of identifying if the drive
      * has encryption capability enabled
      * **IBM**: Through the SPIN index SCSI page
      * **Oracle**: Through the general INQUIRY SCSI page
      * If the data to be written are to be encrypted, an additional check
      * of the encryption capability of the drive is made. In case of
      * encrypted data, but no encryption capability, the session fails.
      In essence, all encryption related operations are made modulo the
    encryption capability of the drive.
      Last, in case of unencrypted I/O, we clear the keys of the drive (if
    encryption capable) to avoid encrypted data with previous keys on
    CASTOR's system failure.
  ## Testing
    Before the merge request's submission, the following tests were
    passed:
      On drives with **encryption capability enabled**:
        * Label session
        * Label with previously set encryption key
        * Write without encryption
        * Read without encryption
        * Write with encryption
        * Read with encryption
        * Write with previously set encryption key
        * Read with previously set encryption key
      On drive with **encryption cabability disabled**:
        * Label session
        * Write without encryption
        * Read without encryption
        * Write with encryption - session **should** fail
        * Read with encryption - session **should** fail
    See merge request !3

55b85a2cb4681d697565116c00ff98c6becea4fb
  Secure session against invalid encryption script output

3a54875c680fe6c1c9d5cf25cf98d2780196e0d1
  Changes in encryption workflow
    - VMGR tag is updated only on write operations
    - Empty key signifies no encryption

f5408cf0ccbae9a4ab94a533f3b6d7be323f72fb
  Minor encryption log enhancements
    * Error line in Read/Write session with ErrorMesage key
    * Fix for delimiter in the end of arguments in argsToString()
2e7204fb0dd24b472a959fa5e13320c34df4f017
  Merging in improvements on tape encryption support.

92533a1746d0744ee528781558a720c63ca3c4d1
  Removed nullptr which is not supported in SLC6's gcc.
  Added automatic deletion of json objects in
  EncryptionControl::parse_json_script_output.

fca3bb9e7fce364b429fc0b5c036fb752fd67ff1
  Fix log typo
parent a4b87732
......@@ -114,6 +114,7 @@ set (COMMON_LIB_SRC_FILES
threading/System.cpp
threading/Threading.cpp
threading/Semaphores.cpp
threading/SubProcess.cpp
utils/GetOptThreadSafe.cpp
utils/utils.cpp
utils/strerror_r_wrapper.cpp
......
/******************************************************************************
*
* This file is part of the Castor project.
* See http://castor.web.cern.ch/castor
*
* Copyright (C) 2003 CERN
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
*
*
* @author Castor Dev team, castor-dev@cern.ch
*****************************************************************************/
#include "SubProcess.hpp"
#include "common/exception/Errnum.hpp"
#include <string.h>
#include <iostream>
#include <sys/signal.h>
#include <sys/wait.h>
#include <fcntl.h>
#include <unistd.h>
#include <spawn.h>
namespace {
class ScopedPosixSpawnFileActions{
public:
ScopedPosixSpawnFileActions() {
::posix_spawn_file_actions_init(&m_action);
}
~ScopedPosixSpawnFileActions() {
::posix_spawn_file_actions_destroy(&m_action);
}
operator ::posix_spawn_file_actions_t * () { return &m_action; }
private:
::posix_spawn_file_actions_t m_action;
};
}
namespace {
class ScopedPosixSpawnAttr{
public:
ScopedPosixSpawnAttr() {
::posix_spawnattr_init(&m_attr);
}
~ScopedPosixSpawnAttr() {
::posix_spawnattr_destroy(&m_attr);
}
operator ::posix_spawnattr_t * () { return &m_attr; }
private:
::posix_spawnattr_t m_attr;
};
}
namespace cta { namespace threading {
SubProcess::SubProcess(const std::string & executable, const std::list<std::string>& argv) {
// Sanity checks
if (argv.size() < 1)
throw cta::exception::Exception(
"In Subprocess::Subprocess: not enough elements in argv");
// Prepare the pipes for the child's stdout and stderr (stdin will be closed)
const size_t readSide=0;
const size_t writeSide=1;
int stdoutPipe[2];
int stderrPipe[2];
cta::exception::Errnum::throwOnNonZero(::pipe2(stdoutPipe, O_NONBLOCK),
"In Subprocess::Subprocess failed to create the stdout pipe");
cta::exception::Errnum::throwOnNonZero(::pipe2(stderrPipe, O_NONBLOCK),
"In Subprocess::Subprocess failed to create the stderr pipe");
// Prepare the actions to be taken on file descriptors
ScopedPosixSpawnFileActions fileActions;
// We will be the child process. Close the read sides of the pipes.
cta::exception::Errnum::throwOnReturnedErrno(posix_spawn_file_actions_addclose(fileActions, stdoutPipe[readSide]),
"In Subprocess::Subprocess(): failed to posix_spawn_file_actions_addclose() (1)");
cta::exception::Errnum::throwOnReturnedErrno(posix_spawn_file_actions_addclose(fileActions, stderrPipe[readSide]),
"In Subprocess::Subprocess(): failed to posix_spawn_file_actions_addclose() (2)");
// Close stdin and rewire the stdout and stderr to the pipes.
cta::exception::Errnum::throwOnReturnedErrno(posix_spawn_file_actions_adddup2(fileActions, stdoutPipe[writeSide], STDOUT_FILENO),
"In Subprocess::Subprocess(): failed to posix_spawn_file_actions_adddup2() (1)");
cta::exception::Errnum::throwOnReturnedErrno(posix_spawn_file_actions_adddup2(fileActions, stderrPipe[writeSide], STDERR_FILENO),
"In Subprocess::Subprocess(): failed to posix_spawn_file_actions_adddup2() (2)");
// Close the now duplicated pipe file descriptors
cta::exception::Errnum::throwOnReturnedErrno(posix_spawn_file_actions_addclose(fileActions, stdoutPipe[writeSide]),
"In Subprocess::Subprocess(): failed to posix_spawn_file_actions_addclose() (3)");
cta::exception::Errnum::throwOnReturnedErrno(posix_spawn_file_actions_addclose(fileActions, stderrPipe[writeSide]),
"In Subprocess::Subprocess(): failed to posix_spawn_file_actions_addclose() (4)");
// And finally spawn the subprocess
// Prepare the spawn attributes (we need vfork)
ScopedPosixSpawnAttr attr;
cta::exception::Errnum::throwOnReturnedErrno(posix_spawnattr_setflags(attr, POSIX_SPAWN_USEVFORK),
"In Subprocess::Subprocess(): failed to posix_spawnattr_setflags()");
char ** cargv = new char*[argv.size()+1];
int index = 0;
for (auto a=argv.cbegin(); a!=argv.cend(); a++) {
cargv[index++] = ::strdup(a->c_str());
}
cargv[argv.size()] = NULL;
int spawnRc=::posix_spawnp(&m_child, executable.c_str(), fileActions, attr, cargv, ::environ);
cta::exception::Errnum::throwOnReturnedErrno(spawnRc, "In Subprocess::Subprocess failed to posix_spawn()");
// We are the parent process. Close the write sides of pipes.
::close(stdoutPipe[writeSide]);
::close(stderrPipe[writeSide]);
m_stdoutFd = stdoutPipe[readSide];
m_stderrFd = stderrPipe[readSide];
}
void SubProcess::kill(int signal) {
::kill(m_child, signal);
}
int SubProcess::exitValue() {
if(!m_child)
throw cta::exception::Exception("In Subprocess::exitValue: child process not waited for");
return WEXITSTATUS(m_childStatus);
}
bool SubProcess::wasKilled() {
if(!m_child)
throw cta::exception::Exception("In Subprocess::wasKilled: child process not waited for");
return WIFSIGNALED(m_childStatus);
}
int SubProcess::killSignal() {
if(!m_child)
throw cta::exception::Exception("In Subprocess::killSignal: child process not waited for");
return WTERMSIG(m_childStatus);
}
void SubProcess::wait() {
::waitpid(m_child, &m_childStatus, 0);
char buff[1000];
int rc;
while (0<(rc=::read(m_stdoutFd, buff, sizeof(buff)))) {
m_stdout.append(buff, rc);
}
::close(m_stdoutFd);
while (0<(rc=::read(m_stderrFd, buff, sizeof(buff)))) {
m_stderr.append(buff, rc);
}
::close(m_stderrFd);
m_childComplete = true;
}
std::string SubProcess::stdout() {
if(!m_child)
throw cta::exception::Exception("In Subprocess::stdout: child process not waited for");
return m_stdout;
}
std::string SubProcess::stderr() {
if(!m_child)
throw cta::exception::Exception("In Subprocess::stderr: child process not waited for");
return m_stderr;
}
SubProcess::~SubProcess() {
if(!m_childComplete) {
this->kill(SIGKILL);
this->wait();
}
}
}} // namespace cta::threading
/******************************************************************************
*
* This file is part of the Castor project.
* See http://castor.web.cern.ch/castor
*
* Copyright (C) 2003 CERN
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
*
*
* @author Castor Dev team, castor-dev@cern.ch
*****************************************************************************/
#pragma once
#include <list>
#include <string>
namespace cta { namespace threading {
/**
* A class spawning a new executable with a program path and arguments.
* StdOut and StdErr can be recovered after execution (and calling wait()).
*/
class SubProcess {
public:
SubProcess(const std::string & program, const std::list<std::string> &argv);
~SubProcess();
void wait(void);
std::string stdout();
std::string stderr();
void kill(int signal);
int exitValue();
bool wasKilled();
int killSignal();
private:
int m_stdoutFd;
int m_stderrFd;
pid_t m_child;
bool m_childComplete;
int m_childStatus;
std::string m_stdout;
std::string m_stderr;
};
}}
......@@ -525,6 +525,15 @@
# tapserverd. Default is do not use LBP in the tapserverd.
#TapeServer UseLogicalBlockProtection no
# The absolute path of the external encryption key management script to be
# executed by tapeserverd once per tape mount for acquiring the encyption key
# associated with a tape.
# When called, it searches for the key associated with the vid passed with the
# --vid argument. If such exists, it will be returned. Otherwise, the relevant
# field in the response will be empty.
# <script> --vid <vid>
#TapeServer ExternalEncryptionKeyScript absolute_path
# The protocol to be used when transfering files to and from disk servers.
# Possible values are RFIO or XROOT. The value is not case sensitive.
#TapeServer RemoteFileProtocol RFIO
......
......@@ -326,6 +326,135 @@ namespace SCSI {
std::string driverStatusSuggestionsToString(
const unsigned short int driverStatus);
namespace encryption {
const unsigned int ENC_KEY_LENGTH = 0x20;
class spinSecurityProtocolPages {
public:
enum {
securityProtocolInformation = 0x00,
tapeDataEncrytpion = 0x20
};
};
class spoutSecurityProtocolPages {
public:
enum{
tapeDataEncryption = 0x20
};
};
class spoutSecurityProtocolSpecificPages {
public:
enum {
setDataEncryptionPage = 0x10,
saEncapsulationPage = 0x11 // not supported by IBM or Oracle
};
};
class encryptionNexusScopes {
public:
enum {
scopePublic = 0,/* All fields other than the scope field and LOCK bit shall be ignored.
The I_T nexus shall use data encryption parameters that are shared
by other I_T nexuses. If no I_T nexuses are sharing data encryption
parameters, the device server shall use default data encryption parameters. */
scopeLocal = 1,/* The data encryption parameters are unique to the I_T nexus associated
with the SECURITY PROTOCOL OUT command and shall not be shared
with other I_T nexuses.*/
scopeAllITNexus = 2 /* The data encryption parameters shall be shared with all I_T nexuses. */
};
};
class checkExternalEncryptionMode {
public:
enum {
vendorSpecific = 0, /* Vendor specific */
noEncryptionCheck = 1, /* Do not check the encryption mode that was in use when the block
was written to the medium.*/
checkExternal = 2, /* On read and verify commands, check the encryption mode that
was in use when the block was written to the medium. Report an
error if the block was written in EXTERNAL mode */
checkEncrypt = 3 /* On read and verify commands, check the encryption mode that
was in use when the block was written to the medium. Report
an error if the block was written in ENCRYPT mode */
};
};
class rawDecryptionModeControl {
public:
enum {
rdmcDefault = 0, /* The device server shall mark each encrypted block per the default
setting for the algorithm */
// value 1 is reserved, according to SSC-3
rdmcUnprotect = 2, /* The device server shall mark each encrypted block written to the
medium in a format specific manner as enabled for raw decryption
mode operations. */
rdmcProtect = 3 /* The device server shall mark each encrypted block written to the
medium in a format specific manner as disabled for raw decryption
mode operations. */
};
};
class encryptionModes {
public:
enum {
modeDisable = 0, /* Data encryption is disabled. */
modeExternal = 1, /* The data associated with the WRITE(6) and WRITE(16) commands
has been encrypted by a system that is compatible with the
algorithm specified by the ALGORITHM INDEX field. */
modeEncrypt = 2 /* The device server shall encrypt all data that it receives for
a WRITE(6) or WRITE(16) command using the algorithm specified
in the ALGORITHM INDEX field and the key specified in the KEY field. */
};
};
class decryptionModes {
public:
enum {
modeDisable = 0, /* Data decryption is disabled. If the device server encounters an encrypted
logical block while reading, it shall not allow access to the data. */
modeRaw = 1, /* Data decryption is disabled. If the device server encounters an encrypted
logical block while reading, it shall pass the encrypted block to the host
without decrypting it. The encrypted block may contain data that is not user data. */
modeDecrypt = 2, /* The device server shall decrypt all data that is read from the medium when
processing a READ(6), READ(16), READ REVERSE(6), READ REVERSE(16), or
RECOVER BUFFERED DATA command or verified when processing a VERIFY(6)
or VERIFY(16) command. The data shall be decrypted using the algorithm specified
in the ALGORITHM INDEX field and the key specified in the KEY field.*/
modeMixed = 3 /* The device server shall decrypt all data that is read from the medium that
the device server determines was encrypted when processing a
READ(6), READ(16), READ REVERSE(6), READ REVERSE(16), or RECOVER BUFFERED DATA
command or verified when processing a VERIFY(6) or VERIFY(16) command.
The data shall be decrypted using the algorithm specified in the ALGORITHM INDEX field
and the key specified in the KEY field.
If the device server encounters unencrypted data when processing a READ(6), READ(16),
READ REVERSE(6), READ REVERSE(16), RECOVER BUFFERED DATA, VERIFY(6), or VERIFY(16)
command, the data shall be processed without decrypting. */
};
};
class keyFormatTypes {
public:
enum {
keyFormatNormal = 0, /* The KEY field contains the key to be used to encrypt or decrypt data. */
keyFormatReference = 1, /* The KEY field contains a vendor-specific key reference. */
keyFormatWrapped = 2, /* The KEY field contains the key wrapped by the device server public key. */
keyFormatESPSCSI = 3 /* The KEY field contains a key that is encrypted using ESP-SCSI. */
};
};
class keyDescriptorTypes {
public:
enum {
ukad = 0, /* Unauthenticated Key Associated Data */
akad = 1, /* Authenticated Key Associated Data */
nonce = 2, /* Nonce value */
meta = 3 /* Metadata Key Associated data */
};
};
}
class logSensePages {
public:
enum {
......
......@@ -249,8 +249,70 @@ namespace SCSI {
unsigned char reserved2[22];
unsigned char vendorSpecific2[1];
};
/**
/**
* Oracle T10K Inquiry data
*/
class inquiryDataT10k_t {
public:
inquiryDataT10k_t () { zeroStruct(this); }
unsigned char perifDevType : 5;
unsigned char perifQualifyer : 3;
unsigned char : 7;
unsigned char RMB : 1;
unsigned char version;
unsigned char respDataFmt : 4;
unsigned char HiSup : 1;
unsigned char normACA : 1;
unsigned char RSVD1: 1;
unsigned char AERC: 1;
unsigned char addLength;
unsigned char protect : 1;
unsigned char : 2;
unsigned char threePC : 1;
unsigned char TPGS : 2;
unsigned char ACC : 1;
unsigned char SCCS : 1;
unsigned char : 3;
unsigned char mChngr: 1;
unsigned char multiP : 1;
unsigned char VS1 : 1;
unsigned char encServ : 1;
unsigned char bQue : 1;
unsigned char VS2 : 1;
unsigned char cmdQue : 1;
unsigned char RSVD2: 1;
unsigned char linked: 1;
unsigned char : 3;
unsigned char relAdr : 1;
char vendorId[8];
char prodId[16];
char prodRevLvl[8];
char vendorSpecific1[14];
unsigned char keyMgmt;
unsigned char CSL : 1;
unsigned char DCMP : 1;
unsigned char volSafe : 1;
unsigned char libAtt : 1;
unsigned char encr : 1;
unsigned char : 3;
unsigned char reserved1[2];
unsigned char versionDescriptor[8][2];
};
/**
* Inquiry unit serial number vital product data as described in SPC-4.
*/
class inquiryUnitSerialNumberData_t {
......@@ -1029,7 +1091,86 @@ namespace SCSI {
/* TODO: add support for other bits. See section 4.5.6
* of SPC-4 for sense key = NO SENSE. */
};
namespace encryption {
class spinCDB_t {
public:
spinCDB_t() {
zeroStruct(this);
opCode = SCSI::Commands::SECURITY_PROTOCOL_IN;
}
unsigned char opCode;
unsigned char securityProtocol;
unsigned char securityProtocolSpecific[2];
unsigned char reserved[2];
unsigned char allocationLength[4];
unsigned char reserved2;
unsigned char controlByte;
};
class spoutCDB_t {
public:
spoutCDB_t() {
zeroStruct(this);
opCode = SCSI::Commands::SECURITY_PROTOCOL_OUT;
}
unsigned char opCode;
unsigned char securityProtocol;
unsigned char securityProtocolSpecific[2];
unsigned char reserved[2];
unsigned char allocationLength[4];
unsigned char reserved2;
unsigned char controlByte;
};
template <int n>
class spinPageList_t {
public:
spinPageList_t() { zeroStruct(this); }
unsigned char reserved[6];
unsigned char supportedProtocolListLength[2];
unsigned char list[n];
};
/**
* Security Protocol OUT-Set Data Encryption Page as described in SSC-4.
*/
class spoutSDEParam_t {
public:
spoutSDEParam_t() {
zeroStruct(this);
setU16(pageCode, SCSI::encryption::spoutSecurityProtocolSpecificPages::setDataEncryptionPage);
setU16(keyLength, SCSI::encryption::ENC_KEY_LENGTH);
}
unsigned char pageCode[2];
unsigned char length[2];
unsigned char lock : 1;
unsigned char : 4;
unsigned char nexusScope : 3; // Specifies the scope of the data encryption parameters
unsigned char CKORL : 1; // Clear key on reservation loss
unsigned char CKORP : 1; // Clear key on reservation preempt
unsigned char CKOD : 1; // Clear key on reservation demount
unsigned char SDK : 1; // Supplemental decryption key
unsigned char RDMC : 2; // Raw decryption mode control
unsigned char CEEM : 2; // Check external encryption mode
unsigned char encryptionMode;
unsigned char decryptionMode;
unsigned char algorithmIndex;
unsigned char keyFormat;
unsigned char kadFormat;
unsigned char reserved[7];
unsigned char keyLength[2];
unsigned char keyData[SCSI::encryption::ENC_KEY_LENGTH];
};
}
template <size_t n>
/**
* Extract a string from a fixed size array. This function
......
......@@ -48,6 +48,7 @@ set(CTATAPESERVERDAEMON_LIBRARY_SRCS
DriveConfig.cpp
DriveConfigMap.cpp
EmptyDriveProbe.cpp
EncryptionControl.cpp
TapeServerReporter.cpp
LabelSession.cpp
MigrationMemoryManager.cpp
......
......@@ -34,7 +34,8 @@ castor::tape::tapeserver::daemon::CleanerSession::CleanerSession(
System::virtualWrapper &sysWrapper,
const std::string &vid,
const bool waitMediaInDrive,
const uint32_t waitMediaInDriveTimeout):
const uint32_t waitMediaInDriveTimeout,
const std::string & externalEncryptionKeyScript):
m_capUtils(capUtils),
m_mc(mc),
m_log(log),
......@@ -42,8 +43,8 @@ castor::tape::tapeserver::daemon::CleanerSession::CleanerSession(
m_sysWrapper(sysWrapper),
m_vid(vid),
m_waitMediaInDrive(waitMediaInDrive),
m_waitMediaInDriveTimeout(waitMediaInDriveTimeout) {
}
m_waitMediaInDriveTimeout(waitMediaInDriveTimeout),
m_encryptionControl(externalEncryptionKeyScript) {}
//------------------------------------------------------------------------------
// execute
......@@ -109,6 +110,8 @@ void castor::tape::tapeserver::daemon::CleanerSession::cleanDrive(drive::DriveIn
return; //return immediately if there is no tape
}
m_encryptionControl.disable(drive);
rewindDrive(drive);
drive.disableLogicalBlockProtection();
......
......@@ -32,6 +32,7 @@
#include "tapeserver/castor/tape/tapeserver/drive/DriveInterface.hpp"
#include "tapeserver/castor/tape/tapeserver/file/Structures.hpp"
#include "tapeserver/castor/tape/tapeserver/SCSI/Device.hpp"
#include "tapeserver/castor/tape/tapeserver/daemon/EncryptionControl.hpp"