Leaked source code of windows server 2003
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.

3245 lines
80 KiB

  1. /*++
  2. Copyright (c) 2000 Microsoft Corporation
  3. Module Name:
  4. credapi.c
  5. Abstract:
  6. This module contains the RPC client side routines for the credential manager.
  7. Author:
  8. Cliff Van Dyke (CliffV) January 11, 2000
  9. Revision History:
  10. --*/
  11. #include "lsaclip.h"
  12. #include "align.h"
  13. #include "credp.h"
  14. #include <rpcasync.h>
  15. DWORD
  16. CredpNtStatusToWinStatus(
  17. IN NTSTATUS Status
  18. )
  19. /*++
  20. Routine Description:
  21. Covert an NT Status code to a windows status code.
  22. There a enough funky status codes to justify this routine.
  23. Arguments:
  24. Status - NT Status code to convert
  25. Return Values:
  26. Windows status code.
  27. --*/
  28. {
  29. //
  30. // Some HRESULTS should simply be returned to the caller
  31. //
  32. if ( HRESULT_FACILITY(Status) == FACILITY_SCARD ||
  33. HRESULT_FACILITY(Status) == FACILITY_SECURITY ) {
  34. return Status;
  35. }
  36. //
  37. // Translate all other status codes
  38. //
  39. switch ( Status ) {
  40. case STATUS_SUCCESS:
  41. return NO_ERROR;
  42. case STATUS_INVALID_ACCOUNT_NAME:
  43. return ERROR_BAD_USERNAME;
  44. case STATUS_INVALID_PARAMETER_1:
  45. return ERROR_INVALID_FLAGS;
  46. default:
  47. return RtlNtStatusToDosError( Status );
  48. }
  49. }
  50. BOOL
  51. APIENTRY
  52. CredpEncodeCredential (
  53. IN OUT PENCRYPTED_CREDENTIALW Credential
  54. )
  55. /*++
  56. Routine Description:
  57. This routine encodes sensitive credential data for passing via LPC to
  58. the LSA process.
  59. Arguments:
  60. Credential - Specifies the credential to be encode.
  61. Encode the buffer in-place. The caller must ensure there is extra space
  62. available in the buffer pointed to by Credential->CredentialBlob by allocating
  63. a buffer AlocatedCredBlobSize() bytes long.
  64. Return Values:
  65. TRUE on success
  66. None
  67. --*/
  68. {
  69. NTSTATUS Status;
  70. //
  71. // If there is no credential blob,
  72. // we're done.
  73. //
  74. if ( Credential->Cred.CredentialBlob == NULL ||
  75. Credential->Cred.CredentialBlobSize == 0 ) {
  76. Credential->Cred.CredentialBlob = NULL;
  77. Credential->Cred.CredentialBlobSize = 0;
  78. Credential->ClearCredentialBlobSize = 0;
  79. //
  80. // Otherwise RtlEncryptMemory it.
  81. // (That's all we need since we're passing the buffer via LPC.)
  82. //
  83. } else {
  84. ULONG PaddingSize;
  85. //
  86. // Compute the real size of the passed in buffer
  87. //
  88. Credential->Cred.CredentialBlobSize = AllocatedCredBlobSize( Credential->ClearCredentialBlobSize );
  89. //
  90. // Clear the padding at the end to ensure we can compare encrypted blobs
  91. //
  92. PaddingSize = Credential->Cred.CredentialBlobSize - Credential->ClearCredentialBlobSize;
  93. if ( PaddingSize != 0 ) {
  94. RtlZeroMemory( &Credential->Cred.CredentialBlob[Credential->ClearCredentialBlobSize],
  95. PaddingSize );
  96. }
  97. Status = RtlEncryptMemory( Credential->Cred.CredentialBlob,
  98. Credential->Cred.CredentialBlobSize,
  99. RTL_ENCRYPT_OPTION_SAME_LOGON );
  100. if ( !NT_SUCCESS(Status)) {
  101. return FALSE;
  102. }
  103. }
  104. return TRUE;
  105. }
  106. BOOL
  107. APIENTRY
  108. CredpDecodeCredential (
  109. IN OUT PENCRYPTED_CREDENTIALW Credential
  110. )
  111. /*++
  112. Routine Description:
  113. This routine decodes sensitive credential data passed via LPC from
  114. the LSA process.
  115. The credential is decoded in-place.
  116. Arguments:
  117. Credential - Specifies the credential to be decode.
  118. Return Values:
  119. None
  120. --*/
  121. {
  122. NTSTATUS Status;
  123. //
  124. // Only decode data if it is there
  125. //
  126. if ( Credential->Cred.CredentialBlobSize != 0 ) {
  127. //
  128. // Sanity check the data
  129. //
  130. if ( Credential->Cred.CredentialBlobSize <
  131. Credential->ClearCredentialBlobSize ) {
  132. return FALSE;
  133. }
  134. //
  135. // Decrypt the data.
  136. //
  137. Status = RtlDecryptMemory( Credential->Cred.CredentialBlob,
  138. Credential->Cred.CredentialBlobSize,
  139. RTL_ENCRYPT_OPTION_SAME_LOGON );
  140. if ( !NT_SUCCESS(Status)) {
  141. return FALSE;
  142. }
  143. //
  144. // Set the used size of the buffer.
  145. //
  146. Credential->Cred.CredentialBlobSize = Credential->ClearCredentialBlobSize;
  147. }
  148. return TRUE;
  149. }
  150. //
  151. // Include shared credential conversion ruotines
  152. //
  153. #include <crconv.c>
  154. DWORD
  155. CredpAllocStrFromStr(
  156. IN WTOA_ENUM WtoA,
  157. IN LPCWSTR InputString,
  158. IN BOOLEAN NullOk,
  159. OUT LPWSTR *OutString
  160. )
  161. /*++
  162. Routine Description:
  163. Convert a string to another format.
  164. Exceptions are caught. So this routine can be used to capture user data.
  165. Arguments:
  166. WtoA - Specifies the direction of the string conversion.
  167. InputString - Specifies the zero terminated string to convert.
  168. NullOk - if TRUE, a NULL string or zero length string is OK.
  169. OutputString - Converted zero terminated string.
  170. The buffer must be freed using MIDL_user_free.
  171. Return Value:
  172. Status of the operation.
  173. --*/
  174. {
  175. DWORD WinStatus;
  176. ULONG Size;
  177. LPWSTR LocalString = NULL;
  178. LPBYTE Where;
  179. *OutString = NULL;
  180. //
  181. // Use an exception handle to prevent bad user parameter from AVing in our code.
  182. //
  183. try {
  184. //
  185. // Determine the size of the string buffer.
  186. //
  187. Size = CredpConvertStringSize ( WtoA, (LPWSTR)InputString );
  188. if ( Size == 0 ) {
  189. if ( NullOk ) {
  190. WinStatus = NO_ERROR;
  191. } else {
  192. WinStatus = ERROR_INVALID_PARAMETER;
  193. }
  194. goto Cleanup;
  195. }
  196. //
  197. // Allocate a buffer for the converted string
  198. //
  199. *OutString = MIDL_user_allocate( Size );
  200. if ( *OutString == NULL ) {
  201. WinStatus = ERROR_NOT_ENOUGH_MEMORY;
  202. goto Cleanup;
  203. }
  204. //
  205. // Covert the string
  206. //
  207. Where = (LPBYTE) *OutString;
  208. WinStatus = CredpConvertString ( WtoA,
  209. (LPWSTR)InputString,
  210. OutString,
  211. &Where );
  212. Cleanup: NOTHING;
  213. } except( EXCEPTION_EXECUTE_HANDLER ) {
  214. WinStatus = ERROR_INVALID_PARAMETER;
  215. }
  216. //
  217. // Clean up
  218. //
  219. if ( WinStatus != NO_ERROR ) {
  220. if ( *OutString != NULL ) {
  221. MIDL_user_free( *OutString );
  222. *OutString = NULL;
  223. }
  224. }
  225. return WinStatus;
  226. }
  227. BOOL
  228. APIENTRY
  229. CredWriteA (
  230. IN PCREDENTIALA Credential,
  231. IN DWORD Flags
  232. )
  233. /*++
  234. Routine Description:
  235. The ANSI version of CredWriteW.
  236. Arguments:
  237. See CredWriteW.
  238. Return Values:
  239. See CredWriteW.
  240. --*/
  241. {
  242. DWORD WinStatus;
  243. PCREDENTIALW EncodedCredential = NULL;
  244. //
  245. // Encode the credential before LPCing it to the LSA process and convert to UNICODE
  246. //
  247. WinStatus = CredpConvertCredential ( DoAtoW, // Ansi to Unicode
  248. DoBlobEncode, // Encode
  249. (PCREDENTIALW)Credential, // Input credential
  250. &EncodedCredential ); // Output credential
  251. if ( WinStatus != NO_ERROR ) {
  252. SetLastError( WinStatus );
  253. return FALSE;
  254. }
  255. //
  256. // Do the RPC call with an exception handler since RPC will raise an
  257. // exception if anything fails. It is up to us to figure out what
  258. // to do once the exception is raised.
  259. //
  260. RpcTryExcept {
  261. NTSTATUS Status;
  262. //
  263. // Call RPC version of the API.
  264. //
  265. Status = CredrWrite(
  266. NULL, // This API is always local.
  267. (PENCRYPTED_CREDENTIALW)EncodedCredential,
  268. Flags );
  269. WinStatus = CredpNtStatusToWinStatus( Status );
  270. } RpcExcept( I_RpcExceptionFilter( RpcExceptionCode()) ) {
  271. WinStatus = RpcExceptionCode();
  272. } RpcEndExcept;
  273. MIDL_user_free( EncodedCredential );
  274. if ( WinStatus != NO_ERROR ) {
  275. SetLastError( WinStatus );
  276. return FALSE;
  277. }
  278. return TRUE;
  279. }
  280. BOOL
  281. APIENTRY
  282. CredWriteW (
  283. IN PCREDENTIALW Credential,
  284. IN DWORD Flags
  285. )
  286. /*++
  287. Routine Description:
  288. The CredWrite API creates a new credential or modifies an existing
  289. credential in the user's credential set. The new credential is
  290. associated with the logon session of the current token. The token
  291. must not have the user's SID disabled.
  292. The CredWrite API creates a credential if none already exists by the
  293. specified TargetName. If the specified TargetName already exists, the
  294. specified credential replaces the existing one.
  295. The CredWrite API is available in ANSI and UNICODE versions.
  296. Arguments:
  297. Credential - Specifies the credential to be written.
  298. Flags - Specifies flags to control the operation of the API.
  299. The following flags are defined:
  300. CRED_PRESERVE_CREDENTIAL_BLOB: The credential blob should be preserved from the
  301. already existing credential with the same credential name and credential type.
  302. Return Values:
  303. On success, TRUE is returned. On failure, FALSE is returned.
  304. GetLastError() may be called to get a more specific status code.
  305. The following status codes may be returned:
  306. ERROR_NO_SUCH_LOGON_SESSION - The logon session does not exist or
  307. there is no credential set associated with this logon session.
  308. Network logon sessions do not have an associated credential set.
  309. ERROR_INVALID_PARAMETER - Certain fields may not be changed in an
  310. existing credential. If such a field does not match the value
  311. specified in the existing credential, this error is returned.
  312. ERROR_NOT_FOUND - There is no credential with the specified TargetName.
  313. Returned only if CRED_PRESERVE_CREDENTIAL_BLOB was specified.
  314. --*/
  315. {
  316. DWORD WinStatus;
  317. PCREDENTIALW EncodedCredential = NULL;
  318. //
  319. // Encode the credential before LPCing it to the LSA process.
  320. //
  321. WinStatus = CredpConvertCredential ( DoWtoW, // Unicode to Unicode
  322. DoBlobEncode, // Encode
  323. (PCREDENTIALW)Credential, // Input credential
  324. &EncodedCredential ); // Output credential
  325. if ( WinStatus != NO_ERROR ) {
  326. SetLastError( WinStatus );
  327. return FALSE;
  328. }
  329. //
  330. // Do the RPC call with an exception handler since RPC will raise an
  331. // exception if anything fails. It is up to us to figure out what
  332. // to do once the exception is raised.
  333. //
  334. RpcTryExcept {
  335. NTSTATUS Status;
  336. //
  337. // Call RPC version of the API.
  338. //
  339. Status = CredrWrite(
  340. NULL, // This API is always local.
  341. (PENCRYPTED_CREDENTIALW)EncodedCredential,
  342. Flags );
  343. WinStatus = CredpNtStatusToWinStatus( Status );
  344. } RpcExcept( I_RpcExceptionFilter( RpcExceptionCode()) ) {
  345. WinStatus = RpcExceptionCode();
  346. } RpcEndExcept;
  347. MIDL_user_free( EncodedCredential );
  348. if ( WinStatus != NO_ERROR ) {
  349. SetLastError( WinStatus );
  350. return FALSE;
  351. }
  352. return TRUE;
  353. }
  354. BOOL
  355. APIENTRY
  356. CredReadA (
  357. IN LPCSTR TargetName,
  358. IN ULONG Type,
  359. IN DWORD Flags,
  360. OUT PCREDENTIALA *Credential
  361. )
  362. /*++
  363. Routine Description:
  364. The ANSI version of CredReadW.
  365. Arguments:
  366. See CredReadW.
  367. Return Values:
  368. See CredReadW.
  369. --*/
  370. {
  371. DWORD WinStatus;
  372. PCREDENTIALW LocalCredential = NULL;
  373. LPWSTR UnicodeTargetName = NULL;
  374. //
  375. // Convert input args to Unicode
  376. //
  377. WinStatus = CredpAllocStrFromStr( DoAtoW, (LPWSTR) TargetName, FALSE, &UnicodeTargetName );
  378. if ( WinStatus != NO_ERROR ) {
  379. goto Cleanup;
  380. }
  381. //
  382. // Do the RPC call with an exception handler since RPC will raise an
  383. // exception if anything fails. It is up to us to figure out what
  384. // to do once the exception is raised.
  385. //
  386. RpcTryExcept {
  387. NTSTATUS Status;
  388. //
  389. // Call RPC version of the API.
  390. //
  391. Status = CredrRead(
  392. NULL, // This API is always local.
  393. UnicodeTargetName,
  394. Type,
  395. Flags,
  396. (PENCRYPTED_CREDENTIALW *)&LocalCredential );
  397. WinStatus = CredpNtStatusToWinStatus( Status );
  398. } RpcExcept( I_RpcExceptionFilter( RpcExceptionCode()) ) {
  399. WinStatus = RpcExceptionCode();
  400. } RpcEndExcept;
  401. //
  402. // Decode the returned credential and align appropriate blobs to ALIGN_WORST bounday
  403. //
  404. if ( WinStatus == NO_ERROR ) {
  405. WinStatus = CredpConvertCredential ( DoWtoA, // Unicode to Ansi
  406. DoBlobDecode, // Decode the credential blob
  407. LocalCredential,
  408. (PCREDENTIALW *)Credential );
  409. }
  410. Cleanup:
  411. if ( UnicodeTargetName != NULL ) {
  412. MIDL_user_free( UnicodeTargetName );
  413. }
  414. if ( LocalCredential != NULL ) {
  415. MIDL_user_free( LocalCredential );
  416. }
  417. if ( WinStatus != NO_ERROR ) {
  418. SetLastError( WinStatus );
  419. return FALSE;
  420. }
  421. return TRUE;
  422. }
  423. BOOL
  424. APIENTRY
  425. CredReadW (
  426. IN LPCWSTR TargetName,
  427. IN ULONG Type,
  428. IN DWORD Flags,
  429. OUT PCREDENTIALW *Credential
  430. )
  431. /*++
  432. Routine Description:
  433. The CredRead API reads a credential from the user's credential set.
  434. The credential set used is the one associated with the logon session
  435. of the current token. The token must not have the user's SID disabled.
  436. The CredRead API is available in ANSI and UNICODE versions.
  437. Arguments:
  438. TargetName - Specifies the name of the credential to read.
  439. Type - Specifies the Type of the credential to find.
  440. One of the CRED_TYPE_* values should be specified.
  441. Flags - Specifies flags to control the operation of the API.
  442. Reserved. Must be zero.
  443. Credential - Returns a pointer to the credential. The returned buffer
  444. must be freed by calling CredFree.
  445. Return Values:
  446. On success, TRUE is returned. On failure, FALSE is returned.
  447. GetLastError() may be called to get a more specific status code.
  448. The following status codes may be returned:
  449. ERROR_NOT_FOUND - There is no credential with the specified TargetName.
  450. ERROR_NO_SUCH_LOGON_SESSION - The logon session does not exist or
  451. there is no credential set associated with this logon session.
  452. Network logon sessions do not have an associated credential set.
  453. --*/
  454. {
  455. DWORD WinStatus;
  456. PCREDENTIALW LocalCredential = NULL;
  457. LPWSTR UnicodeTargetName = NULL;
  458. //
  459. // Capture the input args
  460. //
  461. WinStatus = CredpAllocStrFromStr( DoWtoW, TargetName, FALSE, &UnicodeTargetName );
  462. if ( WinStatus != NO_ERROR ) {
  463. goto Cleanup;
  464. }
  465. //
  466. // Do the RPC call with an exception handler since RPC will raise an
  467. // exception if anything fails. It is up to us to figure out what
  468. // to do once the exception is raised.
  469. //
  470. RpcTryExcept {
  471. NTSTATUS Status;
  472. //
  473. // Call RPC version of the API.
  474. //
  475. Status = CredrRead(
  476. NULL, // This API is always local.
  477. UnicodeTargetName,
  478. Type,
  479. Flags,
  480. (PENCRYPTED_CREDENTIALW *)&LocalCredential );
  481. WinStatus = CredpNtStatusToWinStatus( Status );
  482. } RpcExcept( I_RpcExceptionFilter( RpcExceptionCode()) ) {
  483. WinStatus = RpcExceptionCode();
  484. } RpcEndExcept;
  485. //
  486. // Decode the returned credential and align appropriate blobs to ALIGN_WORST bounday
  487. //
  488. if ( WinStatus == NO_ERROR ) {
  489. WinStatus = CredpConvertCredential ( DoWtoW, // Unicode to Unicode
  490. DoBlobDecode, // Decode the credential blob
  491. LocalCredential,
  492. Credential );
  493. }
  494. Cleanup:
  495. if ( UnicodeTargetName != NULL ) {
  496. MIDL_user_free( UnicodeTargetName );
  497. }
  498. if ( LocalCredential != NULL ) {
  499. MIDL_user_free( LocalCredential );
  500. }
  501. if ( WinStatus != NO_ERROR ) {
  502. SetLastError( WinStatus );
  503. return FALSE;
  504. }
  505. return TRUE;
  506. }
  507. BOOL
  508. APIENTRY
  509. CredEnumerateA (
  510. IN LPCSTR Filter,
  511. IN DWORD Flags,
  512. OUT LPDWORD Count,
  513. OUT PCREDENTIALA **Credentials
  514. )
  515. /*++
  516. Routine Description:
  517. The ANSI version of CredEnumerateW
  518. Arguments:
  519. See CredEnumerateW
  520. Return Values:
  521. See CredEnumerateW
  522. --*/
  523. {
  524. DWORD WinStatus;
  525. CREDENTIAL_ARRAY CredentialArray;
  526. LPWSTR UnicodeFilter = NULL;
  527. //
  528. // Force RPC to allocate the return structure
  529. //
  530. *Count = 0;
  531. *Credentials = NULL;
  532. CredentialArray.CredentialCount = 0;
  533. CredentialArray.Credentials = NULL;
  534. //
  535. // Convert input args to Unicode
  536. //
  537. WinStatus = CredpAllocStrFromStr( DoAtoW, (LPWSTR)Filter, TRUE, &UnicodeFilter );
  538. if ( WinStatus != NO_ERROR ) {
  539. goto Cleanup;
  540. }
  541. //
  542. // Do the RPC call with an exception handler since RPC will raise an
  543. // exception if anything fails. It is up to us to figure out what
  544. // to do once the exception is raised.
  545. //
  546. RpcTryExcept {
  547. NTSTATUS Status;
  548. //
  549. // Call RPC version of the API.
  550. //
  551. Status = CredrEnumerate(
  552. NULL, // This API is always local.
  553. UnicodeFilter,
  554. Flags,
  555. &CredentialArray );
  556. WinStatus = CredpNtStatusToWinStatus( Status );
  557. } RpcExcept( I_RpcExceptionFilter( RpcExceptionCode()) ) {
  558. WinStatus = RpcExceptionCode();
  559. } RpcEndExcept;
  560. //
  561. // Decode the returned credentials and align appropriate blobs to ALIGN_WORST bounday
  562. //
  563. if ( WinStatus == NO_ERROR ) {
  564. WinStatus = CredpConvertCredentials ( DoWtoA, // Unicode to Ansi
  565. DoBlobDecode, // Decode the credential blob
  566. (PCREDENTIALW *)CredentialArray.Credentials,
  567. CredentialArray.CredentialCount,
  568. (PCREDENTIALW **)Credentials );
  569. if ( WinStatus == NO_ERROR ) {
  570. *Count = CredentialArray.CredentialCount;
  571. }
  572. }
  573. Cleanup:
  574. if ( CredentialArray.Credentials != NULL ) {
  575. MIDL_user_free( CredentialArray.Credentials );
  576. }
  577. if ( UnicodeFilter != NULL ) {
  578. MIDL_user_free( UnicodeFilter );
  579. }
  580. if ( WinStatus != NO_ERROR ) {
  581. SetLastError( WinStatus) ;
  582. return FALSE;
  583. }
  584. return TRUE;
  585. }
  586. BOOL
  587. APIENTRY
  588. CredEnumerateW (
  589. IN LPCWSTR Filter,
  590. IN DWORD Flags,
  591. OUT LPDWORD Count,
  592. OUT PCREDENTIALW **Credentials
  593. )
  594. /*++
  595. Routine Description:
  596. The CredEnumerate API enumerates the credentials from the user's credential set.
  597. The credential set used is the one associated with the logon session
  598. of the current token. The token must not have the user's SID disabled.
  599. The CredEnumerate API is available in ANSI and UNICODE versions.
  600. Arguments:
  601. Filter - Specifies a filter for the returned credentials. Only credentials
  602. with a TargetName matching the filter will be returned. The filter specifies
  603. a name prefix followed by an asterisk. For instance, the filter "FRED*" will
  604. return all credentials with a TargetName beginning with the string "FRED".
  605. If NULL is specified, all credentials will be returned.
  606. Flags - Specifies flags to control the operation of the API.
  607. Reserved. Must be zero.
  608. Count - Returns a count of the number of credentials returned in Credentials.
  609. Credentials - Returns a pointer to an array of pointers to credentials.
  610. The returned buffer must be freed by calling CredFree.
  611. Return Values:
  612. On success, TRUE is returned. On failure, FALSE is returned.
  613. GetLastError() may be called to get a more specific status code.
  614. The following status codes may be returned:
  615. ERROR_NOT_FOUND - There is no credentials matching the specified Filter.
  616. ERROR_NO_SUCH_LOGON_SESSION - The logon session does not exist or
  617. there is no credential set associated with this logon session.
  618. Network logon sessions do not have an associated credential set.
  619. --*/
  620. {
  621. DWORD WinStatus;
  622. CREDENTIAL_ARRAY CredentialArray;
  623. LPWSTR UnicodeFilter = NULL;
  624. //
  625. // Force RPC to allocate the return structure
  626. //
  627. *Count = 0;
  628. *Credentials = NULL;
  629. CredentialArray.CredentialCount = 0;
  630. CredentialArray.Credentials = NULL;
  631. //
  632. // Capture the user's input parameters
  633. //
  634. WinStatus = CredpAllocStrFromStr( DoWtoW, Filter, TRUE, &UnicodeFilter );
  635. if ( WinStatus != NO_ERROR ) {
  636. goto Cleanup;
  637. }
  638. //
  639. // Do the RPC call with an exception handler since RPC will raise an
  640. // exception if anything fails. It is up to us to figure out what
  641. // to do once the exception is raised.
  642. //
  643. RpcTryExcept {
  644. NTSTATUS Status;
  645. //
  646. // Call RPC version of the API.
  647. //
  648. Status = CredrEnumerate(
  649. NULL, // This API is always local.
  650. UnicodeFilter,
  651. Flags,
  652. &CredentialArray );
  653. WinStatus = CredpNtStatusToWinStatus( Status );
  654. } RpcExcept( I_RpcExceptionFilter( RpcExceptionCode()) ) {
  655. WinStatus = RpcExceptionCode();
  656. } RpcEndExcept;
  657. //
  658. // Decode the returned credentials and align appropriate blobs to ALIGN_WORST bounday
  659. //
  660. if ( WinStatus == NO_ERROR ) {
  661. WinStatus = CredpConvertCredentials ( DoWtoW, // Unicode to Unicode
  662. DoBlobDecode, // Decode the credential blob
  663. (PCREDENTIALW *)CredentialArray.Credentials,
  664. CredentialArray.CredentialCount,
  665. Credentials );
  666. if ( WinStatus == NO_ERROR ) {
  667. *Count = CredentialArray.CredentialCount;
  668. }
  669. }
  670. Cleanup:
  671. if ( CredentialArray.Credentials != NULL ) {
  672. MIDL_user_free( CredentialArray.Credentials );
  673. }
  674. if ( UnicodeFilter != NULL ) {
  675. MIDL_user_free( UnicodeFilter );
  676. }
  677. if ( WinStatus != NO_ERROR ) {
  678. SetLastError( WinStatus) ;
  679. return FALSE;
  680. }
  681. return TRUE;
  682. }
  683. BOOL
  684. APIENTRY
  685. CredWriteDomainCredentialsA (
  686. IN PCREDENTIAL_TARGET_INFORMATIONA TargetInfo,
  687. IN PCREDENTIALA Credential,
  688. IN DWORD Flags
  689. )
  690. /*++
  691. Routine Description:
  692. The ANSI version of CredWriteDomainCredentialsW
  693. Arguments:
  694. See CredWriteDomainCredentialsW
  695. Return Values:
  696. See CredWriteDomainCredentialsW
  697. --*/
  698. {
  699. DWORD WinStatus;
  700. PCREDENTIAL_TARGET_INFORMATIONW UnicodeTargetInfo = NULL;
  701. PCREDENTIALW EncodedCredential = NULL;
  702. //
  703. // Encode the credential before LPCing it to the LSA process and convert to UNICODE
  704. //
  705. WinStatus = CredpConvertCredential ( DoAtoW, // Ansi to Unicode
  706. DoBlobEncode, // Encode
  707. (PCREDENTIALW)Credential, // Input credential
  708. &EncodedCredential ); // Output credential
  709. if ( WinStatus != NO_ERROR ) {
  710. goto Cleanup;
  711. }
  712. //
  713. // Convert the target info to Unicode
  714. //
  715. WinStatus = CredpConvertTargetInfo( DoAtoW, // Ansi to Unicode
  716. (PCREDENTIAL_TARGET_INFORMATIONW) TargetInfo,
  717. &UnicodeTargetInfo,
  718. NULL );
  719. if ( WinStatus != NO_ERROR ) {
  720. goto Cleanup;
  721. }
  722. //
  723. // Do the RPC call with an exception handler since RPC will raise an
  724. // exception if anything fails. It is up to us to figure out what
  725. // to do once the exception is raised.
  726. //
  727. RpcTryExcept {
  728. NTSTATUS Status;
  729. //
  730. // Call RPC version of the API.
  731. //
  732. Status = CredrWriteDomainCredentials(
  733. NULL, // This API is always local.
  734. UnicodeTargetInfo,
  735. (PENCRYPTED_CREDENTIALW)EncodedCredential,
  736. Flags );
  737. WinStatus = CredpNtStatusToWinStatus( Status );
  738. } RpcExcept( I_RpcExceptionFilter( RpcExceptionCode()) ) {
  739. WinStatus = RpcExceptionCode();
  740. } RpcEndExcept;
  741. Cleanup:
  742. if ( EncodedCredential != NULL ) {
  743. MIDL_user_free( EncodedCredential );
  744. }
  745. if ( UnicodeTargetInfo != NULL ) {
  746. MIDL_user_free( UnicodeTargetInfo );
  747. }
  748. if ( WinStatus != NO_ERROR ) {
  749. SetLastError( WinStatus );
  750. return FALSE;
  751. }
  752. return TRUE;
  753. }
  754. BOOL
  755. APIENTRY
  756. CredWriteDomainCredentialsW (
  757. IN PCREDENTIAL_TARGET_INFORMATIONW TargetInfo,
  758. IN PCREDENTIALW Credential,
  759. IN DWORD Flags
  760. )
  761. /*++
  762. Routine Description:
  763. The CredWriteDomainCredentials API writes a new domain
  764. credential to the user's credential set. The new credential is
  765. associated with the logon session of the current token. The token
  766. must not have the user's SID disabled.
  767. CredWriteDomainCredentials differs from CredWrite in that it handles
  768. the idiosyncrasies of domain (CRED_TYPE_DOMAIN_PASSWORD or CRED_TYPE_DOMAIN_CERTIFICATE)
  769. credentials. Domain credentials contain more than one target field.
  770. At least one of the naming parameters must be specified: NetbiosServerName,
  771. DnsServerName, NetbiosDomainName, DnsDomainName or DnsForestName.
  772. The CredWriteDomainCredentials API is available in ANSI and UNICODE versions.
  773. Arguments:
  774. TargetInfo - Specifies the target information identifying the target server.
  775. Credential - Specifies the credential to be written.
  776. Flags - Specifies flags to control the operation of the API.
  777. Reserved. Must be zero.
  778. Return Values:
  779. On success, TRUE is returned. On failure, FALSE is returned.
  780. GetLastError() may be called to get a more specific status code.
  781. The following status codes may be returned:
  782. ERROR_NO_SUCH_LOGON_SESSION - The logon session does not exist or
  783. there is no credential set associated with this logon session.
  784. Network logon sessions do not have an associated credential set.
  785. ERROR_INVALID_PARAMETER - Certain fields may not be changed in an
  786. existing credential. If such a field does not match the value
  787. specified in the existing credential, this error is returned.
  788. ERROR_INVALID_PARAMETER - None of the naming parameters were specified
  789. or the credential specified did not have the Type field set to
  790. CRED_TYPE_DOMAIN_PASSWORD or CRED_TYPE_DOMAIN_CERTIFICATE.
  791. --*/
  792. {
  793. DWORD WinStatus;
  794. PCREDENTIALW EncodedCredential = NULL;
  795. PCREDENTIAL_TARGET_INFORMATIONW UnicodeTargetInfo = NULL;
  796. //
  797. // Encode the credential before LPCing it to the LSA process
  798. //
  799. WinStatus = CredpConvertCredential ( DoWtoW, // Unicode to Unicode
  800. DoBlobEncode, // Encode
  801. (PCREDENTIALW)Credential, // Input credential
  802. &EncodedCredential ); // Output credential
  803. if ( WinStatus != NO_ERROR ) {
  804. goto Cleanup;
  805. }
  806. //
  807. // Capture the target info to prevent us from AVing in our code.
  808. //
  809. WinStatus = CredpConvertTargetInfo( DoWtoW, // Unicode to Unicode
  810. (PCREDENTIAL_TARGET_INFORMATIONW) TargetInfo,
  811. &UnicodeTargetInfo,
  812. NULL );
  813. if ( WinStatus != NO_ERROR ) {
  814. goto Cleanup;
  815. }
  816. //
  817. // Do the RPC call with an exception handler since RPC will raise an
  818. // exception if anything fails. It is up to us to figure out what
  819. // to do once the exception is raised.
  820. //
  821. RpcTryExcept {
  822. NTSTATUS Status;
  823. //
  824. // Call RPC version of the API.
  825. //
  826. Status = CredrWriteDomainCredentials(
  827. NULL, // This API is always local.
  828. TargetInfo,
  829. (PENCRYPTED_CREDENTIALW)EncodedCredential,
  830. Flags );
  831. WinStatus = CredpNtStatusToWinStatus( Status );
  832. } RpcExcept( I_RpcExceptionFilter( RpcExceptionCode()) ) {
  833. WinStatus = RpcExceptionCode();
  834. } RpcEndExcept;
  835. Cleanup:
  836. if ( EncodedCredential != NULL ) {
  837. MIDL_user_free( EncodedCredential );
  838. }
  839. if ( UnicodeTargetInfo != NULL ) {
  840. MIDL_user_free( UnicodeTargetInfo );
  841. }
  842. if ( WinStatus != NO_ERROR ) {
  843. SetLastError( WinStatus );
  844. return FALSE;
  845. }
  846. return TRUE;
  847. }
  848. BOOL
  849. APIENTRY
  850. CredReadDomainCredentialsA (
  851. IN PCREDENTIAL_TARGET_INFORMATIONA TargetInfo,
  852. IN DWORD Flags,
  853. OUT LPDWORD Count,
  854. OUT PCREDENTIALA **Credentials
  855. )
  856. /*++
  857. Routine Description:
  858. The ANSI version of CredReadDomainCredentialsW
  859. Arguments:
  860. See CredReadDomainCredentialsW
  861. Return Values:
  862. See CredReadDomainCredentialsW
  863. --*/
  864. {
  865. DWORD WinStatus;
  866. CREDENTIAL_ARRAY CredentialArray;
  867. PCREDENTIAL_TARGET_INFORMATIONW UnicodeTargetInfo = NULL;
  868. //
  869. // Force RPC to allocate the return structure
  870. //
  871. *Count = 0;
  872. *Credentials = NULL;
  873. CredentialArray.CredentialCount = 0;
  874. CredentialArray.Credentials = NULL;
  875. //
  876. // Convert the target info to Unicode
  877. //
  878. WinStatus = CredpConvertTargetInfo( DoAtoW, // Ansi to Unicode
  879. (PCREDENTIAL_TARGET_INFORMATIONW) TargetInfo,
  880. &UnicodeTargetInfo,
  881. NULL );
  882. if ( WinStatus != NO_ERROR ) {
  883. goto Cleanup;
  884. }
  885. //
  886. // Do the RPC call with an exception handler since RPC will raise an
  887. // exception if anything fails. It is up to us to figure out what
  888. // to do once the exception is raised.
  889. //
  890. RpcTryExcept {
  891. NTSTATUS Status;
  892. //
  893. // Call RPC version of the API.
  894. Status = CredrReadDomainCredentials(
  895. NULL, // This API is always local.
  896. UnicodeTargetInfo,
  897. Flags,
  898. &CredentialArray );
  899. WinStatus = CredpNtStatusToWinStatus( Status );
  900. } RpcExcept( I_RpcExceptionFilter( RpcExceptionCode()) ) {
  901. WinStatus = RpcExceptionCode();
  902. } RpcEndExcept;
  903. //
  904. // Decode the returned credentials and align appropriate blobs to ALIGN_WORST bounday
  905. //
  906. if ( WinStatus == NO_ERROR ) {
  907. WinStatus = CredpConvertCredentials ( DoWtoA, // Unicode to Ansi
  908. DoBlobDecode, // Decode the credential blob
  909. (PCREDENTIALW *)CredentialArray.Credentials,
  910. CredentialArray.CredentialCount,
  911. (PCREDENTIALW **)Credentials );
  912. if ( WinStatus == NO_ERROR ) {
  913. *Count = CredentialArray.CredentialCount;
  914. }
  915. }
  916. Cleanup:
  917. if ( CredentialArray.Credentials != NULL ) {
  918. MIDL_user_free( CredentialArray.Credentials );
  919. }
  920. if ( UnicodeTargetInfo != NULL ) {
  921. MIDL_user_free( UnicodeTargetInfo );
  922. }
  923. if ( WinStatus != NO_ERROR ) {
  924. SetLastError( WinStatus) ;
  925. return FALSE;
  926. }
  927. return TRUE;
  928. }
  929. BOOL
  930. APIENTRY
  931. CredReadDomainCredentialsW (
  932. IN PCREDENTIAL_TARGET_INFORMATIONW TargetInfo,
  933. IN DWORD Flags,
  934. OUT LPDWORD Count,
  935. OUT PCREDENTIALW **Credentials
  936. )
  937. /*++
  938. Routine Description:
  939. The CredReadDomainCredentials API reads the domain credentials from the user's credential set.
  940. The credential set used is the one associated with the logon session
  941. of the current token. The token must not have the user's SID disabled.
  942. CredReadDomainCredentials differs from CredRead in that it handles the
  943. idiosyncrasies of domain (CRED_TYPE_DOMAIN_PASSWORD or CRED_TYPE_DOMAIN_CERTIFICATE)
  944. credentials. Domain credentials contain more than one target field.
  945. At least one of the naming parameters must be specified: NetbiosServerName,
  946. DnsServerName, NetbiosDomainName, DnsDomainName or DnsForestName. This API returns
  947. the most specific credentials that match the naming parameters. That is, if there
  948. is a credential that matches the target server name and a credential that matches
  949. the target domain name, only the server specific credential is returned. This is
  950. the credential that would be used.
  951. The CredReadDomainCredentials API is available in ANSI and UNICODE versions.
  952. Arguments:
  953. TargetInfo - Specifies the target information identifying the target ser
  954. Flags - Specifies flags to control the operation of the API.
  955. The following flags are defined:
  956. CRED_CACHE_TARGET_INFORMATION: The TargetInfo should be cached for a subsequent read via
  957. CredGetTargetInfo.
  958. Count - Returns a count of the number of credentials returned in Credentials.
  959. Credentials - Returns a pointer to an array of pointers to credentials.
  960. The most specific existing credential matching the TargetInfo is returned.
  961. If there is both a CRED_TYPE_DOMAIN_PASSWORD and CRED_TYPE_DOMAIN_CERTIFICATE
  962. credential, both are returned. If a connection were to be made to the named
  963. target, this most-specific credential would be used.
  964. The returned buffer must be freed by calling CredFree.
  965. Return Values:
  966. On success, TRUE is returned. On failure, FALSE is returned.
  967. GetLastError() may be called to get a more specific status code.
  968. The following status codes may be returned:
  969. ERROR_INVALID_PARAMETER - None of the naming parameters were specified.
  970. ERROR_NOT_FOUND - There are no credentials matching the specified naming parameters.
  971. ERROR_NO_SUCH_LOGON_SESSION - The logon session does not exist or
  972. there is no credential set associated with this logon session.
  973. Network logon sessions do not have an associated credential set.
  974. --*/
  975. {
  976. DWORD WinStatus;
  977. CREDENTIAL_ARRAY CredentialArray;
  978. PCREDENTIAL_TARGET_INFORMATIONW UnicodeTargetInfo = NULL;
  979. //
  980. // Force RPC to allocate the return structure
  981. //
  982. *Count = 0;
  983. *Credentials = NULL;
  984. CredentialArray.CredentialCount = 0;
  985. CredentialArray.Credentials = NULL;
  986. //
  987. // Capture the user's parameters to prevent AVing in our code.
  988. //
  989. WinStatus = CredpConvertTargetInfo( DoWtoW, // Unicode to Unicode
  990. (PCREDENTIAL_TARGET_INFORMATIONW) TargetInfo,
  991. &UnicodeTargetInfo,
  992. NULL );
  993. if ( WinStatus != NO_ERROR ) {
  994. goto Cleanup;
  995. }
  996. //
  997. // Do the RPC call with an exception handler since RPC will raise an
  998. // exception if anything fails. It is up to us to figure out what
  999. // to do once the exception is raised.
  1000. //
  1001. RpcTryExcept {
  1002. NTSTATUS Status;
  1003. //
  1004. // Call RPC version of the API.
  1005. Status = CredrReadDomainCredentials(
  1006. NULL, // This API is always local.
  1007. TargetInfo,
  1008. Flags,
  1009. &CredentialArray );
  1010. WinStatus = CredpNtStatusToWinStatus( Status );
  1011. } RpcExcept( I_RpcExceptionFilter( RpcExceptionCode()) ) {
  1012. WinStatus = RpcExceptionCode();
  1013. } RpcEndExcept;
  1014. //
  1015. // Decode the returned credentials and align appropriate blobs to ALIGN_WORST bounday
  1016. //
  1017. if ( WinStatus == NO_ERROR ) {
  1018. WinStatus = CredpConvertCredentials ( DoWtoW, // Unicode to Unicode
  1019. DoBlobDecode, // Decode the credential blob
  1020. (PCREDENTIALW *)CredentialArray.Credentials,
  1021. CredentialArray.CredentialCount,
  1022. Credentials );
  1023. if ( WinStatus == NO_ERROR ) {
  1024. *Count = CredentialArray.CredentialCount;
  1025. }
  1026. }
  1027. Cleanup:
  1028. if ( CredentialArray.Credentials != NULL ) {
  1029. MIDL_user_free( CredentialArray.Credentials );
  1030. }
  1031. if ( UnicodeTargetInfo != NULL ) {
  1032. MIDL_user_free( UnicodeTargetInfo );
  1033. }
  1034. if ( WinStatus != NO_ERROR ) {
  1035. SetLastError( WinStatus) ;
  1036. return FALSE;
  1037. }
  1038. return TRUE;
  1039. }
  1040. BOOL
  1041. APIENTRY
  1042. CredDeleteA (
  1043. IN LPCSTR TargetName,
  1044. IN ULONG Type,
  1045. IN DWORD Flags
  1046. )
  1047. /*++
  1048. Routine Description:
  1049. The ANSI version of CredDeleteW
  1050. Arguments:
  1051. See CredDeleteW
  1052. Return Values:
  1053. See CredDeleteW
  1054. --*/
  1055. {
  1056. DWORD WinStatus;
  1057. LPWSTR UnicodeTargetName = NULL;
  1058. //
  1059. // Convert input args to Unicode
  1060. //
  1061. WinStatus = CredpAllocStrFromStr( DoAtoW, (LPWSTR)TargetName, FALSE, &UnicodeTargetName );
  1062. if ( WinStatus != NO_ERROR ) {
  1063. goto Cleanup;
  1064. }
  1065. //
  1066. // Do the RPC call with an exception handler since RPC will raise an
  1067. // exception if anything fails. It is up to us to figure out what
  1068. // to do once the exception is raised.
  1069. //
  1070. RpcTryExcept {
  1071. NTSTATUS Status;
  1072. //
  1073. // Call RPC version of the API.
  1074. //
  1075. Status = CredrDelete(
  1076. NULL, // This API is always local.
  1077. UnicodeTargetName,
  1078. Type,
  1079. Flags );
  1080. WinStatus = CredpNtStatusToWinStatus( Status );
  1081. } RpcExcept( I_RpcExceptionFilter( RpcExceptionCode()) ) {
  1082. WinStatus = RpcExceptionCode();
  1083. } RpcEndExcept;
  1084. //
  1085. // Be Tidy
  1086. //
  1087. Cleanup:
  1088. if ( UnicodeTargetName != NULL ) {
  1089. MIDL_user_free( UnicodeTargetName );
  1090. }
  1091. if ( WinStatus != NO_ERROR ) {
  1092. SetLastError( WinStatus );
  1093. return FALSE;
  1094. }
  1095. return TRUE;
  1096. }
  1097. BOOL
  1098. APIENTRY
  1099. CredDeleteW (
  1100. IN LPCWSTR TargetName,
  1101. IN ULONG Type,
  1102. IN DWORD Flags
  1103. )
  1104. /*++
  1105. Routine Description:
  1106. The CredDelete API deletes a credential from the user's credential set.
  1107. The credential set used is the one associated with the logon session
  1108. of the current token. The token must not have the user's SID disabled.
  1109. The CredDelete API is available in ANSI and UNICODE versions.
  1110. Arguments:
  1111. TargetName - Specifies the name of the credential to delete.
  1112. Type - Specifies the Type of the credential to find.
  1113. One of the CRED_TYPE_* values should be specified.
  1114. Flags - Specifies flags to control the operation of the API.
  1115. Reserved. Must be zero.
  1116. Return Values:
  1117. On success, TRUE is returned. On failure, FALSE is returned.
  1118. GetLastError() may be called to get a more specific status code.
  1119. The following status codes may be returned:
  1120. ERROR_NOT_FOUND - There is no credential with the specified TargetName.
  1121. ERROR_NO_SUCH_LOGON_SESSION - The logon session does not exist or
  1122. there is no credential set associated with this logon session.
  1123. Network logon sessions do not have an associated credential set.
  1124. --*/
  1125. {
  1126. DWORD WinStatus;
  1127. LPWSTR UnicodeTargetName = NULL;
  1128. //
  1129. // Capture the input arguments
  1130. //
  1131. WinStatus = CredpAllocStrFromStr( DoWtoW, TargetName, FALSE, &UnicodeTargetName );
  1132. if ( WinStatus != NO_ERROR ) {
  1133. goto Cleanup;
  1134. }
  1135. //
  1136. // Do the RPC call with an exception handler since RPC will raise an
  1137. // exception if anything fails. It is up to us to figure out what
  1138. // to do once the exception is raised.
  1139. //
  1140. RpcTryExcept {
  1141. NTSTATUS Status;
  1142. //
  1143. // Call RPC version of the API.
  1144. //
  1145. Status = CredrDelete(
  1146. NULL, // This API is always local.
  1147. UnicodeTargetName,
  1148. Type,
  1149. Flags );
  1150. WinStatus = CredpNtStatusToWinStatus( Status );
  1151. } RpcExcept( I_RpcExceptionFilter( RpcExceptionCode()) ) {
  1152. WinStatus = RpcExceptionCode();
  1153. } RpcEndExcept;
  1154. //
  1155. // Be Tidy
  1156. //
  1157. Cleanup:
  1158. if ( UnicodeTargetName != NULL ) {
  1159. MIDL_user_free( UnicodeTargetName );
  1160. }
  1161. if ( WinStatus != NO_ERROR ) {
  1162. SetLastError( WinStatus );
  1163. return FALSE;
  1164. }
  1165. return TRUE;
  1166. }
  1167. BOOL
  1168. APIENTRY
  1169. CredRenameA (
  1170. IN LPCSTR OldTargetName,
  1171. IN LPCSTR NewTargetName,
  1172. IN ULONG Type,
  1173. IN DWORD Flags
  1174. )
  1175. /*++
  1176. Routine Description:
  1177. The ANSI version of CredRenameW
  1178. Arguments:
  1179. See CredRenameW
  1180. Return Values:
  1181. See CredRenameW
  1182. --*/
  1183. {
  1184. DWORD WinStatus;
  1185. LPWSTR UnicodeOldTargetName = NULL;
  1186. LPWSTR UnicodeNewTargetName = NULL;
  1187. //
  1188. // Capture the input arguments
  1189. //
  1190. WinStatus = CredpAllocStrFromStr( DoAtoW, (LPCWSTR)OldTargetName, FALSE, &UnicodeOldTargetName );
  1191. if ( WinStatus != NO_ERROR ) {
  1192. goto Cleanup;
  1193. }
  1194. WinStatus = CredpAllocStrFromStr( DoAtoW, (LPCWSTR)NewTargetName, FALSE, &UnicodeNewTargetName );
  1195. if ( WinStatus != NO_ERROR ) {
  1196. goto Cleanup;
  1197. }
  1198. //
  1199. // Do the RPC call with an exception handler since RPC will raise an
  1200. // exception if anything fails. It is up to us to figure out what
  1201. // to do once the exception is raised.
  1202. //
  1203. RpcTryExcept {
  1204. NTSTATUS Status;
  1205. //
  1206. // Call RPC version of the API.
  1207. //
  1208. Status = CredrRename(
  1209. NULL, // This API is always local.
  1210. UnicodeOldTargetName,
  1211. UnicodeNewTargetName,
  1212. Type,
  1213. Flags );
  1214. WinStatus = CredpNtStatusToWinStatus( Status );
  1215. } RpcExcept( I_RpcExceptionFilter( RpcExceptionCode()) ) {
  1216. WinStatus = RpcExceptionCode();
  1217. } RpcEndExcept;
  1218. //
  1219. // Be Tidy
  1220. //
  1221. Cleanup:
  1222. if ( UnicodeOldTargetName != NULL ) {
  1223. MIDL_user_free( UnicodeOldTargetName );
  1224. }
  1225. if ( UnicodeNewTargetName != NULL ) {
  1226. MIDL_user_free( UnicodeNewTargetName );
  1227. }
  1228. if ( WinStatus != NO_ERROR ) {
  1229. SetLastError( WinStatus );
  1230. return FALSE;
  1231. }
  1232. return TRUE;
  1233. }
  1234. BOOL
  1235. APIENTRY
  1236. CredRenameW (
  1237. IN LPCWSTR OldTargetName,
  1238. IN LPCWSTR NewTargetName,
  1239. IN ULONG Type,
  1240. IN DWORD Flags
  1241. )
  1242. /*++
  1243. Routine Description:
  1244. The CredRename API renames a credential in the user's credential set.
  1245. The credential set used is the one associated with the logon session
  1246. of the current token. The token must not have the user's SID disabled.
  1247. The CredRename API is available in ANSI and UNICODE versions.
  1248. Arguments:
  1249. OldTargetName - Specifies the current name of the credential to rename.
  1250. NewTargetName - Specifies the new name of the credential.
  1251. Type - Specifies the Type of the credential to rename
  1252. One of the CRED_TYPE_* values should be specified.
  1253. Flags - Specifies flags to control the operation of the API.
  1254. Reserved. Must be zero.
  1255. Return Values:
  1256. On success, TRUE is returned. On failure, FALSE is returned.
  1257. GetLastError() may be called to get a more specific status code.
  1258. The following status codes may be returned:
  1259. ERROR_NOT_FOUND - There is no credential with the specified OldTargetName.
  1260. ERROR_ALREADY_EXISTS - There is already a credential named NewTargetName.
  1261. ERROR_NO_SUCH_LOGON_SESSION - The logon session does not exist or
  1262. there is no credential set associated with this logon session.
  1263. Network logon sessions do not have an associated credential set.
  1264. --*/
  1265. {
  1266. DWORD WinStatus;
  1267. LPWSTR UnicodeOldTargetName = NULL;
  1268. LPWSTR UnicodeNewTargetName = NULL;
  1269. //
  1270. // Capture the input arguments
  1271. //
  1272. WinStatus = CredpAllocStrFromStr( DoWtoW, OldTargetName, FALSE, &UnicodeOldTargetName );
  1273. if ( WinStatus != NO_ERROR ) {
  1274. goto Cleanup;
  1275. }
  1276. WinStatus = CredpAllocStrFromStr( DoWtoW, NewTargetName, FALSE, &UnicodeNewTargetName );
  1277. if ( WinStatus != NO_ERROR ) {
  1278. goto Cleanup;
  1279. }
  1280. //
  1281. // Do the RPC call with an exception handler since RPC will raise an
  1282. // exception if anything fails. It is up to us to figure out what
  1283. // to do once the exception is raised.
  1284. //
  1285. RpcTryExcept {
  1286. NTSTATUS Status;
  1287. //
  1288. // Call RPC version of the API.
  1289. //
  1290. Status = CredrRename(
  1291. NULL, // This API is always local.
  1292. UnicodeOldTargetName,
  1293. UnicodeNewTargetName,
  1294. Type,
  1295. Flags );
  1296. WinStatus = CredpNtStatusToWinStatus( Status );
  1297. } RpcExcept( I_RpcExceptionFilter( RpcExceptionCode()) ) {
  1298. WinStatus = RpcExceptionCode();
  1299. } RpcEndExcept;
  1300. //
  1301. // Be Tidy
  1302. //
  1303. Cleanup:
  1304. if ( UnicodeOldTargetName != NULL ) {
  1305. MIDL_user_free( UnicodeOldTargetName );
  1306. }
  1307. if ( UnicodeNewTargetName != NULL ) {
  1308. MIDL_user_free( UnicodeNewTargetName );
  1309. }
  1310. if ( WinStatus != NO_ERROR ) {
  1311. SetLastError( WinStatus );
  1312. return FALSE;
  1313. }
  1314. return TRUE;
  1315. }
  1316. VOID
  1317. APIENTRY
  1318. CredFree (
  1319. IN PVOID Buffer
  1320. )
  1321. /*++
  1322. Routine Description:
  1323. The CredFree API de-allocates a buffer returned from the various other Credential API.
  1324. Arguments:
  1325. Buffer -Specifies the buffer to be de-allocated.
  1326. Return Values:
  1327. None
  1328. --*/
  1329. {
  1330. MIDL_user_free( Buffer );
  1331. }
  1332. BOOL
  1333. APIENTRY
  1334. CredGetTargetInfoA (
  1335. IN LPCSTR ServerName,
  1336. IN DWORD Flags,
  1337. OUT PCREDENTIAL_TARGET_INFORMATIONA *TargetInfo
  1338. )
  1339. /*++
  1340. Routine Description:
  1341. The ANSI version of CredGetTargetInfoW
  1342. Arguments:
  1343. See CredGetTargetInfoW
  1344. Return Values:
  1345. See CredGetTargetInfoW
  1346. --*/
  1347. {
  1348. DWORD WinStatus;
  1349. LPWSTR UnicodeServerName = NULL;
  1350. PCREDENTIAL_TARGET_INFORMATIONW UnicodeTargetInfo = NULL;
  1351. //
  1352. // Convert input args to Unicode
  1353. //
  1354. WinStatus = CredpAllocStrFromStr( DoAtoW, (LPWSTR)ServerName, FALSE, &UnicodeServerName );
  1355. if ( WinStatus != NO_ERROR ) {
  1356. goto Cleanup;
  1357. }
  1358. //
  1359. // Do the RPC call with an exception handler since RPC will raise an
  1360. // exception if anything fails. It is up to us to figure out what
  1361. // to do once the exception is raised.
  1362. //
  1363. RpcTryExcept {
  1364. NTSTATUS Status;
  1365. //
  1366. // Call RPC version of the API.
  1367. //
  1368. Status = CredrGetTargetInfo(
  1369. NULL, // This API is always local.
  1370. UnicodeServerName,
  1371. Flags,
  1372. &UnicodeTargetInfo );
  1373. WinStatus = CredpNtStatusToWinStatus( Status );
  1374. } RpcExcept( I_RpcExceptionFilter( RpcExceptionCode()) ) {
  1375. WinStatus = RpcExceptionCode();
  1376. } RpcEndExcept;
  1377. if ( WinStatus != NO_ERROR ) {
  1378. goto Cleanup;
  1379. }
  1380. //
  1381. // Convert the target info to ANSI
  1382. //
  1383. WinStatus = CredpConvertTargetInfo( DoWtoA, // Unicode to Ansi
  1384. UnicodeTargetInfo,
  1385. (PCREDENTIAL_TARGET_INFORMATIONW *)TargetInfo,
  1386. NULL );
  1387. Cleanup:
  1388. if ( UnicodeTargetInfo != NULL ) {
  1389. MIDL_user_free( UnicodeTargetInfo );
  1390. }
  1391. if ( UnicodeServerName != NULL ) {
  1392. MIDL_user_free( UnicodeServerName );
  1393. }
  1394. if ( WinStatus != NO_ERROR ) {
  1395. SetLastError( WinStatus );
  1396. return FALSE;
  1397. }
  1398. return TRUE;
  1399. }
  1400. BOOL
  1401. APIENTRY
  1402. CredGetTargetInfoW (
  1403. IN LPCWSTR ServerName,
  1404. IN DWORD Flags,
  1405. OUT PCREDENTIAL_TARGET_INFORMATIONW *TargetInfo
  1406. )
  1407. /*++
  1408. Routine Description:
  1409. The CredGetTargetInfo API gets all of the known target name information
  1410. for the named target machine. This executed locally
  1411. and does not need any particular privilege. The information returned is expected
  1412. to be passed to the CredReadDomainCredentials and CredWriteDomainCredentials APIs.
  1413. The information should not be used for any other purpose.
  1414. Authentication packages compute TargetInfo when attempting to authenticate to
  1415. ServerName. The authentication packages cache this target information to make it
  1416. available to CredGetTargetInfo. Therefore, the target information will only be
  1417. available if we've recently attempted to authenticate to ServerName.
  1418. Arguments:
  1419. ServerName - This parameter specifies the name of the machine to get the information
  1420. for.
  1421. Flags - Specifies flags to control the operation of the API.
  1422. CRED_ALLOW_NAME_RESOLUTION - Specifies that if no target info can be found for
  1423. TargetName, then name resolution should be done on TargetName to convert it
  1424. to other forms. If target info exists for any of those other forms, that
  1425. target info is returned. Currently only DNS name resolution is done.
  1426. This bit is useful if the application doesn't call the authentication package
  1427. directly. The application might pass the TargetName to another layer of software
  1428. to authenticate to the server. That layer of software might resolve the name and
  1429. pass the resolved name to the authentication package. As such, there will be no
  1430. target info for the original TargetName.
  1431. TargetInfo - Returns a pointer to the target information.
  1432. At least one of the returned fields of TargetInfo will be non-NULL.
  1433. Return Values:
  1434. On success, TRUE is returned. On failure, FALSE is returned.
  1435. GetLastError() may be called to get a more specific status code.
  1436. The following status codes may be returned:
  1437. ERROR_NOT_FOUND - There is no target info for the named server.
  1438. --*/
  1439. {
  1440. DWORD WinStatus;
  1441. LPWSTR UnicodeServerName = NULL;
  1442. PCREDENTIAL_TARGET_INFORMATIONW UnicodeTargetInfo = NULL;
  1443. //
  1444. // Capture the input arguments
  1445. //
  1446. WinStatus = CredpAllocStrFromStr( DoWtoW, ServerName, FALSE, &UnicodeServerName );
  1447. if ( WinStatus != NO_ERROR ) {
  1448. goto Cleanup;
  1449. }
  1450. //
  1451. // Do the RPC call with an exception handler since RPC will raise an
  1452. // exception if anything fails. It is up to us to figure out what
  1453. // to do once the exception is raised.
  1454. //
  1455. RpcTryExcept {
  1456. NTSTATUS Status;
  1457. //
  1458. // Call RPC version of the API.
  1459. //
  1460. Status = CredrGetTargetInfo(
  1461. NULL, // This API is always local.
  1462. UnicodeServerName,
  1463. Flags,
  1464. &UnicodeTargetInfo );
  1465. WinStatus = CredpNtStatusToWinStatus( Status );
  1466. } RpcExcept( I_RpcExceptionFilter( RpcExceptionCode()) ) {
  1467. WinStatus = RpcExceptionCode();
  1468. } RpcEndExcept;
  1469. if ( WinStatus != NO_ERROR ) {
  1470. goto Cleanup;
  1471. }
  1472. //
  1473. // Convert the target info to ANSI
  1474. //
  1475. WinStatus = CredpConvertTargetInfo( DoWtoW, // Unicode to Unicode
  1476. UnicodeTargetInfo,
  1477. TargetInfo,
  1478. NULL );
  1479. Cleanup:
  1480. if ( UnicodeTargetInfo != NULL ) {
  1481. MIDL_user_free( UnicodeTargetInfo );
  1482. }
  1483. if ( UnicodeServerName != NULL ) {
  1484. MIDL_user_free( UnicodeServerName );
  1485. }
  1486. if ( WinStatus != NO_ERROR ) {
  1487. SetLastError( WinStatus );
  1488. return FALSE;
  1489. }
  1490. return TRUE;
  1491. }
  1492. BOOL
  1493. APIENTRY
  1494. CredGetSessionTypes (
  1495. IN DWORD MaximumPersistCount,
  1496. OUT LPDWORD MaximumPersist
  1497. )
  1498. /*++
  1499. Routine Description:
  1500. CredGetSessionTypes returns the maximum persistence supported by the current logon
  1501. session.
  1502. For whistler, CRED_PERSIST_LOCAL_MACHINE and CRED_PERSIST_ENTERPRISE credentials can not
  1503. be stored for sessions where the profile is not loaded. If future releases, credentials
  1504. might not be associated with the user's profile.
  1505. Arguments:
  1506. MaximumPersistCount - Specifies the number of elements in the MaximumPersist array.
  1507. The caller should specify CRED_TYPE_MAXIMUM for this parameter.
  1508. MaximumPersist - Returns the maximum persistance supported by the current logon session for
  1509. each credential type. Index into the array with one of the CRED_TYPE_* defines.
  1510. Returns CRED_PERSIST_NONE if no credential of this type can be stored.
  1511. Returns CRED_PERSIST_SESSION if only session specific credential may be stored.
  1512. Returns CRED_PERSIST_LOCAL_MACHINE if session specific and machine specific credentials
  1513. may be stored.
  1514. Returns CRED_PERSIST_ENTERPRISE if any credential may be stored.
  1515. Return Values:
  1516. On success, TRUE is returned. On failure, FALSE is returned.
  1517. GetLastError() may be called to get a more specific status code.
  1518. The following status codes may be returned:
  1519. ERROR_NO_SUCH_LOGON_SESSION - The logon session does not exist or
  1520. there is no credential set associated with this logon session.
  1521. Network logon sessions do not have an associated credential set.
  1522. --*/
  1523. {
  1524. DWORD WinStatus;
  1525. //
  1526. // Do the RPC call with an exception handler since RPC will raise an
  1527. // exception if anything fails. It is up to us to figure out what
  1528. // to do once the exception is raised.
  1529. //
  1530. RpcTryExcept {
  1531. NTSTATUS Status;
  1532. //
  1533. // Call RPC version of the API.
  1534. //
  1535. Status = CredrGetSessionTypes(
  1536. NULL, // This API is always local.
  1537. MaximumPersistCount,
  1538. MaximumPersist );
  1539. WinStatus = CredpNtStatusToWinStatus( Status );
  1540. } RpcExcept( I_RpcExceptionFilter( RpcExceptionCode()) ) {
  1541. WinStatus = RpcExceptionCode();
  1542. } RpcEndExcept;
  1543. if ( WinStatus != NO_ERROR ) {
  1544. SetLastError( WinStatus );
  1545. return FALSE;
  1546. }
  1547. return TRUE;
  1548. }
  1549. BOOL
  1550. APIENTRY
  1551. CredProfileLoaded (
  1552. VOID
  1553. )
  1554. /*++
  1555. Routine Description:
  1556. The CredProfileLoaded API is a private API used by LoadUserProfile to notify the
  1557. credential manager that the profile for the current user has been loaded.
  1558. The caller must be impersonating the logged on user.
  1559. Arguments:
  1560. None.
  1561. Return Values:
  1562. On success, TRUE is returned. On failure, FALSE is returned.
  1563. GetLastError() may be called to get a more specific status code.
  1564. The following status codes may be returned:
  1565. ERROR_NO_SUCH_LOGON_SESSION - The logon session does not exist or
  1566. there is no credential set associated with this logon session.
  1567. Network logon sessions do not have an associated credential set.
  1568. --*/
  1569. {
  1570. DWORD WinStatus;
  1571. //
  1572. // Do the RPC call with an exception handler since RPC will raise an
  1573. // exception if anything fails. It is up to us to figure out what
  1574. // to do once the exception is raised.
  1575. //
  1576. RpcTryExcept {
  1577. NTSTATUS Status;
  1578. //
  1579. // Call RPC version of the API.
  1580. //
  1581. Status = CredrProfileLoaded(
  1582. NULL ); // This API is always local.
  1583. WinStatus = CredpNtStatusToWinStatus( Status );
  1584. } RpcExcept( I_RpcExceptionFilter( RpcExceptionCode()) ) {
  1585. WinStatus = RpcExceptionCode();
  1586. } RpcEndExcept;
  1587. if ( WinStatus != NO_ERROR ) {
  1588. SetLastError( WinStatus );
  1589. return FALSE;
  1590. }
  1591. return TRUE;
  1592. }
  1593. VOID
  1594. CredpMarshalChar(
  1595. IN OUT LPWSTR *Current,
  1596. IN ULONG Byte
  1597. )
  1598. /*++
  1599. Routine Description:
  1600. This routine marshals 6 bits into a buffer.
  1601. Arguments:
  1602. Current - On input, points to a pointer of the current location in the marshaled buffer.
  1603. On output, is modified to point to the next available location in the marshaled buffer.
  1604. Byte - Specifies the 6 bits to marshal
  1605. Return Values:
  1606. None.
  1607. --*/
  1608. {
  1609. UCHAR MappingTable[] = {
  1610. 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
  1611. 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
  1612. 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
  1613. 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '#', '-'
  1614. };
  1615. if ( Byte > 0x3F ) {
  1616. *(*Current) = '=';
  1617. } else {
  1618. *(*Current) = MappingTable[Byte];
  1619. }
  1620. (*Current)++;
  1621. }
  1622. ULONG
  1623. CredpMarshalSize(
  1624. IN ULONG ByteCount
  1625. )
  1626. /*++
  1627. Routine Description:
  1628. This routine returns the number of bytes that would be marshaled by
  1629. CredpMarshalBytes when passed a buffer ByteCount bytes long.
  1630. Arguments:
  1631. ByteCount - Specifies the number of bytes to marshal
  1632. Return Values:
  1633. The number of bytes that would be marshaled.
  1634. --*/
  1635. {
  1636. ULONG CharCount;
  1637. ULONG ExtraBytes;
  1638. //
  1639. // If byte count is a multiple of 3, the char count is straight forward
  1640. //
  1641. CharCount = ByteCount / 3 * 4;
  1642. ExtraBytes = ByteCount % 3;
  1643. if ( ExtraBytes == 1 ) {
  1644. CharCount += 2;
  1645. } else if ( ExtraBytes == 2 ) {
  1646. CharCount += 3;
  1647. }
  1648. return CharCount * sizeof(WCHAR);
  1649. }
  1650. VOID
  1651. CredpMarshalBytes(
  1652. IN OUT LPWSTR *Current,
  1653. IN LPBYTE Bytes,
  1654. IN ULONG ByteCount
  1655. )
  1656. /*++
  1657. Routine Description:
  1658. This routine marshals bytes into a buffer.
  1659. Arguments:
  1660. Current - On input, points to a pointer of the current location in the marshaled buffer.
  1661. On output, is modified to point to the next available location in the marshaled buffer.
  1662. Bytes - Specifies the buffer to marshal
  1663. ByteCount - Specifies the number of bytes to marshal
  1664. Return Values:
  1665. None.
  1666. --*/
  1667. {
  1668. ULONG i;
  1669. union {
  1670. BYTE ByteValues[3];
  1671. struct {
  1672. ULONG Bits1 :6;
  1673. ULONG Bits2 :6;
  1674. ULONG Bits3 :6;
  1675. ULONG Bits4 :6;
  1676. } BitValues;
  1677. } Bits;
  1678. //
  1679. // Loop through marshaling 3 bytes at a time.
  1680. //
  1681. for ( i=0; i<ByteCount; i+=3 ) {
  1682. ULONG BytesToCopy;
  1683. //
  1684. // Grab up to 3 bytes from the input buffer.
  1685. //
  1686. BytesToCopy = min( 3, ByteCount-i );
  1687. if ( BytesToCopy != 3 ) {
  1688. RtlZeroMemory( Bits.ByteValues, 3);
  1689. }
  1690. RtlCopyMemory( Bits.ByteValues, &Bytes[i], BytesToCopy );
  1691. //
  1692. // Marshal the first twelve bits
  1693. //
  1694. CredpMarshalChar( Current, Bits.BitValues.Bits1 );
  1695. CredpMarshalChar( Current, Bits.BitValues.Bits2 );
  1696. //
  1697. // Optionally marshal the next bits.
  1698. //
  1699. if ( BytesToCopy > 1 ) {
  1700. CredpMarshalChar( Current, Bits.BitValues.Bits3 );
  1701. if ( BytesToCopy > 2 ) {
  1702. CredpMarshalChar( Current, Bits.BitValues.Bits4 );
  1703. }
  1704. }
  1705. }
  1706. }
  1707. BOOL
  1708. CredpUnmarshalChar(
  1709. IN OUT LPWSTR *Current,
  1710. IN LPCWSTR End,
  1711. OUT PULONG Value
  1712. )
  1713. /*++
  1714. Routine Description:
  1715. This routine unmarshals 6 bits from a buffer.
  1716. Arguments:
  1717. Current - On input, points to a pointer of the current location in the marshaled buffer.
  1718. On output, is modified to point to the next available location in the marshaled buffer.
  1719. End - Points to the first character beyond the end of the marshaled buffer.
  1720. Value - returns the unmarshaled 6 bits value.
  1721. Return Values:
  1722. TRUE - if the bytes we're unmarshaled sucessfully
  1723. FALSE - if the byte could not be unmarshaled from the buffer.
  1724. --*/
  1725. {
  1726. WCHAR CurrentChar;
  1727. //
  1728. // Ensure the character is available in the buffer
  1729. //
  1730. if ( *Current >= End ) {
  1731. return FALSE;
  1732. }
  1733. //
  1734. // Grab the character
  1735. //
  1736. CurrentChar = *(*Current);
  1737. (*Current)++;
  1738. //
  1739. // Map it the 6 bit value
  1740. //
  1741. switch ( CurrentChar ) {
  1742. case 'A':
  1743. case 'B':
  1744. case 'C':
  1745. case 'D':
  1746. case 'E':
  1747. case 'F':
  1748. case 'G':
  1749. case 'H':
  1750. case 'I':
  1751. case 'J':
  1752. case 'K':
  1753. case 'L':
  1754. case 'M':
  1755. case 'N':
  1756. case 'O':
  1757. case 'P':
  1758. case 'Q':
  1759. case 'R':
  1760. case 'S':
  1761. case 'T':
  1762. case 'U':
  1763. case 'V':
  1764. case 'W':
  1765. case 'X':
  1766. case 'Y':
  1767. case 'Z':
  1768. *Value = CurrentChar - 'A';
  1769. break;
  1770. case 'a':
  1771. case 'b':
  1772. case 'c':
  1773. case 'd':
  1774. case 'e':
  1775. case 'f':
  1776. case 'g':
  1777. case 'h':
  1778. case 'i':
  1779. case 'j':
  1780. case 'k':
  1781. case 'l':
  1782. case 'm':
  1783. case 'n':
  1784. case 'o':
  1785. case 'p':
  1786. case 'q':
  1787. case 'r':
  1788. case 's':
  1789. case 't':
  1790. case 'u':
  1791. case 'v':
  1792. case 'w':
  1793. case 'x':
  1794. case 'y':
  1795. case 'z':
  1796. *Value = CurrentChar - 'a' + 26;
  1797. break;
  1798. case '0':
  1799. case '1':
  1800. case '2':
  1801. case '3':
  1802. case '4':
  1803. case '5':
  1804. case '6':
  1805. case '7':
  1806. case '8':
  1807. case '9':
  1808. *Value = CurrentChar - '0' + 26 + 26;
  1809. break;
  1810. case '#':
  1811. *Value = 26 + 26 + 10;
  1812. break;
  1813. case '-':
  1814. *Value = 26 + 26 + 10 + 1;
  1815. break;
  1816. default:
  1817. return FALSE;
  1818. }
  1819. return TRUE;
  1820. }
  1821. BOOL
  1822. CredpUnmarshalBytes(
  1823. IN OUT LPWSTR *Current,
  1824. IN LPCWSTR End,
  1825. IN LPBYTE Bytes,
  1826. IN ULONG ByteCount
  1827. )
  1828. /*++
  1829. Routine Description:
  1830. This routine unmarshals bytes bytes from a buffer.
  1831. Arguments:
  1832. Current - On input, points to a pointer of the current location in the marshaled buffer.
  1833. On output, is modified to point to the next available location in the marshaled buffer.
  1834. End - Points to the first character beyond the end of the marshaled buffer.
  1835. Bytes - Specifies the buffer to unmarsal into
  1836. ByteCount - Specifies the number of bytes to unmarshal
  1837. Return Values:
  1838. TRUE - if the bytes we're unmarshaled sucessfully
  1839. FALSE - if the byte could not be unmarshaled from the buffer.
  1840. --*/
  1841. {
  1842. ULONG i;
  1843. ULONG Value;
  1844. union {
  1845. BYTE ByteValues[3];
  1846. struct {
  1847. ULONG Bits1 :6;
  1848. ULONG Bits2 :6;
  1849. ULONG Bits3 :6;
  1850. ULONG Bits4 :6;
  1851. } BitValues;
  1852. } Bits;
  1853. //
  1854. // Loop through unmarshaling 3 bytes at a time.
  1855. //
  1856. for ( i=0; i<ByteCount; i+=3 ) {
  1857. ULONG BytesToCopy;
  1858. //
  1859. // Grab up to 3 bytes from the input buffer.
  1860. //
  1861. BytesToCopy = min( 3, ByteCount-i );
  1862. if ( BytesToCopy != 3 ) {
  1863. RtlZeroMemory( Bits.ByteValues, 3);
  1864. }
  1865. //
  1866. // Unarshal the first twelve bits
  1867. //
  1868. if ( !CredpUnmarshalChar( Current, End, &Value ) ) {
  1869. return FALSE;
  1870. }
  1871. Bits.BitValues.Bits1 = Value;
  1872. if ( !CredpUnmarshalChar( Current, End, &Value ) ) {
  1873. return FALSE;
  1874. }
  1875. Bits.BitValues.Bits2 = Value;
  1876. //
  1877. // Optionally marshal the next bits.
  1878. //
  1879. if ( BytesToCopy > 1 ) {
  1880. if ( !CredpUnmarshalChar( Current, End, &Value ) ) {
  1881. return FALSE;
  1882. }
  1883. Bits.BitValues.Bits3 = Value;
  1884. if ( BytesToCopy > 2 ) {
  1885. if ( !CredpUnmarshalChar( Current, End, &Value ) ) {
  1886. return FALSE;
  1887. }
  1888. Bits.BitValues.Bits4 = Value;
  1889. }
  1890. }
  1891. //
  1892. // Copy the unmarshaled bytes to the caller's buffer.
  1893. //
  1894. RtlCopyMemory( &Bytes[i], Bits.ByteValues, BytesToCopy );
  1895. }
  1896. return TRUE;
  1897. }
  1898. BOOL
  1899. APIENTRY
  1900. CredMarshalCredentialA(
  1901. IN CRED_MARSHAL_TYPE CredType,
  1902. IN PVOID Credential,
  1903. OUT LPSTR *MarshaledCredential
  1904. )
  1905. /*++
  1906. Routine Description:
  1907. The ANSI version of CredMarshalCredentialW
  1908. Arguments:
  1909. See CredMarshalCredentialW.
  1910. Return Values:
  1911. See CredMarshalCredentialW.
  1912. --*/
  1913. {
  1914. BOOL RetVal;
  1915. DWORD WinStatus;
  1916. LPWSTR UnicodeMarshaledCredential;
  1917. RetVal = CredMarshalCredentialW( CredType, Credential, &UnicodeMarshaledCredential );
  1918. if ( RetVal ) {
  1919. //
  1920. // Convert the value to ANSI.
  1921. //
  1922. WinStatus = CredpAllocStrFromStr( DoWtoA, UnicodeMarshaledCredential, FALSE, (LPWSTR *)MarshaledCredential );
  1923. if ( WinStatus != NO_ERROR ) {
  1924. SetLastError( WinStatus );
  1925. RetVal = FALSE;
  1926. }
  1927. CredFree( UnicodeMarshaledCredential );
  1928. }
  1929. return RetVal;
  1930. }
  1931. BOOL
  1932. APIENTRY
  1933. CredMarshalCredentialW(
  1934. IN CRED_MARSHAL_TYPE CredType,
  1935. IN PVOID Credential,
  1936. OUT LPWSTR *MarshaledCredential
  1937. )
  1938. /*++
  1939. Routine Description:
  1940. The CredMarshalCredential API is a private API used by the keyring UI to marshal a
  1941. credential. The keyring UI needs to be able to pass a certificate credential through
  1942. interfaces (e.g., NetUseAdd) that have historically accepted DomainName UserName and Password.
  1943. Arguments:
  1944. CredType - Specifies the type of credential to marshal.
  1945. This enum will be expanded in the future.
  1946. Credential - Specifies the credential to marshal.
  1947. If CredType is CertCredential, then Credential points to a CERT_CREDENTIAL_INFO structure.
  1948. MarshaledCredential - Returns a text string containing the marshaled credential.
  1949. The marshaled credential should be passed as the UserName string to any API that
  1950. is currently passed credentials. If that API is currently passed a
  1951. password, the password should be passed as NULL or empty. If that API is
  1952. currently passed a domain name, that domain name should be passed as NULL or empty.
  1953. The caller should free the returned buffer using CredFree.
  1954. Return Values:
  1955. On success, TRUE is returned. On failure, FALSE is returned.
  1956. GetLastError() may be called to get a more specific status code.
  1957. The following status codes may be returned:
  1958. ERROR_INVALID_PARAMETER - CredType is invalid.
  1959. --*/
  1960. {
  1961. DWORD WinStatus;
  1962. ULONG Size;
  1963. LPWSTR RetCredential = NULL;
  1964. LPWSTR Current;
  1965. PCERT_CREDENTIAL_INFO CertCredentialInfo = NULL;
  1966. PUSERNAME_TARGET_CREDENTIAL_INFO UsernameTargetCredentialInfo = NULL;
  1967. ULONG UsernameTargetUserNameSize;
  1968. #define CRED_MARSHAL_HEADER L"@@"
  1969. #define CRED_MARSHAL_HEADER_LENGTH 2
  1970. //
  1971. // Ensure credential isn't null
  1972. //
  1973. if ( Credential == NULL ) {
  1974. WinStatus = ERROR_INVALID_PARAMETER;
  1975. goto Cleanup;
  1976. }
  1977. //
  1978. // Validate CredType
  1979. //
  1980. Size = (CRED_MARSHAL_HEADER_LENGTH+2) * sizeof(WCHAR);
  1981. switch ( CredType ) {
  1982. case CertCredential:
  1983. CertCredentialInfo = (PCERT_CREDENTIAL_INFO) Credential;
  1984. if ( CertCredentialInfo->cbSize < sizeof(CERT_CREDENTIAL_INFO) ) {
  1985. WinStatus = ERROR_INVALID_PARAMETER;
  1986. goto Cleanup;
  1987. }
  1988. Size += CredpMarshalSize( sizeof(CertCredentialInfo->rgbHashOfCert) );
  1989. break;
  1990. case UsernameTargetCredential:
  1991. UsernameTargetCredentialInfo = (PUSERNAME_TARGET_CREDENTIAL_INFO) Credential;
  1992. if ( UsernameTargetCredentialInfo->UserName == NULL ) {
  1993. WinStatus = ERROR_INVALID_PARAMETER;
  1994. goto Cleanup;
  1995. }
  1996. UsernameTargetUserNameSize = wcslen(UsernameTargetCredentialInfo->UserName)*sizeof(WCHAR);
  1997. if ( UsernameTargetUserNameSize == 0 ) {
  1998. WinStatus = ERROR_INVALID_PARAMETER;
  1999. goto Cleanup;
  2000. }
  2001. Size += CredpMarshalSize( sizeof(UsernameTargetUserNameSize) ) +
  2002. CredpMarshalSize( UsernameTargetUserNameSize );
  2003. break;
  2004. default:
  2005. WinStatus = ERROR_INVALID_PARAMETER;
  2006. goto Cleanup;
  2007. }
  2008. //
  2009. // Allocate a buffer to put the marshaled string into.
  2010. //
  2011. RetCredential = (LPWSTR) MIDL_user_allocate( Size );
  2012. if ( RetCredential == NULL ) {
  2013. WinStatus = ERROR_NOT_ENOUGH_MEMORY;
  2014. goto Cleanup;
  2015. }
  2016. //
  2017. // Add the header onto the marshaled string
  2018. //
  2019. Current = RetCredential;
  2020. RtlCopyMemory( Current, CRED_MARSHAL_HEADER, CRED_MARSHAL_HEADER_LENGTH*sizeof(WCHAR) );
  2021. Current += CRED_MARSHAL_HEADER_LENGTH;
  2022. //
  2023. // Add the CredType
  2024. //
  2025. CredpMarshalChar( &Current, CredType );
  2026. //
  2027. // Marshal the CredType specific data
  2028. //
  2029. switch ( CredType ) {
  2030. case CertCredential:
  2031. CredpMarshalBytes( &Current, CertCredentialInfo->rgbHashOfCert, sizeof(CertCredentialInfo->rgbHashOfCert) );
  2032. break;
  2033. case UsernameTargetCredential:
  2034. CredpMarshalBytes( &Current, (LPBYTE)&UsernameTargetUserNameSize, sizeof(UsernameTargetUserNameSize) );
  2035. CredpMarshalBytes( &Current, (LPBYTE)UsernameTargetCredentialInfo->UserName, UsernameTargetUserNameSize );
  2036. break;
  2037. }
  2038. //
  2039. // Finally, zero terminate the string
  2040. //
  2041. *Current = L'\0';
  2042. Current ++;
  2043. //
  2044. // Return the marshaled credential to the caller.
  2045. //
  2046. ASSERT( Current == &RetCredential[Size/sizeof(WCHAR)] );
  2047. *MarshaledCredential = RetCredential;
  2048. RetCredential = NULL;
  2049. WinStatus = NO_ERROR;
  2050. Cleanup:
  2051. if ( RetCredential != NULL ) {
  2052. MIDL_user_free( RetCredential );
  2053. }
  2054. if ( WinStatus != NO_ERROR ) {
  2055. SetLastError( WinStatus );
  2056. return FALSE;
  2057. }
  2058. return TRUE;
  2059. }
  2060. BOOL
  2061. APIENTRY
  2062. CredUnmarshalCredentialA(
  2063. IN LPCSTR MarshaledCredential,
  2064. OUT PCRED_MARSHAL_TYPE CredType,
  2065. OUT PVOID *Credential
  2066. )
  2067. /*++
  2068. Routine Description:
  2069. The ANSI version of CredUnmarshalCredentialW
  2070. Arguments:
  2071. See CredUnmarshalCredentialW.
  2072. Return Values:
  2073. See CredUnmarshalCredentialW.
  2074. --*/
  2075. {
  2076. DWORD WinStatus;
  2077. LPWSTR UnicodeMarshaledCredential = NULL;
  2078. //
  2079. // Convert input args to Unicode
  2080. //
  2081. WinStatus = CredpAllocStrFromStr( DoAtoW, (LPWSTR)MarshaledCredential, FALSE, &UnicodeMarshaledCredential );
  2082. if ( WinStatus != NO_ERROR ) {
  2083. goto Cleanup;
  2084. }
  2085. //
  2086. // Do the unmarshaling
  2087. //
  2088. if ( !CredUnmarshalCredentialW( UnicodeMarshaledCredential,
  2089. CredType,
  2090. Credential ) ) {
  2091. WinStatus = GetLastError();
  2092. goto Cleanup;
  2093. }
  2094. WinStatus = NO_ERROR;
  2095. Cleanup:
  2096. if ( UnicodeMarshaledCredential != NULL ) {
  2097. MIDL_user_free( UnicodeMarshaledCredential );
  2098. }
  2099. if ( WinStatus != NO_ERROR ) {
  2100. SetLastError( WinStatus );
  2101. return FALSE;
  2102. }
  2103. return TRUE;
  2104. }
  2105. BOOL
  2106. APIENTRY
  2107. CredUnmarshalCredentialW(
  2108. IN LPCWSTR MarshaledCredential,
  2109. OUT PCRED_MARSHAL_TYPE CredType,
  2110. OUT PVOID *Credential
  2111. )
  2112. /*++
  2113. Routine Description:
  2114. The CredMarshalCredential API is a private API used by an authentication package to unmarshal a
  2115. credential. The keyring UI needs to be able to pass a certificate credential through
  2116. interfaces (e.g., NetUseAdd) that have historically accepted DomainName UserName and Password.
  2117. Arguments:
  2118. MarshaledCredential - Specifies a text string containing the marshaled credential.
  2119. CredType - Returns the type of credential.
  2120. Credential - Returns a pointer to the unmarshaled credential.
  2121. If CredType is CertCredential, then the returned pointer is to a CERT_CREDENTIAL_INFO structure.
  2122. The caller should free the returned buffer using CredFree.
  2123. Return Values:
  2124. On success, TRUE is returned. On failure, FALSE is returned.
  2125. GetLastError() may be called to get a more specific status code.
  2126. The following status codes may be returned:
  2127. ERROR_INVALID_PARAMETER - MarshaledCredential is not valid
  2128. --*/
  2129. {
  2130. DWORD WinStatus;
  2131. LPWSTR Current;
  2132. LPCWSTR End;
  2133. PCERT_CREDENTIAL_INFO CertCredentialInfo;
  2134. PUSERNAME_TARGET_CREDENTIAL_INFO UsernameTargetCredentialInfo;
  2135. PVOID RetCredential = NULL;
  2136. ULONG UsernameTargetUserNameSize;
  2137. LPBYTE Where;
  2138. ULONG MarshaledCredentialLength;
  2139. //
  2140. // Validate the passed in buffer.
  2141. //
  2142. if ( MarshaledCredential == NULL ) {
  2143. WinStatus = ERROR_INVALID_PARAMETER;
  2144. goto Cleanup;
  2145. }
  2146. //
  2147. // Ensure the first few bytes are the appropriate header
  2148. //
  2149. if ( MarshaledCredential[0] != CRED_MARSHAL_HEADER[0] || MarshaledCredential[1] != CRED_MARSHAL_HEADER[1] ) {
  2150. WinStatus = ERROR_INVALID_PARAMETER;
  2151. goto Cleanup;
  2152. }
  2153. //
  2154. // Validate the credential type
  2155. //
  2156. MarshaledCredentialLength = wcslen(MarshaledCredential);
  2157. Current = (LPWSTR) &MarshaledCredential[2];
  2158. End = &MarshaledCredential[MarshaledCredentialLength];
  2159. if ( !CredpUnmarshalChar( &Current, End, (PULONG)CredType ) ) {
  2160. WinStatus = ERROR_INVALID_PARAMETER;
  2161. goto Cleanup;
  2162. }
  2163. switch ( *CredType ) {
  2164. case CertCredential:
  2165. //
  2166. // Allocate a buffer that will be more than big enough
  2167. //
  2168. CertCredentialInfo = MIDL_user_allocate( sizeof(*CertCredentialInfo) );
  2169. if ( CertCredentialInfo == NULL ) {
  2170. WinStatus = ERROR_NOT_ENOUGH_MEMORY;
  2171. goto Cleanup;
  2172. }
  2173. RetCredential = CertCredentialInfo;
  2174. CertCredentialInfo->cbSize = sizeof(*CertCredentialInfo);
  2175. //
  2176. // Unmarshal the data
  2177. //
  2178. if ( !CredpUnmarshalBytes( &Current, End, CertCredentialInfo->rgbHashOfCert, sizeof(CertCredentialInfo->rgbHashOfCert) ) ) {
  2179. WinStatus = ERROR_INVALID_PARAMETER;
  2180. goto Cleanup;
  2181. }
  2182. break;
  2183. case UsernameTargetCredential:
  2184. //
  2185. // Allocate a buffer that will be more than big enough
  2186. //
  2187. UsernameTargetCredentialInfo = MIDL_user_allocate(
  2188. sizeof(*UsernameTargetCredentialInfo) +
  2189. MarshaledCredentialLength*sizeof(WCHAR) +
  2190. sizeof(WCHAR) );
  2191. if ( UsernameTargetCredentialInfo == NULL ) {
  2192. WinStatus = ERROR_NOT_ENOUGH_MEMORY;
  2193. goto Cleanup;
  2194. }
  2195. RetCredential = UsernameTargetCredentialInfo;
  2196. Where = (LPBYTE)(UsernameTargetCredentialInfo+1);
  2197. //
  2198. // Unmarshal the size of the data
  2199. //
  2200. if ( !CredpUnmarshalBytes( &Current, End, (LPBYTE)&UsernameTargetUserNameSize, sizeof(UsernameTargetUserNameSize) ) ) {
  2201. WinStatus = ERROR_INVALID_PARAMETER;
  2202. goto Cleanup;
  2203. }
  2204. if ( UsernameTargetUserNameSize != ROUND_UP_COUNT( UsernameTargetUserNameSize, sizeof(WCHAR)) ) {
  2205. WinStatus = ERROR_INVALID_PARAMETER;
  2206. goto Cleanup;
  2207. }
  2208. if ( UsernameTargetUserNameSize == 0 ) {
  2209. WinStatus = ERROR_INVALID_PARAMETER;
  2210. goto Cleanup;
  2211. }
  2212. //
  2213. // Unmarshal the data
  2214. //
  2215. UsernameTargetCredentialInfo->UserName = (LPWSTR)Where;
  2216. if ( !CredpUnmarshalBytes( &Current, End, Where, UsernameTargetUserNameSize ) ) {
  2217. WinStatus = ERROR_INVALID_PARAMETER;
  2218. goto Cleanup;
  2219. }
  2220. Where += UsernameTargetUserNameSize;
  2221. //
  2222. // Zero terminate it
  2223. //
  2224. *((PWCHAR)Where) = L'\0';
  2225. break;
  2226. default:
  2227. WinStatus = ERROR_INVALID_PARAMETER;
  2228. goto Cleanup;
  2229. }
  2230. //
  2231. // Ensure we've unmarshalled the entire string
  2232. //
  2233. if ( Current != End ) {
  2234. WinStatus = ERROR_INVALID_PARAMETER;
  2235. goto Cleanup;
  2236. }
  2237. WinStatus = NO_ERROR;
  2238. *Credential = RetCredential;
  2239. Cleanup:
  2240. if ( WinStatus != NO_ERROR ) {
  2241. *Credential = NULL;
  2242. if ( RetCredential != NULL ) {
  2243. MIDL_user_free( RetCredential );
  2244. }
  2245. SetLastError( WinStatus );
  2246. return FALSE;
  2247. }
  2248. return TRUE;
  2249. }
  2250. BOOL
  2251. APIENTRY
  2252. CredIsMarshaledCredentialA(
  2253. IN LPCSTR MarshaledCredential
  2254. )
  2255. /*++
  2256. Routine Description:
  2257. The ANSI version of CredIsMarshaledCredentialW
  2258. Arguments:
  2259. MarshaledCredential - Specifies a text string containing the marshaled credential.
  2260. Return Values:
  2261. Returns TRUE if the credential is a marshalled credential.
  2262. --*/
  2263. {
  2264. DWORD WinStatus;
  2265. CRED_MARSHAL_TYPE CredType;
  2266. PVOID UnmarshalledUsername;
  2267. if ( !CredUnmarshalCredentialA( MarshaledCredential, &CredType, &UnmarshalledUsername ) ) {
  2268. return FALSE;
  2269. }
  2270. CredFree( UnmarshalledUsername );
  2271. return TRUE;
  2272. }
  2273. BOOL
  2274. APIENTRY
  2275. CredIsMarshaledCredentialW(
  2276. IN LPCWSTR MarshaledCredential
  2277. )
  2278. /*++
  2279. Routine Description:
  2280. The CredIsMarshaledCredential API is a private API used by an authentication package to
  2281. determine if a credential is a unmarshaled credential or not.
  2282. Arguments:
  2283. MarshaledCredential - Specifies a text string containing the marshaled credential.
  2284. Return Values:
  2285. Returns TRUE if the credential is a marshalled credential.
  2286. --*/
  2287. {
  2288. DWORD WinStatus;
  2289. CRED_MARSHAL_TYPE CredType;
  2290. PVOID UnmarshalledUsername;
  2291. if ( !CredUnmarshalCredentialW( MarshaledCredential, &CredType, &UnmarshalledUsername ) ) {
  2292. return FALSE;
  2293. }
  2294. CredFree( UnmarshalledUsername );
  2295. return TRUE;
  2296. }