VirtualBox

Changeset 55182 in vbox for trunk/src/VBox


Ignore:
Timestamp:
Apr 10, 2015 2:26:59 PM (10 years ago)
Author:
vboxsync
Message:

Main,FE/VBoxManage: Support exporting machines as appliances which have encrypted disks. Because the OVF standard doesn't support encrypted disks so far we always decrypt exported images which requires the password before starting the export proess

Location:
trunk/src/VBox
Files:
2 added
11 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Frontends/VBoxManage/VBoxManage.cpp

    r54885 r55182  
    301301    return rcExit;
    302302}
     303
     304RTEXITCODE readPasswordFromConsole(com::Utf8Str *pPassword, const char *pszPrompt, ...)
     305{
     306    RTEXITCODE rcExit = RTEXITCODE_SUCCESS;
     307    char aszPwdInput[_1K] = { 0 };
     308    va_list vaArgs;
     309
     310    va_start(vaArgs, pszPrompt);
     311    int vrc = RTStrmPrintfV(g_pStdOut, pszPrompt, vaArgs);
     312    if (RT_SUCCESS(vrc))
     313    {
     314        bool fEchoOld = false;
     315        vrc = RTStrmInputGetEchoChars(g_pStdIn, &fEchoOld);
     316        if (RT_SUCCESS(vrc))
     317        {
     318            vrc = RTStrmInputSetEchoChars(g_pStdIn, false);
     319            if (RT_SUCCESS(vrc))
     320            {
     321                vrc = RTStrmGetLine(g_pStdIn, &aszPwdInput[0], sizeof(aszPwdInput));
     322                if (RT_SUCCESS(vrc))
     323                    *pPassword = aszPwdInput;
     324                else
     325                    rcExit = RTMsgErrorExit(RTEXITCODE_FAILURE, "Failed read password from command line (%Rrc)", vrc);
     326
     327                int vrc2 = RTStrmInputSetEchoChars(g_pStdIn, fEchoOld);
     328                AssertRC(vrc2);
     329            }
     330            else
     331                rcExit = RTMsgErrorExit(RTEXITCODE_FAILURE, "Failed to disable echoing typed characters (%Rrc)", vrc);
     332        }
     333        else
     334            rcExit = RTMsgErrorExit(RTEXITCODE_FAILURE, "Failed to retrieve echo setting (%Rrc)", vrc);
     335
     336        RTStrmPutStr(g_pStdOut, "\n");
     337    }
     338    else
     339        rcExit = RTMsgErrorExit(RTEXITCODE_FAILURE, "Failed to print prompt (%Rrc)", vrc);
     340    va_end(vaArgs);
     341
     342    return rcExit;
     343}
     344
    303345#endif
    304346
  • trunk/src/VBox/Frontends/VBoxManage/VBoxManage.h

    r54885 r55182  
    188188#ifndef VBOX_ONLY_DOCS
    189189RTEXITCODE readPasswordFile(const char *pszFilename, com::Utf8Str *pPasswd);
     190RTEXITCODE readPasswordFromConsole(com::Utf8Str *pPassword, const char *pszPrompt, ...);
    190191
    191192int handleInternalCommands(HandlerArg *a);
  • trunk/src/VBox/Frontends/VBoxManage/VBoxManageAppliance.cpp

    r54991 r55182  
    12021202            break;
    12031203
     1204        /* Query required passwords and supply them to the appliance. */
     1205        com::SafeArray<BSTR> aIdentifiers;
     1206
     1207        CHECK_ERROR_BREAK(pAppliance, GetPasswordIds(ComSafeArrayAsOutParam(aIdentifiers)));
     1208
     1209        if (aIdentifiers.size() > 0)
     1210        {
     1211            com::SafeArray<BSTR> aPasswords(aIdentifiers.size());
     1212            RTPrintf("Enter the passwords for the following identifiers to export the apppliance:\n");
     1213            for (unsigned idxId = 0; idxId < aIdentifiers.size(); idxId++)
     1214            {
     1215                com::Utf8Str strPassword;
     1216                Bstr bstrPassword;
     1217                Bstr bstrId = aIdentifiers[idxId];
     1218
     1219                RTEXITCODE rcExit = readPasswordFromConsole(&strPassword, "Password ID %s:", Utf8Str(bstrId).c_str());
     1220                if (rcExit == RTEXITCODE_FAILURE)
     1221                    return rcExit;
     1222
     1223                bstrPassword = strPassword;
     1224                bstrPassword.detachTo(&aPasswords[idxId]);
     1225            }
     1226
     1227            CHECK_ERROR_BREAK(pAppliance, AddPasswords(ComSafeArrayAsInParam(aIdentifiers),
     1228                                                       ComSafeArrayAsInParam(aPasswords)));
     1229        }
     1230
    12041231        if (fManifest)
    12051232            options.push_back(ExportOptions_CreateManifest);
  • trunk/src/VBox/Frontends/VBoxManage/VBoxManageDisk.cpp

    r54885 r55182  
    5050    RTMsgErrorV(pszFormat, va);
    5151    RTMsgError("Error code %Rrc at %s(%u) in function %s", rc, RT_SRC_POS_ARGS);
    52 }
    53 
    54 static int getPassword(const char *pszPrompt, Utf8Str *pPassword)
    55 {
    56     char aszPwdInput[_1K] = { 0 };
    57 
    58     int vrc = RTStrmPutStr(g_pStdOut, pszPrompt);
    59     if (RT_SUCCESS(vrc))
    60     {
    61         bool fEchoOld = false;
    62         vrc = RTStrmInputGetEchoChars(g_pStdIn, &fEchoOld);
    63         if (RT_SUCCESS(vrc))
    64         {
    65             vrc = RTStrmInputSetEchoChars(g_pStdIn, false);
    66             if (RT_SUCCESS(vrc))
    67             {
    68                 vrc = RTStrmGetLine(g_pStdIn, &aszPwdInput[0], sizeof(aszPwdInput));
    69                 if (RT_SUCCESS(vrc))
    70                     *pPassword = aszPwdInput;
    71 
    72                 int vrc2 = RTStrmInputSetEchoChars(g_pStdIn, fEchoOld);
    73                 AssertRC(vrc2);
    74             }
    75         }
    76         RTStrmPutStr(g_pStdOut, "\n");
    77     }
    78 
    79     return vrc;
    8052}
    8153
     
    17671739        {
    17681740            /* Get password from console. */
    1769             vrc = getPassword("Enter new password:", &strPasswordNew);
    1770             if (RT_FAILURE(vrc))
    1771             {
    1772                 RTMsgError("Failed to read new password from standard input");
    1773                 return 1;
    1774             }
     1741            RTEXITCODE rcExit = readPasswordFromConsole(&strPasswordNew, "Enter new password:");
     1742            if (rcExit == RTEXITCODE_FAILURE)
     1743                return rcExit;
    17751744        }
    17761745        else
     
    17901759        {
    17911760            /* Get password from console. */
    1792             vrc = getPassword("Enter old password:", &strPasswordOld);
    1793             if (RT_FAILURE(vrc))
    1794             {
    1795                 RTMsgError("Failed to read old password from standard input");
    1796                 return 1;
    1797             }
     1761            RTEXITCODE rcExit = readPasswordFromConsole(&strPasswordOld, "Enter old password:");
     1762            if (rcExit == RTEXITCODE_FAILURE)
     1763                return rcExit;
    17981764        }
    17991765        else
     
    18571823    {
    18581824        /* Get password from console. */
    1859         vrc = getPassword("Enter password:", &strPassword);
    1860         if (RT_FAILURE(vrc))
    1861         {
    1862             RTMsgError("Failed to read password from standard input");
    1863             return 1;
    1864         }
     1825        RTEXITCODE rcExit = readPasswordFromConsole(&strPassword, "Enter password:");
     1826        if (rcExit == RTEXITCODE_FAILURE)
     1827            return rcExit;
    18651828    }
    18661829    else
  • trunk/src/VBox/Main/Makefile.kmk

    r55095 r55182  
    357357        src-all/ProgressImpl.cpp \
    358358        src-all/QMTranslatorImpl.cpp \
     359        src-all/SecretKeyStore.cpp \
    359360        src-all/SharedFolderImpl.cpp \
    360361        src-all/AutoCaller.cpp \
     
    716717        src-all/PCIDeviceAttachmentImpl.cpp \
    717718        src-all/ProgressImpl.cpp \
     719        src-all/SecretKeyStore.cpp \
    718720        src-all/SharedFolderImpl.cpp \
    719721        src-all/AutoCaller.cpp \
  • trunk/src/VBox/Main/idl/VirtualBox.xidl

    r55133 r55182  
    29872987  <interface
    29882988    name="IAppliance" extends="$unknown"
    2989     uuid="3059cf9e-25c7-4f0b-9fa5-3c42e441670b"
     2989    uuid="d9432012-2740-499f-b3b3-0991da3679f3"
    29902990    wsmap="managed"
    29912991    >
     
    32403240      <param name="warnings" type="wstring" dir="return" safearray="yes">
    32413241        <desc></desc>
     3242      </param>
     3243    </method>
     3244
     3245    <method name="getPasswordIds">
     3246      <desc>
     3247        Returns a list of password identifiers which must be supplied to import or export
     3248        encrypted virtual machines.
     3249      </desc>
     3250
     3251      <param name="identifiers" type="wstring" dir="return" safearray="yes">
     3252        The list of password identifiers required on success.
     3253      </param>
     3254    </method>
     3255
     3256    <method name="addPasswords">
     3257      <desc>
     3258        Adds a list of passwords required to import or export encrypted virtual
     3259        machines.
     3260      </desc>
     3261
     3262      <param name="identifiers" type="wstring" dir="in" safearray="yes">
     3263        <desc>List of identifiers.</desc>
     3264      </param>
     3265
     3266      <param name="passwords" type="wstring" dir="in" safearray="yes">
     3267        <desc>List of matching passwords.</desc>
    32423268      </param>
    32433269    </method>
  • trunk/src/VBox/Main/include/MediumImpl.h

    r54948 r55182  
    2424#include "VirtualBoxBase.h"
    2525#include "AutoCaller.h"
     26#include "SecretKeyStore.h"
    2627class Progress;
    2728class MediumFormat;
     
    204205                         const ComObjPtr<MediumFormat> &aFormat,
    205206                         MediumVariant_T aVariant,
     207                         SecretKeyStore *pKeyStore,
    206208                         PVDINTERFACEIO aVDImageIOIf, void *aVDImageIOUser,
    207209                         const ComObjPtr<Progress> &aProgress);
     
    216218                        const ComObjPtr<Medium> &aParent, IProgress **aProgress,
    217219                        uint32_t idxSrcImageSame, uint32_t idxDstImageSame);
     220
     221    const Utf8Str& i_getKeyId();
    218222
    219223private:
  • trunk/src/VBox/Main/src-client/ConsoleImpl.cpp

    r55180 r55182  
    430430#endif
    431431    , mBusMgr(NULL)
     432    , m_pKeyStore(NULL)
    432433    , mpIfSecKey(NULL)
    433434    , mpIfSecKeyHlp(NULL)
     
    627628#endif
    628629
     630        unconst(m_pKeyStore) = new SecretKeyStore(true /* fKeyBufNonPageable */);
     631        AssertReturn(m_pKeyStore, E_FAIL);
     632
    629633        /* VirtualBox events registration. */
    630634        {
     
    768772    }
    769773
     774    if (m_pKeyStore)
     775    {
     776        delete m_pKeyStore;
     777        unconst(m_pKeyStore) = NULL;
     778    }
     779
    770780    m_mapGlobalSharedFolders.clear();
    771781    m_mapMachineSharedFolders.clear();
     
    774784    mRemoteUSBDevices.clear();
    775785    mUSBDevices.clear();
    776 
    777     for (SecretKeyMap::iterator it = m_mapSecretKeys.begin();
    778          it != m_mapSecretKeys.end();
    779          it++)
    780         delete it->second;
    781     m_mapSecretKeys.clear();
    782786
    783787    if (mVRDEServerInfo)
     
    33683372    AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
    33693373
    3370     /* Check that the ID is not existing already. */
    3371     SecretKeyMap::const_iterator it = m_mapSecretKeys.find(aId);
    3372     if (it != m_mapSecretKeys.end())
    3373         return setError(VBOX_E_OBJECT_IN_USE, tr("A password with the given ID already exists"));
    3374 
    33753374    HRESULT hrc = S_OK;
    33763375    size_t cbKey = aPassword.length() + 1; /* Include terminator */
    3377     uint8_t *pbKey = NULL;
    3378     int rc = RTMemSaferAllocZEx((void **)&pbKey, cbKey, RTMEMSAFER_F_REQUIRE_NOT_PAGABLE);
     3376    const uint8_t *pbKey = (const uint8_t *)aPassword.c_str();
     3377
     3378    int rc = m_pKeyStore->addSecretKey(aId, pbKey, cbKey);
    33793379    if (RT_SUCCESS(rc))
    33803380    {
    33813381        unsigned cDisksConfigured = 0;
    3382         memcpy(pbKey, aPassword.c_str(), cbKey);
    3383 
    3384         /* Scramble content to make retrieving the key more difficult. */
    3385         rc = RTMemSaferScramble(pbKey, cbKey);
    3386         AssertRC(rc);
    3387         SecretKey *pKey = new SecretKey(pbKey, cbKey, !!aClearOnSuspend);
    3388         /* Add the key to the map */
    3389         m_mapSecretKeys.insert(std::make_pair(aId, pKey));
     3382
    33903383        hrc = i_configureEncryptionForDisk(aId, &cDisksConfigured);
    33913384        if (SUCCEEDED(hrc))
    33923385        {
    3393             pKey->m_cDisks = cDisksConfigured;
     3386            SecretKey *pKey = NULL;
     3387            rc = m_pKeyStore->retainSecretKey(aId, &pKey);
     3388            AssertRCReturn(rc, E_FAIL);
     3389
     3390            pKey->setUsers(cDisksConfigured);
     3391            pKey->setRemoveOnSuspend(!!aClearOnSuspend);
     3392            m_pKeyStore->releaseSecretKey(aId);
    33943393            m_cDisksPwProvided += cDisksConfigured;
    33953394
     
    34113410            }
    34123411        }
    3413         else
    3414             m_mapSecretKeys.erase(aId);
    3415     }
     3412    }
     3413    else if (rc == VERR_ALREADY_EXISTS)
     3414        hrc = setError(VBOX_E_OBJECT_IN_USE, tr("A password with the given ID already exists"));
     3415    else if (rc == VERR_NO_MEMORY)
     3416        hrc = setError(E_FAIL, tr("Failed to allocate enough secure memory for the key"));
    34163417    else
    3417         return setError(E_FAIL, tr("Failed to allocate secure memory for the password (%Rrc)"), rc);
     3418        hrc = setError(E_FAIL, tr("Unknown error happened while adding a password (%Rrc)"), rc);
    34183419
    34193420    return hrc;
     
    34373438    for (unsigned i = 0; i < aIds.size(); i++)
    34383439    {
    3439         SecretKeyMap::const_iterator it = m_mapSecretKeys.find(aIds[i]);
    3440         if (it != m_mapSecretKeys.end())
     3440        SecretKey *pKey = NULL;
     3441        int rc = m_pKeyStore->retainSecretKey(aIds[i], &pKey);
     3442        if (rc != VERR_NOT_FOUND)
     3443        {
     3444            AssertPtr(pKey);
     3445            if (pKey)
     3446                pKey->release();
    34413447            return setError(VBOX_E_OBJECT_IN_USE, tr("A password with the given ID already exists"));
     3448        }
    34423449    }
    34433450
    34443451    for (unsigned i = 0; i < aIds.size(); i++)
    34453452    {
    3446         size_t cbKey = aPasswords[i].length() + 1; /* Include terminator */
    3447         uint8_t *pbKey = NULL;
    3448         int rc = RTMemSaferAllocZEx((void **)&pbKey, cbKey, RTMEMSAFER_F_REQUIRE_NOT_PAGABLE);
    3449         if (RT_SUCCESS(rc))
    3450         {
    3451             unsigned cDisksConfigured = 0;
    3452             memcpy(pbKey, aPasswords[i].c_str(), cbKey);
    3453 
    3454             /* Scramble content to make retrieving the key more difficult. */
    3455             rc = RTMemSaferScramble(pbKey, cbKey);
    3456             AssertRC(rc);
    3457             SecretKey *pKey = new SecretKey(pbKey, cbKey, !!aClearOnSuspend);
    3458             /* Add the key to the map */
    3459             m_mapSecretKeys.insert(std::make_pair(aIds[i], pKey));
    3460             hrc = i_configureEncryptionForDisk(aIds[i], &cDisksConfigured);
    3461             if (FAILED(hrc))
    3462                 m_mapSecretKeys.erase(aIds[i]);
    3463             else
    3464                 pKey->m_cDisks = cDisksConfigured;
    3465         }
    3466         else
    3467             hrc = setError(E_FAIL, tr("Failed to allocate secure memory for the password (%Rrc)"), rc);
    3468 
     3453        hrc = addDiskEncryptionPassword(aIds[i], aPasswords[i], aClearOnSuspend);
    34693454        if (FAILED(hrc))
    34703455        {
     
    34843469    }
    34853470
    3486     if (   SUCCEEDED(hrc)
    3487         && m_cDisksPwProvided == m_cDisksEncrypted
    3488         && mMachineState == MachineState_Paused)
    3489     {
    3490         /* get the VM handle. */
    3491         SafeVMPtr ptrVM(this);
    3492         if (!ptrVM.isOk())
    3493             return ptrVM.rc();
    3494 
    3495         alock.release();
    3496         int vrc = VMR3Resume(ptrVM.rawUVM(), VMRESUMEREASON_RECONFIG);
    3497 
    3498         hrc = RT_SUCCESS(vrc) ? S_OK :
    3499                 setError(VBOX_E_VM_ERROR,
    3500                          tr("Could not resume the machine execution (%Rrc)"), vrc);
    3501     }
    3502 
    35033471    return hrc;
    35043472}
     
    35113479    AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
    35123480
    3513     SecretKeyMap::iterator it = m_mapSecretKeys.find(aId);
    3514     if (it == m_mapSecretKeys.end())
    3515         return setError(VBOX_E_OBJECT_NOT_FOUND, tr("A password with the given ID does not exist"));
    3516 
    3517     SecretKey *pKey = it->second;
    3518     if (pKey->m_cRefs)
    3519         return setError(VBOX_E_OBJECT_IN_USE, tr("The password is still in use by the VM"));
    3520 
    3521     m_cDisksPwProvided -= pKey->m_cDisks;
    3522     m_mapSecretKeys.erase(it);
    3523     delete pKey;
     3481    SecretKey *pKey = NULL;
     3482    int rc = m_pKeyStore->retainSecretKey(aId, &pKey);
     3483    if (RT_SUCCESS(rc))
     3484    {
     3485        m_cDisksPwProvided -= pKey->getUsers();
     3486        m_pKeyStore->releaseSecretKey(aId);
     3487        rc = m_pKeyStore->deleteSecretKey(aId);
     3488        AssertRCReturn(rc, E_FAIL);
     3489    }
     3490    else if (rc == VERR_NOT_FOUND)
     3491        return setError(VBOX_E_OBJECT_NOT_FOUND, tr("A password with the ID \"%s\" does not exist"),
     3492                                                 aId.c_str());
     3493    else
     3494        return setError(E_FAIL, tr("Failed to remove password with ID \"%s\" (%Rrc)"),
     3495                                aId.c_str(), rc);
    35243496
    35253497    return S_OK;
     
    35303502    AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
    35313503
    3532     /* First check whether a password is still in use. */
    3533     for (SecretKeyMap::iterator it = m_mapSecretKeys.begin();
    3534         it != m_mapSecretKeys.end();
    3535         it++)
    3536     {
    3537         SecretKey *pKey = it->second;
    3538         if (pKey->m_cRefs)
    3539             return setError(VBOX_E_OBJECT_IN_USE, tr("The password with ID \"%s\" is still in use by the VM"),
    3540                             it->first.c_str());
    3541     }
    3542 
    3543     for (SecretKeyMap::iterator it = m_mapSecretKeys.begin();
    3544         it != m_mapSecretKeys.end();
    3545         it++)
    3546         delete it->second;
    3547     m_mapSecretKeys.clear();
     3504    int rc = m_pKeyStore->deleteAllSecretKeys(false /* fSuspend */, false /* fForce */);
     3505    if (rc == VERR_RESOURCE_IN_USE)
     3506        return setError(VBOX_E_OBJECT_IN_USE, tr("A password is still in use by the VM"));
     3507    else if (RT_FAILURE(rc))
     3508        return setError(E_FAIL, tr("Deleting all passwords failed (%Rrc)"));
     3509
    35483510    m_cDisksPwProvided = 0;
    3549 
    35503511    return S_OK;
    35513512}
     
    35983559        case StorageControllerType_USB:
    35993560            return "Msd";
     3561        case StorageControllerType_NVMe:
     3562            return "nvme";
    36003563        default:
    36013564            return NULL;
     
    50735036                if (RT_SUCCESS(rc))
    50745037                {
    5075                     SecretKey *pKey = new SecretKey(pbKey, cbKey, true /* fRemoveOnSuspend */);
    5076                     /* Add the key to the map */
    5077                     m_mapSecretKeys.insert(std::make_pair(Utf8Str(pszUuid), pKey));
    5078                     hrc = i_configureEncryptionForDisk(Utf8Str(pszUuid), NULL);
    5079                     if (FAILED(hrc))
     5038                    rc = m_pKeyStore->addSecretKey(Utf8Str(pszUuid), pbKey, cbKey);
     5039                    if (RT_SUCCESS(rc))
    50805040                    {
    5081                         /* Delete the key from the map. */
    5082                         m_mapSecretKeys.erase(Utf8Str(pszUuid));
     5041                        hrc = i_configureEncryptionForDisk(Utf8Str(pszUuid), NULL);
     5042                        if (FAILED(hrc))
     5043                        {
     5044                            /* Delete the key from the map. */
     5045                            rc = m_pKeyStore->deleteSecretKey(Utf8Str(pszUuid));
     5046                            AssertRC(rc);
     5047                        }
    50835048                    }
    50845049                }
     
    50875052                                   tr("Failed to decode the key (%Rrc)"),
    50885053                                   rc);
     5054
     5055                RTMemSaferFree(pbKey, cbKey);
    50895056            }
    50905057            else
     
    51335100{
    51345101    /* Remove keys which are supposed to be removed on a suspend. */
    5135     SecretKeyMap::iterator it = m_mapSecretKeys.begin();
    5136     while (it != m_mapSecretKeys.end())
    5137     {
    5138         SecretKey *pKey = it->second;
    5139         if (pKey->m_fRemoveOnSuspend)
    5140         {
    5141             /* Unconfigure disk encryption from all attachments associated with this key. */
    5142             i_clearDiskEncryptionKeysOnAllAttachmentsWithKeyId(it->first);
    5143 
    5144             AssertMsg(!pKey->m_cRefs, ("No one should access the stored key at this point anymore!\n"));
    5145             m_cDisksPwProvided -= pKey->m_cDisks;
    5146             delete pKey;
    5147             m_mapSecretKeys.erase(it++);
    5148         }
    5149         else
    5150             it++;
    5151     }
     5102    int rc = m_pKeyStore->deleteAllSecretKeys(true /* fSuspend */, true /* fForce */);
    51525103}
    51535104
     
    1068210633
    1068310634    AutoReadLock thatLock(pConsole COMMA_LOCKVAL_SRC_POS);
    10684     SecretKeyMap::const_iterator it = pConsole->m_mapSecretKeys.find(Utf8Str(pszId));
    10685     if (it != pConsole->m_mapSecretKeys.end())
    10686     {
    10687         SecretKey *pKey = (*it).second;
    10688 
    10689         ASMAtomicIncU32(&pKey->m_cRefs);
    10690         *ppbKey = pKey->m_pbKey;
    10691         *pcbKey = pKey->m_cbKey;
    10692         return VINF_SUCCESS;
    10693     }
    10694 
    10695     return VERR_NOT_FOUND;
     10635    SecretKey *pKey = NULL;
     10636
     10637    int rc = pConsole->m_pKeyStore->retainSecretKey(Utf8Str(pszId), &pKey);
     10638    if (RT_SUCCESS(rc))
     10639    {
     10640        *ppbKey = (const uint8_t *)pKey->getKeyBuffer();
     10641        *pcbKey = pKey->getKeySize();
     10642    }
     10643
     10644    return rc;
    1069610645}
    1069710646
     
    1070510654
    1070610655    AutoReadLock thatLock(pConsole COMMA_LOCKVAL_SRC_POS);
    10707     SecretKeyMap::const_iterator it = pConsole->m_mapSecretKeys.find(Utf8Str(pszId));
    10708     if (it != pConsole->m_mapSecretKeys.end())
    10709     {
    10710         SecretKey *pKey = (*it).second;
    10711         ASMAtomicDecU32(&pKey->m_cRefs);
    10712         return VINF_SUCCESS;
    10713     }
    10714 
    10715     return VERR_NOT_FOUND;
     10656    return pConsole->m_pKeyStore->releaseSecretKey(Utf8Str(pszId));
    1071610657}
    1071710658
     
    1072510666
    1072610667    AutoReadLock thatLock(pConsole COMMA_LOCKVAL_SRC_POS);
    10727     SecretKeyMap::const_iterator it = pConsole->m_mapSecretKeys.find(Utf8Str(pszId));
    10728     if (it != pConsole->m_mapSecretKeys.end())
    10729     {
    10730         SecretKey *pKey = (*it).second;
    10731 
    10732         uint32_t cRefs = ASMAtomicIncU32(&pKey->m_cRefs);
    10733         if (cRefs == 1)
    10734         {
    10735             int rc = RTMemSaferUnscramble(pKey->m_pbKey, pKey->m_cbKey);
    10736             AssertRC(rc);
    10737         }
    10738         *ppszPassword = (const char *)pKey->m_pbKey;
    10739         return VINF_SUCCESS;
    10740     }
    10741 
    10742     return VERR_NOT_FOUND;
     10668    SecretKey *pKey = NULL;
     10669
     10670    int rc = pConsole->m_pKeyStore->retainSecretKey(Utf8Str(pszId), &pKey);
     10671    if (RT_SUCCESS(rc))
     10672        *ppszPassword = (const char *)pKey->getKeyBuffer();
     10673
     10674    return rc;
    1074310675}
    1074410676
     
    1075210684
    1075310685    AutoReadLock thatLock(pConsole COMMA_LOCKVAL_SRC_POS);
    10754     SecretKeyMap::const_iterator it = pConsole->m_mapSecretKeys.find(Utf8Str(pszId));
    10755     if (it != pConsole->m_mapSecretKeys.end())
    10756     {
    10757         SecretKey *pKey = (*it).second;
    10758         uint32_t cRefs = ASMAtomicDecU32(&pKey->m_cRefs);
    10759         if (!cRefs)
    10760         {
    10761             int rc = RTMemSaferScramble(pKey->m_pbKey, pKey->m_cbKey);
    10762             AssertRC(rc);
    10763         }
    10764         return VINF_SUCCESS;
    10765     }
    10766 
    10767     return VERR_NOT_FOUND;
     10686    return pConsole->m_pKeyStore->releaseSecretKey(Utf8Str(pszId));
    1076810687}
    1076910688
  • trunk/src/VBox/Main/src-server/ApplianceImpl.cpp

    r54979 r55182  
    404404    // initialize data
    405405    m = new Data;
     406    m->m_pSecretKeyStore = new SecretKeyStore(false /* fRequireNonPageable*/);
     407    AssertReturn(m->m_pSecretKeyStore, E_FAIL);
    406408
    407409    i_initApplianceIONameMap();
     
    425427    if (autoUninitSpan.uninitDone())
    426428        return;
     429
     430    if (m->m_pSecretKeyStore)
     431        delete m->m_pSecretKeyStore;
    427432
    428433    delete m;
     
    601606}
    602607
     608HRESULT Appliance::getPasswordIds(std::vector<com::Utf8Str> &aIdentifiers)
     609{
     610    AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
     611
     612    aIdentifiers = m->m_vecPasswordIdentifiers;
     613    return S_OK;
     614}
     615
     616HRESULT Appliance::addPasswords(const std::vector<com::Utf8Str> &aIdentifiers,
     617                                const std::vector<com::Utf8Str> &aPasswords)
     618{
     619    HRESULT hrc = S_OK;
     620
     621    AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
     622
     623    /* Check that the IDs do not exist already before changing anything. */
     624    for (unsigned i = 0; i < aIdentifiers.size(); i++)
     625    {
     626        SecretKey *pKey = NULL;
     627        int rc = m->m_pSecretKeyStore->retainSecretKey(aIdentifiers[i], &pKey);
     628        if (rc != VERR_NOT_FOUND)
     629        {
     630            AssertPtr(pKey);
     631            if (pKey)
     632                pKey->release();
     633            return setError(VBOX_E_OBJECT_IN_USE, tr("A password with the given ID already exists"));
     634        }
     635    }
     636
     637    for (unsigned i = 0; i < aIdentifiers.size() && SUCCEEDED(hrc); i++)
     638    {
     639        size_t cbKey = aPasswords[i].length() + 1; /* Include terminator */
     640        const uint8_t *pbKey = (const uint8_t *)aPasswords[i].c_str();
     641
     642        int rc = m->m_pSecretKeyStore->addSecretKey(aIdentifiers[i], pbKey, cbKey);
     643        if (RT_SUCCESS(rc))
     644            m->m_cPwProvided++;
     645        else if (rc == VERR_NO_MEMORY)
     646            hrc = setError(E_OUTOFMEMORY, tr("Failed to allocate enough secure memory for the key"));
     647        else
     648            hrc = setError(E_FAIL, tr("Unknown error happened while adding a password (%Rrc)"), rc);
     649    }
     650
     651    return hrc;
     652}
     653
    603654////////////////////////////////////////////////////////////////////////////////
    604655//
  • trunk/src/VBox/Main/src-server/ApplianceImplExport.cpp

    r52856 r55182  
    358358                rc = pBaseMedium->COMGETTER(Size)(&llSize);
    359359                if (FAILED(rc)) throw rc;
     360
     361                /* If the medium is encrypted add the key identifier to the */
     362                IMedium *iBaseMedium = pBaseMedium;
     363                Medium *pBase = static_cast<Medium*>(iBaseMedium);
     364                const com::Utf8Str strKeyId = pBase->i_getKeyId();
     365                if (!strKeyId.isEmpty())
     366                {
     367                    bool fKnown = false;
     368
     369                    /* Check whether the ID is already in our sequence, add it otherwise. */
     370                    for (unsigned i = 0; i < pAppliance->m->m_vecPasswordIdentifiers.size(); i++)
     371                    {
     372                        if (strKeyId.equals(pAppliance->m->m_vecPasswordIdentifiers[i]))
     373                        {
     374                            fKnown = true;
     375                            break;
     376                        }
     377                    }
     378
     379                    if (!fKnown)
     380                        pAppliance->m->m_vecPasswordIdentifiers.push_back(strKeyId);
     381                }
    360382            }
    361383            else if (   deviceType == DeviceType_DVD
     
    649671        return setError(VBOX_E_FILE_ERROR,
    650672                        tr("Invalid format \"%s\" specified"), aFormat.c_str());
     673
     674    /* Check whether all passwords are supplied or error out. */
     675    if (m->m_cPwProvided < m->m_vecPasswordIdentifiers.size())
     676        return setError(VBOX_E_INVALID_OBJECT_STATE,
     677                        tr("Appliance export failed because not all passwords were provided for all encrypted media"));
    651678
    652679    /* as of OVF 2.0 we have to use SHA256 */
     
    21682195                                                   format,
    21692196                                                   MediumVariant_VmdkStreamOptimized,
     2197                                                   m->m_pSecretKeyStore,
    21702198                                                   pIfIo,
    21712199                                                   pStorage,
  • trunk/src/VBox/Main/src-server/MediumImpl.cpp

    r54950 r55182  
    572572               MediumFormat *aFormat,
    573573               MediumVariant_T aVariant,
     574               SecretKeyStore *pSecretKeyStore,
    574575               VDINTERFACEIO *aVDImageIOIf,
    575576               void *aVDImageIOUser,
     
    581582          mFormat(aFormat),
    582583          mVariant(aVariant),
     584          m_pSecretKeyStore(pSecretKeyStore),
    583585          mfKeepSourceMediumLockList(fKeepSourceMediumLockList)
    584586    {
     
    606608    MediumVariant_T mVariant;
    607609    PVDINTERFACE mVDImageIfaces;
     610    SecretKeyStore *m_pSecretKeyStore;
    608611
    609612private:
     
    55875590 * @param aVariant              Which exact image format variant to use
    55885591 *                              for the destination image.
     5592 * @param pKeyStore             The optional key store for decrypting the data
     5593 *                              for encrypted media during the export.
    55895594 * @param aVDImageIOCallbacks   Pointer to the callback table for a
    55905595 *                              VDINTERFACEIO interface. May be NULL.
     
    55975602                             const ComObjPtr<MediumFormat> &aFormat,
    55985603                             MediumVariant_T aVariant,
     5604                             SecretKeyStore *pKeyStore,
    55995605                             PVDINTERFACEIO aVDImageIOIf, void *aVDImageIOUser,
    56005606                             const ComObjPtr<Progress> &aProgress)
     
    56385644        /* setup task object to carry out the operation asynchronously */
    56395645        pTask = new Medium::ExportTask(this, aProgress, aFilename, aFormat,
    5640                                        aVariant, aVDImageIOIf,
     5646                                       aVariant, pKeyStore, aVDImageIOIf,
    56415647                                       aVDImageIOUser, pSourceMediumLockList);
    56425648        rc = pTask->rc();
     
    58985904
    58995905    return rc;
     5906}
     5907
     5908/**
     5909 * Returns the key identifier for this medium if encryption is configured.
     5910 *
     5911 * @returns Key identifier or empty string if no encryption is configured.
     5912 */
     5913const Utf8Str& Medium::i_getKeyId()
     5914{
     5915    ComObjPtr<Medium> pBase = i_getBase();
     5916
     5917    AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
     5918
     5919    settings::StringsMap::const_iterator it = pBase->m->mapProperties.find("CRYPT/KeyId");
     5920    if (it == pBase->m->mapProperties.end())
     5921        return Utf8Str::Empty;
     5922
     5923    return it->second;
    59005924}
    59015925
     
    87288752         * signal from the task initiator (which releases it only after
    87298753         * RTThreadCreate()) that we can start the job. */
     8754        ComObjPtr<Medium> pBase = i_getBase();
    87308755        AutoWriteLock thisLock(this COMMA_LOCKVAL_SRC_POS);
    87318756
     
    87368761        try
    87378762        {
     8763            settings::StringsMap::iterator itKeyStore = pBase->m->mapProperties.find("CRYPT/KeyStore");
     8764            if (itKeyStore != pBase->m->mapProperties.end())
     8765            {
     8766                settings::StringsMap::iterator itKeyId = pBase->m->mapProperties.find("CRYPT/KeyId");
     8767
     8768#ifdef VBOX_WITH_EXTPACK
     8769                static const Utf8Str strExtPackPuel("Oracle VM VirtualBox Extension Pack");
     8770                static const char *s_pszVDPlugin = "VDPluginCrypt";
     8771                ExtPackManager *pExtPackManager = m->pVirtualBox->i_getExtPackManager();
     8772                if (pExtPackManager->i_isExtPackUsable(strExtPackPuel.c_str()))
     8773                {
     8774                    /* Load the plugin */
     8775                    Utf8Str strPlugin;
     8776                    rc = pExtPackManager->i_getLibraryPathForExtPack(s_pszVDPlugin, &strExtPackPuel, &strPlugin);
     8777                    if (SUCCEEDED(rc))
     8778                    {
     8779                        vrc = VDPluginLoadFromFilename(strPlugin.c_str());
     8780                        if (RT_FAILURE(vrc))
     8781                            throw setError(VBOX_E_NOT_SUPPORTED,
     8782                                           tr("Retrieving encryption settings of the image failed because the encryption plugin could not be loaded (%s)"),
     8783                                           i_vdError(vrc).c_str());
     8784                    }
     8785                    else
     8786                        throw setError(VBOX_E_NOT_SUPPORTED,
     8787                                       tr("Encryption is not supported because the extension pack '%s' is missing the encryption plugin (old extension pack installed?)"),
     8788                                       strExtPackPuel.c_str());
     8789                }
     8790                else
     8791                    throw setError(VBOX_E_NOT_SUPPORTED,
     8792                                   tr("Encryption is not supported because the extension pack '%s' is missing"),
     8793                                   strExtPackPuel.c_str());
     8794#else
     8795                throw setError(VBOX_E_NOT_SUPPORTED,
     8796                               tr("Encryption is not supported because extension pack support is not built in"));
     8797#endif
     8798
     8799                if (itKeyId == pBase->m->mapProperties.end())
     8800                    throw setError(VBOX_E_INVALID_OBJECT_STATE,
     8801                                   tr("Image '%s' is configured for encryption but doesn't has a key identifier set"),
     8802                                   pBase->m->strLocationFull.c_str());
     8803
     8804                /* Find the proper secret key in the key store. */
     8805                if (!task.m_pSecretKeyStore)
     8806                    throw setError(VBOX_E_INVALID_OBJECT_STATE,
     8807                                   tr("Image '%s' is configured for encryption but there is no key store to retrieve the password from"),
     8808                                   pBase->m->strLocationFull.c_str());
     8809
     8810                SecretKey *pKey = NULL;
     8811                vrc = task.m_pSecretKeyStore->retainSecretKey(itKeyId->second, &pKey);
     8812                if (RT_FAILURE(vrc))
     8813                    throw setError(VBOX_E_INVALID_OBJECT_STATE,
     8814                                   tr("Failed to retrieve the secret key with ID \"%s\" from the store (%Rrc)"),
     8815                                   itKeyId->second.c_str(), vrc);
     8816
     8817                Medium::CryptoFilterSettings CryptoSettingsRead;
     8818                i_taskEncryptSettingsSetup(&CryptoSettingsRead, NULL, itKeyStore->second.c_str(), (const char *)pKey->getKeyBuffer(),
     8819                                           false /* fCreateKeyStore */);
     8820                vrc = VDFilterAdd(hdd, "CRYPT", VD_FILTER_FLAGS_READ, CryptoSettingsRead.vdFilterIfaces);
     8821                if (vrc == VERR_VD_PASSWORD_INCORRECT)
     8822                {
     8823                    task.m_pSecretKeyStore->releaseSecretKey(itKeyId->second);
     8824                    throw setError(VBOX_E_PASSWORD_INCORRECT,
     8825                                   tr("The password to decrypt the image is incorrect"));
     8826                }
     8827                else if (RT_FAILURE(vrc))
     8828                {
     8829                    task.m_pSecretKeyStore->releaseSecretKey(itKeyId->second);
     8830                    throw setError(VBOX_E_INVALID_OBJECT_STATE,
     8831                                   tr("Failed to load the decryption filter: %s"),
     8832                                   i_vdError(vrc).c_str());
     8833                }
     8834
     8835                task.m_pSecretKeyStore->releaseSecretKey(itKeyId->second);
     8836            }
     8837
    87388838            /* Open all media in the source chain. */
    87398839            MediumLockList::Base::const_iterator sourceListBegin =
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette