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.

3369 lines
87 KiB

  1. //=============================================================================
  2. // Copyright (c) 2000 Microsoft Corporation
  3. //
  4. // utils.cpp
  5. //
  6. // Credential manager user interface utility functions.
  7. //
  8. // Created 06/06/2000 johnstep (John Stephens)
  9. //=============================================================================
  10. #include "precomp.hpp"
  11. #include <lm.h>
  12. #include <credp.h>
  13. #include "wininet.h"
  14. #include <windns.h> // DnsValidateName_W
  15. extern "C"
  16. {
  17. #include <names.h> // NetpIsDomainNameValid
  18. }
  19. #include "shpriv.h"
  20. extern BOOL gbWaitingForSSOCreds;
  21. extern WCHAR gszSSOUserName[CREDUI_MAX_USERNAME_LENGTH];
  22. extern WCHAR gszSSOPassword[CREDUI_MAX_PASSWORD_LENGTH];
  23. extern BOOL gbStoredSSOCreds;
  24. #define SIZE_OF_SALT 37
  25. #define SALT_SHIFT 2
  26. WCHAR g_szSalt[] = L"82BD0E67-9FEA-4748-8672-D5EFE5B779B0";
  27. HMODULE hAdvapi32 = NULL;
  28. CRITICAL_SECTION CredConfirmationCritSect;
  29. CRED_AWAITING_CONFIRMATION* pCredConfirmationListHead = NULL;
  30. //-----------------------------------------------------------------------------
  31. // Functions
  32. //-----------------------------------------------------------------------------
  33. //=============================================================================
  34. // CreduiIsPostfixString
  35. //
  36. // This function determines if the postfix string is in fact a postfix string
  37. // of the source string. This is similar to a strstr type of function, except
  38. // the substring (postfix) must be at the end of the source string.
  39. //
  40. // Arguments:
  41. // source (in) - The string to search
  42. // postfix (in) - The postfix string to search for
  43. //
  44. // Return TRUE if postfix is a postfix string of source or FALSE otherwise
  45. //
  46. // Created 03/09/2000 johnstep (John Stephens)
  47. //=============================================================================
  48. BOOL
  49. CreduiIsPostfixString(
  50. WCHAR *source,
  51. WCHAR *postfix
  52. )
  53. {
  54. ULONG sourceLength = wcslen(source);
  55. ULONG postfixLength = wcslen(postfix);
  56. if (sourceLength >= postfixLength)
  57. {
  58. return _wcsicmp(source + sourceLength - postfixLength, postfix) == 0;
  59. }
  60. return FALSE;
  61. }
  62. //=============================================================================
  63. // CreduiIsSpecialCredential
  64. //
  65. // Returns TRUE if the credential is a special type which we should not
  66. // update or FALSE otherwise.
  67. //
  68. // Created 05/25/2000 johnstep (John Stephens)
  69. //
  70. //=============================================================================
  71. BOOL
  72. CreduiIsSpecialCredential(
  73. CREDENTIAL *credential
  74. )
  75. {
  76. ASSERT(credential != NULL);
  77. // If credential empty for some reason, don't attempt the test
  78. if (credential->TargetName == NULL) return FALSE;
  79. if ((credential->TargetName[0] == L'*') &&
  80. (credential->TargetName[1] == L'\0'))
  81. {
  82. // The magical global wildcard credential, which we never create nor
  83. // update. This is a special credential:
  84. return TRUE;
  85. }
  86. if (_wcsicmp(credential->TargetName, CRED_SESSION_WILDCARD_NAME) == 0)
  87. {
  88. // This is another special credential:
  89. return TRUE;
  90. }
  91. return FALSE;
  92. }
  93. //=============================================================================
  94. // CreduiLookupLocalSidFromRid
  95. //
  96. // Looks up the SID from the RID, allocates storage for the SID, and returns a
  97. // pointer to it. The caller is responsible for freeing the memory via the
  98. // delete [] operator.
  99. //
  100. // Arguments:
  101. // rid (in)
  102. // sid (out)
  103. //
  104. // Returns TRUE on success or FALSE otherwise.
  105. //
  106. // Created 04/12/2000 johnstep (John Stephens)
  107. //=============================================================================
  108. BOOL
  109. CreduiLookupLocalSidFromRid(
  110. DWORD rid,
  111. PSID *sid
  112. )
  113. {
  114. BOOL success = FALSE;
  115. *sid = NULL;
  116. // Get the account domain SID on the target machine.
  117. //
  118. // Note: If you were looking up multiple SIDs based on the same account
  119. // domain, you only need to call this once.
  120. USER_MODALS_INFO_2 *userInfo;
  121. if (NetUserModalsGet(
  122. NULL,
  123. 2,
  124. reinterpret_cast<BYTE **>(&userInfo)) == NERR_Success)
  125. {
  126. UCHAR subAuthCount =
  127. *GetSidSubAuthorityCount(userInfo->usrmod2_domain_id);
  128. SID *newSid =
  129. reinterpret_cast<SID *>(
  130. new BYTE [GetSidLengthRequired(subAuthCount + 1)]);
  131. if (newSid != NULL)
  132. {
  133. InitializeSid(
  134. newSid,
  135. GetSidIdentifierAuthority(userInfo->usrmod2_domain_id),
  136. subAuthCount + 1);
  137. // Copy existing sub authorities from account SID into new SID:
  138. for (ULONG i = 0; i < subAuthCount; ++i)
  139. {
  140. *GetSidSubAuthority(newSid, i) =
  141. *GetSidSubAuthority(userInfo->usrmod2_domain_id, i);
  142. }
  143. // Append RID to new SID:
  144. *GetSidSubAuthority(newSid, subAuthCount) = rid;
  145. *sid = newSid;
  146. success = TRUE;
  147. }
  148. // Finished with userInfo, so free it here:
  149. NetApiBufferFree(userInfo);
  150. }
  151. return success;
  152. }
  153. //=============================================================================
  154. // CreduiLookupLocalNameFromRid
  155. //
  156. // Looks up the Name from the RID, allocates storage for the Name, and returns a
  157. // pointer to it. The caller is responsible for freeing the memory via the
  158. // delete [] operator.
  159. //
  160. // Arguments:
  161. // rid (in)
  162. // name (out)
  163. //
  164. // Returns TRUE on success or FALSE otherwise.
  165. //
  166. // Created 04/12/2000 johnstep (John Stephens)
  167. //=============================================================================
  168. BOOL
  169. CreduiLookupLocalNameFromRid(
  170. DWORD rid,
  171. LPWSTR *name
  172. )
  173. {
  174. BOOL RetVal = FALSE;
  175. PSID Sid;
  176. WCHAR NameBuffer[UNLEN+1];
  177. DWORD NameLen;
  178. WCHAR DomainBuffer[DNLEN+1];
  179. DWORD DomainLen;
  180. SID_NAME_USE NameUse;
  181. //
  182. // First translate the rid to a SID
  183. //
  184. if ( !CreduiLookupLocalSidFromRid( rid, &Sid )) {
  185. return FALSE;
  186. }
  187. //
  188. // Translate the SID to a name
  189. //
  190. NameLen = UNLEN+1;
  191. DomainLen = DNLEN+1;
  192. if ( LookupAccountSid( NULL,
  193. Sid,
  194. NameBuffer,
  195. &NameLen,
  196. DomainBuffer,
  197. &DomainLen,
  198. &NameUse ) ) {
  199. //
  200. // Allocate a buffer for the name
  201. //
  202. *name = (LPWSTR)( new WCHAR[NameLen+1]);
  203. if ( *name != NULL ) {
  204. RtlCopyMemory( *name, NameBuffer, (NameLen+1)*sizeof(WCHAR) );
  205. RetVal = TRUE;
  206. }
  207. }
  208. delete Sid;
  209. return RetVal;
  210. }
  211. //=============================================================================
  212. // CreduiGetAdministratorsGroupInfo
  213. //
  214. // Returns a structure containing members of the well-known local
  215. // Administrators group. The caller is responsible for freeing the returned
  216. // memory via NetApiBufferFree.
  217. //
  218. // Arguments:
  219. // groupInfo (out)
  220. // memberCount (out)
  221. //
  222. // Returns TRUE on success or FALSE otherwise.
  223. //
  224. // Created 04/13/2000 johnstep (John Stephens)
  225. //=============================================================================
  226. BOOL
  227. CreduiGetAdministratorsGroupInfo(
  228. LOCALGROUP_MEMBERS_INFO_2 **groupInfo,
  229. DWORD *memberCount
  230. )
  231. {
  232. BOOL success = FALSE;
  233. *groupInfo = NULL;
  234. *memberCount = 0;
  235. SID_IDENTIFIER_AUTHORITY ntAuth = SECURITY_NT_AUTHORITY;
  236. SID *adminsSid = NULL;
  237. if (AllocateAndInitializeSid(&ntAuth,
  238. 2,
  239. SECURITY_BUILTIN_DOMAIN_RID,
  240. DOMAIN_ALIAS_RID_ADMINS,
  241. 0,
  242. 0,
  243. 0,
  244. 0,
  245. 0,
  246. 0,
  247. reinterpret_cast<VOID **>(&adminsSid)))
  248. {
  249. WCHAR user[UNLEN + 1];
  250. WCHAR domain[UNLEN + 1];
  251. DWORD userLength = (sizeof user) / (sizeof (WCHAR));
  252. DWORD domainLength = (sizeof domain) / (sizeof (WCHAR));
  253. SID_NAME_USE nameUse;
  254. // Get the name of the well-known Administrators SID:
  255. if (LookupAccountSid(NULL,
  256. adminsSid,
  257. user,
  258. &userLength,
  259. domain,
  260. &domainLength,
  261. &nameUse))
  262. {
  263. LOCALGROUP_MEMBERS_INFO_2 *info;
  264. DWORD count;
  265. DWORD total;
  266. if (NetLocalGroupGetMembers(NULL,
  267. user,
  268. 2,
  269. reinterpret_cast<BYTE **>(&info),
  270. MAX_PREFERRED_LENGTH,
  271. &count,
  272. &total,
  273. NULL) == NERR_Success)
  274. {
  275. *groupInfo = info;
  276. *memberCount = count;
  277. success = TRUE;
  278. }
  279. }
  280. FreeSid(adminsSid);
  281. }
  282. return success;
  283. }
  284. //=============================================================================
  285. // CreduiIsRemovableCertificate
  286. //
  287. // Arguments:
  288. // certContext (in) - certificate context to query
  289. //
  290. // Returns TRUE if the certificate has a removable component (such as a smart
  291. // card) or FALSE otherwise.
  292. //
  293. // Created 04/09/2000 johnstep (John Stephens)
  294. //=============================================================================
  295. BOOL
  296. CreduiIsRemovableCertificate(
  297. CONST CERT_CONTEXT *certContext
  298. )
  299. {
  300. ASSERT(certContext != NULL);
  301. BOOL isRemovable = FALSE;
  302. // First, determine the buffer size:
  303. DWORD bufferSize = 0;
  304. if (CertGetCertificateContextProperty(
  305. certContext,
  306. CERT_KEY_PROV_INFO_PROP_ID,
  307. NULL,
  308. &bufferSize))
  309. {
  310. // Allocate the buffer on the stack:
  311. CRYPT_KEY_PROV_INFO *provInfo;
  312. __try
  313. {
  314. provInfo = static_cast<CRYPT_KEY_PROV_INFO *>(alloca(bufferSize));
  315. }
  316. __except(
  317. (GetExceptionCode() == EXCEPTION_STACK_OVERFLOW) ?
  318. EXCEPTION_EXECUTE_HANDLER :
  319. EXCEPTION_CONTINUE_SEARCH)
  320. {
  321. _resetstkoflw();
  322. provInfo = NULL;
  323. }
  324. if (provInfo != NULL)
  325. {
  326. if (CertGetCertificateContextProperty(
  327. certContext,
  328. CERT_KEY_PROV_INFO_PROP_ID,
  329. provInfo,
  330. &bufferSize))
  331. {
  332. HCRYPTPROV provContext;
  333. if (CryptAcquireContext(
  334. &provContext,
  335. NULL,
  336. provInfo->pwszProvName,
  337. provInfo->dwProvType,
  338. CRYPT_VERIFYCONTEXT | CRYPT_SILENT))
  339. {
  340. DWORD impType;
  341. DWORD impTypeSize = sizeof impType;
  342. if (CryptGetProvParam(
  343. provContext,
  344. PP_IMPTYPE,
  345. reinterpret_cast<BYTE *>(&impType),
  346. &impTypeSize,
  347. 0))
  348. {
  349. if (impType & CRYPT_IMPL_REMOVABLE)
  350. {
  351. isRemovable = TRUE;
  352. }
  353. }
  354. if (!CryptReleaseContext(provContext, 0))
  355. {
  356. CreduiDebugLog(
  357. "CreduiIsRemovableCertificate: "
  358. "CryptReleaseContext failed: %u\n",
  359. GetLastError());
  360. }
  361. }
  362. }
  363. }
  364. }
  365. return isRemovable;
  366. }
  367. //=============================================================================
  368. // CreduiIsExpiredCertificate
  369. //
  370. // Arguments:
  371. // certContext (in) - certificate context to query
  372. //
  373. // Returns TRUE if the certificate has expired or FALSE otherwise.
  374. //
  375. // Created 06/12/2000 johnstep (John Stephens)
  376. //=============================================================================
  377. BOOL
  378. CreduiIsExpiredCertificate(
  379. CONST CERT_CONTEXT *certContext
  380. )
  381. {
  382. ASSERT(certContext != NULL);
  383. DWORD flags = CERT_STORE_TIME_VALIDITY_FLAG;
  384. return CertVerifySubjectCertificateContext(certContext,
  385. NULL,
  386. &flags) &&
  387. (flags & CERT_STORE_TIME_VALIDITY_FLAG);
  388. }
  389. //=============================================================================
  390. // CreduiIsClientAuthCertificate
  391. //
  392. // Arguments:
  393. // certContext (in) - certificate context to query
  394. //
  395. // Returns TRUE if the certificate has the client authentication enhanced key
  396. // usage extension (not property) or FALSE otherwise.
  397. //
  398. // Created 07/12/2000 johnstep (John Stephens)
  399. //=============================================================================
  400. BOOL
  401. CreduiIsClientAuthCertificate(
  402. CONST CERT_CONTEXT *certContext
  403. )
  404. {
  405. ASSERT(certContext != NULL);
  406. BOOL isClientAuth = FALSE;
  407. // First, determine the buffer size:
  408. DWORD bufferSize = 0;
  409. if (CertGetEnhancedKeyUsage(
  410. certContext,
  411. CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG,
  412. NULL,
  413. &bufferSize))
  414. {
  415. // Allocate the buffer on the stack:
  416. CERT_ENHKEY_USAGE *usage;
  417. __try
  418. {
  419. usage = static_cast<CERT_ENHKEY_USAGE *>(alloca(bufferSize));
  420. }
  421. __except(
  422. (GetExceptionCode() == EXCEPTION_STACK_OVERFLOW) ?
  423. EXCEPTION_EXECUTE_HANDLER :
  424. EXCEPTION_CONTINUE_SEARCH)
  425. {
  426. _resetstkoflw();
  427. usage = NULL;
  428. }
  429. if (usage != NULL)
  430. {
  431. if (CertGetEnhancedKeyUsage(
  432. certContext,
  433. CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG,
  434. usage,
  435. &bufferSize))
  436. {
  437. for (UINT i = 0; i < usage->cUsageIdentifier; ++i)
  438. {
  439. if (strcmp(usage->rgpszUsageIdentifier[i],
  440. szOID_PKIX_KP_CLIENT_AUTH) == 0)
  441. {
  442. isClientAuth = TRUE;
  443. break;
  444. }
  445. if (strcmp(usage->rgpszUsageIdentifier[i],
  446. szOID_KP_SMARTCARD_LOGON) == 0)
  447. {
  448. isClientAuth = TRUE;
  449. break;
  450. }
  451. }
  452. }
  453. }
  454. }
  455. return isClientAuth;
  456. }
  457. //=============================================================================
  458. // CreduiGetCertificateDisplayName
  459. //
  460. // Arguments:
  461. // certContext (in)
  462. // displayName (out)
  463. // displayNameMaxChars (in)
  464. // certificateString (in)
  465. // dwDisplayType (in)
  466. //
  467. // Returns TRUE if a display name was stored or FALSE otherwise.
  468. //
  469. // Created 06/12/2000 johnstep (John Stephens)
  470. //=============================================================================
  471. BOOL
  472. CreduiGetCertificateDisplayName(
  473. CONST CERT_CONTEXT *certContext,
  474. WCHAR *displayName,
  475. ULONG displayNameMaxChars,
  476. WCHAR *certificateString,
  477. DWORD dwDisplayType
  478. )
  479. {
  480. BOOL success = FALSE;
  481. if (displayNameMaxChars < 16)
  482. {
  483. goto Exit;
  484. }
  485. WCHAR *tempName;
  486. ULONG tempNameMaxChars = displayNameMaxChars / 2 - 1;
  487. ULONG ulccDisplayRoom = displayNameMaxChars;
  488. __try
  489. {
  490. tempName =
  491. static_cast<WCHAR *>(
  492. alloca(tempNameMaxChars * sizeof (WCHAR)));
  493. }
  494. __except(
  495. (GetExceptionCode() == EXCEPTION_STACK_OVERFLOW) ?
  496. EXCEPTION_EXECUTE_HANDLER :
  497. EXCEPTION_CONTINUE_SEARCH)
  498. {
  499. _resetstkoflw();
  500. tempName = NULL;
  501. }
  502. if (tempName == NULL)
  503. {
  504. goto Exit;
  505. }
  506. displayName[0] = L'\0';
  507. tempName[0] = L'\0';
  508. if (CertGetNameString(
  509. certContext,
  510. dwDisplayType,
  511. 0,
  512. NULL,
  513. tempName,
  514. tempNameMaxChars))
  515. {
  516. success = TRUE;
  517. StringCchCopyW(displayName, displayNameMaxChars, tempName);
  518. ulccDisplayRoom -= wcslen(displayName);
  519. }
  520. if (CertGetNameString(
  521. certContext,
  522. dwDisplayType,
  523. CERT_NAME_ISSUER_FLAG,
  524. NULL,
  525. tempName,
  526. tempNameMaxChars))
  527. {
  528. if (_wcsicmp(displayName, tempName) != 0)
  529. {
  530. success = TRUE;
  531. WCHAR *where = &displayName[wcslen(displayName)];
  532. if (ulccDisplayRoom > 3)
  533. {
  534. if (where > displayName)
  535. {
  536. *where++ = L' ';
  537. *where++ = L'-';
  538. *where++ = L' ';
  539. ulccDisplayRoom -= 3;
  540. }
  541. StringCchCopyW(where, ulccDisplayRoom, tempName);
  542. }
  543. }
  544. }
  545. Exit:
  546. if (!success)
  547. {
  548. StringCchCopyW(
  549. displayName,
  550. displayNameMaxChars,
  551. certificateString);
  552. }
  553. return success;
  554. }
  555. //=============================================================================
  556. // CreduiIsWildcardTargetName
  557. //
  558. // This function determines if the given target name is a wildcard name.
  559. // Currently, that means it either starts with a '*' or ends with a '*'. I
  560. // suppose, a more general solution is to simply search for a '*' anywhere in
  561. // the name.
  562. //
  563. // Arguments:
  564. // targetName (in) - The string to search
  565. //
  566. // Return TRUE if the target name is a wildcard name or FALSE otherwise.
  567. //
  568. // Created 03/09/2000 johnstep (John Stephens)
  569. //=============================================================================
  570. BOOL
  571. CreduiIsWildcardTargetName(
  572. WCHAR *targetName
  573. )
  574. {
  575. if ((targetName != NULL) && (targetName[0] != L'\0'))
  576. {
  577. return (targetName[0] == L'*') ||
  578. (targetName[wcslen(targetName) - 1] == L'*');
  579. }
  580. else
  581. {
  582. return FALSE;
  583. }
  584. }
  585. //
  586. // returns TRUE if pszUserName exists as a prefix of pszCredential
  587. //
  588. // The UserName can either be an exact match or must be a prefix of a significant component.
  589. // That is, the first unmatched character must be an @ or \ character
  590. BOOL
  591. LookForUserNameMatch (
  592. const WCHAR * pszUserName,
  593. const WCHAR * pszCredential
  594. )
  595. {
  596. ULONG length;
  597. int cmp;
  598. if ( pszUserName == NULL || pszCredential == NULL )
  599. return FALSE;
  600. length = wcslen ( pszUserName );
  601. if ( length <= 0 )
  602. return FALSE;
  603. if ( _wcsicmp ( pszUserName, pszCredential ) == 0 )
  604. return TRUE;
  605. if ( _wcsnicmp ( pszUserName, pszCredential, length ) == 0 ) {
  606. if ( pszCredential[length] == '@' || pszCredential[length] == '\\' ) {
  607. return TRUE;
  608. }
  609. }
  610. // didn't find it
  611. return FALSE;
  612. }
  613. // copies the marshalled name of pCert into pszMarshalledName.
  614. // pszMarshalledName must be at least CREDUI_MAX_USERNAME_LENGTH in length
  615. //
  616. // returns TRUE if successful, FALSE if not
  617. BOOL
  618. CredUIMarshallNode (
  619. CERT_ENUM * pCert,
  620. WCHAR* pszMarshalledName
  621. )
  622. {
  623. BOOL bMarshalled = FALSE;
  624. // marshall username
  625. WCHAR *marshaledCred;
  626. CERT_CREDENTIAL_INFO certCredInfo;
  627. certCredInfo.cbSize = sizeof certCredInfo;
  628. if (pCert != NULL)
  629. {
  630. DWORD length = CERT_HASH_LENGTH;
  631. if (CertGetCertificateContextProperty(
  632. pCert->pCertContext,
  633. CERT_SHA1_HASH_PROP_ID,
  634. static_cast<VOID *>(
  635. certCredInfo.rgbHashOfCert),
  636. &length))
  637. {
  638. if (LocalCredMarshalCredentialW(CertCredential,
  639. &certCredInfo,
  640. &marshaledCred))
  641. {
  642. if (SUCCEEDED(StringCchCopyW(
  643. pszMarshalledName,
  644. CREDUI_MAX_USERNAME_LENGTH,
  645. marshaledCred)))
  646. {
  647. bMarshalled = TRUE;
  648. }
  649. LocalCredFree(static_cast<VOID *>(marshaledCred));
  650. }
  651. }
  652. }
  653. return bMarshalled;
  654. }
  655. #define MAX_KEY_LENGTH 1024
  656. // removes any leading *. from pszIn and copies the right hand portion to pszOut.
  657. // Assumes pszOut is at least MAX_KEY_LENGTH in size
  658. void
  659. StripLeadingWildcard (
  660. WCHAR* pszIn,
  661. WCHAR* pszOut )
  662. {
  663. WCHAR* pStartPtr = pszIn;
  664. if ( wcslen ( pszIn ) > 2 )
  665. {
  666. if ( pszIn[0] == L'*' && pszIn[1] == L'.' )
  667. {
  668. pStartPtr += 2;
  669. }
  670. }
  671. StringCchCopyW(pszOut, MAX_KEY_LENGTH, pStartPtr);
  672. }
  673. // copies pszIn to pszOut and trucates pszOut at the first '\'
  674. // Assumes pszOut is at least MAX_KEY_LENGTH in size
  675. void
  676. StripTrailingWildcard (
  677. WCHAR* pszIn,
  678. WCHAR* pszOut )
  679. {
  680. StringCchCopyW(pszOut, MAX_KEY_LENGTH, pszIn);
  681. wcstok ( pszOut, L"\\" );
  682. }
  683. // Looks in the registry for an SSO entry for the specified package.
  684. // Fills in the SSOPackage struct and returns TRUE if found. Returns
  685. // FALSE if no registry entry found
  686. BOOL
  687. GetSSOPackageInfo (
  688. CREDENTIAL_TARGET_INFORMATION* pTargetInfo,
  689. SSOPACKAGE* pSSOStruct
  690. )
  691. {
  692. BOOL bSSO = FALSE;
  693. WCHAR szKeyName[MAX_KEY_LENGTH];
  694. HKEY key;
  695. DWORD dwType;
  696. DWORD dwSize;
  697. WCHAR szSSOName[MAX_KEY_LENGTH];
  698. if ( pSSOStruct == NULL )
  699. {
  700. return FALSE;
  701. }
  702. pSSOStruct->szBrand[0] = '\0';
  703. pSSOStruct->szURL[0] = '\0';
  704. pSSOStruct->szAttrib[0] = '\0';
  705. pSSOStruct->dwRegistrationCompleted = 0;
  706. pSSOStruct->dwNumRegistrationRuns = 0;
  707. pSSOStruct->pRegistrationWizard = NULL;
  708. // figure out SSO Name from Target Info
  709. if ( pTargetInfo == NULL )
  710. {
  711. return FALSE;
  712. }
  713. if ((pTargetInfo->PackageName == NULL) ||
  714. FAILED(StringCchCopyW(
  715. szSSOName,
  716. RTL_NUMBER_OF(szSSOName),
  717. pTargetInfo->PackageName)))
  718. {
  719. return FALSE;
  720. }
  721. StringCchPrintfW(
  722. szKeyName,
  723. RTL_NUMBER_OF(szKeyName),
  724. L"SYSTEM\\CurrentControlSet\\Control\\Lsa\\SSO\\%s",
  725. szSSOName);
  726. if ( RegOpenKeyEx(
  727. HKEY_LOCAL_MACHINE,
  728. szKeyName,
  729. 0,
  730. KEY_READ,
  731. &key) == ERROR_SUCCESS)
  732. {
  733. dwSize = MAX_SSO_URL_SIZE * sizeof(WCHAR);
  734. bSSO = TRUE;
  735. if ( RegQueryValueEx(
  736. key,
  737. L"SSOBrand",
  738. NULL,
  739. &dwType,
  740. (LPBYTE)(pSSOStruct->szBrand),
  741. &dwSize) == ERROR_SUCCESS )
  742. {
  743. bSSO = TRUE;
  744. }
  745. dwSize = MAX_SSO_URL_SIZE * sizeof(WCHAR);
  746. if ( RegQueryValueEx(
  747. key,
  748. L"SSOAttribute",
  749. NULL,
  750. &dwType,
  751. (LPBYTE)(pSSOStruct->szAttrib),
  752. &dwSize ) != ERROR_SUCCESS )
  753. {
  754. if ( wcsstr ( szSSOName, L"Passport" ) )
  755. {
  756. StringCchCopyW(
  757. pSSOStruct->szAttrib,
  758. RTL_NUMBER_OF(pSSOStruct->szAttrib),
  759. L"Passport");
  760. }
  761. }
  762. RegCloseKey(key);
  763. }
  764. // Now get stuff under Internet Settings
  765. StringCchPrintfW(
  766. szKeyName,
  767. RTL_NUMBER_OF(szKeyName),
  768. L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Internet Settings\\%s",
  769. pSSOStruct->szAttrib);
  770. if ( RegOpenKeyEx(
  771. HKEY_LOCAL_MACHINE,
  772. szKeyName,
  773. 0,
  774. KEY_READ,
  775. &key) == ERROR_SUCCESS)
  776. {
  777. dwSize = MAX_SSO_URL_SIZE * sizeof(WCHAR);
  778. if ( RegQueryValueEx(
  779. key,
  780. L"RegistrationUrl",
  781. NULL,
  782. &dwType,
  783. (LPBYTE)(pSSOStruct->szRegURL),
  784. &dwSize) == ERROR_SUCCESS )
  785. {
  786. }
  787. dwSize = MAX_SSO_URL_SIZE * sizeof(WCHAR);
  788. if ( RegQueryValueEx(
  789. key,
  790. L"Help",
  791. NULL,
  792. &dwType,
  793. (LPBYTE)(pSSOStruct->szHelpURL),
  794. &dwSize) == ERROR_SUCCESS )
  795. {
  796. }
  797. RegCloseKey(key);
  798. }
  799. if ( RegOpenKeyEx(
  800. HKEY_CURRENT_USER,
  801. szKeyName,
  802. 0,
  803. KEY_READ,
  804. &key) == ERROR_SUCCESS)
  805. {
  806. dwSize = sizeof(DWORD);
  807. if ( RegQueryValueEx(
  808. key,
  809. L"RegistrationCompleted",
  810. NULL,
  811. &dwType,
  812. (LPBYTE)&(pSSOStruct->dwRegistrationCompleted),
  813. &dwSize ) == ERROR_SUCCESS )
  814. {
  815. }
  816. dwSize = sizeof(DWORD);
  817. if ( RegQueryValueEx(
  818. key,
  819. L"NumRegistrationRuns",
  820. NULL,
  821. &dwType,
  822. (LPBYTE)&(pSSOStruct->dwNumRegistrationRuns),
  823. &dwSize ) == ERROR_SUCCESS )
  824. {
  825. }
  826. RegCloseKey(key);
  827. }
  828. // TBD - get regwizard CLSID
  829. if ( bSSO && IsDeaultSSORealm ( pTargetInfo->DnsDomainName ) )
  830. {
  831. pSSOStruct->pRegistrationWizard = &CLSID_PassportWizard;
  832. }
  833. return bSSO;
  834. }
  835. // returns TRUE if it was found, with the value copied to pszRealm.
  836. // pszRealm is expected to be at least (DNS_MAX_NAME_LENGTH + 1) in length
  837. // returns FALSE if not found
  838. BOOL ReadPassportRealmFromRegistry (
  839. WCHAR* pszRealm
  840. )
  841. {
  842. BOOL retval = FALSE;
  843. HKEY key;
  844. if ( pszRealm == NULL )
  845. {
  846. return FALSE;
  847. }
  848. if ( RegOpenKeyEx(
  849. HKEY_LOCAL_MACHINE,
  850. L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Internet Settings\\Passport",
  851. 0,
  852. KEY_READ,
  853. &key) == ERROR_SUCCESS)
  854. {
  855. DWORD dwType;
  856. DWORD dwSize;
  857. dwSize = (DNS_MAX_NAME_LENGTH + 1) * sizeof(WCHAR);
  858. if ( RegQueryValueEx(
  859. key,
  860. L"LoginServerRealm",
  861. NULL,
  862. &dwType,
  863. (LPBYTE)(pszRealm),
  864. &dwSize) == ERROR_SUCCESS )
  865. {
  866. if ( ( dwType == REG_SZ ) &&
  867. ( dwSize >= 4 ) &&
  868. ( pszRealm[(dwSize - 1) / sizeof(WCHAR)] == L'\0') )
  869. {
  870. retval = TRUE;
  871. }
  872. else
  873. {
  874. retval = FALSE;
  875. }
  876. }
  877. else
  878. {
  879. retval = FALSE;
  880. pszRealm[0] = L'\0';
  881. }
  882. RegCloseKey(key);
  883. }
  884. return retval;
  885. }
  886. BOOL CheckForSSOCred( WCHAR* pszTargetRealm )
  887. {
  888. BOOL bIsItThere = FALSE;
  889. WCHAR szTargetName[CREDUI_MAX_DOMAIN_TARGET_LENGTH + 1];
  890. if ( pszTargetRealm != NULL )
  891. {
  892. StringCchCopyExW(
  893. szTargetName,
  894. RTL_NUMBER_OF(szTargetName) - 2,
  895. pszTargetRealm,
  896. NULL,
  897. NULL,
  898. STRSAFE_NULL_ON_FAILURE);
  899. }
  900. else
  901. {
  902. GetDeaultSSORealm ( szTargetName, FALSE );
  903. }
  904. if (szTargetName[0] != L'\0')
  905. {
  906. // finalize the target name, ensuring that the tail will fit.
  907. if (SUCCEEDED(StringCchCatW(
  908. szTargetName,
  909. RTL_NUMBER_OF(szTargetName),
  910. L"\\*")))
  911. {
  912. PCREDENTIALW pCred;
  913. DWORD dwFlags = 0;
  914. // first call credmgr to set the target info
  915. if ( CredReadW ( szTargetName,
  916. CRED_TYPE_DOMAIN_VISIBLE_PASSWORD,
  917. dwFlags,
  918. &pCred ) )
  919. {
  920. bIsItThere = TRUE;
  921. CredFree ( pCred );
  922. }
  923. }
  924. }
  925. return bIsItThere;
  926. }
  927. EXTERN_C typedef BOOL (STDAPICALLTYPE *PFN_FORCENEXUSLOOKUP)();
  928. void GetDeaultSSORealm ( WCHAR* pszTargetName, BOOL bForceLookup )
  929. {
  930. if ( pszTargetName == NULL )
  931. {
  932. return;
  933. }
  934. pszTargetName[0] = L'\0';
  935. // check the registry to see if we've already written the passport
  936. if ( ! ReadPassportRealmFromRegistry ( pszTargetName ) && bForceLookup )
  937. {
  938. // if not, call winiet to do this and then re-read the registry
  939. HMODULE hWininet = LoadLibrary(L"wininet.dll");
  940. if ( hWininet )
  941. {
  942. PFN_FORCENEXUSLOOKUP pfnForceNexusLookup = (PFN_FORCENEXUSLOOKUP)GetProcAddress(hWininet, "ForceNexusLookup");
  943. if ( pfnForceNexusLookup )
  944. {
  945. pfnForceNexusLookup();
  946. }
  947. FreeLibrary ( hWininet );
  948. }
  949. // try again
  950. if ( ! ReadPassportRealmFromRegistry ( pszTargetName ) )
  951. {
  952. return;
  953. }
  954. }
  955. }
  956. // returns TRUE if the targetrealm equals the default
  957. BOOL IsDeaultSSORealm ( WCHAR* pszTargetName )
  958. {
  959. BOOL bRet = FALSE;
  960. if ( pszTargetName == NULL )
  961. {
  962. return FALSE; // can't be the default if it doesn't exist
  963. }
  964. WCHAR szTarget[DNS_MAX_NAME_LENGTH + 1];
  965. GetDeaultSSORealm ( szTarget, TRUE );
  966. if ( wcslen ( szTarget ) > 0 )
  967. {
  968. if ( _wcsicmp ( szTarget, pszTargetName) == 0 )
  969. {
  970. bRet = TRUE;
  971. }
  972. }
  973. return bRet;
  974. }
  975. // encrypt cred
  976. DWORD EncryptPassword ( PWSTR pszPassword, PVOID* ppszEncryptedPassword, DWORD* pSize )
  977. {
  978. DWORD dwResult = ERROR_GEN_FAILURE;
  979. if ( pszPassword == NULL || ppszEncryptedPassword == NULL )
  980. {
  981. return ERROR_INVALID_PARAMETER;
  982. }
  983. DATA_BLOB InBlob;
  984. DATA_BLOB OutBlob;
  985. InBlob.pbData = (BYTE*)pszPassword;
  986. InBlob.cbData = sizeof(WCHAR)*(wcslen(pszPassword)+1);
  987. DATA_BLOB EntropyBlob;
  988. WCHAR szSalt[SIZE_OF_SALT];
  989. // g_szSalt is a constant, cc = SIZE_OF_SALT including the null.
  990. StringCchCopyW(szSalt, RTL_NUMBER_OF(szSalt), g_szSalt);
  991. for ( int i = 0; i < SIZE_OF_SALT; i++ )
  992. {
  993. szSalt[i] <<= SALT_SHIFT;
  994. }
  995. EntropyBlob.pbData = (BYTE*)szSalt;
  996. EntropyBlob.cbData = sizeof(WCHAR)*(wcslen(szSalt)+1);
  997. if ( CryptProtectData ( &InBlob,
  998. L"SSOCred",
  999. &EntropyBlob, // optional entropy
  1000. // NULL, // optional entropy
  1001. NULL,
  1002. NULL,
  1003. CRYPTPROTECT_UI_FORBIDDEN,
  1004. &OutBlob ) )
  1005. {
  1006. *ppszEncryptedPassword = (PWSTR)LocalAlloc(LMEM_ZEROINIT, OutBlob.cbData);
  1007. if ( *ppszEncryptedPassword )
  1008. {
  1009. memcpy ( *ppszEncryptedPassword, OutBlob.pbData, OutBlob.cbData );
  1010. *pSize = OutBlob.cbData;
  1011. dwResult = ERROR_SUCCESS;
  1012. }
  1013. LocalFree ( OutBlob.pbData );
  1014. }
  1015. SecureZeroMemory(szSalt, sizeof szSalt);
  1016. return dwResult;
  1017. }
  1018. BOOL IsPasswordEncrypted ( PVOID pPassword, DWORD cbSize )
  1019. {
  1020. BOOL bRet = FALSE;
  1021. DATA_BLOB InBlob;
  1022. DATA_BLOB OutBlob;
  1023. LPWSTR pszDesc;
  1024. InBlob.pbData = (BYTE*)pPassword;
  1025. InBlob.cbData = cbSize;
  1026. DATA_BLOB EntropyBlob;
  1027. WCHAR szSalt[SIZE_OF_SALT];
  1028. // g_szSalt is a constant, cc = SIZE_OF_SALT including the null.
  1029. StringCchCopyW(szSalt, RTL_NUMBER_OF(szSalt), g_szSalt);
  1030. for ( int i = 0; i < SIZE_OF_SALT; i++ )
  1031. {
  1032. szSalt[i] <<= SALT_SHIFT;
  1033. }
  1034. EntropyBlob.pbData = (BYTE*)szSalt;
  1035. EntropyBlob.cbData = sizeof(WCHAR)*(wcslen(szSalt)+1);
  1036. if ( CryptUnprotectData ( &InBlob,
  1037. &pszDesc,
  1038. &EntropyBlob,
  1039. // NULL,
  1040. NULL,
  1041. NULL,
  1042. CRYPTPROTECT_UI_FORBIDDEN,
  1043. &OutBlob ) )
  1044. {
  1045. if ( wcscmp (L"SSOCred", pszDesc) == 0 )
  1046. {
  1047. bRet = TRUE;
  1048. }
  1049. LocalFree ( pszDesc );
  1050. LocalFree ( OutBlob.pbData );
  1051. }
  1052. SecureZeroMemory(szSalt, sizeof szSalt);
  1053. return bRet;
  1054. }
  1055. // cred confirmation routines
  1056. VOID
  1057. DeleteConfirmationListEntry (
  1058. IN CRED_AWAITING_CONFIRMATION* pConf
  1059. )
  1060. /*++
  1061. Routine Description:
  1062. This routine deletes a single confirmation list entry.
  1063. Arguments:
  1064. pConf - Confirmation list entry to delete
  1065. Return Values:
  1066. None.
  1067. --*/
  1068. {
  1069. //
  1070. // Delete the target info
  1071. //
  1072. if ( pConf->TargetInfo != NULL ) {
  1073. LocalCredFree( pConf->TargetInfo );
  1074. }
  1075. //
  1076. // Delete the credential
  1077. //
  1078. if ( pConf->EncodedCredential != NULL ) {
  1079. if ( pConf->EncodedCredential->CredentialBlobSize != 0 &&
  1080. pConf->EncodedCredential->CredentialBlob != NULL ) {
  1081. SecureZeroMemory( pConf->EncodedCredential->CredentialBlob,
  1082. pConf->EncodedCredential->CredentialBlobSize );
  1083. }
  1084. LocalCredFree( pConf->EncodedCredential );
  1085. }
  1086. //
  1087. // Free the confirmation list entry itself
  1088. //
  1089. delete (pConf);
  1090. }
  1091. DWORD
  1092. WriteCred(
  1093. IN PCWSTR pszTargetName,
  1094. IN DWORD Flags,
  1095. IN PCREDENTIAL_TARGET_INFORMATION TargetInfo OPTIONAL,
  1096. IN PCREDENTIAL Credential,
  1097. IN DWORD dwCredWriteFlags,
  1098. IN BOOL DelayCredentialWrite,
  1099. IN BOOL EncryptedVisiblePassword
  1100. )
  1101. /*++
  1102. Routine Description:
  1103. This routine writes a credential.
  1104. If the credential needs confirmation, the credential will be added to the
  1105. confirmation list.
  1106. Arguments:
  1107. pszTargetName - The target name of the resource that caused the credential to be
  1108. written.
  1109. Flags - Flags passed by the original caller.
  1110. CREDUI_FLAGS_EXPECT_CONFIRMATION - Specifies that the credential is to be written
  1111. to the confirmation list instead of being written immediately.
  1112. TargetInfo - The target information associated with the target name.
  1113. If not specified, the target informatio isn't known.
  1114. Credential - The credential that is to be written.
  1115. dwCredWriteFlags - Flags to pass to CredWrite when writing the credential
  1116. DelayCredentialWrite - TRUE if the credential is to be written only upon confirmation.
  1117. FALSE, if the credential is to be written now as a session credential then
  1118. morphed to a more persistent credential upon confirmation.
  1119. This field is ignored if Flags doesn't specify CREDUI_FLAGS_EXPECT_CONFIRMATION.
  1120. Return Values:
  1121. TRUE - The cred was sucessfully added to the confirmation list.
  1122. FALSE - There isn't enough memory to add the cred to the confirmation list.
  1123. --*/
  1124. {
  1125. DWORD Win32Status = NO_ERROR;
  1126. BOOL WriteCredNow;
  1127. PVOID pCredentialBlob = NULL;
  1128. DWORD dwCredentialBlobSize = 0;
  1129. CREDENTIAL TempCredential;
  1130. CreduiDebugLog("WriteCred called for %S, with flags %x, delay %x\n",pszTargetName,Flags,DelayCredentialWrite);
  1131. //
  1132. // Check to see if we should wait for confirmation
  1133. //
  1134. // ISSUE-2000/12/14-CliffV - there's no reason to avoid adding 'visible' passwords to
  1135. // the confirmation list.
  1136. //
  1137. if ( (Flags & CREDUI_FLAGS_EXPECT_CONFIRMATION) != 0 &&
  1138. Credential->Type != CRED_TYPE_DOMAIN_VISIBLE_PASSWORD ) {
  1139. if ( AddCredToConfirmationList ( pszTargetName,
  1140. TargetInfo,
  1141. Credential,
  1142. dwCredWriteFlags,
  1143. DelayCredentialWrite ) ) {
  1144. //
  1145. // Alter cred persistence type
  1146. // Then, at least, the credential will disappear upon logoff
  1147. //
  1148. Credential->Persist = CRED_PERSIST_SESSION;
  1149. WriteCredNow = !DelayCredentialWrite;
  1150. } else {
  1151. // If we couldn't queue the CredWrite, do it now.
  1152. WriteCredNow = TRUE;
  1153. }
  1154. //
  1155. // If the caller doesn't supply a confirmation,
  1156. // write the credential now.
  1157. //
  1158. } else {
  1159. WriteCredNow = TRUE;
  1160. }
  1161. //
  1162. // Determine if we should encrypt the visible password
  1163. //
  1164. if ( Credential->Type == CRED_TYPE_DOMAIN_VISIBLE_PASSWORD && EncryptedVisiblePassword ) {
  1165. // encrypt it
  1166. Win32Status = EncryptPassword ( (WCHAR*)Credential->CredentialBlob,
  1167. &pCredentialBlob,
  1168. &dwCredentialBlobSize );
  1169. if ( Win32Status == ERROR_SUCCESS )
  1170. {
  1171. // Make a copy of the credential so we don't modify the original
  1172. TempCredential = *Credential;
  1173. Credential = &TempCredential;
  1174. Credential->CredentialBlob = (LPBYTE)pCredentialBlob;
  1175. Credential->CredentialBlobSize = dwCredentialBlobSize;
  1176. }
  1177. }
  1178. //
  1179. // If the credential needs to be written now,
  1180. // do it
  1181. //
  1182. if ( WriteCredNow && Win32Status == NO_ERROR ) { // ERROR_SUCCESS == NO_ERROR == 0
  1183. if ( TargetInfo != NULL ) {
  1184. if ( !LocalCredWriteDomainCredentialsW ( TargetInfo, Credential, dwCredWriteFlags) ) {
  1185. Win32Status = GetLastError();
  1186. }
  1187. } else {
  1188. if (!LocalCredWriteW( Credential, dwCredWriteFlags)) {
  1189. Win32Status = GetLastError();
  1190. }
  1191. }
  1192. }
  1193. //
  1194. // Free any credential blob we allocated.
  1195. if ( pCredentialBlob )
  1196. {
  1197. SecureZeroMemory ( pCredentialBlob, dwCredentialBlobSize );
  1198. LocalFree ( pCredentialBlob );
  1199. }
  1200. return Win32Status;
  1201. }
  1202. BOOL
  1203. AddCredToConfirmationList (
  1204. IN PCWSTR pszTargetName,
  1205. IN PCREDENTIAL_TARGET_INFORMATION TargetInfo OPTIONAL,
  1206. IN PCREDENTIAL Credential,
  1207. IN DWORD dwCredWriteFlags,
  1208. IN BOOL DelayCredentialWrite
  1209. )
  1210. /*++
  1211. Routine Description:
  1212. This routine adds a credential to the confirmation list. Such a credential must
  1213. be confirmed at a later point in time or it will be deleted.
  1214. Arguments:
  1215. pszTargetName - The target name of the resource that caused the credential to be
  1216. written. This target name is the handle used to identify the confirmation list
  1217. entry.
  1218. TargetInfo - The target information associated with the target name.
  1219. If not specified, the target informatio isn't known.
  1220. Credential - The credential that is to be written.
  1221. dwCredWriteFlags - Flags to pass to CredWrite when writing the credential
  1222. DelayCredentialWrite - TRUE if the credential is to be written only upon confirmation.
  1223. FALSE, if the credential is to be written now as a session credential then
  1224. morphed to a more persistent credential upon confirmation.
  1225. Return Values:
  1226. TRUE - The cred was sucessfully added to the confirmation list.
  1227. FALSE - There isn't enough memory to add the cred to the confirmation list.
  1228. --*/
  1229. {
  1230. DWORD Win32Status;
  1231. BOOLEAN bRetVal;
  1232. CRED_AWAITING_CONFIRMATION* pNewEntry = NULL;
  1233. CRED_AWAITING_CONFIRMATION* pOldEntry;
  1234. CreduiDebugLog(
  1235. "AddCredToConfirmationList: "
  1236. "Called for target %S with target info %x\n",
  1237. pszTargetName,(void *)TargetInfo);
  1238. //
  1239. // Allocate the entry itself
  1240. //
  1241. pNewEntry = new CRED_AWAITING_CONFIRMATION;
  1242. if ( pNewEntry == NULL ) {
  1243. bRetVal = FALSE;
  1244. goto Cleanup;
  1245. }
  1246. //
  1247. // Fill in the
  1248. StringCchCopyW(
  1249. pNewEntry->szTargetName,
  1250. RTL_NUMBER_OF(pNewEntry->szTargetName),
  1251. pszTargetName);
  1252. pNewEntry->EncodedCredential = NULL;
  1253. pNewEntry->TargetInfo = NULL;
  1254. pNewEntry->DelayCredentialWrite = DelayCredentialWrite;
  1255. pNewEntry->dwCredWriteFlags =dwCredWriteFlags;
  1256. //
  1257. // Make a copy of the target info
  1258. //
  1259. if ( TargetInfo != NULL ) {
  1260. Win32Status = CredpConvertTargetInfo (
  1261. DoWtoW,
  1262. TargetInfo,
  1263. &pNewEntry->TargetInfo,
  1264. NULL );
  1265. if ( Win32Status != NO_ERROR ) {
  1266. bRetVal = FALSE;
  1267. goto Cleanup;
  1268. }
  1269. }
  1270. //
  1271. // Make a copy of the credential
  1272. //
  1273. Win32Status = CredpConvertCredential (
  1274. DoWtoW,
  1275. DoBlobEncode, // Encode the copied credential
  1276. Credential,
  1277. &pNewEntry->EncodedCredential );
  1278. if ( Win32Status != NO_ERROR ) {
  1279. bRetVal = FALSE;
  1280. goto Cleanup;
  1281. }
  1282. //
  1283. // Delete any existing entry
  1284. // (Wait until the new entry is allocated to ensure we don't delete the old
  1285. // entry when failing to create the new one.)
  1286. //
  1287. ConfirmCred( pszTargetName, FALSE, FALSE );
  1288. //
  1289. // Link the new entry into the global list
  1290. //
  1291. EnterCriticalSection( &CredConfirmationCritSect );
  1292. if ( pCredConfirmationListHead == NULL) {
  1293. pNewEntry->pNext = NULL;
  1294. } else {
  1295. pNewEntry->pNext = (void*)pCredConfirmationListHead;
  1296. }
  1297. pCredConfirmationListHead = pNewEntry;
  1298. LeaveCriticalSection( &CredConfirmationCritSect );
  1299. pNewEntry = NULL;
  1300. bRetVal = TRUE;
  1301. //
  1302. // Release any locally used resources
  1303. //
  1304. Cleanup:
  1305. //
  1306. // Free any partially allocated entry
  1307. //
  1308. if ( pNewEntry != NULL) {
  1309. DeleteConfirmationListEntry( pNewEntry );
  1310. }
  1311. // Trim the list to 5 entries total
  1312. INT i=0; // count the entries
  1313. if ((pOldEntry = pCredConfirmationListHead) != NULL)
  1314. {
  1315. EnterCriticalSection( &CredConfirmationCritSect );
  1316. while((pNewEntry = (CRED_AWAITING_CONFIRMATION*)(pOldEntry->pNext)) != NULL)
  1317. {
  1318. if (++i > 4)
  1319. {
  1320. // leave old (5th) entry alone, and remove all following one at a time
  1321. pOldEntry->pNext = pNewEntry->pNext;
  1322. CreduiDebugLog(
  1323. "AddCredToConfirmationList: "
  1324. "Removing excess waiting credential #%d for %S\n",
  1325. i,pNewEntry->szTargetName);
  1326. // discard this record and continue to end
  1327. DeleteConfirmationListEntry(pNewEntry);
  1328. }
  1329. else
  1330. {
  1331. pOldEntry = pNewEntry;
  1332. CreduiDebugLog(
  1333. "AddCredToConfirmationList: "
  1334. "Walking the list #%d\n",
  1335. i);
  1336. }
  1337. }
  1338. LeaveCriticalSection( &CredConfirmationCritSect );
  1339. }
  1340. return bRetVal;
  1341. }
  1342. DWORD
  1343. ConfirmCred (
  1344. IN PCWSTR pszTargetName,
  1345. IN BOOL bConfirm,
  1346. IN BOOL bOkToDelete
  1347. )
  1348. /*++
  1349. Routine Description:
  1350. This routine either confirms (bConfirm = TRUE ) or cancels (bConfirm = FALSE) the credential
  1351. Arguments:
  1352. pszTargetName - The target name of the resource that caused the credential to be
  1353. written. This target name is the handle used to identify the confirmation list
  1354. entry.
  1355. ISSUE-2000/11/29-CliffV: We shouldn't be using pszTargetName as the handle. It isn't
  1356. specific enough. We should use something that maps to a particular credential with a
  1357. particular type.
  1358. bConfirm - If TRUE, commits the credential.
  1359. If FALSE, Aborts the transaction. Deletes the transaction history.
  1360. bOkToDelete - If TRUE and bConfirm is FALSE, any session credential created at the
  1361. beginning of the transaction is deleted. If FALSE, any session credential created at
  1362. the begining of the transaction remains.
  1363. Return Values:
  1364. Status of the operation.
  1365. --*/
  1366. {
  1367. DWORD Result = NO_ERROR;
  1368. CRED_AWAITING_CONFIRMATION* pPrev = NULL;
  1369. CRED_AWAITING_CONFIRMATION* pConf;
  1370. //
  1371. // Find the credential in the global list.
  1372. //
  1373. CreduiDebugLog("ConfirmCred: Cred %S confirm %x.\n",pszTargetName,bConfirm );
  1374. EnterCriticalSection( &CredConfirmationCritSect );
  1375. pConf = pCredConfirmationListHead;
  1376. while ( pConf != NULL ) {
  1377. if ( _wcsicmp ( pszTargetName, pConf->szTargetName ) == 0 ) {
  1378. break;
  1379. }
  1380. pPrev = pConf;
  1381. pConf = (CRED_AWAITING_CONFIRMATION*)pConf->pNext;
  1382. }
  1383. //
  1384. // We found the cred indicated
  1385. //
  1386. if (pConf == NULL) {
  1387. //return ERROR_NOT_FOUND; cannot return here
  1388. Result = ERROR_NOT_FOUND;
  1389. goto Cleanup;
  1390. }
  1391. else {
  1392. //
  1393. // If the caller wants to commit the change,
  1394. // do it by writing the cred to cred manager.
  1395. //
  1396. // This works even if DelayCredentialWrite is false.
  1397. // In that case, a session persistent credential has already been written.
  1398. // However, the cached credential is better than that credential in every respect.
  1399. //
  1400. if ( bConfirm ) {
  1401. //
  1402. // Decode the Credential before writing it
  1403. //
  1404. if (!CredpDecodeCredential( (PENCRYPTED_CREDENTIALW)pConf->EncodedCredential ) ) {
  1405. Result = ERROR_INVALID_PARAMETER;
  1406. //
  1407. // Actually write the credential
  1408. //
  1409. } else if ( pConf->TargetInfo != NULL ) {
  1410. if ( !LocalCredWriteDomainCredentialsW ( pConf->TargetInfo,
  1411. pConf->EncodedCredential,
  1412. pConf->dwCredWriteFlags) ) {
  1413. Result = GetLastError();
  1414. }
  1415. } else {
  1416. if ( !LocalCredWriteW ( pConf->EncodedCredential,
  1417. pConf->dwCredWriteFlags) ) {
  1418. Result = GetLastError();
  1419. }
  1420. }
  1421. //
  1422. // If the caller wants to abort the commit,
  1423. // delete any credential credui already created.
  1424. //
  1425. } else {
  1426. //
  1427. // Only do this if credui actually wrote the credential.
  1428. //
  1429. // Note there is a timing window where we might be deleting a credential
  1430. // other than the one credui just wrote. However, we're weeding out
  1431. // the applications that don't use DelayCredentialWrite. That's the
  1432. // real fix. In the mean time, it is better to delete creds that that
  1433. // don't work.
  1434. //
  1435. if ( !pConf->DelayCredentialWrite && bOkToDelete ) {
  1436. if ( !LocalCredDeleteW ( pConf->EncodedCredential->TargetName,
  1437. pConf->EncodedCredential->Type,
  1438. 0 ) ) {
  1439. Result = GetLastError();
  1440. }
  1441. }
  1442. }
  1443. //
  1444. // remove it from list
  1445. //
  1446. if ( pPrev ) {
  1447. pPrev->pNext = pConf->pNext;
  1448. } else {
  1449. pCredConfirmationListHead = (CRED_AWAITING_CONFIRMATION*)(pConf->pNext);
  1450. }
  1451. DeleteConfirmationListEntry(pConf);
  1452. }
  1453. Cleanup:
  1454. LeaveCriticalSection( &CredConfirmationCritSect );
  1455. return Result;
  1456. }
  1457. void
  1458. CleanUpConfirmationList ()
  1459. {
  1460. CRED_AWAITING_CONFIRMATION* pNext;
  1461. CRED_AWAITING_CONFIRMATION* pConf;
  1462. EnterCriticalSection( &CredConfirmationCritSect );
  1463. pConf = pCredConfirmationListHead;
  1464. while ( pConf != NULL )
  1465. {
  1466. pNext = (CRED_AWAITING_CONFIRMATION*)pConf->pNext;
  1467. DeleteConfirmationListEntry(pConf);
  1468. pConf = pNext;
  1469. }
  1470. pCredConfirmationListHead = NULL;
  1471. LeaveCriticalSection( &CredConfirmationCritSect );
  1472. //
  1473. // Delete the Critical Section used to serialize access to the global list
  1474. //
  1475. DeleteCriticalSection( &CredConfirmationCritSect );
  1476. }
  1477. BOOL
  1478. InitConfirmationList ()
  1479. {
  1480. //
  1481. // Initialize the Critical Section used to serialize access to the global list
  1482. //
  1483. pCredConfirmationListHead = NULL;
  1484. return InitializeCriticalSectionAndSpinCount( &CredConfirmationCritSect, 0 );
  1485. }
  1486. /////////////////
  1487. // wincred.h dynamic stuff
  1488. //
  1489. BOOL bCredMgrAvailable = FALSE;
  1490. PFN_CREDWRITEW pfnCredWriteW = NULL;
  1491. PFN_CREDREADW pfnCredReadW = NULL;
  1492. PFN_CREDENUMERATEW pfnCredEnumerateW = NULL;
  1493. PFN_CREDWRITEDOMAINCREDENTIALSW pfnCredWriteDomainCredentialsW = NULL;
  1494. PFN_CREDREADDOMAINCREDENTIALSW pfnCredReadDomainCredentialsW = NULL;
  1495. PFN_CREDDELETEW pfnCredDeleteW = NULL;
  1496. PFN_CREDRENAMEW pfnCredRenameW = NULL;
  1497. PFN_CREDGETTARGETINFOW pfnCredGetTargetInfoW = NULL;
  1498. PFN_CREDMARSHALCREDENTIALW pfnCredMarshalCredentialW = NULL;
  1499. PFN_CREDUNMARSHALCREDENTIALW pfnCredUnMarshalCredentialW = NULL;
  1500. PFN_CREDISMARSHALEDCREDENTIALW pfnCredIsMarshaledCredentialW = NULL;
  1501. PFN_CREDISMARSHALEDCREDENTIALA pfnCredIsMarshaledCredentialA = NULL;
  1502. PFN_CREDGETSESSIONTYPES pfnCredGetSessionTypes = NULL;
  1503. PFN_CREDFREE pfnCredFree = NULL;
  1504. // attempts to load credmgr functions - returns TRUE if credmgr is avail, FALSE if not
  1505. BOOL
  1506. InitializeCredMgr ()
  1507. {
  1508. bCredMgrAvailable = FALSE;
  1509. if ( hAdvapi32 == NULL )
  1510. hAdvapi32 = LoadLibrary(L"advapi32.dll");
  1511. if ( hAdvapi32 != NULL )
  1512. {
  1513. pfnCredWriteW = (PFN_CREDWRITEW)
  1514. GetProcAddress(hAdvapi32, "CredWriteW");
  1515. if (*pfnCredWriteW == NULL)
  1516. {
  1517. FreeLibrary(hAdvapi32);
  1518. hAdvapi32 = NULL;
  1519. goto Exit;
  1520. }
  1521. pfnCredReadW = (PFN_CREDREADW)
  1522. GetProcAddress(hAdvapi32, "CredReadW");
  1523. if (*pfnCredReadW == NULL)
  1524. {
  1525. FreeLibrary(hAdvapi32);
  1526. hAdvapi32 = NULL;
  1527. goto Exit;
  1528. }
  1529. pfnCredEnumerateW = (PFN_CREDENUMERATEW)
  1530. GetProcAddress(hAdvapi32, "CredEnumerateW");
  1531. if (*pfnCredEnumerateW == NULL)
  1532. {
  1533. FreeLibrary(hAdvapi32);
  1534. hAdvapi32 = NULL;
  1535. goto Exit;
  1536. }
  1537. pfnCredWriteDomainCredentialsW = (PFN_CREDWRITEDOMAINCREDENTIALSW)
  1538. GetProcAddress(hAdvapi32, "CredWriteDomainCredentialsW");
  1539. if (*pfnCredWriteDomainCredentialsW == NULL)
  1540. {
  1541. FreeLibrary(hAdvapi32);
  1542. hAdvapi32 = NULL;
  1543. goto Exit;
  1544. }
  1545. pfnCredReadDomainCredentialsW = (PFN_CREDREADDOMAINCREDENTIALSW)
  1546. GetProcAddress(hAdvapi32, "CredReadDomainCredentialsW");
  1547. if (*pfnCredReadDomainCredentialsW == NULL)
  1548. {
  1549. FreeLibrary(hAdvapi32);
  1550. hAdvapi32 = NULL;
  1551. goto Exit;
  1552. }
  1553. pfnCredDeleteW = (PFN_CREDDELETEW)
  1554. GetProcAddress(hAdvapi32, "CredDeleteW");
  1555. if (*pfnCredDeleteW == NULL)
  1556. {
  1557. FreeLibrary(hAdvapi32);
  1558. hAdvapi32 = NULL;
  1559. goto Exit;
  1560. }
  1561. pfnCredRenameW = (PFN_CREDRENAMEW)
  1562. GetProcAddress(hAdvapi32, "CredRenameW");
  1563. if (*pfnCredRenameW == NULL)
  1564. {
  1565. FreeLibrary(hAdvapi32);
  1566. hAdvapi32 = NULL;
  1567. goto Exit;
  1568. }
  1569. pfnCredGetTargetInfoW = (PFN_CREDGETTARGETINFOW)
  1570. GetProcAddress(hAdvapi32, "CredGetTargetInfoW");
  1571. if (*pfnCredGetTargetInfoW == NULL)
  1572. {
  1573. FreeLibrary(hAdvapi32);
  1574. hAdvapi32 = NULL;
  1575. goto Exit;
  1576. }
  1577. pfnCredMarshalCredentialW = (PFN_CREDMARSHALCREDENTIALW)
  1578. GetProcAddress(hAdvapi32, "CredMarshalCredentialW");
  1579. if (*pfnCredMarshalCredentialW == NULL)
  1580. {
  1581. FreeLibrary(hAdvapi32);
  1582. hAdvapi32 = NULL;
  1583. goto Exit;
  1584. }
  1585. pfnCredUnMarshalCredentialW = (PFN_CREDUNMARSHALCREDENTIALW)
  1586. GetProcAddress(hAdvapi32, "CredUnmarshalCredentialW");
  1587. if (*pfnCredUnMarshalCredentialW == NULL)
  1588. {
  1589. FreeLibrary(hAdvapi32);
  1590. hAdvapi32 = NULL;
  1591. goto Exit;
  1592. }
  1593. pfnCredIsMarshaledCredentialW = (PFN_CREDISMARSHALEDCREDENTIALW)
  1594. GetProcAddress(hAdvapi32, "CredIsMarshaledCredentialW");
  1595. if (*pfnCredIsMarshaledCredentialW == NULL)
  1596. {
  1597. FreeLibrary(hAdvapi32);
  1598. hAdvapi32 = NULL;
  1599. goto Exit;
  1600. }
  1601. pfnCredIsMarshaledCredentialA = (PFN_CREDISMARSHALEDCREDENTIALA)
  1602. GetProcAddress(hAdvapi32, "CredIsMarshaledCredentialA");
  1603. if (*pfnCredIsMarshaledCredentialA == NULL)
  1604. {
  1605. FreeLibrary(hAdvapi32);
  1606. hAdvapi32 = NULL;
  1607. goto Exit;
  1608. }
  1609. pfnCredGetSessionTypes = (PFN_CREDGETSESSIONTYPES)
  1610. GetProcAddress(hAdvapi32, "CredGetSessionTypes");
  1611. if (*pfnCredGetSessionTypes == NULL)
  1612. {
  1613. FreeLibrary(hAdvapi32);
  1614. hAdvapi32 = NULL;
  1615. goto Exit;
  1616. }
  1617. pfnCredFree = (PFN_CREDFREE)
  1618. GetProcAddress(hAdvapi32, "CredFree");
  1619. if (*pfnCredFree == NULL)
  1620. {
  1621. FreeLibrary(hAdvapi32);
  1622. hAdvapi32 = NULL;
  1623. goto Exit;
  1624. }
  1625. bCredMgrAvailable = TRUE;
  1626. }
  1627. Exit:
  1628. return bCredMgrAvailable;
  1629. }
  1630. void
  1631. UninitializeCredMgr ()
  1632. {
  1633. if ( hAdvapi32 != NULL )
  1634. FreeLibrary(hAdvapi32);
  1635. bCredMgrAvailable = FALSE;
  1636. }
  1637. /////////////////////
  1638. // Local functions to indirect CredMgr funcs
  1639. //
  1640. BOOL
  1641. WINAPI
  1642. LocalCredWriteW (
  1643. IN PCREDENTIALW Credential,
  1644. IN DWORD Flags
  1645. )
  1646. {
  1647. if ( bCredMgrAvailable && pfnCredWriteW != NULL )
  1648. {
  1649. if (pfnCredWriteW(Credential,Flags))
  1650. {
  1651. return TRUE;
  1652. }
  1653. else
  1654. {
  1655. if (ERROR_INVALID_PARAMETER == GetLastError())
  1656. {
  1657. // attempt to null the alias field of the cred and try again
  1658. Credential->TargetAlias = NULL;
  1659. return pfnCredWriteW(Credential,Flags);
  1660. }
  1661. else
  1662. {
  1663. // Something else was wrong
  1664. return FALSE;
  1665. }
  1666. }
  1667. }
  1668. else
  1669. {
  1670. return FALSE;
  1671. }
  1672. }
  1673. BOOL
  1674. WINAPI
  1675. LocalCredReadW (
  1676. IN LPCWSTR TargetName,
  1677. IN DWORD Type,
  1678. IN DWORD Flags,
  1679. OUT PCREDENTIALW *Credential
  1680. )
  1681. {
  1682. if ( bCredMgrAvailable && pfnCredReadW != NULL )
  1683. {
  1684. return pfnCredReadW ( TargetName, Type, Flags, Credential );
  1685. }
  1686. else
  1687. {
  1688. return FALSE;
  1689. }
  1690. }
  1691. BOOL
  1692. WINAPI
  1693. LocalCredEnumerateW (
  1694. IN LPCWSTR Filter,
  1695. IN DWORD Flags,
  1696. OUT DWORD *Count,
  1697. OUT PCREDENTIALW **Credential
  1698. )
  1699. {
  1700. if ( bCredMgrAvailable && pfnCredEnumerateW != NULL )
  1701. {
  1702. return pfnCredEnumerateW ( Filter, Flags, Count, Credential );
  1703. }
  1704. else
  1705. {
  1706. return FALSE;
  1707. }
  1708. }
  1709. BOOL
  1710. WINAPI
  1711. LocalCredWriteDomainCredentialsW (
  1712. IN PCREDENTIAL_TARGET_INFORMATIONW TargetInfo,
  1713. IN PCREDENTIALW Credential,
  1714. IN DWORD Flags
  1715. )
  1716. {
  1717. if ( bCredMgrAvailable && pfnCredWriteDomainCredentialsW != NULL )
  1718. {
  1719. if (pfnCredWriteDomainCredentialsW ( TargetInfo, Credential, Flags ))
  1720. {
  1721. return TRUE;
  1722. }
  1723. else
  1724. {
  1725. if (ERROR_INVALID_PARAMETER == GetLastError())
  1726. {
  1727. // attempt to null the alias field of the cred and try again
  1728. Credential->TargetAlias = NULL;
  1729. return pfnCredWriteDomainCredentialsW ( TargetInfo, Credential, Flags );
  1730. }
  1731. else
  1732. {
  1733. return FALSE;
  1734. }
  1735. }
  1736. }
  1737. else
  1738. {
  1739. return FALSE;
  1740. }
  1741. }
  1742. BOOL
  1743. WINAPI
  1744. LocalCredReadDomainCredentialsW (
  1745. IN PCREDENTIAL_TARGET_INFORMATIONW TargetInfo,
  1746. IN DWORD Flags,
  1747. OUT DWORD *Count,
  1748. OUT PCREDENTIALW **Credential
  1749. )
  1750. {
  1751. if ( bCredMgrAvailable && pfnCredReadDomainCredentialsW != NULL )
  1752. {
  1753. return pfnCredReadDomainCredentialsW ( TargetInfo, Flags, Count, Credential );
  1754. }
  1755. else
  1756. {
  1757. return FALSE;
  1758. }
  1759. }
  1760. BOOL
  1761. WINAPI
  1762. LocalCredDeleteW (
  1763. IN LPCWSTR TargetName,
  1764. IN DWORD Type,
  1765. IN DWORD Flags
  1766. )
  1767. {
  1768. if ( bCredMgrAvailable && pfnCredDeleteW != NULL )
  1769. {
  1770. return pfnCredDeleteW ( TargetName, Type, Flags );
  1771. }
  1772. else
  1773. {
  1774. return FALSE;
  1775. }
  1776. }
  1777. BOOL
  1778. WINAPI
  1779. LocalCredRenameW (
  1780. IN LPCWSTR OldTargetName,
  1781. IN LPCWSTR NewTargetName,
  1782. IN DWORD Type,
  1783. IN DWORD Flags
  1784. )
  1785. {
  1786. if ( bCredMgrAvailable && pfnCredRenameW != NULL )
  1787. {
  1788. return pfnCredRenameW ( OldTargetName, NewTargetName, Type, Flags );
  1789. }
  1790. else
  1791. {
  1792. return FALSE;
  1793. }
  1794. }
  1795. BOOL
  1796. WINAPI
  1797. LocalCredGetTargetInfoW (
  1798. IN LPCWSTR TargetName,
  1799. IN DWORD Flags,
  1800. OUT PCREDENTIAL_TARGET_INFORMATIONW *TargetInfo
  1801. )
  1802. {
  1803. if ( bCredMgrAvailable && pfnCredGetTargetInfoW != NULL )
  1804. {
  1805. return pfnCredGetTargetInfoW ( TargetName, Flags, TargetInfo);
  1806. }
  1807. else
  1808. {
  1809. return FALSE;
  1810. }
  1811. }
  1812. BOOL
  1813. WINAPI
  1814. LocalCredMarshalCredentialW(
  1815. IN CRED_MARSHAL_TYPE CredType,
  1816. IN PVOID Credential,
  1817. OUT LPWSTR *MarshaledCredential
  1818. )
  1819. {
  1820. if ( bCredMgrAvailable && pfnCredMarshalCredentialW != NULL )
  1821. {
  1822. return pfnCredMarshalCredentialW ( CredType, Credential, MarshaledCredential );
  1823. }
  1824. else
  1825. {
  1826. return FALSE;
  1827. }
  1828. }
  1829. BOOL
  1830. WINAPI
  1831. LocalCredUnmarshalCredentialW(
  1832. IN LPCWSTR MarshaledCredential,
  1833. OUT PCRED_MARSHAL_TYPE CredType,
  1834. OUT PVOID *Credential
  1835. )
  1836. {
  1837. if ( bCredMgrAvailable && pfnCredUnMarshalCredentialW != NULL )
  1838. {
  1839. return pfnCredUnMarshalCredentialW ( MarshaledCredential, CredType, Credential );
  1840. }
  1841. else
  1842. {
  1843. return FALSE;
  1844. }
  1845. }
  1846. BOOL
  1847. WINAPI
  1848. LocalCredIsMarshaledCredentialW(
  1849. IN LPCWSTR MarshaledCredential
  1850. )
  1851. {
  1852. if ( bCredMgrAvailable && pfnCredIsMarshaledCredentialW != NULL )
  1853. {
  1854. return pfnCredIsMarshaledCredentialW ( MarshaledCredential );
  1855. }
  1856. else
  1857. {
  1858. return FALSE;
  1859. }
  1860. }
  1861. BOOL
  1862. WINAPI
  1863. LocalCredIsMarshaledCredentialA(
  1864. IN LPCSTR MarshaledCredential
  1865. )
  1866. {
  1867. if ( bCredMgrAvailable && pfnCredIsMarshaledCredentialA != NULL )
  1868. {
  1869. return pfnCredIsMarshaledCredentialA ( MarshaledCredential );
  1870. }
  1871. else
  1872. {
  1873. return FALSE;
  1874. }
  1875. }
  1876. BOOL
  1877. WINAPI
  1878. LocalCredGetSessionTypes (
  1879. IN DWORD MaximumPersistCount,
  1880. OUT LPDWORD MaximumPersist
  1881. )
  1882. {
  1883. if ( bCredMgrAvailable && pfnCredGetSessionTypes != NULL )
  1884. {
  1885. return pfnCredGetSessionTypes ( MaximumPersistCount, MaximumPersist );
  1886. }
  1887. else
  1888. {
  1889. return FALSE;
  1890. }
  1891. }
  1892. VOID
  1893. WINAPI
  1894. LocalCredFree (
  1895. IN PVOID Buffer
  1896. )
  1897. {
  1898. if ( bCredMgrAvailable && pfnCredFree != NULL )
  1899. {
  1900. pfnCredFree ( Buffer );
  1901. }
  1902. else
  1903. {
  1904. }
  1905. }
  1906. VOID
  1907. CredPutStdout(
  1908. IN LPWSTR String
  1909. )
  1910. /*++
  1911. Routine Description:
  1912. Output a string to stdout in the Console code page
  1913. We can't use fputws since it uses the wrong code page.
  1914. Arguments:
  1915. String - String to output
  1916. Return Values:
  1917. None.
  1918. --*/
  1919. {
  1920. int size;
  1921. LPSTR Buffer = NULL;
  1922. DWORD dwcc = 0; // char count
  1923. DWORD dwWritten = 0; // chars actually sent
  1924. BOOL fIsConsole = TRUE; // default - tested and set
  1925. HANDLE hC = GetStdHandle(STD_OUTPUT_HANDLE); // std output device handle
  1926. if (INVALID_HANDLE_VALUE == hC) return;
  1927. if (String == NULL) return; // done if no string
  1928. DWORD ft = GetFileType(hC);
  1929. ft &= ~FILE_TYPE_REMOTE;
  1930. fIsConsole = (ft == FILE_TYPE_CHAR);
  1931. dwcc = wcslen(String);
  1932. if (fIsConsole)
  1933. {
  1934. WriteConsole(hC,String,dwcc,&dwWritten,NULL);
  1935. return;
  1936. }
  1937. // Handle non-console output routing
  1938. //
  1939. // Compute the size of the converted string
  1940. //
  1941. size = WideCharToMultiByte( GetConsoleOutputCP(),
  1942. 0,
  1943. String,
  1944. -1,
  1945. NULL,
  1946. 0,
  1947. NULL,
  1948. NULL );
  1949. if ( size == 0 ) {
  1950. return;
  1951. }
  1952. //
  1953. // Allocate a buffer for it
  1954. //
  1955. __try {
  1956. Buffer = static_cast<LPSTR>( alloca(size) );
  1957. }
  1958. __except ( ( GetExceptionCode() == EXCEPTION_STACK_OVERFLOW ) ?
  1959. EXCEPTION_EXECUTE_HANDLER :
  1960. EXCEPTION_CONTINUE_SEARCH )
  1961. {
  1962. _resetstkoflw();
  1963. Buffer = NULL;
  1964. }
  1965. if ( Buffer == NULL) {
  1966. return;
  1967. }
  1968. //
  1969. // Convert the string to the console code page
  1970. //
  1971. size = WideCharToMultiByte( GetConsoleOutputCP(),
  1972. 0,
  1973. String,
  1974. -1,
  1975. Buffer,
  1976. size,
  1977. NULL,
  1978. NULL );
  1979. if ( size == 0 ) {
  1980. return;
  1981. }
  1982. //
  1983. // Write the string to stdout
  1984. //
  1985. //fputs( Buffer, stdout );
  1986. WriteFile(hC,Buffer,size,&dwWritten,NULL);
  1987. }
  1988. /*** GetPasswdStr -- read in password string
  1989. *
  1990. * DWORD GetPasswdStr(char far *, USHORT);
  1991. *
  1992. * ENTRY: buf buffer to put string in
  1993. * buflen size of buffer
  1994. * &len address of USHORT to place length in
  1995. *
  1996. * RETURNS:
  1997. * 0 or NERR_BufTooSmall if user typed too much. Buffer
  1998. * contents are only valid on 0 return.
  1999. *
  2000. * History:
  2001. * who when what
  2002. * erichn 5/10/89 initial code
  2003. * dannygl 5/28/89 modified DBCS usage
  2004. * erichn 7/04/89 handles backspaces
  2005. * danhi 4/16/91 32 bit version for NT
  2006. * cliffv 3/12/01 Stolen from netcmd
  2007. */
  2008. #define CR 0xD
  2009. #define BACKSPACE 0x8
  2010. DWORD
  2011. GetPasswdStr(
  2012. LPWSTR buf,
  2013. DWORD buflen,
  2014. PDWORD len
  2015. )
  2016. {
  2017. WCHAR ch;
  2018. WCHAR *bufPtr = buf;
  2019. DWORD c;
  2020. DWORD err;
  2021. DWORD mode;
  2022. buflen -= 1; /* make space for null terminator */
  2023. *len = 0; /* GP fault probe (a la API's) */
  2024. //
  2025. // Init mode in case GetConsoleMode() fails
  2026. //
  2027. mode = ENABLE_LINE_INPUT | ENABLE_ECHO_INPUT | ENABLE_PROCESSED_INPUT |
  2028. ENABLE_MOUSE_INPUT;
  2029. GetConsoleMode(GetStdHandle(STD_INPUT_HANDLE), &mode);
  2030. SetConsoleMode(GetStdHandle(STD_INPUT_HANDLE),
  2031. (~(ENABLE_ECHO_INPUT|ENABLE_LINE_INPUT)) & mode);
  2032. while (TRUE) {
  2033. err = ReadConsole(GetStdHandle(STD_INPUT_HANDLE), &ch, 1, &c, 0);
  2034. if (!err || c != 1) {
  2035. ch = 0xffff;
  2036. }
  2037. if ((ch == CR) || (ch == 0xffff)) /* end of the line */
  2038. {
  2039. break;
  2040. }
  2041. if (ch == BACKSPACE) /* back up one or two */
  2042. {
  2043. /*
  2044. * IF bufPtr == buf then the next two lines are
  2045. * a no op.
  2046. */
  2047. if (bufPtr != buf)
  2048. {
  2049. bufPtr--;
  2050. (*len)--;
  2051. }
  2052. }
  2053. else
  2054. {
  2055. *bufPtr = ch;
  2056. if (*len < buflen)
  2057. bufPtr++ ; /* don't overflow buf */
  2058. (*len)++; /* always increment len */
  2059. }
  2060. }
  2061. SetConsoleMode(GetStdHandle(STD_INPUT_HANDLE), mode);
  2062. *bufPtr = '\0'; /* null terminate the string */
  2063. putchar( '\n' );
  2064. return ((*len <= buflen) ? 0 : NERR_BufTooSmall);
  2065. }
  2066. /*** GetString -- read in string with echo
  2067. *
  2068. * DWORD GetString(char far *, USHORT, USHORT far *, char far *);
  2069. *
  2070. * ENTRY: buf buffer to put string in
  2071. * buflen size of buffer
  2072. * &len address of USHORT to place length in
  2073. *
  2074. * RETURNS:
  2075. * 0 or NERR_BufTooSmall if user typed too much. Buffer
  2076. * contents are only valid on 0 return. Len is ALWAYS valid.
  2077. *
  2078. * OTHER EFFECTS:
  2079. * len is set to hold number of bytes typed, regardless of
  2080. * buffer length.
  2081. *
  2082. * Read in a string a character at a time. Is aware of DBCS.
  2083. *
  2084. * History:
  2085. * who when what
  2086. * erichn 5/11/89 initial code
  2087. * dannygl 5/28/89 modified DBCS usage
  2088. * danhi 3/20/91 ported to 32 bits
  2089. * cliffv 3/12/01 Stolen from netcmd
  2090. */
  2091. DWORD
  2092. GetString(
  2093. LPWSTR buf,
  2094. DWORD buflen,
  2095. PDWORD len
  2096. )
  2097. {
  2098. DWORD c;
  2099. DWORD err;
  2100. buflen -= 1; /* make space for null terminator */
  2101. *len = 0; /* GP fault probe (a la API's) */
  2102. while (TRUE) {
  2103. err = ReadConsole(GetStdHandle(STD_INPUT_HANDLE), buf, 1, &c, 0);
  2104. if (!err || c != 1) {
  2105. *buf = 0xffff;
  2106. }
  2107. if (*buf == (WCHAR)EOF) {
  2108. break;
  2109. }
  2110. if (*buf == '\r' || *buf == '\n' ) {
  2111. INPUT_RECORD ir;
  2112. DWORD cr;
  2113. if (PeekConsoleInput(GetStdHandle(STD_INPUT_HANDLE), &ir, 1, &cr)) {
  2114. ReadConsole(GetStdHandle(STD_INPUT_HANDLE), buf, 1, &c, 0);
  2115. }
  2116. break;
  2117. }
  2118. buf += (*len < buflen) ? 1 : 0; /* don't overflow buf */
  2119. (*len)++; /* always increment len */
  2120. }
  2121. *buf = '\0'; /* null terminate the string */
  2122. return ((*len <= buflen) ? 0 : NERR_BufTooSmall);
  2123. }
  2124. VOID
  2125. CredGetStdin(
  2126. OUT LPWSTR Buffer,
  2127. IN DWORD BufferMaxChars,
  2128. IN BOOLEAN EchoChars
  2129. )
  2130. /*++
  2131. Routine Description:
  2132. Input a string from stdin in the Console code page.
  2133. We can't use fgetws since it uses the wrong code page.
  2134. Arguments:
  2135. Buffer - Buffer to put the read string into.
  2136. The Buffer will be zero terminated and will have any traing CR/LF removed
  2137. BufferMaxChars - Maximum number of characters to return in the buffer not including
  2138. the trailing NULL.
  2139. EchoChars - TRUE if the typed characters are to be echoed.
  2140. FALSE if not.
  2141. Return Values:
  2142. None.
  2143. --*/
  2144. {
  2145. DWORD NetStatus;
  2146. DWORD Length;
  2147. if ( EchoChars ) {
  2148. NetStatus = GetString( Buffer,
  2149. BufferMaxChars+1,
  2150. &Length );
  2151. } else {
  2152. NetStatus = GetPasswdStr( Buffer,
  2153. BufferMaxChars+1,
  2154. &Length );
  2155. }
  2156. if ( NetStatus == NERR_BufTooSmall ) {
  2157. Buffer[0] = '\0';
  2158. }
  2159. }
  2160. BOOLEAN
  2161. CredpValidateDnsString(
  2162. IN OUT LPWSTR String OPTIONAL,
  2163. IN DNS_NAME_FORMAT DnsNameFormat,
  2164. OUT PULONG StringSize
  2165. )
  2166. /*++
  2167. Routine Description:
  2168. This routine validates a passed in string. The string must be a valid DNS name.
  2169. Any trailing . is truncated.
  2170. Arguments:
  2171. String - String to validate
  2172. Any trailing . is truncated.
  2173. This field is only modified if the routine returns TRUE.
  2174. DnsNameFormat - Expected format of the name.
  2175. StringSize - Returns the length of the string (in bytes) including the
  2176. trailing zero character.
  2177. This field is only updated if the routine returns TRUE.
  2178. Return Values:
  2179. TRUE - String is valid.
  2180. FALSE - String is not valid.
  2181. --*/
  2182. {
  2183. ULONG TempStringLen;
  2184. if ( String == NULL ) {
  2185. return FALSE;
  2186. }
  2187. TempStringLen = wcslen( String );
  2188. if ( TempStringLen == 0 ) {
  2189. return FALSE;
  2190. } else {
  2191. //
  2192. // Remove the trailing .
  2193. //
  2194. if ( String[TempStringLen-1] == L'.' ) {
  2195. TempStringLen -= 1;
  2196. //
  2197. // Ensure the string isn't empty now.
  2198. //
  2199. if ( TempStringLen == 0 ) {
  2200. return FALSE;
  2201. //
  2202. // Ensure there aren't multiple trailing .'s
  2203. //
  2204. } else {
  2205. if ( String[TempStringLen-1] == L'.' ) {
  2206. return FALSE;
  2207. }
  2208. }
  2209. }
  2210. //
  2211. // Have DNS finish the validation
  2212. //
  2213. if ( TempStringLen != 0 ) {
  2214. DWORD WinStatus;
  2215. WinStatus = DnsValidateName_W( String, DnsNameFormat );
  2216. if ( WinStatus != NO_ERROR &&
  2217. WinStatus != DNS_ERROR_NON_RFC_NAME ) {
  2218. //
  2219. // The RFC says hostnames cannot have numeric leftmost labels.
  2220. // However, Win 2K servers have such hostnames.
  2221. // So, allow them here forever more.
  2222. //
  2223. if ( DnsNameFormat == DnsNameHostnameFull &&
  2224. WinStatus == DNS_ERROR_NUMERIC_NAME ) {
  2225. /* Drop through */
  2226. } else {
  2227. return FALSE;
  2228. }
  2229. }
  2230. }
  2231. }
  2232. if ( TempStringLen > DNS_MAX_NAME_LENGTH ) {
  2233. return FALSE;
  2234. }
  2235. String[TempStringLen] = L'\0';
  2236. *StringSize = (TempStringLen + 1) * sizeof(WCHAR);
  2237. return TRUE;
  2238. }
  2239. DWORD
  2240. CredUIParseUserNameWithType(
  2241. CONST WCHAR *UserName,
  2242. WCHAR *user,
  2243. ULONG userBufferSize,
  2244. WCHAR *domain,
  2245. ULONG domainBufferSize,
  2246. PCREDUI_USERNAME_TYPE UsernameType
  2247. )
  2248. /*++
  2249. Routine Description:
  2250. Same as CredUIParseUserNameW except it returns an enum defining which username
  2251. syntax was found.
  2252. Arguments:
  2253. UserName - The user name to be parsed.
  2254. user - Specifies a buffer to copy the user name portion of the parsed string to.
  2255. userBufferSize - Specifies the size of the 'user' array in characters.
  2256. The caller can ensure the passed in array is large enough by using an array
  2257. that is CRED_MAX_USERNAME_LENGTH+1 characters long or by passing in an array that
  2258. is wcslen(UserName)+1 characters long.
  2259. domain - Specifies a buffer to copy the domain name portion of the parsed string to.
  2260. domainBufferSize - Specifies the size of the 'domain' array in characters.
  2261. The caller can ensure the passed in array is large enough by using an array
  2262. that is CRED_MAX_USERNAME_LENGTH+1 characters long or by passing in an array that
  2263. is wcslen(UserName)+1 characters long.
  2264. Return Values:
  2265. The following status codes may be returned:
  2266. ERROR_INVALID_ACCOUNT_NAME - The user name is not valid.
  2267. ERROR_INVALID_PARAMETER - One of the parameters is invalid.
  2268. ERROR_INSUFFICIENT_BUFFER - One of the buffers is too small.
  2269. --*/
  2270. {
  2271. DWORD Status;
  2272. ULONG UserNameLength;
  2273. LPWSTR LocalUserName = NULL;
  2274. LPWSTR SlashPointer;
  2275. LPWSTR AtPointer;
  2276. ULONG LocalStringSize;
  2277. LPCWSTR UserNameToCopy = NULL;
  2278. LPCWSTR DomainNameToCopy = NULL;
  2279. //
  2280. // Validate the input parameters
  2281. //
  2282. if ( UserName == NULL ||
  2283. user == NULL ||
  2284. domain == NULL ||
  2285. userBufferSize == 0 ||
  2286. domainBufferSize == 0 ) {
  2287. return ERROR_INVALID_PARAMETER;
  2288. }
  2289. user[0] = L'\0';
  2290. domain[0] = L'\0';
  2291. //
  2292. // Compute the length of the UserName
  2293. //
  2294. UserNameLength = wcslen ( UserName );
  2295. if ( UserNameLength > CRED_MAX_USERNAME_LENGTH ) {
  2296. return ERROR_INVALID_ACCOUNT_NAME;
  2297. }
  2298. //
  2299. // If this is a marshalled credential reference,
  2300. // just copy the entire string as the username.
  2301. // Set the domain name to an empty string.
  2302. //
  2303. if (LocalCredIsMarshaledCredentialW( UserName)) {
  2304. UserNameToCopy = UserName;
  2305. *UsernameType = CreduiMarshalledUsername;
  2306. Status = NO_ERROR;
  2307. goto Cleanup;
  2308. }
  2309. //
  2310. // Grab a local writable copy of the string.
  2311. //
  2312. LocalUserName = (LPWSTR) LocalAlloc( 0, (UserNameLength+1)*sizeof(WCHAR) );
  2313. if ( LocalUserName == NULL ) {
  2314. Status = ERROR_NOT_ENOUGH_MEMORY;
  2315. goto Cleanup;
  2316. }
  2317. RtlCopyMemory( LocalUserName, UserName, (UserNameLength+1)*sizeof(WCHAR) );
  2318. //
  2319. // Classify the input account name.
  2320. //
  2321. // The name is considered to be <DomainName>\<UserName> if the string
  2322. // contains an \.
  2323. //
  2324. SlashPointer = wcsrchr( LocalUserName, L'\\' );
  2325. if ( SlashPointer != NULL ) {
  2326. LPWSTR LocalUserNameEnd;
  2327. LPWSTR AfterSlashPointer;
  2328. //
  2329. // Skip the backslash
  2330. //
  2331. *SlashPointer = L'\0';
  2332. AfterSlashPointer = SlashPointer + 1;
  2333. //
  2334. // Ensure the string to the left of the \ is a valid domain name
  2335. //
  2336. // (Do DNS name first to allow the name to be canonicalized.)
  2337. if ( !CredpValidateDnsString( LocalUserName, DnsNameDomain, &LocalStringSize ) &&
  2338. !NetpIsDomainNameValid( LocalUserName ) ) {
  2339. Status = ERROR_INVALID_ACCOUNT_NAME;
  2340. goto Cleanup;
  2341. }
  2342. //
  2343. // Ensure the string to the right of the \ is a valid user name
  2344. //
  2345. if ( !NetpIsUserNameValid( AfterSlashPointer )) {
  2346. Status = ERROR_INVALID_ACCOUNT_NAME;
  2347. goto Cleanup;
  2348. }
  2349. //
  2350. // Copy the user name and domain name back to the caller.
  2351. //
  2352. UserNameToCopy = AfterSlashPointer;
  2353. DomainNameToCopy = LocalUserName;
  2354. *UsernameType = CreduiAbsoluteUsername;
  2355. Status = NO_ERROR;
  2356. goto Cleanup;
  2357. }
  2358. //
  2359. // A UPN has the syntax <AccountName>@<DnsDomainName>.
  2360. // If there are multiple @ signs,
  2361. // use the last one since an AccountName can have an @ in it.
  2362. //
  2363. //
  2364. AtPointer = wcsrchr( LocalUserName, L'@' );
  2365. if ( AtPointer != NULL ) {
  2366. //
  2367. // The string to the left of the @ can really have any syntax.
  2368. // But must be non-null.
  2369. //
  2370. if ( AtPointer == LocalUserName ) {
  2371. Status = ERROR_INVALID_ACCOUNT_NAME;
  2372. goto Cleanup;
  2373. }
  2374. //
  2375. // Ensure the string to the right of the @ is a DNS domain name
  2376. //
  2377. AtPointer ++;
  2378. if ( !CredpValidateDnsString( AtPointer, DnsNameDomain, &LocalStringSize ) ) {
  2379. Status = ERROR_INVALID_ACCOUNT_NAME;
  2380. goto Cleanup;
  2381. }
  2382. //
  2383. // Return the entire UPN in the username field
  2384. //
  2385. UserNameToCopy = UserName;
  2386. *UsernameType = CreduiUpn;
  2387. Status = NO_ERROR;
  2388. goto Cleanup;
  2389. }
  2390. //
  2391. // Finally, check to see it it is an unqualified user name
  2392. //
  2393. if ( NetpIsUserNameValid( LocalUserName )) {
  2394. UserNameToCopy = UserName;
  2395. *UsernameType = CreduiRelativeUsername;
  2396. Status = NO_ERROR;
  2397. goto Cleanup;
  2398. }
  2399. //
  2400. // All other values are invalid
  2401. //
  2402. Status = ERROR_INVALID_ACCOUNT_NAME;
  2403. //
  2404. // Cleanup
  2405. //
  2406. Cleanup:
  2407. //
  2408. // On Success,
  2409. // copy the names back to the caller.
  2410. //
  2411. if ( Status == NO_ERROR ) {
  2412. ULONG Length;
  2413. //
  2414. // Copy the user name back to the caller.
  2415. //
  2416. if (FAILED(StringCchCopyExW(
  2417. user,
  2418. userBufferSize,
  2419. UserNameToCopy,
  2420. NULL,
  2421. NULL,
  2422. STRSAFE_NULL_ON_FAILURE)))
  2423. {
  2424. Status = ERROR_INSUFFICIENT_BUFFER;
  2425. }
  2426. //
  2427. // Copy the domain name back to the caller
  2428. //
  2429. if ( Status == NO_ERROR && DomainNameToCopy != NULL ) {
  2430. //
  2431. // Copy the user name back to the caller.
  2432. //
  2433. if (FAILED(StringCchCopyExW(
  2434. domain,
  2435. domainBufferSize,
  2436. DomainNameToCopy,
  2437. NULL,
  2438. NULL,
  2439. STRSAFE_NULL_ON_FAILURE)))
  2440. {
  2441. Status = ERROR_INSUFFICIENT_BUFFER;
  2442. }
  2443. }
  2444. }
  2445. LocalFree( LocalUserName );
  2446. return Status;
  2447. }
  2448. LPWSTR
  2449. GetAccountDomainName(
  2450. VOID
  2451. )
  2452. /*++
  2453. Routine Description:
  2454. Returns the name of the account domain for this machine.
  2455. For workstatations, the account domain is the netbios computer name.
  2456. For DCs, the account domain is the netbios domain name.
  2457. Arguments:
  2458. None.
  2459. Return Values:
  2460. Returns a pointer to the name. The name should be free using NetApiBufferFree.
  2461. NULL - on error.
  2462. --*/
  2463. {
  2464. DWORD WinStatus;
  2465. LPWSTR AllocatedName = NULL;
  2466. //
  2467. // If this machine is a domain controller,
  2468. // get the domain name.
  2469. //
  2470. if ( CreduiIsDomainController ) {
  2471. WinStatus = NetpGetDomainName( &AllocatedName );
  2472. if ( WinStatus != NO_ERROR ) {
  2473. return NULL;
  2474. }
  2475. //
  2476. // Otherwise, the 'account domain' is the computername
  2477. //
  2478. } else {
  2479. WinStatus = NetpGetComputerName( &AllocatedName );
  2480. if ( WinStatus != NO_ERROR ) {
  2481. return NULL;
  2482. }
  2483. }
  2484. return AllocatedName;
  2485. }
  2486. BOOL
  2487. CompleteUserName(
  2488. IN OUT LPWSTR UserName,
  2489. IN ULONG UserNameMaxChars,
  2490. IN PCREDENTIAL_TARGET_INFORMATIONW TargetInfo OPTIONAL,
  2491. IN LPWSTR TargetName OPTIONAL,
  2492. IN DWORD Flags
  2493. )
  2494. /*++
  2495. Routine Description:
  2496. Searches the user name for a domain name, and determines whether this
  2497. specifies the target server or a domain. If a domain is not present in the
  2498. user name, add it if this is a workstation or no target information is
  2499. available.
  2500. Arguments:
  2501. UserName - The username to modify. The buffer is modified in place.
  2502. UserNameMaxChars - Size (in chars) of the UserName buffer not including space for the
  2503. trailing NULL.
  2504. The input string may be shorter than this.
  2505. TargetInfo - The TargetInfo describing the target these credentials are for.
  2506. If not specified, the Target info will not be used to contruct the domain name.
  2507. TargetName - The user supplied target name describing the target these credentials are for.
  2508. Flags - As passed to CredUIPromptForCredentials()
  2509. Return Values:
  2510. Returns TRUE if a domain was already present in the user name, or if we
  2511. added one. Otherwise, return FALSE.
  2512. --*/
  2513. {
  2514. BOOLEAN RetVal;
  2515. DWORD WinStatus;
  2516. WCHAR RetUserName[CRED_MAX_USERNAME_LENGTH + 1];
  2517. WCHAR RetDomainName[CRED_MAX_USERNAME_LENGTH + 1];
  2518. WCHAR LogonDomainName[CRED_MAX_USERNAME_LENGTH + 1];
  2519. CREDUI_USERNAME_TYPE UsernameType;
  2520. LPWSTR AllocatedName = NULL;
  2521. WCHAR *serverName = NULL;
  2522. if ((Flags & CREDUI_FLAGS_GENERIC_CREDENTIALS) &&
  2523. !(Flags & CREDUI_FLAGS_COMPLETE_USERNAME)) return FALSE;
  2524. //
  2525. // Determine the type and validity of the user name
  2526. //
  2527. WinStatus = CredUIParseUserNameWithType(
  2528. UserName,
  2529. RetUserName,
  2530. CRED_MAX_USERNAME_LENGTH + 1,
  2531. RetDomainName,
  2532. CRED_MAX_USERNAME_LENGTH + 1,
  2533. &UsernameType );
  2534. if ( WinStatus != NO_ERROR ) {
  2535. RetVal = FALSE;
  2536. goto Cleanup;
  2537. }
  2538. //
  2539. // Most Types don't need to be completed
  2540. //
  2541. if ( UsernameType != CreduiRelativeUsername ) {
  2542. RetVal = TRUE;
  2543. goto Cleanup;
  2544. }
  2545. //
  2546. // If we have target info,
  2547. // Use the information from the TargetInfo to qualify the username.
  2548. //
  2549. if (TargetInfo != NULL) {
  2550. //
  2551. // See if the target system claims to be a standalone system.
  2552. // In which case we just fill in the server name for the domain since
  2553. // all accounts valid for the system
  2554. if ( TargetInfo->DnsTreeName != NULL ||
  2555. TargetInfo->DnsDomainName != NULL ||
  2556. TargetInfo->NetbiosDomainName != NULL ||
  2557. (TargetInfo->Flags & CRED_TI_SERVER_FORMAT_UNKNOWN) != 0
  2558. ) {
  2559. // The target info contains domain information, so this is probably
  2560. // not a standalone server; the user should enter the domain name:
  2561. // gm: But we will prepend the user's logon domain name...
  2562. ULONG ulSize = CRED_MAX_USERNAME_LENGTH;
  2563. if (GetUserNameEx(NameSamCompatible,LogonDomainName,&ulSize))
  2564. {
  2565. WCHAR *pwc=wcschr(LogonDomainName, L'\\');
  2566. if (NULL != pwc)
  2567. {
  2568. *pwc = '\0'; // term username at logon domain name only
  2569. serverName = LogonDomainName;
  2570. }
  2571. }
  2572. else
  2573. {
  2574. RetVal = FALSE;
  2575. goto Cleanup;
  2576. }
  2577. }
  2578. else
  2579. {
  2580. if (TargetInfo->NetbiosServerName) {
  2581. serverName = TargetInfo->NetbiosServerName;
  2582. } else {
  2583. serverName = TargetName;
  2584. }
  2585. }
  2586. }
  2587. else if ( (TargetName != NULL) &&
  2588. !CreduiIsWildcardTargetName(TargetName) &&
  2589. !(Flags & CREDUI_FLAGS_USERNAME_TARGET_CREDENTIALS) )
  2590. {
  2591. // No target information, but this is not a wildcard target name, so
  2592. // use this as the domain for the user name:
  2593. serverName = TargetName;
  2594. //
  2595. // There is no target.
  2596. // therefore, the target must be the local machine.
  2597. // Use the 'account domain' of the local machine.
  2598. } else {
  2599. AllocatedName = GetAccountDomainName();
  2600. serverName = AllocatedName;
  2601. }
  2602. //
  2603. // If no name was found,
  2604. // we're done.
  2605. //
  2606. if (serverName == NULL) {
  2607. RetVal = FALSE;
  2608. goto Cleanup;
  2609. }
  2610. //
  2611. // Append the found name
  2612. //
  2613. WCHAR *where;
  2614. ULONG userNameLength = wcslen(UserName);
  2615. ULONG serverLength = wcslen(serverName);
  2616. if ((userNameLength == 0 ) ||
  2617. (userNameLength + serverLength + 1) > UserNameMaxChars)
  2618. {
  2619. RetVal = FALSE;
  2620. goto Cleanup;
  2621. }
  2622. WCHAR *source = UserName + userNameLength + 1;
  2623. where = source + serverLength;
  2624. while (source > UserName)
  2625. {
  2626. *where-- = *--source;
  2627. }
  2628. StringCchCopyW(UserName, UserNameMaxChars, serverName);
  2629. *where = L'\\';
  2630. RetVal = TRUE;
  2631. Cleanup:
  2632. if ( AllocatedName != NULL ) {
  2633. NetApiBufferFree ( AllocatedName );
  2634. }
  2635. return RetVal;
  2636. }
  2637. // returns TRUE if the wizard was sucessfull, FALSE if not and a dialog should be popped
  2638. BOOL TryLauchRegWizard (
  2639. SSOPACKAGE* pSSOPackage,
  2640. HWND hwndParent,
  2641. BOOL HasLogonSession,
  2642. WCHAR *userName,
  2643. ULONG userNameMaxChars,
  2644. WCHAR *password,
  2645. ULONG passwordMaxChars,
  2646. DWORD* pResult
  2647. )
  2648. {
  2649. BOOL bDoPasswordDialog = TRUE;
  2650. if ( pSSOPackage == NULL )
  2651. {
  2652. return TRUE;
  2653. }
  2654. if ( pResult == NULL )
  2655. {
  2656. return TRUE;
  2657. }
  2658. *pResult = ERROR_CANCELLED;
  2659. IModalWindow* pPPWizModalWindow;
  2660. // launch wizard, if one is registered
  2661. if ( pSSOPackage->pRegistrationWizard != NULL )
  2662. {
  2663. gbStoredSSOCreds = FALSE;
  2664. HRESULT hr = CoCreateInstance ( *(pSSOPackage->pRegistrationWizard), NULL, CLSCTX_INPROC_SERVER,
  2665. IID_IModalWindow, (LPVOID*)&pPPWizModalWindow );
  2666. if ( FAILED(hr) || pPPWizModalWindow == NULL )
  2667. {
  2668. bDoPasswordDialog = TRUE;
  2669. }
  2670. else
  2671. {
  2672. // check to see if we have a logon session to do passport creds
  2673. if ( !HasLogonSession )
  2674. {
  2675. if ( gbWaitingForSSOCreds )
  2676. {
  2677. // can't re-enter this section of code, just do the dialog
  2678. bDoPasswordDialog = TRUE;
  2679. }
  2680. else
  2681. {
  2682. gbWaitingForSSOCreds = TRUE;
  2683. bDoPasswordDialog = FALSE;
  2684. SecureZeroMemory(gszSSOUserName, sizeof gszSSOUserName);
  2685. SecureZeroMemory(gszSSOPassword, sizeof gszSSOPassword);
  2686. }
  2687. }
  2688. else
  2689. {
  2690. bDoPasswordDialog = FALSE;
  2691. }
  2692. if ( bDoPasswordDialog == FALSE )
  2693. {
  2694. // try the wizard
  2695. pPPWizModalWindow->Show(hwndParent);
  2696. // check to see if it's been set
  2697. if ( HasLogonSession )
  2698. {
  2699. // look in credmgr
  2700. if ( gbStoredSSOCreds ) //CheckForSSOCred( NULL ) )
  2701. {
  2702. *pResult = ERROR_SUCCESS;
  2703. }
  2704. else
  2705. {
  2706. *pResult = ERROR_CANCELLED;
  2707. }
  2708. // copy them to user-supplied input
  2709. if ( userName != NULL && password != NULL )
  2710. {
  2711. StringCchCopyW(userName, userNameMaxChars, gszSSOUserName);
  2712. StringCchCopyW(password, passwordMaxChars, gszSSOPassword);
  2713. }
  2714. }
  2715. else
  2716. {
  2717. // look to see if it was squirreled away
  2718. if ( wcslen (gszSSOUserName) > 0 )
  2719. {
  2720. *pResult = ERROR_SUCCESS;
  2721. // copy them to user-supplied input
  2722. if ( userName != NULL && password != NULL )
  2723. {
  2724. StringCchCopyW(userName, userNameMaxChars, gszSSOUserName);
  2725. StringCchCopyW(password, passwordMaxChars, gszSSOPassword);
  2726. }
  2727. else
  2728. {
  2729. // can't do anything, return appropriate error to indicate no credmgr
  2730. *pResult = ERROR_NO_SUCH_LOGON_SESSION;
  2731. }
  2732. }
  2733. else
  2734. {
  2735. *pResult = ERROR_CANCELLED;
  2736. }
  2737. gbWaitingForSSOCreds = FALSE;
  2738. }
  2739. // zero out global strings
  2740. SecureZeroMemory(gszSSOUserName, sizeof gszSSOUserName);
  2741. SecureZeroMemory(gszSSOPassword, sizeof gszSSOPassword);
  2742. }
  2743. }
  2744. }
  2745. return !bDoPasswordDialog;
  2746. }