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.

528 lines
14 KiB

  1. #include "stdafx.h"
  2. #include "KeyObjs.h"
  3. #include "CmnKey.h"
  4. #include "W3Key.h"
  5. #include "W3Serv.h"
  6. #include "resource.h"
  7. #include "kmlsa.h"
  8. #include "CnctDlg.h"
  9. extern HINSTANCE g_hInstance;
  10. // defines taken from the old KeyGen utility
  11. #define MESSAGE_HEADER "-----BEGIN NEW CERTIFICATE REQUEST-----\r\n"
  12. #define MESSAGE_TRAILER "-----END NEW CERTIFICATE REQUEST-----\r\n"
  13. #define MIME_TYPE "Content-Type: application/x-pkcs10\r\n"
  14. #define MIME_ENCODING "Content-Transfer-Encoding: base64\r\n\r\n"
  15. IMPLEMENT_DYNCREATE(CW3Key, CKey);
  16. CW3Key::CW3Key() :
  17. m_fDefault(FALSE)
  18. {
  19. }
  20. CW3Key::~CW3Key()
  21. {
  22. }
  23. //-------------------------------------------------------------
  24. // update the key's caption
  25. void CW3Key::UpdateCaption( void )
  26. {
  27. // specify the resources to use
  28. HINSTANCE hOldRes = AfxGetResourceHandle();
  29. AfxSetResourceHandle( g_hInstance );
  30. // the caption is based on the name of the key
  31. CString szCaption = m_szName;
  32. // if the key is not attached at all, do not put the brackets on at all
  33. if ( m_fDefault || !m_szIPAddress.IsEmpty() )
  34. {
  35. // now we take on info about the server it is attached to
  36. szCaption += _T(" <");
  37. if ( m_fDefault )
  38. {
  39. CString szDefault;
  40. szDefault.LoadString( IDS_DEFAULT );
  41. szCaption += szDefault;
  42. }
  43. else
  44. {
  45. szCaption += m_szIPAddress;
  46. }
  47. szCaption += _T(">");
  48. }
  49. // and setup the caption
  50. m_szItemName = szCaption;
  51. FSetCaption(szCaption);
  52. // update the icon too
  53. UpdateIcon();
  54. // restore the resources
  55. AfxSetResourceHandle( hOldRes );
  56. }
  57. //-------------------------------------------------------------
  58. // init from keyset key
  59. //-------------------------------------------------------------
  60. BOOL CW3Key::FInitKey( HANDLE hPolicy, PWCHAR pwszName )
  61. {
  62. ASSERT( hPolicy && pwszName );
  63. // set the initial strings
  64. m_szName.LoadString( IDS_UNTITLED );
  65. // import the w3 key information
  66. if ( !ImportW3Key(hPolicy, pwszName) )
  67. return FALSE;
  68. // bring over the sz_ipaddress for the key
  69. m_szIPAddress = pwszName;
  70. // if it is the default key, flip the flag
  71. if ( m_szIPAddress == _T("Default") )
  72. {
  73. m_fDefault = TRUE;
  74. m_szIPAddress.Empty();
  75. }
  76. // build the caption name
  77. UpdateCaption();
  78. return TRUE;
  79. }
  80. //-------------------------------------------------------------
  81. // init from stored keyset key
  82. //-------------------------------------------------------------
  83. BOOL CW3Key::FInitKey( PVOID pData, DWORD cbSrc)
  84. {
  85. ASSERT( pData );
  86. // init from the data
  87. if ( !InitializeFromPointer( (PUCHAR)pData, cbSrc ) )
  88. return FALSE;
  89. // build the caption name
  90. UpdateCaption();
  91. return TRUE;
  92. }
  93. //-------------------------------------------------------------
  94. // make a copy of the key
  95. //-------------------------------------------------------------
  96. CKey* CW3Key::PClone( void )
  97. {
  98. CW3Key* pClone = NULL;
  99. // TRY to make a new key object
  100. try
  101. {
  102. pClone = new CW3Key;
  103. // copy over all the data
  104. pClone->CopyDataFrom( this );
  105. }
  106. catch( CException e )
  107. {
  108. // if the object had been made, delete it
  109. if ( pClone )
  110. delete pClone;
  111. return NULL;
  112. }
  113. return (CKey*)pClone;
  114. }
  115. //-------------------------------------------------------------
  116. // copy the members from a key into this key
  117. //-------------------------------------------------------------
  118. void CW3Key::CopyDataFrom( CKey* pKey )
  119. {
  120. // copy over the base data
  121. CKey::CopyDataFrom( pKey );
  122. // if the key we are copying from is a W3 key, copy over
  123. // the w3 specific information as well
  124. if ( pKey->IsKindOf(RUNTIME_CLASS(CW3Key)) )
  125. {
  126. CW3Key* pW3Key = (CW3Key*)pKey;
  127. m_szName = pW3Key->m_szName;
  128. }
  129. else
  130. {
  131. m_szName = pKey->m_szItemName;
  132. }
  133. // we do NOT copy over the default-type settings
  134. m_fDefault = FALSE;
  135. m_szName.Empty();
  136. }
  137. //-------------------------------------------------------------
  138. void CW3Key::OnProperties()
  139. {
  140. // specify the resources to use
  141. HINSTANCE hOldRes = AfxGetResourceHandle();
  142. AfxSetResourceHandle( g_hInstance );
  143. // the properties of the w3 key invove its ip address relationship
  144. CConnectionDlg dlg;
  145. // set the instance members of the dialog
  146. dlg.m_int_connection_type = CONNECTION_NONE;
  147. if ( m_fDefault )
  148. dlg.m_int_connection_type = CONNECTION_DEFAULT;
  149. if ( !m_szIPAddress.IsEmpty() )
  150. dlg.m_int_connection_type = CONNECTION_IPADDRESS;
  151. dlg.m_szIPAddress = m_szIPAddress;
  152. dlg.m_pKey = this;
  153. // run the dialog
  154. if ( dlg.DoModal() == IDOK )
  155. {
  156. // get the ip address
  157. m_szIPAddress = dlg.m_szIPAddress;
  158. // get whether or not this is the default and set it
  159. if ( dlg.m_int_connection_type == CONNECTION_DEFAULT )
  160. SetDefault();
  161. else
  162. m_fDefault = FALSE;
  163. // cause the name to rebuild
  164. UpdateCaption();
  165. // set it dirty
  166. SetDirty( TRUE );
  167. }
  168. // restore the resources
  169. AfxSetResourceHandle( hOldRes );
  170. }
  171. //-------------------------------------------------------------
  172. // install a cert - mostly just use the default action
  173. BOOL CW3Key::FInstallCertificate( PVOID pCert, DWORD cbCert, CString &szPass )
  174. {
  175. // first, we should test that the certificate and password are valid
  176. // for this particular key
  177. // cache the old certificate in case the new one fails
  178. DWORD old_cbCertificate = m_cbCertificate;
  179. PVOID old_pCertificate = m_pCertificate;
  180. // set the new one into place
  181. m_cbCertificate = cbCert;
  182. m_pCertificate = pCert;
  183. // verify the password - verify password puts up any error dialogs
  184. if ( !FVerifyValidPassword(szPass) )
  185. {
  186. // resore the old values
  187. m_cbCertificate = old_cbCertificate;
  188. m_pCertificate = old_pCertificate;
  189. // dispose of the new stuff
  190. GlobalFree( pCert );
  191. // return false
  192. return FALSE;
  193. }
  194. // run the default action
  195. BOOL fDefault = CKey::FInstallCertificate(pCert, cbCert, szPass);
  196. // if the default works, then take into account the ip releationship
  197. if ( fDefault )
  198. {
  199. // get the owning service object
  200. CW3KeyService* pService = (CW3KeyService*)PGetParent();
  201. // if this key is not set to any ip addresses or the default, check to
  202. // see if there is a default on this service. If there isn't, then set
  203. // this key to be the default.
  204. if ( pService && !m_fDefault && m_szIPAddress.IsEmpty() )
  205. {
  206. // get the service's default key
  207. CW3Key* pKeyDefault = pService->PGetDefaultKey();
  208. // if there is no default key, then this is easy, just set the default flag
  209. if ( !pKeyDefault )
  210. m_fDefault = TRUE;
  211. else
  212. // tell the user to select a connection option
  213. AfxMessageBox( IDS_SelectConnectMsg, MB_OK|MB_ICONINFORMATION );
  214. // cause the name to rebuild
  215. UpdateCaption();
  216. }
  217. }
  218. // return the default answer
  219. return fDefault;
  220. }
  221. //-------------------------------------------------------------
  222. void CW3Key::SetDefault()
  223. {
  224. // get the owning service object
  225. CW3KeyService* pService = (CW3KeyService*)PGetParent();
  226. // get the service's default key
  227. CW3Key* pKeyDefault = pService->PGetDefaultKey();
  228. // we only need to bother if there is a default key
  229. if ( pKeyDefault )
  230. {
  231. // change the old default key from default to none and update its caption
  232. pKeyDefault->m_fDefault = FALSE;
  233. pKeyDefault->UpdateCaption();
  234. }
  235. // set the default flag
  236. m_fDefault = TRUE;
  237. }
  238. //================ storage related methods
  239. //------------------------------------------------------------------------------
  240. BOOL CW3Key::WriteKey( HANDLE hPolicy, WORD iKey, PWCHAR pwcharName )
  241. {
  242. HGLOBAL hKeyData;
  243. PVOID pKeyData;
  244. SIZE_T cbKeyData;
  245. BOOL f = TRUE;
  246. DWORD err;
  247. // blank out the wide name of the string
  248. ASSERT( pwcharName );
  249. wcscpy( pwcharName, L"" );
  250. // now write out the normal part of the key
  251. PCHAR pName = (PCHAR)GlobalAlloc( GPTR, MAX_PATH+1 );
  252. PWCHAR pWName = (PWCHAR)GlobalAlloc( GPTR, (MAX_PATH+1) * sizeof(WCHAR) );
  253. // make sure we got the name buffers
  254. ASSERT( pName && pWName );
  255. if ( !pName || !pWName ) return FALSE;
  256. // if this key should write out W3 compatible keys, then do so
  257. if ( m_fDefault || !m_szIPAddress.IsEmpty() )
  258. {
  259. // if it is the default key, then the name is really easy
  260. if ( m_fDefault )
  261. {
  262. f = WriteW3Keys( hPolicy, KEYSET_DEFAULT );
  263. wcscpy( pwcharName, KEYSET_DEFAULT );
  264. }
  265. else
  266. {
  267. // prepare the name
  268. MultiByteToWideChar( CP_ACP, MB_PRECOMPOSED, m_szIPAddress, -1, pWName, MAX_PATH+1 );
  269. // write the keys
  270. f = WriteW3Keys( hPolicy, pWName );
  271. wcscpy( pwcharName, pWName );
  272. }
  273. }
  274. // get the data from the key
  275. hKeyData = HGenerateDataHandle( TRUE );
  276. if ( !hKeyData )
  277. {
  278. GlobalFree( (HGLOBAL)pName );
  279. GlobalFree( (HGLOBAL)pWName );
  280. return FALSE;
  281. }
  282. // prepare the name of the secret. - Base name plus the number+1
  283. sprintf( pName, "%s%d", KEY_NAME_BASE, iKey+1 );
  284. // unicodize the name
  285. MultiByteToWideChar( CP_ACP, MB_PRECOMPOSED, pName, -1, pWName, MAX_PATH+1 );
  286. // lock it down and get its size
  287. cbKeyData = GlobalSize(hKeyData);
  288. pKeyData = GlobalLock(hKeyData);
  289. ASSERT( cbKeyData < 0xFFFF );
  290. // write out the secret
  291. f &= FStoreLSASecret( hPolicy, pWName, pKeyData, (WORD)cbKeyData, &err );
  292. // unlock the data and get rid of it
  293. GlobalUnlock(hKeyData);
  294. GlobalFree( hKeyData );
  295. // free the string buffers
  296. GlobalFree( (HANDLE)pName );
  297. GlobalFree( (HANDLE)pWName );
  298. // set the dirty flag
  299. SetDirty( !f );
  300. // return success
  301. return f;
  302. }
  303. //------------------------------------------------------------------------------
  304. // If the key is being initialized from a keyset key, we must import the old W3 info
  305. BOOL CW3Key::ImportW3Key( HANDLE hPolicy, WCHAR* pWName )
  306. {
  307. DWORD err;
  308. PWCHAR pWSecret = (PWCHAR)GlobalAlloc( GPTR, (MAX_PATH+1) * sizeof(WCHAR) );
  309. PLSA_UNICODE_STRING pLSAData;
  310. #ifdef _DEBUG
  311. CString szName = pWName;
  312. #endif
  313. // make sure we got the buffers
  314. ASSERT( pWName && pWSecret );
  315. if ( !pWSecret )
  316. {
  317. AfxThrowMemoryException();
  318. return FALSE;
  319. }
  320. // start by retrieving the private key
  321. swprintf( pWSecret, KEYSET_PRIV_KEY, pWName );
  322. #ifdef _DEBUG
  323. szName = pWSecret;
  324. #endif
  325. pLSAData = FRetrieveLSASecret( hPolicy, pWSecret, &err );
  326. if ( !pLSAData )
  327. {
  328. AfxMessageBox( IDS_IMPORT_KEYSET_PRIV_ERROR );
  329. return FALSE;
  330. }
  331. // make room for the public key and put it in its place
  332. m_cbPrivateKey = pLSAData->Length;
  333. m_pPrivateKey = GlobalAlloc( GPTR, m_cbPrivateKey );
  334. if ( !m_pPrivateKey ) AfxThrowMemoryException();
  335. CopyMemory( m_pPrivateKey, pLSAData->Buffer, m_cbPrivateKey );
  336. // dispose of the data
  337. DisposeLSAData( pLSAData );
  338. // start by retrieving the public key (certificate)
  339. swprintf( pWSecret, KEYSET_PUB_KEY, pWName );
  340. #ifdef _DEBUG
  341. szName = pWSecret;
  342. #endif
  343. pLSAData = FRetrieveLSASecret( hPolicy, pWSecret, &err );
  344. if ( !pLSAData )
  345. {
  346. AfxMessageBox( IDS_IMPORT_KEYSET_PUB_ERROR );
  347. return FALSE;
  348. }
  349. // make room for the public key and put it in its place
  350. m_cbCertificate = pLSAData->Length;
  351. m_pCertificate = GlobalAlloc( GPTR, m_cbCertificate );
  352. if ( !m_pCertificate ) AfxThrowMemoryException();
  353. CopyMemory( m_pCertificate, pLSAData->Buffer, m_cbCertificate );
  354. // dispose of the data
  355. DisposeLSAData( pLSAData );
  356. // lastly, get the password
  357. swprintf( pWSecret, KEYSET_PASSWORD, pWName );
  358. #ifdef _DEBUG
  359. szName = pWSecret;
  360. #endif
  361. pLSAData = FRetrieveLSASecret( hPolicy, pWSecret, &err );
  362. if ( !pLSAData )
  363. {
  364. AfxMessageBox( IDS_IMPORT_KEYSET_PASS_ERROR );
  365. return FALSE;
  366. }
  367. // this is actually really easy because CString does the work for us
  368. // this is NOT stored as UNICODE!!!!
  369. m_szPassword = (PSTR)pLSAData->Buffer;
  370. // dispose of the data
  371. DisposeLSAData( pLSAData );
  372. // free the buffer for the secret names
  373. if ( pWSecret )
  374. GlobalFree( pWSecret );
  375. // return success
  376. return TRUE;
  377. }
  378. //------------------------------------------------------------------------------
  379. // write the important parts of the key out to the server as W3 readable secrets
  380. // the name is put into the list elsewhere
  381. BOOL CW3Key::WriteW3Keys( HANDLE hPolicy, WCHAR* pWName )
  382. {
  383. DWORD err;
  384. PWCHAR pWSecret = (PWCHAR)GlobalAlloc( GPTR, (MAX_PATH+1) * sizeof(WCHAR) );
  385. BOOL f;
  386. // make sure we got the buffer
  387. ASSERT( pWName && pWSecret );
  388. if ( !pWSecret )
  389. {
  390. AfxThrowMemoryException();
  391. return FALSE;
  392. }
  393. // write out the keys
  394. swprintf( pWSecret, KEYSET_PRIV_KEY, pWName );
  395. ASSERT( m_cbPrivateKey < 0xFFFF );
  396. ASSERT( m_pPrivateKey );
  397. f = FStoreLSASecret( hPolicy, pWSecret, m_pPrivateKey, (WORD)m_cbPrivateKey, &err );
  398. swprintf( pWSecret, KEYSET_PUB_KEY, pWName );
  399. ASSERT( m_cbCertificate < 0xFFFF );
  400. ASSERT( m_pCertificate );
  401. if ( f )
  402. f = FStoreLSASecret( hPolicy, pWSecret, m_pCertificate, (WORD)m_cbCertificate, &err );
  403. // The password is NOT stored as UNICODE!!!!!!!
  404. swprintf( pWSecret, KEYSET_PASSWORD, pWName );
  405. ASSERT( m_szPassword );
  406. if ( f )
  407. f = FStoreLSASecret( hPolicy, pWSecret, (void*)LPCSTR(m_szPassword),
  408. m_szPassword.GetLength()+1, &err );
  409. // free the buffer for the secret names
  410. GlobalFree( (HANDLE)pWSecret );
  411. // return whether or not we succeeded
  412. return f;
  413. }
  414.