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.

1006 lines
23 KiB

  1. /*++
  2. Copyright (c) 1995 Microsoft Corporation
  3. Module Name:
  4. httpfilt.cxx
  5. Abstract:
  6. This module contains the code to create or set the HTTP PCT/SSL keys and
  7. password
  8. Author:
  9. John Ludeman (johnl) 19-Oct-1995
  10. Revision History:
  11. --*/
  12. #include <nt.h>
  13. #include <ntrtl.h>
  14. #include <nturtl.h>
  15. #include <ntsecapi.h>
  16. #include <windows.h>
  17. #define SECURITY_WIN32
  18. #include <sspi.h>
  19. #include <spseal.h>
  20. #include <issperr.h>
  21. #include <sslsp.h>
  22. #include <w3svc.h>
  23. #include <stdio.h>
  24. #include <stdlib.h>
  25. #include <string.h>
  26. #include <fcntl.h>
  27. #include <io.h>
  28. #include <strings.h>
  29. //
  30. // macros
  31. //
  32. #define IS_ARG(c) ((c) == L'-' || (c) == L'/')
  33. #define TO_UNICODE( pch, ach ) \
  34. MultiByteToWideChar( CP_ACP, MB_PRECOMPOSED, (pch), -1, (ach), sizeof((ach))/sizeof(WCHAR))
  35. #define TO_ANSI( pch, ach ) \
  36. WideCharToMultiByte( CP_ACP, WC_COMPOSITECHECK, pch, -1, ach, sizeof(ach), 0, 0 )
  37. //
  38. // Private constants.
  39. //
  40. //
  41. // Private types.
  42. //
  43. BOOL fUUDecode = TRUE;
  44. //
  45. // Private prototypes.
  46. //
  47. DWORD
  48. SetRegKeys(
  49. IN LPWSTR pszServer,
  50. IN LPWSTR pszPrivateKeyFile,
  51. IN LPWSTR pszCertificateFile,
  52. IN LPWSTR pszPassword,
  53. IN LPWSTR pszAddress
  54. );
  55. BOOL
  56. SetKeySecret(
  57. WCHAR * pszServer,
  58. WCHAR * pszFormat,
  59. WCHAR * pszAddress,
  60. VOID * pvData,
  61. DWORD cbData
  62. );
  63. void usage();
  64. VOID
  65. uudecode_cert(
  66. char * bufcoded,
  67. DWORD * pcbDecoded
  68. );
  69. VOID
  70. printfids(
  71. DWORD ids,
  72. ...
  73. );
  74. DWORD
  75. DeleteAll(
  76. WCHAR * pszServer
  77. );
  78. BOOL
  79. TsGetSecretW(
  80. WCHAR * pszSecretName,
  81. WCHAR * * ppchValue
  82. );
  83. //
  84. // Public functions.
  85. //
  86. int
  87. __cdecl
  88. main(
  89. int argc,
  90. char * argv[]
  91. )
  92. {
  93. DWORD err;
  94. CHAR buff[MAX_PATH+1];
  95. BOOL fDeleteAll = FALSE;
  96. LPWSTR password = NULL;
  97. LPWSTR privatekey = NULL;
  98. LPWSTR cert = NULL;
  99. LPWSTR address = NULL;
  100. LPWSTR server = NULL;
  101. WCHAR achpassword[MAX_PATH+1];
  102. WCHAR achprivatekey[MAX_PATH+1];
  103. WCHAR achcert[MAX_PATH+1];
  104. WCHAR achaddress[MAX_PATH+1];
  105. WCHAR achserver[MAX_PATH+1];
  106. printfids( IDS_BANNER1 );
  107. printfids( IDS_BANNER2 );
  108. for (--argc, ++argv; argc; --argc, ++argv) {
  109. if (IS_ARG(**argv)) {
  110. switch (*++*argv) {
  111. case 'u':
  112. case 'U':
  113. fUUDecode = FALSE;
  114. break;
  115. case 'd':
  116. case 'D':
  117. fDeleteAll = TRUE;
  118. break;
  119. default:
  120. printfids( IDS_BAD_FLAG, **argv );
  121. usage();
  122. }
  123. } else if ( !server && (*argv)[0] == L'\\' && (*argv)[1] == L'\\'
  124. && !password ) {
  125. TO_UNICODE( (*argv) + 2, achserver );
  126. server = achserver;
  127. } else if (!password) {
  128. TO_UNICODE( *argv, achpassword );
  129. password = achpassword;
  130. } else if (!privatekey) {
  131. TO_UNICODE( *argv, achprivatekey );
  132. privatekey = achprivatekey;
  133. } else if (!cert) {
  134. TO_UNICODE( *argv, achcert );
  135. cert = achcert;
  136. } else if (!address) {
  137. TO_UNICODE( *argv, achaddress );
  138. address = achaddress;
  139. } else {
  140. printfids( IDS_BAD_ARG, *argv);
  141. usage();
  142. }
  143. }
  144. if ( fDeleteAll )
  145. {
  146. return DeleteAll( server );
  147. }
  148. //
  149. // Address and server are optional
  150. //
  151. if (!(password && privatekey && cert)) {
  152. printfids( IDS_MISSING_ARG );
  153. usage();
  154. }
  155. if ( err = SetRegKeys( server, privatekey, cert, password, address ) )
  156. {
  157. printfids( IDS_FAILED_TO_SET );
  158. }
  159. else
  160. {
  161. if ( address )
  162. {
  163. TO_ANSI( address, buff );
  164. printfids( IDS_SUCCESSFUL_SET,
  165. buff );
  166. }
  167. else
  168. {
  169. printfids( IDS_SUCCESSFUL_SET_DEF );
  170. }
  171. }
  172. return err;
  173. } // main
  174. void usage()
  175. {
  176. printfids( IDS_USAGE1 );
  177. printfids( IDS_USAGE2 );
  178. //printfids( IDS_USAGE3 ); // -p help
  179. printfids( IDS_USAGE4 );
  180. printfids( IDS_USAGE5 );
  181. printfids( IDS_USAGE6 );
  182. printfids( IDS_USAGE7 );
  183. printfids( IDS_USAGE8 );
  184. printfids( IDS_USAGE9 );
  185. printfids( IDS_USAGE10 );
  186. printfids( IDS_USAGE11 );
  187. printfids( IDS_USAGE12 );
  188. printfids( IDS_USAGE13 );
  189. //printfids( IDS_USAGE14 ); // -p help
  190. printfids( IDS_USAGE15 );
  191. printfids( IDS_USAGE16 );
  192. printfids( IDS_USAGE17 );
  193. printfids( IDS_USAGE18 );
  194. printfids( IDS_USAGE19 );
  195. printfids( IDS_USAGE20 );
  196. exit(1);
  197. }
  198. //+---------------------------------------------------------------------------
  199. //
  200. // Function: SetRegKeys
  201. //
  202. // Synopsis: This loads the data contained in two files, a private key
  203. // file, which contains the key, and a certificate file,
  204. // which contains the certificate of the public portion of the key.
  205. // These are loaded, then turned into a credential handle, then
  206. // set in the registry as secrets
  207. //
  208. // Arguments: [pszServer] -- Server to create secrets, NULL for local
  209. // [pszPrivateKeyFile] -- Unicode file name
  210. // [pszCertificateFile] -- Unicode file name
  211. // [pszPassword] -- Unicode password
  212. // [pszAddress] -- Unicode IP address for name or NULL
  213. //
  214. // History: 9-27-95 RichardW Created
  215. //
  216. // Notes:
  217. //
  218. //----------------------------------------------------------------------------
  219. DWORD
  220. SetRegKeys(
  221. IN LPWSTR pszServer,
  222. IN LPWSTR pszPrivateKeyFile,
  223. IN LPWSTR pszCertificateFile,
  224. IN LPWSTR pszPassword,
  225. IN LPWSTR pszAddress
  226. )
  227. {
  228. HANDLE hFile;
  229. SSL_CREDENTIAL_CERTIFICATE creds;
  230. DWORD cbRead;
  231. SECURITY_STATUS scRet = 0;
  232. TimeStamp tsExpiry;
  233. CHAR achPassword[MAX_PATH + 1];
  234. CredHandle hCreds;
  235. DWORD cch;
  236. CHAR buff[MAX_PATH+1];
  237. //
  238. // Fetch data from files:
  239. //
  240. hFile = CreateFileW( pszPrivateKeyFile,
  241. GENERIC_READ,
  242. FILE_SHARE_READ,
  243. NULL,
  244. OPEN_EXISTING,
  245. 0,
  246. NULL
  247. );
  248. if (hFile == INVALID_HANDLE_VALUE)
  249. {
  250. TO_ANSI( pszPrivateKeyFile, buff );
  251. printfids( IDS_FILE_NOT_FOUND,
  252. GetLastError(),
  253. buff );
  254. return GetLastError();
  255. }
  256. creds.cbPrivateKey = GetFileSize( hFile, NULL );
  257. if (creds.cbPrivateKey == (DWORD) -1 )
  258. {
  259. CloseHandle( hFile );
  260. return GetLastError();
  261. }
  262. creds.pPrivateKey = LocalAlloc( LMEM_FIXED, creds.cbPrivateKey );
  263. if ( !creds.pPrivateKey )
  264. {
  265. CloseHandle( hFile );
  266. return GetLastError();
  267. }
  268. if (! ReadFile( hFile,
  269. creds.pPrivateKey,
  270. creds.cbPrivateKey,
  271. &cbRead,
  272. NULL ) )
  273. {
  274. CloseHandle( hFile );
  275. LocalFree( creds.pPrivateKey );
  276. return GetLastError();
  277. }
  278. CloseHandle( hFile );
  279. //
  280. // Only the certificate is UUencoded
  281. //
  282. hFile = CreateFileW( pszCertificateFile,
  283. GENERIC_READ,
  284. FILE_SHARE_READ,
  285. NULL,
  286. OPEN_EXISTING,
  287. 0,
  288. NULL );
  289. if (hFile == INVALID_HANDLE_VALUE)
  290. {
  291. TO_ANSI( pszCertificateFile, buff );
  292. printfids( IDS_FILE_NOT_FOUND,
  293. GetLastError(),
  294. buff );
  295. LocalFree( creds.pPrivateKey );
  296. return GetLastError();
  297. }
  298. creds.cbCertificate = GetFileSize( hFile, NULL );
  299. if (creds.cbCertificate == (DWORD) -1 )
  300. {
  301. CloseHandle( hFile );
  302. LocalFree( creds.pPrivateKey );
  303. return GetLastError();
  304. }
  305. creds.pCertificate = LocalAlloc( LMEM_FIXED, creds.cbCertificate + 1);
  306. if ( !creds.pCertificate )
  307. {
  308. CloseHandle( hFile );
  309. LocalFree( creds.pPrivateKey );
  310. return GetLastError();
  311. }
  312. if (! ReadFile( hFile,
  313. creds.pCertificate,
  314. creds.cbCertificate,
  315. &cbRead,
  316. NULL ) )
  317. {
  318. CloseHandle( hFile );
  319. LocalFree( creds.pPrivateKey );
  320. LocalFree( creds.pCertificate );
  321. return GetLastError();
  322. }
  323. CloseHandle( hFile );
  324. //
  325. // Zero terminate so we can uudecode
  326. //
  327. ((BYTE *)creds.pCertificate)[cbRead] = '\0';
  328. if ( fUUDecode )
  329. {
  330. uudecode_cert( creds.pCertificate,
  331. &creds.cbCertificate );
  332. }
  333. //
  334. // Whew! Now that we have safely loaded the keys from disk, get a cred
  335. // handle based on the certificate/prv key combo
  336. //
  337. //
  338. // BUGBUG - password field should be Unicode, do a quick conversion
  339. // until structure is fixed
  340. //
  341. cch = TO_ANSI( pszPassword, achPassword );
  342. if ( !cch )
  343. {
  344. return GetLastError();
  345. }
  346. creds.pszPassword = achPassword;
  347. //
  348. // Note we always do the credential check locally even if the server is
  349. // remote. This means the local machine must have the correct security
  350. // provider package installed.
  351. //
  352. #if 0
  353. if ( !pszServer )
  354. {
  355. #endif
  356. scRet = AcquireCredentialsHandleW( NULL, // My name (ignored)
  357. SSLSP_NAME_W, // Package
  358. SECPKG_CRED_INBOUND,// Use
  359. NULL, // Logon Id (ign.)
  360. &creds, // auth data
  361. NULL, // dce-stuff
  362. NULL, // dce-stuff
  363. &hCreds, // Handle
  364. &tsExpiry );
  365. if ( FAILED(scRet) )
  366. {
  367. if ( scRet == SEC_E_NOT_OWNER )
  368. {
  369. printfids( IDS_BAD_PASSWORD );
  370. }
  371. else if ( scRet == SEC_E_SECPKG_NOT_FOUND )
  372. {
  373. printfids( IDS_SECPKG_NOT_FOUND );
  374. }
  375. else
  376. {
  377. printfids( IDS_KEYCHECK_FAILED,
  378. scRet );
  379. }
  380. }
  381. #if 0
  382. }
  383. else
  384. {
  385. printf("\nWarning! Bypassing credential check because target is remote\n");
  386. }
  387. #endif
  388. //
  389. // If we successfully acquired a credential handle, set the secrets
  390. //
  391. if ( !FAILED( scRet ))
  392. {
  393. if ( !pszServer )
  394. {
  395. FreeCredentialsHandle( &hCreds );
  396. }
  397. //
  398. // Supply the default name if none was supplied
  399. //
  400. if ( !pszAddress )
  401. pszAddress = L"Default";
  402. //
  403. // Set the secrets
  404. //
  405. if ( !SetKeySecret( pszServer,
  406. L"W3_PUBLIC_KEY_%s",
  407. pszAddress,
  408. creds.pCertificate,
  409. creds.cbCertificate ) ||
  410. !SetKeySecret( pszServer,
  411. L"W3_PRIVATE_KEY_%s",
  412. pszAddress,
  413. creds.pPrivateKey,
  414. creds.cbPrivateKey ) ||
  415. !SetKeySecret( pszServer,
  416. L"W3_KEY_PASSWORD_%s",
  417. pszAddress,
  418. achPassword,
  419. strlen( achPassword ) + 1) )
  420. {
  421. printfids( IDS_SETSECRET_FAILED,
  422. GetLastError());
  423. scRet = (SECURITY_STATUS) GetLastError();
  424. }
  425. else
  426. {
  427. WCHAR InstalledKeys[16384];
  428. WCHAR * pchKeys;
  429. *InstalledKeys = L'\0';
  430. //
  431. // Ok if this fails, it may not exist yet
  432. //
  433. if ( TsGetSecretW( W3_SSL_KEY_LIST_SECRET,
  434. &pchKeys ))
  435. {
  436. wcscpy( InstalledKeys, pchKeys );
  437. }
  438. wcscat( InstalledKeys, pszAddress );
  439. wcscat( InstalledKeys, L"," );
  440. #if DBG
  441. printf("New list: %S\n", InstalledKeys);
  442. #endif
  443. if ( !SetKeySecret( pszServer,
  444. L"W3_KEY_LIST",
  445. pszAddress,
  446. InstalledKeys,
  447. (wcslen( InstalledKeys ) + 1) * sizeof(WCHAR)))
  448. {
  449. #if DBG
  450. printf("Warning: failed to set key list data, error %d\n");
  451. #endif
  452. scRet = (SECURITY_STATUS) GetLastError();
  453. }
  454. }
  455. }
  456. //
  457. // Zero out and free the key data memory, on success or fail
  458. //
  459. ZeroMemory( creds.pPrivateKey, creds.cbPrivateKey );
  460. ZeroMemory( creds.pCertificate, creds.cbCertificate );
  461. ZeroMemory( achPassword, cch );
  462. ZeroMemory( pszPassword, cch );
  463. LocalFree( creds.pPrivateKey );
  464. LocalFree( creds.pCertificate );
  465. //
  466. // Tell the caller about it.
  467. //
  468. return( scRet );
  469. }
  470. BOOL
  471. SetKeySecret(
  472. WCHAR * pszServer,
  473. WCHAR * pszFormat,
  474. WCHAR * pszAddress,
  475. VOID * pvData,
  476. DWORD cbData
  477. )
  478. {
  479. BOOL fResult;
  480. NTSTATUS ntStatus;
  481. LSA_UNICODE_STRING unicodeName;
  482. LSA_UNICODE_STRING unicodeSecret;
  483. LSA_UNICODE_STRING unicodeServer;
  484. LSA_HANDLE hPolicy;
  485. LSA_OBJECT_ATTRIBUTES ObjectAttributes;
  486. WCHAR achSecretName[MAX_PATH+1];
  487. CHAR buff[MAX_PATH+1];
  488. //
  489. // Open a policy to the remote LSA
  490. //
  491. InitializeObjectAttributes( &ObjectAttributes,
  492. NULL,
  493. 0L,
  494. NULL,
  495. NULL );
  496. if ( pszServer )
  497. {
  498. unicodeServer.Buffer = pszServer;
  499. unicodeServer.Length = wcslen( pszServer ) * sizeof(WCHAR);
  500. unicodeServer.MaximumLength = unicodeServer.Length + sizeof(WCHAR);
  501. }
  502. ntStatus = LsaOpenPolicy( pszServer ? &unicodeServer : NULL,
  503. &ObjectAttributes,
  504. POLICY_ALL_ACCESS,
  505. &hPolicy );
  506. if ( !NT_SUCCESS( ntStatus ) )
  507. {
  508. SetLastError( LsaNtStatusToWinError( ntStatus ) );
  509. TO_ANSI( pszServer, buff );
  510. printfids(IDS_FAILED_OPENING_SERVER,
  511. buff,
  512. GetLastError() );
  513. return FALSE;
  514. }
  515. //
  516. // Build the secret name
  517. //
  518. wsprintfW( achSecretName,
  519. pszFormat,
  520. pszAddress );
  521. unicodeSecret.Buffer = pvData;
  522. unicodeSecret.Length = (USHORT) cbData;
  523. unicodeSecret.MaximumLength = (USHORT) cbData;
  524. unicodeName.Buffer = achSecretName;
  525. unicodeName.Length = wcslen( achSecretName ) * sizeof(WCHAR);
  526. unicodeName.MaximumLength = unicodeName.Length + sizeof(WCHAR);
  527. //
  528. // Query the secret value.
  529. //
  530. ntStatus = LsaStorePrivateData( hPolicy,
  531. &unicodeName,
  532. pvData ? &unicodeSecret : NULL );
  533. fResult = NT_SUCCESS(ntStatus);
  534. //
  535. // Cleanup & exit.
  536. //
  537. LsaClose( hPolicy );
  538. if ( !fResult )
  539. SetLastError( LsaNtStatusToWinError( ntStatus ));
  540. return fResult;
  541. } // SetKeySecret
  542. VOID
  543. printfids(
  544. DWORD ids,
  545. ...
  546. )
  547. {
  548. CHAR szBuff[2048];
  549. CHAR szString[2048];
  550. va_list argList;
  551. //
  552. // Try and load the string
  553. //
  554. if ( !LoadString( GetModuleHandle( NULL ),
  555. ids,
  556. szString,
  557. sizeof( szString ) ))
  558. {
  559. printf( "Error loading string ID %d\n",
  560. ids );
  561. return;
  562. }
  563. va_start( argList, ids );
  564. vsprintf( szBuff, szString, argList );
  565. va_end( argList );
  566. printf( szBuff );
  567. }
  568. const int pr2six[256]={
  569. 64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
  570. 64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,62,64,64,64,63,
  571. 52,53,54,55,56,57,58,59,60,61,64,64,64,64,64,64,64,0,1,2,3,4,5,6,7,8,9,
  572. 10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,64,64,64,64,64,64,26,27,
  573. 28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,
  574. 64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
  575. 64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
  576. 64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
  577. 64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
  578. 64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
  579. 64,64,64,64,64,64,64,64,64,64,64,64,64
  580. };
  581. //
  582. // We have to squirt a record into the decoded stream
  583. //
  584. #define CERT_RECORD 13
  585. #define CERT_SIZE_HIBYTE 2 // Index into record of record size
  586. #define CERT_SIZE_LOBYTE 3
  587. unsigned char abCertHeader[] = {0x30, 0x82, // Record
  588. 0x00, 0x00, // Size of cert + buff
  589. 0x04, 0x0b, 0x63, 0x65,// Cert record data
  590. 0x72, 0x74, 0x69, 0x66,
  591. 0x69, 0x63, 0x61, 0x74,
  592. 0x65 };
  593. VOID uudecode_cert(char * bufcoded,
  594. DWORD * pcbDecoded )
  595. {
  596. int nbytesdecoded;
  597. char *bufin = bufcoded;
  598. unsigned char *bufout = bufcoded;
  599. unsigned char *pbuf;
  600. int nprbytes;
  601. char * beginbuf = bufcoded;
  602. /* Strip leading whitespace. */
  603. while(*bufcoded==' ' ||
  604. *bufcoded == '\t' ||
  605. *bufcoded == '\r' ||
  606. *bufcoded == '\n' )
  607. {
  608. bufcoded++;
  609. }
  610. //
  611. // If there is a beginning '---- ....' then skip the first line
  612. //
  613. if ( bufcoded[0] == '-' && bufcoded[1] == '-' )
  614. {
  615. bufin = strchr( bufcoded, '\n' );
  616. if ( bufin )
  617. {
  618. bufin++;
  619. bufcoded = bufin;
  620. }
  621. else
  622. {
  623. bufin = bufcoded;
  624. }
  625. }
  626. else
  627. {
  628. bufin = bufcoded;
  629. }
  630. //
  631. // Strip all cr/lf from the block
  632. //
  633. pbuf = bufin;
  634. while ( *pbuf )
  635. {
  636. if ( *pbuf == '\r' || *pbuf == '\n' )
  637. {
  638. memmove( pbuf, pbuf+1, strlen( pbuf + 1) + 1 );
  639. }
  640. else
  641. {
  642. pbuf++;
  643. }
  644. }
  645. /* Figure out how many characters are in the input buffer.
  646. * If this would decode into more bytes than would fit into
  647. * the output buffer, adjust the number of input bytes downwards.
  648. */
  649. while(pr2six[*(bufin++)] <= 63);
  650. nprbytes = bufin - bufcoded - 1;
  651. nbytesdecoded = ((nprbytes+3)/4) * 3;
  652. bufin = bufcoded;
  653. while (nprbytes > 0) {
  654. *(bufout++) =
  655. (unsigned char) (pr2six[*bufin] << 2 | pr2six[bufin[1]] >> 4);
  656. *(bufout++) =
  657. (unsigned char) (pr2six[bufin[1]] << 4 | pr2six[bufin[2]] >> 2);
  658. *(bufout++) =
  659. (unsigned char) (pr2six[bufin[2]] << 6 | pr2six[bufin[3]]);
  660. bufin += 4;
  661. nprbytes -= 4;
  662. }
  663. if(nprbytes & 03) {
  664. if(pr2six[bufin[-2]] > 63)
  665. nbytesdecoded -= 2;
  666. else
  667. nbytesdecoded -= 1;
  668. }
  669. //
  670. // Now we need to add a new wrapper sequence around the certificate
  671. // indicating this is a certificate
  672. //
  673. memmove( beginbuf + sizeof(abCertHeader),
  674. beginbuf,
  675. nbytesdecoded );
  676. memcpy( beginbuf,
  677. abCertHeader,
  678. sizeof(abCertHeader) );
  679. //
  680. // The beginning record size is the total number of bytes decoded plus
  681. // the number of bytes in the certificate header
  682. //
  683. beginbuf[CERT_SIZE_HIBYTE] = (BYTE) (((USHORT)nbytesdecoded+CERT_RECORD) >> 8);
  684. beginbuf[CERT_SIZE_LOBYTE] = (BYTE) ((USHORT)nbytesdecoded+CERT_RECORD);
  685. nbytesdecoded += sizeof(abCertHeader);
  686. if ( pcbDecoded )
  687. *pcbDecoded = nbytesdecoded;
  688. }
  689. BOOL
  690. TsGetSecretW(
  691. WCHAR * pszSecretName,
  692. WCHAR * * ppchValue
  693. )
  694. /*++
  695. Description:
  696. Retrieves the specified unicode secret
  697. Note we're loose with the allocated buffer since we're a simple
  698. command line app.
  699. Arguments:
  700. pszSecretName - LSA Secret to retrieve
  701. ppchValue - Receives pointer to allocated buffer
  702. Returns:
  703. TRUE on success and FALSE if any failure.
  704. --*/
  705. {
  706. NTSTATUS ntStatus;
  707. LSA_UNICODE_STRING * punicodePassword = NULL;
  708. LSA_UNICODE_STRING unicodeSecret;
  709. LSA_HANDLE hPolicy;
  710. LSA_OBJECT_ATTRIBUTES ObjectAttributes;
  711. //
  712. // Open a policy to the remote LSA
  713. //
  714. InitializeObjectAttributes( &ObjectAttributes,
  715. NULL,
  716. 0L,
  717. NULL,
  718. NULL );
  719. ntStatus = LsaOpenPolicy( NULL,
  720. &ObjectAttributes,
  721. POLICY_ALL_ACCESS,
  722. &hPolicy );
  723. if ( !NT_SUCCESS( ntStatus ) )
  724. {
  725. SetLastError( LsaNtStatusToWinError( ntStatus ) );
  726. return FALSE;
  727. }
  728. unicodeSecret.Buffer = pszSecretName;
  729. unicodeSecret.Length = wcslen( pszSecretName ) * sizeof(WCHAR);
  730. unicodeSecret.MaximumLength = unicodeSecret.Length + sizeof(WCHAR);
  731. //
  732. // Query the secret value.
  733. //
  734. ntStatus = LsaRetrievePrivateData( hPolicy,
  735. &unicodeSecret,
  736. &punicodePassword );
  737. if( NT_SUCCESS(ntStatus) )
  738. {
  739. *ppchValue = (WCHAR *) punicodePassword->Buffer;
  740. return TRUE;
  741. }
  742. return FALSE;
  743. } // TsGetSecretW
  744. DWORD
  745. DeleteAll(
  746. WCHAR * pszServer
  747. )
  748. {
  749. WCHAR * pchKeys;
  750. WCHAR * pszAddress;
  751. if ( !TsGetSecretW( L"W3_KEY_LIST",
  752. &pchKeys ))
  753. {
  754. printfids( IDS_NO_KEYS_INSTALLED );
  755. return NO_ERROR;
  756. }
  757. #if DBG
  758. printf("Installed keys: %S\n", pchKeys);
  759. #endif
  760. pszAddress = pchKeys;
  761. while ( pchKeys = wcschr( pchKeys, L',' ))
  762. {
  763. //
  764. // Ignore empty segments
  765. //
  766. if ( *pszAddress != L',' )
  767. {
  768. *pchKeys = L'\0';
  769. #if DBG
  770. printf("deleting %S\n", pszAddress );
  771. #endif
  772. //
  773. // Nuke the secrets
  774. //
  775. SetKeySecret( pszServer,
  776. L"W3_PUBLIC_KEY_%s",
  777. pszAddress,
  778. NULL,
  779. 0 );
  780. SetKeySecret( pszServer,
  781. L"W3_PRIVATE_KEY_%s",
  782. pszAddress,
  783. NULL,
  784. 0 );
  785. SetKeySecret( pszServer,
  786. L"W3_KEY_PASSWORD_%s",
  787. pszAddress,
  788. NULL,
  789. 0 );
  790. }
  791. pchKeys++;
  792. pszAddress = pchKeys;
  793. }
  794. //
  795. // Now delete the list key
  796. //
  797. if ( !SetKeySecret( pszServer,
  798. L"W3_KEY_LIST",
  799. L"",
  800. NULL,
  801. 0 ))
  802. {
  803. #if DBG
  804. printf("Warning: failed to set key list data, error %d\n");
  805. #endif
  806. return GetLastError();
  807. }
  808. printfids( IDS_DELETE_SUCCESSFUL );
  809. return NO_ERROR;
  810. }