Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

361 lines
7.5 KiB

  1. #include "stdafx.h"
  2. LPCWSTR g_CredentialBlobDescription = L"BITS job credentials";
  3. //------------------------------------------------------------------------
  4. CEncryptedBlob::CEncryptedBlob(
  5. void * Buffer,
  6. size_t Length,
  7. LPCWSTR Description
  8. )
  9. : m_Length( Length )
  10. {
  11. m_Blob.pbData = 0;
  12. m_Blob.cbData = 0;
  13. DATA_BLOB blobIn;
  14. blobIn.pbData = reinterpret_cast<BYTE *>( Buffer );
  15. blobIn.cbData = Length;
  16. // Encrypt the data.
  17. if (!CryptProtectData( &blobIn,
  18. Description,
  19. NULL,
  20. NULL,
  21. NULL,
  22. CRYPTPROTECT_UI_FORBIDDEN,
  23. &m_Blob))
  24. {
  25. ThrowLastError();
  26. }
  27. }
  28. CEncryptedBlob::CEncryptedBlob()
  29. {
  30. m_Length = 0;
  31. m_Blob.cbData = 0;
  32. m_Blob.pbData = 0;
  33. }
  34. CEncryptedBlob::~CEncryptedBlob()
  35. {
  36. if (m_Blob.pbData)
  37. {
  38. LocalFree( m_Blob.pbData );
  39. }
  40. }
  41. void
  42. CEncryptedBlob::Decrypt(
  43. void * Buffer,
  44. size_t Length
  45. )
  46. {
  47. if (Length < m_Length)
  48. {
  49. THROW_HRESULT( E_INVALIDARG );
  50. }
  51. DATA_BLOB blobOut;
  52. // Decrypt the data.
  53. if (!CryptUnprotectData( &m_Blob,
  54. NULL,
  55. NULL,
  56. NULL,
  57. NULL,
  58. CRYPTPROTECT_UI_FORBIDDEN,
  59. &blobOut))
  60. {
  61. ThrowLastError();
  62. }
  63. ASSERT( blobOut.cbData == Length );
  64. memcpy( Buffer, blobOut.pbData, Length );
  65. LocalFree( blobOut.pbData );
  66. }
  67. void CEncryptedBlob::Serialize( HANDLE hFile )
  68. {
  69. SafeWriteFile( hFile, m_Length );
  70. SafeWriteFile( hFile, m_Blob.cbData );
  71. SafeWriteFile( hFile, m_Blob.pbData, m_Blob.cbData );
  72. }
  73. void CEncryptedBlob::Unserialize( HANDLE hFile )
  74. {
  75. SafeReadFile( hFile, &m_Length );
  76. SafeReadFile( hFile, &m_Blob.cbData );
  77. m_Blob.pbData = static_cast<BYTE *> (LocalAlloc( LMEM_FIXED, m_Blob.cbData ));
  78. if (m_Blob.pbData == NULL)
  79. {
  80. throw ComError( E_OUTOFMEMORY );
  81. }
  82. SafeReadFile( hFile, m_Blob.pbData, m_Blob.cbData );
  83. }
  84. //------------------------------------------------------------------------
  85. CEncryptedCredentials::CEncryptedCredentials( const BG_AUTH_CREDENTIALS & cred )
  86. {
  87. size_t Length = CAuthCredentialsMarshaller::Size( &cred );
  88. auto_ptr<char> Buffer( new char[ Length ] );
  89. CMarshalCursor Cursor( Buffer.get(), Length );
  90. CAuthCredentialsMarshaller m1( Cursor, &cred );
  91. m_Blob = new CEncryptedBlob( Buffer.get(), Length, g_CredentialBlobDescription );
  92. }
  93. CEncryptedCredentials::~CEncryptedCredentials()
  94. {
  95. delete m_Blob;
  96. }
  97. BG_AUTH_CREDENTIALS * CEncryptedCredentials::Decrypt()
  98. {
  99. BG_AUTH_CREDENTIALS * cred = 0;
  100. size_t Length = m_Blob->GetLength();
  101. auto_ptr<char> Buffer( new char[ Length ] );
  102. m_Blob->Decrypt( Buffer.get(), Length );
  103. CMarshalCursor Cursor( Buffer.get(), Length );
  104. CAuthCredentialsUnmarshaller m1( Cursor, &cred );
  105. return cred;
  106. }
  107. //------------------------------------------------------------------------
  108. CCredentialsContainer::CCredentialsContainer()
  109. {
  110. }
  111. CCredentialsContainer::~CCredentialsContainer()
  112. {
  113. Clear();
  114. }
  115. void
  116. CCredentialsContainer::Clear()
  117. {
  118. Dictionary::iterator iter;
  119. //
  120. // Keep deleting the first element until the map is empty.
  121. //
  122. while (iter = m_Dictionary.begin(), (iter != m_Dictionary.end()))
  123. {
  124. CEncryptedCredentials * cred = iter->second;
  125. m_Dictionary.erase( iter );
  126. delete cred;
  127. }
  128. }
  129. HRESULT
  130. CCredentialsContainer::Update(
  131. const BG_AUTH_CREDENTIALS * Credentials
  132. )
  133. {
  134. try
  135. {
  136. KEY Key = MakeKey( Credentials->Target, Credentials->Scheme );
  137. CEncryptedCredentials * OldCredentials = m_Dictionary[ Key ];
  138. auto_ptr<CEncryptedCredentials> NewCredentials(new CEncryptedCredentials( *Credentials ));
  139. m_Dictionary[ Key ] = NewCredentials.get();
  140. NewCredentials.release();
  141. delete OldCredentials;
  142. return S_OK;
  143. }
  144. catch( ComError err )
  145. {
  146. return err.Error();
  147. }
  148. }
  149. HRESULT
  150. CCredentialsContainer::Remove(
  151. BG_AUTH_TARGET Target,
  152. BG_AUTH_SCHEME Scheme
  153. )
  154. {
  155. try
  156. {
  157. KEY Key = MakeKey( Target, Scheme );
  158. CEncryptedCredentials * OldCredentials = m_Dictionary[ Key ];
  159. m_Dictionary[ Key ] = 0;
  160. delete OldCredentials;
  161. if (OldCredentials == NULL)
  162. {
  163. return S_FALSE;
  164. }
  165. return S_OK;
  166. }
  167. catch( ComError err )
  168. {
  169. return err.Error();
  170. }
  171. }
  172. size_t CCredentialsContainer::GetSizeEstimate(
  173. const BG_AUTH_CREDENTIALS * Credentials
  174. ) const
  175. {
  176. const Overhead = 1000;
  177. //
  178. // accurate sizing is expensive, so do something cheap and conservative.
  179. //
  180. size_t Size = Overhead;
  181. Size += CUnicodeStringMarshaller::Size( Credentials->Credentials.Basic.UserName );
  182. Size += CUnicodeStringMarshaller::Size( Credentials->Credentials.Basic.Password );
  183. return Size;
  184. }
  185. HRESULT CCredentialsContainer::Find(
  186. BG_AUTH_TARGET Target,
  187. BG_AUTH_SCHEME Scheme,
  188. BG_AUTH_CREDENTIALS ** pCredentials
  189. ) const
  190. {
  191. *pCredentials = 0;
  192. KEY Key = MakeKey( Target, Scheme );
  193. try
  194. {
  195. // This is what we want, except that it doesn't work on a const container:
  196. // CEncryptedCredentials * cred = m_Dictionary[ Key ];
  197. CEncryptedCredentials * cred = 0;
  198. Dictionary::iterator iter = m_Dictionary.find( Key );
  199. if (iter != m_Dictionary.end())
  200. {
  201. cred = iter->second;
  202. }
  203. if (!cred)
  204. {
  205. return S_FALSE;
  206. }
  207. *pCredentials = cred->Decrypt();
  208. return S_OK;
  209. }
  210. catch( ComError err )
  211. {
  212. return err.Error();
  213. }
  214. }
  215. BG_AUTH_CREDENTIALS * CCredentialsContainer::FindFirst( Cookie & cookie ) const
  216. {
  217. cookie = m_Dictionary.begin();
  218. return FindNext( cookie );
  219. }
  220. BG_AUTH_CREDENTIALS * CCredentialsContainer::FindNext( Cookie & cookie ) const
  221. {
  222. while (cookie != m_Dictionary.end() && cookie->second == NULL)
  223. {
  224. ++cookie;
  225. }
  226. if (cookie == m_Dictionary.end())
  227. {
  228. return NULL;
  229. }
  230. CEncryptedCredentials * EncryptedCredentials = cookie->second;
  231. BG_AUTH_CREDENTIALS * Credentials = EncryptedCredentials->Decrypt();
  232. ++cookie;
  233. return Credentials;
  234. }
  235. void
  236. CCredentialsContainer::Serialize( HANDLE hFile )
  237. {
  238. Dictionary::iterator iter;
  239. long count = 0;
  240. for ( iter = m_Dictionary.begin(); iter != m_Dictionary.end(); ++iter)
  241. {
  242. KEY Key = iter->first;
  243. CEncryptedCredentials * cred = iter->second;
  244. if (cred)
  245. {
  246. count++;
  247. }
  248. }
  249. SafeWriteFile( hFile, count );
  250. for ( iter = m_Dictionary.begin(); iter != m_Dictionary.end(); ++iter)
  251. {
  252. KEY Key = iter->first;
  253. CEncryptedCredentials * cred = iter->second;
  254. if (!cred)
  255. {
  256. continue;
  257. }
  258. SafeWriteFile( hFile, Key );
  259. cred->Serialize( hFile );
  260. }
  261. }
  262. void
  263. CCredentialsContainer::Unserialize( HANDLE hFile )
  264. {
  265. long count;
  266. SafeReadFile( hFile, &count );
  267. while (count-- > 0)
  268. {
  269. KEY Key;
  270. auto_ptr<CEncryptedCredentials> cred( new CEncryptedCredentials );
  271. SafeReadFile( hFile, &Key );
  272. cred->Unserialize( hFile );
  273. m_Dictionary[ Key ] = cred.get();
  274. cred.release();
  275. }
  276. }