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.

642 lines
29 KiB

  1. #include <windows.h>
  2. #define SECURITY_WIN32
  3. #include <sspi.h>
  4. #include <issperr.h>
  5. #include <security.h>
  6. #define SSP_SPM_NT_DLL "security.dll"
  7. #define SSP_SPM_WIN95_DLL "secur32.dll"
  8. struct DIGEST_PKG_DATA
  9. {
  10. LPSTR szAppCtx;
  11. LPSTR szUserCtx;
  12. };
  13. #define SIG_DIGEST 'HTUA'
  14. DIGEST_PKG_DATA PkgData;
  15. SEC_WINNT_AUTH_IDENTITY_EXA SecIdExA;
  16. PSecurityFunctionTable g_pFuncTbl = NULL;
  17. HINSTANCE hSecLib;
  18. //----------------------------------------------------------------------------
  19. // InitializeSecurityInterface
  20. //----------------------------------------------------------------------------
  21. VOID InitializeSecurityInterface(BOOL fDirect)
  22. {
  23. INIT_SECURITY_INTERFACE addrProcISI = NULL;
  24. OSVERSIONINFO VerInfo;
  25. CHAR szDLL[MAX_PATH];
  26. if (!fDirect)
  27. {
  28. VerInfo.dwOSVersionInfoSize = sizeof (OSVERSIONINFO);
  29. GetVersionEx (&VerInfo);
  30. if (VerInfo.dwPlatformId == VER_PLATFORM_WIN32_NT)
  31. {
  32. lstrcpy (szDLL, SSP_SPM_NT_DLL);
  33. }
  34. else if (VerInfo.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS)
  35. {
  36. lstrcpy (szDLL, SSP_SPM_WIN95_DLL);
  37. }
  38. }
  39. else
  40. {
  41. strcpy(szDLL, "digest.dll");
  42. }
  43. hSecLib = LoadLibrary (szDLL);
  44. addrProcISI = (INIT_SECURITY_INTERFACE) GetProcAddress( hSecLib,
  45. SECURITY_ENTRYPOINT_ANSI);
  46. g_pFuncTbl = (*addrProcISI)();
  47. }
  48. //----------------------------------------------------------------------------
  49. // HaveDigest
  50. //----------------------------------------------------------------------------
  51. BOOL HaveDigest()
  52. {
  53. SECURITY_STATUS ssResult;
  54. DWORD cPackages;
  55. PSecPkgInfoA pSecPkgInfo;
  56. BOOL fHaveDigest;
  57. // ***** SSPI call *****
  58. ssResult = (*(g_pFuncTbl->EnumerateSecurityPackagesA))(&cPackages, &pSecPkgInfo);
  59. // Check if we have digest.
  60. fHaveDigest = FALSE;
  61. if (ssResult == SEC_E_OK)
  62. {
  63. for (DWORD i = 0; i < cPackages; i++)
  64. {
  65. if (strcmp(pSecPkgInfo[i].Name, "Digest") == 0)
  66. {
  67. fHaveDigest = TRUE;
  68. break;
  69. }
  70. }
  71. }
  72. return fHaveDigest;
  73. }
  74. //----------------------------------------------------------------------------
  75. // LogonToDigestPkg
  76. //----------------------------------------------------------------------------
  77. SECURITY_STATUS LogonToDigestPkg(LPSTR szAppCtx, LPSTR szUserCtx, PCredHandle phCred)
  78. {
  79. SECURITY_STATUS ssResult;
  80. // Logon with szAppCtx = szUserCtx = NULL.
  81. PkgData.szAppCtx = PkgData.szUserCtx = NULL;
  82. memset(&SecIdExA, 0, sizeof(SEC_WINNT_AUTH_IDENTITY_EXA));
  83. PkgData.szAppCtx = szAppCtx;
  84. PkgData.szUserCtx = szUserCtx;
  85. SecIdExA.Version = sizeof(SEC_WINNT_AUTH_IDENTITY_EXA);
  86. SecIdExA.User = (unsigned char*) &PkgData;
  87. SecIdExA.UserLength = sizeof(DIGEST_PKG_DATA);
  88. // ***** SSPI CALL *****
  89. ssResult = (*(g_pFuncTbl->AcquireCredentialsHandleA))
  90. (NULL, // pszPrinciple NULL
  91. "Digest", // pszPackageName (Package name)
  92. SECPKG_CRED_OUTBOUND, // dwCredentialUse (Credentials aren't pulled from OS)
  93. NULL, // pvLogonID (not used)
  94. &SecIdExA, // pAuthData ptr to g_PkgData
  95. NULL, // pGetKeyFn (not used)
  96. 0, // pvGetKeyArgument (not used)
  97. phCred, // phCredential (credential returned)
  98. NULL); // PTimeStamp (not used)
  99. return ssResult;
  100. }
  101. //----------------------------------------------------------------------------
  102. // LogoffOfDigestPkg
  103. //----------------------------------------------------------------------------
  104. SECURITY_STATUS LogoffOfDigestPkg(PCredHandle phCred)
  105. {
  106. SECURITY_STATUS ssResult;
  107. // ***** SSPI CALL *****
  108. ssResult = (*(g_pFuncTbl->FreeCredentialsHandle))(phCred);
  109. return ssResult;
  110. }
  111. //----------------------------------------------------------------------------
  112. // Authenticate
  113. //----------------------------------------------------------------------------
  114. SECURITY_STATUS
  115. DoAuthenticate(PCredHandle phCred,
  116. PCtxtHandle phCtxt,
  117. PCtxtHandle phNewCtxt,
  118. DWORD fContextReq,
  119. LPSTR szHeader,
  120. LPSTR szRealm,
  121. LPSTR szHost,
  122. LPSTR szUrl,
  123. LPSTR szMethod,
  124. LPSTR szUser,
  125. LPSTR szPass,
  126. LPSTR szNonce,
  127. HWND hWnd,
  128. LPSTR szResponse)
  129. {
  130. SECURITY_STATUS ssResult;
  131. // Input buffers and descriptor.
  132. SecBuffer sbIn[10];
  133. SecBufferDesc sbdIn;
  134. sbdIn.pBuffers = sbIn;
  135. sbdIn.cBuffers = 10;
  136. sbIn[0].pvBuffer = szHeader; // Challenge header
  137. sbIn[1].pvBuffer = szRealm; // realm if preauth
  138. sbIn[2].pvBuffer = szHost; // host
  139. sbIn[3].pvBuffer = szUrl; // url
  140. sbIn[4].pvBuffer = szMethod; // http method
  141. sbIn[5].pvBuffer = szUser; // username (optional)
  142. sbIn[6].pvBuffer = szPass; // password (optional, not used currently)
  143. sbIn[7].pvBuffer = szNonce; // nonce
  144. sbIn[8].pvBuffer = NULL; // nonce count not passed in.
  145. sbIn[9].pvBuffer = &hWnd; // window handle.
  146. // Output buffer and descriptor.
  147. SecBuffer sbOut[1];
  148. SecBufferDesc sbdOut;
  149. sbdOut.pBuffers = sbOut;
  150. sbdOut.cBuffers = 1;
  151. // Set output buffer.
  152. sbOut[0].pvBuffer = szResponse;
  153. // ***** SSPI CALL *****
  154. ssResult = (*(g_pFuncTbl->InitializeSecurityContextA))
  155. (phCred, // phCredential (from AcquireCredentialsHandle)
  156. phCtxt, // phContext (NULL on first call, phNewCtxt on subsequent calls).
  157. NULL, // pszTargetName (not used)
  158. fContextReq, // fContextReq (auth from cache, prompt or auth using supplied creds)
  159. 0, // Reserved1 (not used)
  160. 0, // TargetDataRep (not used)
  161. &sbdIn, // PSecBufDesc (input buffer descriptor)
  162. 0, // Reserved2 (not used)
  163. phNewCtxt, // phNewContext (should be passed back as phCtxt on subsequent calls)
  164. &sbdOut, // pOutput (output buffer descriptor)
  165. NULL, // pfContextAttr (pfContextAttr, not used)
  166. NULL); // ptsExpiry (not used)
  167. return ssResult;
  168. }
  169. VOID PrimeCredCache(CredHandle CredHandle, LPSTR szRealm, LPSTR szUser, LPSTR szPass)
  170. {
  171. DWORD ssResult;
  172. CtxtHandle hCtxt;
  173. SecBufferDesc sbdIn;
  174. SecBuffer sbIn[3];
  175. hCtxt.dwLower = CredHandle.dwLower;
  176. hCtxt.dwUpper = CredHandle.dwUpper;
  177. sbIn[0].pvBuffer = szRealm;
  178. sbIn[0].cbBuffer = strlen(szRealm);
  179. sbIn[1].pvBuffer = szUser;
  180. sbIn[1].cbBuffer = strlen(szUser);
  181. sbIn[2].pvBuffer = szPass;
  182. sbIn[2].cbBuffer = strlen(szPass);
  183. sbdIn.cBuffers = 3;
  184. sbdIn.pBuffers = sbIn;
  185. ssResult = (*(g_pFuncTbl->ApplyControlToken))(&hCtxt, &sbdIn);
  186. }
  187. //----------------------------------------------------------------------------
  188. // main
  189. //----------------------------------------------------------------------------
  190. #ifdef UNIX
  191. #define main prog_main
  192. int main(int argc, char **argv);
  193. int WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR pszCmdLine, int nCmdShow) {
  194. extern int __argc;
  195. extern char **__argv;
  196. return main(__argc, __argv);
  197. }
  198. int main(int argc, char **argv)
  199. #else
  200. INT main()
  201. #endif
  202. {
  203. #define IDENTITY_1 "Alice"
  204. #define IDENTITY_2 "Bob"
  205. DWORD dwReturn = 0;
  206. SECURITY_STATUS ssResult;
  207. // Get (global) dispatch table.
  208. InitializeSecurityInterface(TRUE);
  209. // Check to see if we have digest.
  210. if (!HaveDigest())
  211. {
  212. dwReturn = 1;
  213. goto exit;
  214. }
  215. // Credential handle and pointer.
  216. CredHandle hCred1, hCred2, hCred3;
  217. CtxtHandle hCtxt1, hCtxt2, hCtxt3;
  218. // Three apps logon using the same keys (appctx, userctx, both NULL);
  219. // These sessions will be used for authentication.
  220. LogonToDigestPkg(NULL, IDENTITY_1, &hCred1);
  221. LogonToDigestPkg(NULL, IDENTITY_1, &hCred2);
  222. LogonToDigestPkg(NULL, IDENTITY_1, &hCred3);
  223. // Three more apps also logon using the same keys.
  224. // we will prime the password cache with credentials for these apps
  225. // and expect to be able to share the credentials via the auth dialog.
  226. CredHandle hCred4, hCred5, hCred6;
  227. LogonToDigestPkg(NULL, IDENTITY_1, &hCred4);
  228. LogonToDigestPkg(NULL, IDENTITY_1, &hCred5);
  229. LogonToDigestPkg(NULL, IDENTITY_1, &hCred6);
  230. PrimeCredCache(hCred4, "[email protected]", "Wilma", "password");
  231. PrimeCredCache(hCred5, "[email protected]", "Betty", "passwordxxxx");
  232. PrimeCredCache(hCred6, "[email protected]", "Pebbles", "passwordxxxxx");
  233. // Finally, three more apps also logon using a different logon key (identity)
  234. // we will prime the password cache with credentials for these apps
  235. // Because of the different logon key we should never see these creds.
  236. CredHandle hCred7, hCred8, hCred9;
  237. LogonToDigestPkg(NULL, IDENTITY_2, &hCred7);
  238. LogonToDigestPkg(NULL, IDENTITY_2, &hCred8);
  239. LogonToDigestPkg(NULL, IDENTITY_2, &hCred9);
  240. PrimeCredCache(hCred7, "[email protected]", "Fred", "password");
  241. PrimeCredCache(hCred8, "[email protected]", "Barney", "passwordxxxx");
  242. PrimeCredCache(hCred9, "[email protected]", "Bam Bam", "passwordxxxxxxxx");
  243. //-------------------------------------------------------------------------------------------------------------
  244. // App 1 makes a request from a server, does not have credentials and must prompt
  245. // before finally succeeding.
  246. // Challenge from server.
  247. LPSTR szChallenge;
  248. // szChallenge = "realm=\"[email protected]\", ms-message = \"foo\", ms-message-lang = \"bar\", ms-trustmark = \"baz\", stale = FALSE, qop=\"auth,auth-int\", nonce=\"dcd98b7102dd2f0e8b11d0f600bfb0c093\", opaque=\"5ccc069c403ebaf9f0171e9517f40e41\"";
  249. szChallenge = "realm=\"[email protected]\", stale = FALSE, qop=\"auth,auth-int\", nonce=\"dcd98b7102dd2f0e8b11d0f600bfb0c093\", opaque=\"5ccc069c403ebaf9f0171e9517f40e41\"";
  250. // Package will dump response into this buffer.
  251. CHAR szResponse[4096];
  252. // First try at authenticating.
  253. ssResult =
  254. DoAuthenticate( &hCred1, // Cred from logging on.
  255. NULL, // Ctxt not specified first time.
  256. &hCtxt1, // Output context.
  257. 0, // auth from cache.
  258. szChallenge, // Server challenge header.
  259. NULL, // no realm since not preauth.
  260. "www.foo.com", // Host.
  261. "/bar/baz/boz/bif.html", // Url.
  262. "GET", // Method.
  263. NULL, // no Username
  264. NULL, // no Password.
  265. NULL, // no nonce
  266. NULL, // don't need hwnd for auth.
  267. szResponse); // Response buffer.
  268. // Expect to not have credentials the first time - prompt.
  269. if (ssResult == SEC_E_NO_CREDENTIALS)
  270. {
  271. ssResult =
  272. DoAuthenticate( &hCred1, // Cred from logging on.
  273. &hCtxt1, // Ctxt from previous call
  274. &hCtxt1, // Output context (same as from previous).
  275. ISC_REQ_PROMPT_FOR_CREDS, // prompt
  276. szChallenge, // Server challenge
  277. NULL, // No realm
  278. "www.foo.com", // Host
  279. "/bar/baz/boz/bif.html", // Url
  280. "GET", // Method
  281. NULL, // no username
  282. NULL, // no password
  283. NULL, // no nonce
  284. GetDesktopWindow(), // desktop window
  285. szResponse); // Response buffer
  286. }
  287. //-------------------------------------------------------------------------------------------------------------
  288. // App 2 makes a request to the same server and gets challenged for the same realm. First auth attempt will
  289. // not be successful since this is the first challenge this session, so it will have to prompt for credentials.
  290. // When prompting, because it shares credentials with App1, the drop-down will contain App1's credentials.
  291. ssResult =
  292. DoAuthenticate( &hCred2, // Cred from logging on.
  293. NULL, // Ctxt not specified first time.
  294. &hCtxt2, // Output context.
  295. 0, // auth from cache.
  296. szChallenge, // Server challenge header.
  297. NULL, // no realm since not preauth.
  298. "www.foo.com", // Host.
  299. "/bar/baz/boz/bif.html", // Url.
  300. "GET", // Method.
  301. NULL, // no Username
  302. NULL, // no Password.
  303. NULL, // no nonce
  304. NULL, // don't need hwnd for auth.
  305. szResponse); // Response buffer.
  306. // Generate the confirmation dialog and auth. User can choose App1's creds or enter new credentials.
  307. if (ssResult == SEC_E_NO_CREDENTIALS)
  308. {
  309. ssResult =
  310. DoAuthenticate( &hCred2, // Cred from logging on.
  311. &hCtxt2, // Ctxt from previous call
  312. &hCtxt2, // Output context (same as from previous).
  313. ISC_REQ_PROMPT_FOR_CREDS, // prompt
  314. szChallenge, // Server challenge
  315. NULL , // No realm
  316. "www.foo.com", // Host
  317. "/bar/baz/boz/bif.html", // Url
  318. "GET", // Method
  319. NULL, // no username
  320. NULL, // no password
  321. NULL, // no nonce
  322. GetDesktopWindow(), // desktop window
  323. szResponse); // Response buffer
  324. }
  325. //-------------------------------------------------------------------------------------------------------------
  326. // App 3 makes a request to the same server and gets challenged for the same realm. First auth attempt will
  327. // not be successful since this is the first challenge this session, so it will have to prompt for credentials.
  328. // When prompting, because it shares credentials with App1 and App2 the drop-down could show two choices if
  329. // App2 entered new credentials (or just one if App2 chose to use App1's credential).
  330. ssResult =
  331. DoAuthenticate( &hCred3, // Cred from logging on.
  332. NULL, // Ctxt not specified first time.
  333. &hCtxt3, // Output context.
  334. 0, // auth from cache.
  335. szChallenge, // Server challenge header.
  336. NULL, // no realm since not preauth.
  337. "www.foo.com", // Host.
  338. "/bar/baz/boz/bif.html", // Url.
  339. "GET", // Method.
  340. NULL, // no Username
  341. NULL, // no Password.
  342. NULL, // no nonce
  343. NULL, // don't need hwnd for auth.
  344. szResponse); // Response buffer.
  345. // Generate the confirmation dialog and auth. User can choose App1's creds or enter new credentials.
  346. if (ssResult == SEC_E_NO_CREDENTIALS)
  347. {
  348. ssResult =
  349. DoAuthenticate( &hCred3, // Cred from logging on.
  350. &hCtxt3, // Ctxt from previous call
  351. &hCtxt3, // Output context (same as from previous).
  352. ISC_REQ_PROMPT_FOR_CREDS, // prompt
  353. szChallenge, // Server challenge
  354. NULL , // No realm
  355. "www.foo.com", // Host
  356. "/bar/baz/boz/bif.html", // Url
  357. "GET", // Method
  358. NULL, // no username
  359. NULL, // no password
  360. NULL, // no nonce
  361. GetDesktopWindow(), // desktop window
  362. szResponse); // Response buffer
  363. }
  364. //-------------------------------------------------------------------------------------------------------------
  365. // App2 preauthenticates to "[email protected]" for a new url. Note that the credential that will be used
  366. // for preauthentication is whatever App2 chose or entered previously. The same would be true for
  367. // App1 or App3.
  368. ssResult =
  369. DoAuthenticate( &hCred2, // Cred from logging on.
  370. NULL, // Ctxt not specified first time.
  371. &hCtxt2, // Output context.
  372. 0, // auth (preauth)
  373. NULL, // No challenge header
  374. "[email protected]", // Realm for preauth.
  375. "www.foo.com", // Host.
  376. "/bar/baz.gif", // Url
  377. "GET", // Method.
  378. NULL, // no sername
  379. NULL, // no password.
  380. NULL, // no nonce
  381. NULL, // no hwnd
  382. szResponse); // Response buffer.
  383. //-------------------------------------------------------------------------------------------------------------
  384. // App3 made another request to the same server but did not preauthenticate. It got challenged for the
  385. // same realm and can authenticate without prompting because it has credentials for that realm.
  386. szChallenge = "realm=\"[email protected]\", stale = TRUE, qop=\"auth,auth-int\", nonce=\"abcdefge8b11d0f600bfb0c093\", opaque=\"efghijklmnopc403ebaf9f0171e9517f40e41\"";
  387. ssResult =
  388. DoAuthenticate( &hCred3, // Cred from logging on.
  389. NULL, // Ctxt not specified first time.
  390. &hCtxt3, // Output context.
  391. 0, // auth
  392. szChallenge, // Challenge from server.
  393. NULL, // no realm
  394. "www.foo.com", // Host.
  395. "/bar/baz.htm", // Url
  396. "GET", // Method.
  397. NULL, // no username
  398. NULL, // no password
  399. NULL, // no nonce
  400. NULL, // no hwnd
  401. szResponse); // Response buffer.
  402. //-------------------------------------------------------------------------------------------------------------
  403. // App1 authenticates for an md5-sess challenge.
  404. szChallenge = "realm=\"[email protected]\", algorithm=\"md5-sess\", stale = TRUE, qop=\"auth,auth-int\", nonce=\"dcd98b7102dd2f0e8b11d0f600bfb0c093\", opaque=\"5ccc069c403ebaf9f0171e9517f40e41\"";
  405. ssResult =
  406. DoAuthenticate( &hCred1, // Cred from logging on.
  407. NULL, // Ctxt not specified first time.
  408. &hCtxt1, // Output context.
  409. 0, // auth from cache.
  410. szChallenge, // Server challenge header.
  411. NULL, // no realm since not preauth.
  412. "www.foo.com", // Host.
  413. "/bar/baz/boz/bif.html", // Url.
  414. "GET", // Method.
  415. NULL, // no Username
  416. NULL, // no Password.
  417. NULL, // no nonce
  418. NULL, // don't need hwnd for auth.
  419. szResponse); // Response buffer.
  420. //-------------------------------------------------------------------------------------------------------------
  421. // App1 preauthenticates for 10 documents using md5-sess
  422. DWORD i;
  423. CHAR szBuf[1024];
  424. for (i = 0; i < 10; i++)
  425. {
  426. wsprintf(szBuf, "/bar/baz/boz/%x.html", i);
  427. ssResult =
  428. DoAuthenticate( &hCred1, // Cred from logging on.
  429. NULL, // Ctxt not specified first time.
  430. &hCtxt1, // Output context.
  431. 0, // auth from cache.
  432. NULL, // Server challenge header.
  433. "[email protected]", // realm.
  434. "www.foo.com", // Host.
  435. szBuf, // Url.
  436. "GET", // Method.
  437. NULL, // no Username
  438. NULL, // no Password.
  439. NULL, // no nonce
  440. NULL, // don't need hwnd for auth.
  441. szResponse); // Response buffer.
  442. }
  443. //-------------------------------------------------------------------------------------------------------------
  444. // App1 received a new md5-sess challenge.
  445. szChallenge = "realm=\"[email protected]\", algorithm=\"md5-sess\", stale = TRUE, qop=\"auth,auth-int\", nonce=\"dcd98b7102dd2f0e8b11d0f600bfb0c093\", opaque=\"5ccc069c403ebaf9f0171e9517f40e41\"";
  446. ssResult =
  447. DoAuthenticate( &hCred1, // Cred from logging on.
  448. NULL, // Ctxt not specified first time.
  449. &hCtxt1, // Output context.
  450. 0, // auth from cache.
  451. szChallenge, // Server challenge header.
  452. NULL, // no realm since not preauth.
  453. "www.foo.com", // Host.
  454. "/bar/baz/boz/bif.html", // Url.
  455. "GET", // Method.
  456. NULL, // no Username
  457. NULL, // no Password.
  458. NULL, // no nonce
  459. NULL, // don't need hwnd for auth.
  460. szResponse); // Response buffer.
  461. //-------------------------------------------------------------------------------------------------------------
  462. // App1 preauths using new md5-sess
  463. for (i = 0; i < 10; i++)
  464. {
  465. wsprintf(szBuf, "/bar/baz/boz/%x.html", i);
  466. ssResult =
  467. DoAuthenticate( &hCred1, // Cred from logging on.
  468. NULL, // Ctxt not specified first time.
  469. &hCtxt1, // Output context.
  470. 0, // auth from cache.
  471. NULL, // Server challenge header.
  472. "[email protected]", // realm.
  473. "www.foo.com", // Host.
  474. szBuf, // Url.
  475. "GET", // Method.
  476. NULL, // no Username
  477. NULL, // no Password.
  478. NULL, // no nonce
  479. NULL, // don't need hwnd for auth.
  480. szResponse); // Response buffer.
  481. }
  482. szChallenge = "realm=\"Microsoft.Passport\", algorithm=MD5-sess, qop=\"auth\", nonce=ykjOzYDMxMzY4kjOEFkUSVkTB5kM6QUQSJVROFkTyojM6QzY0QGNhJmNjVDNhFGZiZjM3I2MiFWO3MDZyQTNyY2M";
  483. ssResult =
  484. DoAuthenticate( &hCred1, // Cred from logging on.
  485. NULL, // Ctxt not specified first time.
  486. &hCtxt1, // Output context.
  487. 0, // auth from cache.
  488. szChallenge, // Server challenge header.
  489. NULL, // no realm since not preauth.
  490. "darrenan2", // Host.
  491. "/passport/protected/test.asp", // Url.
  492. "GET", // Method.
  493. "darrenan2", // Given Username
  494. NULL, // no Password.
  495. NULL, // no nonce
  496. NULL, // don't need hwnd for auth.
  497. szResponse); // Response buffer.
  498. ssResult =
  499. DoAuthenticate( &hCred1, // Cred from logging on.
  500. NULL, // Ctxt not specified first time.
  501. &hCtxt1, // Output context.
  502. ISC_REQ_PROMPT_FOR_CREDS, // auth from cache.
  503. szChallenge, // Server challenge header.
  504. NULL, // no realm since not preauth.
  505. "darrenan2", // Host.
  506. "/passport/protected/test.asp", // Url.
  507. "GET", // Method.
  508. "darrenan2", // Given username.
  509. NULL, // no Password.
  510. NULL, // no nonce
  511. NULL, // don't need hwnd for auth.
  512. szResponse); // Response buffer.
  513. // Logoff all three sessions
  514. ssResult = LogoffOfDigestPkg(&hCred1);
  515. ssResult = LogoffOfDigestPkg(&hCred2);
  516. ssResult = LogoffOfDigestPkg(&hCred3);
  517. ssResult = LogoffOfDigestPkg(&hCred4);
  518. ssResult = LogoffOfDigestPkg(&hCred5);
  519. ssResult = LogoffOfDigestPkg(&hCred6);
  520. ssResult = LogoffOfDigestPkg(&hCred7);
  521. ssResult = LogoffOfDigestPkg(&hCred8);
  522. ssResult = LogoffOfDigestPkg(&hCred9);
  523. if (hSecLib)
  524. FreeLibrary(hSecLib);
  525. exit:
  526. return dwReturn;
  527. }