- Timestamp:
- Jul 12, 2012 10:39:18 AM (13 years ago)
- Location:
- trunk/src/VBox
- Files:
-
- 8 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Frontends/VBoxManage/VBoxManage.cpp
r41100 r42125 37 37 #include <iprt/asm.h> 38 38 #include <iprt/buildconfig.h> 39 #include <iprt/ctype.h> 39 40 #include <iprt/initterm.h> 40 41 #include <iprt/path.h> … … 245 246 246 247 248 #ifndef VBOX_ONLY_DOCS 249 static RTEXITCODE settingsPasswordFile(ComPtr<IVirtualBox> virtualBox, const char *pszFile) 250 { 251 size_t cbFile; 252 char szPasswd[512]; 253 int vrc = VINF_SUCCESS; 254 RTEXITCODE rcExit = RTEXITCODE_SUCCESS; 255 bool fStdIn = !strcmp(pszFile, "stdin"); 256 PRTSTREAM pStrm; 257 if (!fStdIn) 258 vrc = RTStrmOpen(pszFile, "r", &pStrm); 259 else 260 pStrm = g_pStdIn; 261 if (RT_SUCCESS(vrc)) 262 { 263 vrc = RTStrmReadEx(pStrm, szPasswd, sizeof(szPasswd)-1, &cbFile); 264 if (RT_SUCCESS(vrc)) 265 { 266 if (cbFile >= sizeof(szPasswd)-1) 267 rcExit = RTMsgErrorExit(RTEXITCODE_FAILURE, "Provided password too long"); 268 else 269 { 270 unsigned i; 271 for (i = 0; i < cbFile && !RT_C_IS_CNTRL(szPasswd[i]); i++) 272 ; 273 szPasswd[i] = '\0'; 274 int rc; 275 CHECK_ERROR(virtualBox, SetSettingsSecret(com::Bstr(szPasswd).raw())); 276 if (FAILED(rc)) 277 rcExit = RTEXITCODE_FAILURE; 278 } 279 } 280 if (!fStdIn) 281 RTStrmClose(pStrm); 282 } 283 else 284 rcExit = RTMsgErrorExit(RTEXITCODE_FAILURE, "Cannot open password file '%s' (%Rrc)", pszFile); 285 286 return rcExit; 287 } 288 #endif 289 247 290 int main(int argc, char *argv[]) 248 291 { … … 260 303 int iCmd = 1; 261 304 int iCmdArg; 305 const char *g_pszSettingsPw = NULL; 306 const char *g_pszSettingsPwFile = NULL; 262 307 263 308 for (int i = 1; i < argc || argc <= iCmd; i++) … … 316 361 iCmd++; 317 362 } 363 else if (!strcmp(argv[i], "--settingspw")) 364 { 365 if (i >= argc-1) 366 return RTMsgErrorExit(RTEXITCODE_FAILURE, 367 "Password expected"); 368 /* password for certain settings */ 369 g_pszSettingsPw = argv[i+1]; 370 iCmd += 2; 371 } 372 else if (!strcmp(argv[i], "--settingspwfile")) 373 { 374 if (i >= argc-1) 375 return RTMsgErrorExit(RTEXITCODE_FAILURE, 376 "No password file specified"); 377 g_pszSettingsPwFile = argv[i+1]; 378 iCmd += 2; 379 } 318 380 else 319 {320 381 break; 321 }322 382 } 323 383 … … 447 507 }; 448 508 509 if (g_pszSettingsPw) 510 { 511 int rc; 512 CHECK_ERROR(virtualBox, SetSettingsSecret(Bstr(g_pszSettingsPw).raw())); 513 if (FAILED(rc)) 514 { 515 rcExit = RTEXITCODE_FAILURE; 516 break; 517 } 518 } 519 else if (g_pszSettingsPwFile) 520 { 521 rcExit = settingsPasswordFile(virtualBox, g_pszSettingsPwFile); 522 if (rcExit != RTEXITCODE_SUCCESS) 523 break; 524 } 525 449 526 HandlerArg handlerArg = { 0, NULL, virtualBox, session }; 450 527 int commandIndex; -
trunk/src/VBox/Frontends/VBoxManage/VBoxManageHelp.cpp
r41925 r42125 99 99 if (u64Cmd == USAGE_ALL) 100 100 RTStrmPrintf(pStrm, 101 "VBoxManage [-v|--version] print version number and exit\n" 102 "VBoxManage [-q|--nologo] ... suppress the logo\n" 101 "VBoxManage [-v|--version] print version number and exit\n" 102 "VBoxManage [-q|--nologo] ... suppress the logo\n" 103 "VBoxManage [--settingspw <pw>] ...\n" 104 "VBoxManage [--settingspwfile] ... provide the settings password\n" 103 105 "\n"); 104 106 -
trunk/src/VBox/Main/idl/VirtualBox.xidl
r42105 r42125 2100 2100 <param name="value" type="wstring" dir="in"> 2101 2101 <desc>Value to assign to the key.</desc> 2102 </param> 2103 </method> 2104 2105 <method name="setSettingsSecret"> 2106 <desc> 2107 Unlocks the secret data by passing the unlock password to the 2108 server. The server will cache the password for that machine. 2109 2110 <result name="VBOX_E_INVALID_VM_STATE"> 2111 Virtual machine is not mutable. 2112 </result> 2113 2114 </desc> 2115 <param name="password" type="wstring" dir="in"> 2116 <desc> 2117 The cipher key. 2118 </desc> 2102 2119 </param> 2103 2120 </method> -
trunk/src/VBox/Main/include/MediumImpl.h
r41231 r42125 183 183 bool getFirstRegistryMachineId(Guid &uuid) const; 184 184 void markRegistriesModified(); 185 186 HRESULT setPropertyDirect(const Utf8Str &aName, const Utf8Str &aValue); 185 187 186 188 HRESULT addBackReference(const Guid &aMachineId, … … 188 190 HRESULT removeBackReference(const Guid &aMachineId, 189 191 const Guid &aSnapshotId = Guid::Empty); 192 190 193 191 194 const Guid* getFirstMachineBackrefId() const; -
trunk/src/VBox/Main/include/VirtualBoxImpl.h
r41999 r42125 153 153 STDMETHOD(GetExtraData)(IN_BSTR aKey, BSTR *aValue); 154 154 STDMETHOD(SetExtraData)(IN_BSTR aKey, IN_BSTR aValue); 155 STDMETHOD(SetSettingsSecret)(IN_BSTR aKey); 155 156 156 157 STDMETHOD(CreateDHCPServer)(IN_BSTR aName, IDHCPServer ** aServer); … … 286 287 RWLockHandle& getMediaTreeLockHandle(); 287 288 289 int encryptSetting(const Utf8Str &aPlaintext, Utf8Str *aCiphertext); 290 int decryptSetting(Utf8Str *aPlaintext, const Utf8Str &aCiphertext); 291 void storeSettingsKey(const Utf8Str &aKey); 292 288 293 private: 289 294 … … 305 310 HRESULT unregisterDHCPServer(DHCPServer *aDHCPServer, 306 311 bool aSaveRegistry = true); 312 313 void decryptSettings(); 314 void decryptMediumSettings(Medium *pMedium); 315 int decryptSettingBytes(uint8_t *aPlaintext, const uint8_t *aCiphertext, 316 size_t aCiphertextSize) const; 317 int encryptSettingBytes(const uint8_t *aPlaintext, uint8_t *aCiphertext, 318 size_t aPlaintextSize, size_t aCiphertextSize) const; 307 319 308 320 struct Data; // opaque data structure, defined in VirtualBoxImpl.cpp -
trunk/src/VBox/Main/src-server/MediumImpl.cpp
r42109 r42125 1180 1180 } 1181 1181 1182 /* try to decrypt an optional iSCSI initiator secret */ 1183 settings::StringsMap::const_iterator itCph = data.properties.find("InitiatorSecretEncrypted"); 1184 if ( itCph != data.properties.end() 1185 && !itCph->second.isEmpty()) 1186 { 1187 Utf8Str strPlaintext; 1188 int vrc = m->pVirtualBox->decryptSetting(&strPlaintext, itCph->second); 1189 if (RT_SUCCESS(vrc)) 1190 m->mapProperties["InitiatorSecret"] = strPlaintext; 1191 } 1192 1182 1193 Utf8Str strFull; 1183 1194 if (m->formatObj->getCapabilities() & MediumFormatCapabilities_File) … … 3754 3765 /* optional properties */ 3755 3766 data.properties.clear(); 3767 3768 /* handle iSCSI initiator secrets transparently */ 3769 bool fHaveInitiatorSecretEncrypted = false; 3770 Utf8Str strCiphertext; 3771 settings::StringsMap::const_iterator itPln = m->mapProperties.find("InitiatorSecret"); 3772 if ( itPln != m->mapProperties.end() 3773 && !itPln->second.isEmpty()) 3774 { 3775 /* Encrypt the plain secret. If that does not work (i.e. no settings key specified), 3776 * just use the encrypted secret (if there is any). */ 3777 int rc = m->pVirtualBox->encryptSetting(itPln->second, &strCiphertext); 3778 NOREF(rc); 3779 fHaveInitiatorSecretEncrypted = true; 3780 } 3756 3781 for (settings::StringsMap::const_iterator it = m->mapProperties.begin(); 3757 3782 it != m->mapProperties.end(); … … 3763 3788 const Utf8Str &name = it->first; 3764 3789 const Utf8Str &value = it->second; 3765 data.properties[name] = value; 3766 } 3790 /* do NOT store the plain InitiatorSecret */ 3791 if ( !fHaveInitiatorSecretEncrypted 3792 || !name.equals("InitiatorSecret")) 3793 data.properties[name] = value; 3794 } 3795 if (fHaveInitiatorSecretEncrypted) 3796 data.properties["InitiatorSecretEncrypted"] = strCiphertext; 3767 3797 } 3768 3798 … … 5799 5829 5800 5830 return rc; 5831 } 5832 5833 /** 5834 * Like SetProperty but do not trigger a settings store. Only for internal use! 5835 */ 5836 HRESULT Medium::setPropertyDirect(const Utf8Str &aName, const Utf8Str &aValue) 5837 { 5838 AutoCaller autoCaller(this); 5839 if (FAILED(autoCaller.rc())) return autoCaller.rc(); 5840 5841 AutoWriteLock mlock(this COMMA_LOCKVAL_SRC_POS); 5842 5843 switch (m->state) 5844 { 5845 case MediumState_Created: 5846 case MediumState_Inaccessible: 5847 break; 5848 default: 5849 return setStateError(); 5850 } 5851 5852 m->mapProperties[aName] = aValue; 5853 5854 return S_OK; 5801 5855 } 5802 5856 -
trunk/src/VBox/Main/src-server/VirtualBoxImpl.cpp
r41999 r42125 17 17 18 18 #include <iprt/asm.h> 19 #include <iprt/base64.h> 19 20 #include <iprt/buildconfig.h> 20 21 #include <iprt/cpp/utils.h> … … 24 25 #include <iprt/path.h> 25 26 #include <iprt/process.h> 27 #include <iprt/rand.h> 28 #include <iprt/sha.h> 26 29 #include <iprt/string.h> 27 30 #include <iprt/stream.h> … … 295 298 /** The global autostart database for the user. */ 296 299 AutostartDb * const pAutostartDb; 300 301 /** Settings secret */ 302 bool fSettingsCipherKeySet; 303 uint8_t SettingsCipherKey[RTSHA512_HASH_SIZE]; 297 304 }; 305 298 306 299 307 // constructor / destructor … … 446 454 if (FAILED(rc = initMachines())) 447 455 throw rc; 448 449 456 450 457 #ifdef DEBUG … … 1967 1974 } 1968 1975 1976 /** 1977 * 1978 */ 1979 STDMETHODIMP VirtualBox::SetSettingsSecret(IN_BSTR aValue) 1980 { 1981 storeSettingsKey(aValue); 1982 decryptSettings(); 1983 return S_OK; 1984 } 1985 1986 void VirtualBox::decryptMediumSettings(Medium *pMedium) 1987 { 1988 Bstr bstrCipher; 1989 HRESULT hrc = pMedium->GetProperty(Bstr("InitiatorSecretEncrypted").raw(), 1990 bstrCipher.asOutParam()); 1991 if (SUCCEEDED(hrc)) 1992 { 1993 Bstr bstrName; 1994 pMedium->COMGETTER(Name)(bstrName.asOutParam()); 1995 Utf8Str strPlaintext; 1996 int rc = decryptSetting(&strPlaintext, bstrCipher); 1997 if (RT_SUCCESS(rc)) 1998 pMedium->setPropertyDirect("InitiatorSecret", strPlaintext); 1999 } 2000 } 2001 2002 /** 2003 * Decrypt all encrypted settings. 2004 * 2005 * So far we only have encrypted iSCSI initiator secrets so we just go through 2006 * all hard disk mediums and determine the plain 'InitiatorSecret' from 2007 * 'InitiatorSecretEncrypted. The latter is stored as Base64 because medium 2008 * properties need to be null-terminated strings. 2009 */ 2010 void VirtualBox::decryptSettings() 2011 { 2012 AutoReadLock al(m->allHardDisks.getLockHandle() COMMA_LOCKVAL_SRC_POS); 2013 for (MediaList::const_iterator mt = m->allHardDisks.begin(); 2014 mt != m->allHardDisks.end(); 2015 ++mt) 2016 { 2017 ComObjPtr<Medium> pMedium = *mt; 2018 AutoCaller medCaller(pMedium); 2019 if (FAILED(medCaller.rc())) 2020 continue; 2021 AutoWriteLock mlock(pMedium COMMA_LOCKVAL_SRC_POS); 2022 decryptMediumSettings(pMedium); 2023 } 2024 } 2025 2026 /** 2027 * Encode. 2028 * 2029 * @param aPlaintext plaintext to be encrypted 2030 * @param aCiphertext resulting ciphertext (base64-encoded) 2031 */ 2032 int VirtualBox::encryptSetting(const Utf8Str &aPlaintext, Utf8Str *aCiphertext) 2033 { 2034 uint8_t abCiphertext[32]; 2035 char szCipherBase64[128]; 2036 size_t cchCipherBase64; 2037 int rc = encryptSettingBytes((uint8_t*)aPlaintext.c_str(), abCiphertext, 2038 aPlaintext.length()+1, sizeof(abCiphertext)); 2039 if (RT_SUCCESS(rc)) 2040 { 2041 rc = RTBase64Encode(abCiphertext, sizeof(abCiphertext), 2042 szCipherBase64, sizeof(szCipherBase64), 2043 &cchCipherBase64); 2044 if (RT_SUCCESS(rc)) 2045 *aCiphertext = szCipherBase64; 2046 } 2047 return rc; 2048 } 2049 2050 /** 2051 * Decode. 2052 * 2053 * @param aPlaintext resulting plaintext 2054 * @param aCiphertext ciphertext (base64-encoded) to decrypt 2055 */ 2056 int VirtualBox::decryptSetting(Utf8Str *aPlaintext, const Utf8Str &aCiphertext) 2057 { 2058 uint8_t abPlaintext[64]; 2059 uint8_t abCiphertext[64]; 2060 size_t cbCiphertext; 2061 int rc = RTBase64Decode(aCiphertext.c_str(), 2062 abCiphertext, sizeof(abCiphertext), 2063 &cbCiphertext, NULL); 2064 if (RT_SUCCESS(rc)) 2065 { 2066 rc = decryptSettingBytes(abPlaintext, abCiphertext, cbCiphertext); 2067 if (RT_SUCCESS(rc)) 2068 { 2069 /* check if this is really a Null-terminated string. */ 2070 for (unsigned i = 0; i < cbCiphertext; i++) 2071 { 2072 if (abPlaintext[i] == '\0') 2073 { 2074 *aPlaintext = Utf8Str((const char*)abPlaintext); 2075 return VINF_SUCCESS; 2076 } 2077 } 2078 rc = VERR_INVALID_PARAMETER; 2079 } 2080 } 2081 return rc; 2082 } 2083 2084 /** 2085 * Encrypt secret bytes. Use the m->SettingsCipherKey as key. 2086 * 2087 * @param aPlaintext clear text to be encrypted 2088 * @param aCiphertext resulting encrypted text 2089 * @param aPlaintextSize size of the plaintext 2090 * @param aCiphertextSize size of the ciphertext 2091 */ 2092 int VirtualBox::encryptSettingBytes(const uint8_t *aPlaintext, uint8_t *aCiphertext, 2093 size_t aPlaintextSize, size_t aCiphertextSize) const 2094 { 2095 unsigned i, j; 2096 uint8_t aBytes[64]; 2097 2098 if (!m->fSettingsCipherKeySet) 2099 return VERR_INVALID_STATE; 2100 2101 if (aCiphertextSize > sizeof(aBytes)) 2102 return VERR_BUFFER_OVERFLOW; 2103 2104 for (i = 0, j = 0; i < aPlaintextSize && i < aCiphertextSize; i++) 2105 { 2106 aCiphertext[i] = (aPlaintext[i] ^ m->SettingsCipherKey[j]); 2107 if (++j >= sizeof(m->SettingsCipherKey)) 2108 j = 0; 2109 } 2110 2111 /* fill with random data to have a minimal length */ 2112 if (i < aCiphertextSize) 2113 { 2114 RTRandBytes(aBytes, aCiphertextSize - i); 2115 for (; i < aCiphertextSize; i++) 2116 { 2117 aCiphertext[i] = aBytes[i] ^ m->SettingsCipherKey[j]; 2118 if (++j >= sizeof(m->SettingsCipherKey)) 2119 j = 0; 2120 } 2121 } 2122 2123 return VINF_SUCCESS; 2124 } 2125 2126 /** 2127 * Decrypt secret bytes. Use the m->SettingsCipherKey as key. 2128 * 2129 * @param aPlaintext resulting plaintext 2130 * @param aCiphertext ciphertext to be decrypted 2131 * @param aCiphertextSize size of the ciphertext == size of the plaintext 2132 */ 2133 int VirtualBox::decryptSettingBytes(uint8_t *aPlaintext, 2134 const uint8_t *aCiphertext, size_t aCiphertextSize) const 2135 { 2136 if (!m->fSettingsCipherKeySet) 2137 return VERR_INVALID_STATE; 2138 2139 for (unsigned i = 0, j = 0; i < aCiphertextSize; i++) 2140 { 2141 aPlaintext[i] = aCiphertext[i] ^ m->SettingsCipherKey[j]; 2142 if (++j >= sizeof(m->SettingsCipherKey)) 2143 j = 0; 2144 } 2145 2146 return VINF_SUCCESS; 2147 } 2148 2149 /** 2150 * Store a settings key. 2151 * 2152 * @param aKey the key to store 2153 */ 2154 void VirtualBox::storeSettingsKey(const Utf8Str &aKey) 2155 { 2156 RTSha512(aKey.c_str(), aKey.length(), m->SettingsCipherKey); 2157 m->fSettingsCipherKeySet = true; 2158 } 2159 1969 2160 // public methods only for internal purposes 1970 2161 ///////////////////////////////////////////////////////////////////////////// … … 3998 4189 rc = saveSettings(); 3999 4190 } 4191 NOREF(rc); /* XXX */ 4000 4192 } 4001 4193 -
trunk/src/VBox/Storage/ISCSI.cpp
r41785 r42125 3771 3771 /* Validate configuration, detect unknown keys. */ 3772 3772 if (!VDCFGAreKeysValid(pImage->pIfConfig, 3773 "TargetName\0InitiatorName\0LUN\0TargetAddress\0InitiatorUsername\0InitiatorSecret\0TargetUsername\0TargetSecret\0WriteSplit\0Timeout\0HostIPStack\0")) 3773 "TargetName\0" 3774 "InitiatorName\0" 3775 "LUN\0" 3776 "TargetAddress\0" 3777 "InitiatorUsername\0" 3778 "InitiatorSecret\0" 3779 "InitiatorSecretEncrypted\0" 3780 "TargetUsername\0" 3781 "TargetSecret\0" 3782 "WriteSplit\0" 3783 "Timeout\0" 3784 "HostIPStack\0")) 3774 3785 { 3775 3786 rc = vdIfError(pImage->pIfError, VERR_VD_ISCSI_UNKNOWN_CFG_VALUES, RT_SRC_POS, N_("iSCSI: configuration error: unknown configuration keys present"));
Note:
See TracChangeset
for help on using the changeset viewer.