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.

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