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.

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