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.

1014 lines
35 KiB

  1. #include <windows.h>
  2. #include <stdio.h>
  3. #include <process.h>
  4. #define SECURITY_WIN32
  5. #include <security.h>
  6. #include <sspi.h>
  7. #include <issperr.h>
  8. #include "main.hxx"
  9. #define SSP_SPM_NT_DLL "security.dll"
  10. #define SSP_SPM_WIN95_DLL "secur32.dll"
  11. PSecurityFunctionTable g_pFuncTbl = NULL;
  12. HINSTANCE hSecLib;
  13. LPSTR
  14. issperr2str( SECURITY_STATUS error );
  15. struct DIGEST_PKG_DATA
  16. {
  17. LPSTR szAppCtx;
  18. LPSTR szUserCtx;
  19. };
  20. #define SIG_DIGEST 'HTUA'
  21. DIGEST_PKG_DATA PkgData;
  22. SEC_WINNT_AUTH_IDENTITY_EXA SecIdExA;
  23. //----------------------------------------------------------------------------
  24. // InitializeSecurityInterface
  25. //----------------------------------------------------------------------------
  26. VOID InitializeSecurityInterface(BOOL fDirect)
  27. {
  28. INIT_SECURITY_INTERFACE addrProcISI = NULL;
  29. OSVERSIONINFO VerInfo;
  30. CHAR szDLL[MAX_PATH];
  31. if (!fDirect)
  32. {
  33. VerInfo.dwOSVersionInfoSize = sizeof (OSVERSIONINFO);
  34. GetVersionEx (&VerInfo);
  35. if (VerInfo.dwPlatformId == VER_PLATFORM_WIN32_NT)
  36. {
  37. lstrcpy (szDLL, SSP_SPM_NT_DLL);
  38. }
  39. else if (VerInfo.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS)
  40. {
  41. lstrcpy (szDLL, SSP_SPM_WIN95_DLL);
  42. }
  43. }
  44. else
  45. {
  46. strcpy(szDLL, "digest.dll");
  47. }
  48. hSecLib = LoadLibrary (szDLL);
  49. addrProcISI = (INIT_SECURITY_INTERFACE) GetProcAddress( hSecLib,
  50. SECURITY_ENTRYPOINT_ANSI);
  51. g_pFuncTbl = (*addrProcISI)();
  52. }
  53. //----------------------------------------------------------------------------
  54. // HaveDigest
  55. //----------------------------------------------------------------------------
  56. BOOL HaveDigest()
  57. {
  58. SECURITY_STATUS ssResult;
  59. DWORD cPackages;
  60. PSecPkgInfoA pSecPkgInfo;
  61. BOOL fHaveDigest;
  62. // ***** SSPI call *****
  63. ssResult = (*(g_pFuncTbl->EnumerateSecurityPackagesA))(&cPackages, &pSecPkgInfo);
  64. // Check if we have digest.
  65. fHaveDigest = FALSE;
  66. if (ssResult == SEC_E_OK)
  67. {
  68. for (DWORD i = 0; i < cPackages; i++)
  69. {
  70. if (strcmp(pSecPkgInfo[i].Name, "Digest") == 0)
  71. {
  72. fHaveDigest = TRUE;
  73. break;
  74. }
  75. }
  76. }
  77. return fHaveDigest;
  78. }
  79. //----------------------------------------------------------------------------
  80. // LogonToDigestPkg
  81. //----------------------------------------------------------------------------
  82. SECURITY_STATUS LogonToDigestPkg(LPSTR szAppCtx, LPSTR szUserCtx, PCredHandle phCred)
  83. {
  84. SECURITY_STATUS ssResult;
  85. // Logon with szAppCtx = szUserCtx = NULL.
  86. PkgData.szAppCtx = PkgData.szUserCtx = NULL;
  87. memset(&SecIdExA, 0, sizeof(SEC_WINNT_AUTH_IDENTITY_EXA));
  88. PkgData.szAppCtx = szAppCtx;
  89. PkgData.szUserCtx = szUserCtx;
  90. SecIdExA.Version = sizeof(SEC_WINNT_AUTH_IDENTITY_EXA);
  91. SecIdExA.User = (unsigned char*) &PkgData;
  92. SecIdExA.UserLength = sizeof(DIGEST_PKG_DATA);
  93. // ***** SSPI CALL *****
  94. dprintf(API,"AcquireCredentialsHandleA(\n"
  95. "PackageName: %s\n"
  96. "dwCredentialUse: %s\n"
  97. "pAuthData: %#x\n"
  98. "phCredential: %#x\n",
  99. "Digest", // pszPackageName (Package name)
  100. "OUTBOUND", // dwCredentialUse (Credentials aren't pulled from OS)
  101. &SecIdExA, // pAuthData ptr to g_PkgData
  102. phCred // phCredential (credential returned)
  103. );
  104. ssResult = (*(g_pFuncTbl->AcquireCredentialsHandleA))
  105. (NULL, // pszPrinciple NULL
  106. "Digest", // pszPackageName (Package name)
  107. SECPKG_CRED_OUTBOUND, // dwCredentialUse (Credentials aren't pulled from OS)
  108. NULL, // pvLogonID (not used)
  109. &SecIdExA, // pAuthData ptr to g_PkgData
  110. NULL, // pGetKeyFn (not used)
  111. 0, // pvGetKeyArgument (not used)
  112. phCred, // phCredential (credential returned)
  113. NULL); // PTimeStamp (not used)
  114. dprintf(API,"AcquireCredentialHandle(%s,%s) returns [%d,%d]\n",
  115. szAppCtx,
  116. szUserCtx,
  117. phCred->dwUpper,
  118. phCred->dwLower);
  119. return ssResult;
  120. }
  121. //----------------------------------------------------------------------------
  122. // LogoffOfDigestPkg
  123. //----------------------------------------------------------------------------
  124. SECURITY_STATUS LogoffOfDigestPkg(PCredHandle phCred)
  125. {
  126. SECURITY_STATUS ssResult;
  127. // ***** SSPI CALL *****
  128. ssResult = (*(g_pFuncTbl->FreeCredentialsHandle))(phCred);
  129. dprintf(API,"FreeCredentialsHandle([%d,%d]) returns %s\n",
  130. phCred->dwUpper,
  131. phCred->dwLower,
  132. issperr2str(ssResult));
  133. return ssResult;
  134. }
  135. //----------------------------------------------------------------------------
  136. // Authenticate
  137. //----------------------------------------------------------------------------
  138. SECURITY_STATUS
  139. DoAuthenticate(PCredHandle phCred,
  140. PCtxtHandle phCtxt,
  141. PCtxtHandle phNewCtxt,
  142. DWORD fContextReq,
  143. LPSTR szHeader,
  144. LPSTR szRealm,
  145. LPSTR szHost,
  146. LPSTR szUrl,
  147. LPSTR szMethod,
  148. LPSTR szUser,
  149. LPSTR szPass,
  150. LPSTR szNonce,
  151. HWND hWnd,
  152. LPSTR szResponse,
  153. DWORD cbResponse)
  154. {
  155. SECURITY_STATUS ssResult;
  156. ISC_PARAMS ISC_Params;
  157. HANDLE hThread = NULL;
  158. DWORD dwRet;
  159. int i,j;
  160. BOOL fPersist = FALSE;
  161. TCHAR szUsername[256];
  162. TCHAR szPassword[256];
  163. dprintf(ENTRY_EXIT, "ENTER: DoAuthenticate ...\n");
  164. dprintf(INFO,
  165. "DoAuthenticate(\n"
  166. "szHeader %s \n"
  167. "szRealm %s \n"
  168. "szHost %s \n"
  169. "szUrl %s \n"
  170. "szMethod %s \n"
  171. "szUser %s \n"
  172. "szPass %s \n"
  173. "szNonce %s \n"
  174. ,
  175. szHeader,
  176. szRealm,
  177. szHost,
  178. szUrl,
  179. szMethod,
  180. szUser,
  181. szPass,
  182. szNonce);
  183. memset( (LPVOID)&ISC_Params, 0, sizeof(ISC_PARAMS) );
  184. ISC_Params.phCred = phCred;
  185. ISC_Params.phCtxt = phCtxt;
  186. ISC_Params.phNewCtxt = phNewCtxt;
  187. ISC_Params.fContextReq = fContextReq;
  188. ISC_Params.szHeader = szHeader;
  189. ISC_Params.szRealm = szRealm;
  190. ISC_Params.szHost = szHost;
  191. ISC_Params.szUrl = szUrl;
  192. ISC_Params.szMethod = szMethod;
  193. ISC_Params.szUser = szUser;
  194. ISC_Params.szPass = szPass;
  195. ISC_Params.szNonce = szNonce;
  196. ISC_Params.hWnd = hWnd;
  197. ISC_Params.szResponse = szResponse;
  198. ISC_Params.cbResponse = cbResponse;
  199. i = rand() % 10;
  200. j = rand() % 10;
  201. sprintf(szUsername,"user%d_%[email protected]",i,j);
  202. sprintf(szPassword,"pass%d_%d",i,j);
  203. if( ( rand() % 100 ) > 50 )
  204. fPersist = TRUE;
  205. if( ISC_Params.fContextReq & ISC_REQ_PROMPT_FOR_CREDS ) {
  206. //
  207. // we need to start the UI thread
  208. //
  209. hThread = (HANDLE) _beginthread(fnUiThread,0,(LPVOID)&ISC_Params);
  210. //fnUiThread((LPVOID)&ISC_Params);
  211. SetUIUserNameAndPassword(szUsername,szPassword, fPersist);
  212. printf("Waiting for UI thread to complete\n");
  213. dwRet = WaitForSingleObject( hThread, INFINITE );
  214. } else {
  215. fnUiThread((LPVOID)&ISC_Params);
  216. }
  217. ssResult = ISC_Params.ss;
  218. // ***** SSPI CALL *****
  219. // ssResult = (*(g_pFuncTbl->InitializeSecurityContextA))
  220. // (phCred, // phCredential (from AcquireCredentialsHandle)
  221. // phCtxt, // phContext (NULL on first call, phNewCtxt on subsequent calls).
  222. // NULL, // pszTargetName (not used)
  223. // NULL, // fContextReq (not used)
  224. // 0, // Reserved1 (not used)
  225. // 0, // TargetDataRep (not used)
  226. // &sbdIn, // PSecBufDesc (input buffer descriptor)
  227. // 0, // Reserved2 (not used)
  228. // phNewCtxt, // phNewContext (should be passed back as phCtxt on subsequent calls)
  229. // &sbdOut, // pOutput (output buffer descriptor)
  230. // &fContextAttr, // pfContextAttr (auth from cache, prompt or auth using supplied creds)
  231. // NULL); // ptsExpiry (not used)
  232. return ssResult;
  233. }
  234. void __cdecl fnUiThread( LPVOID lpData )
  235. {
  236. LPISC_PARAMS lpIscParams = (LPISC_PARAMS) lpData;
  237. lpIscParams -> ss =
  238. _InitializeSecurityContext(
  239. lpIscParams -> phCred,
  240. lpIscParams -> phCtxt,
  241. lpIscParams -> phNewCtxt,
  242. lpIscParams -> fContextReq,
  243. lpIscParams -> szHeader,
  244. lpIscParams -> szRealm,
  245. lpIscParams -> szHost,
  246. lpIscParams -> szUrl,
  247. lpIscParams -> szMethod,
  248. lpIscParams -> szUser,
  249. lpIscParams -> szPass,
  250. lpIscParams -> szNonce,
  251. lpIscParams -> hWnd,
  252. lpIscParams -> szResponse,
  253. lpIscParams -> cbResponse);
  254. return;
  255. }
  256. SECURITY_STATUS
  257. _InitializeSecurityContext(PCredHandle phCred,
  258. PCtxtHandle phCtxt,
  259. PCtxtHandle phNewCtxt,
  260. DWORD fContextReq,
  261. LPSTR szHeader,
  262. LPSTR szRealm,
  263. LPSTR szHost,
  264. LPSTR szUrl,
  265. LPSTR szMethod,
  266. LPSTR szUser,
  267. LPSTR szPass,
  268. LPSTR szNonce,
  269. HWND hWnd,
  270. LPSTR szResponse,
  271. DWORD cbResponse)
  272. {
  273. SECURITY_STATUS ssResult;
  274. // Input buffers and descriptor.
  275. SecBuffer sbIn[10];
  276. SecBufferDesc sbdIn;
  277. sbdIn.pBuffers = sbIn;
  278. sbdIn.cBuffers = 10;
  279. dprintf(API,"InitializeSecurityContext(\n"
  280. "Cred: [%d(%#x),%d(%#x)]\n"
  281. "Ctxt: [%d(%#x),%d(%#x)]\n"
  282. "New Ctxt: [%d(%#x),%d(%#x)]\n",
  283. (phCred?(phCred->dwUpper):0),
  284. (phCred?(phCred->dwUpper):0),
  285. (phCred?(phCred->dwLower):0),
  286. (phCred?(phCred->dwLower):0),
  287. (phCtxt?(phCtxt->dwUpper):0),
  288. (phCtxt?(phCtxt->dwUpper):0),
  289. (phCtxt?(phCtxt->dwLower):0),
  290. (phCtxt?(phCtxt->dwLower):0),
  291. (phNewCtxt?(phNewCtxt->dwUpper):0),
  292. (phNewCtxt?(phNewCtxt->dwUpper):0),
  293. (phNewCtxt?(phNewCtxt->dwLower):0),
  294. (phNewCtxt?(phNewCtxt->dwLower):0));
  295. sbIn[0].pvBuffer = szHeader; // Challenge header
  296. sbIn[1].pvBuffer = szRealm; // realm if preauth
  297. sbIn[2].pvBuffer = szHost; // host
  298. sbIn[3].pvBuffer = szUrl; // url
  299. sbIn[4].pvBuffer = szMethod; // http method
  300. sbIn[5].pvBuffer = szUser; // username (optional)
  301. sbIn[6].pvBuffer = szPass; // password (optional, not used currently)
  302. sbIn[7].pvBuffer = szNonce; // nonce
  303. sbIn[8].pvBuffer = NULL; // nonce count not passed in.
  304. sbIn[9].pvBuffer = &hWnd; // window handle.
  305. // Output buffer and descriptor.
  306. SecBuffer sbOut[1];
  307. SecBufferDesc sbdOut;
  308. sbdOut.pBuffers = sbOut;
  309. sbdOut.cBuffers = 1;
  310. // Set output buffer.
  311. sbOut[0].pvBuffer = szResponse;
  312. sbOut[0].cbBuffer = cbResponse;
  313. // ***** SSPI CALL *****
  314. ssResult = (*(g_pFuncTbl->InitializeSecurityContextA))
  315. (phCred, // phCredential (from AcquireCredentialsHandle)
  316. phCtxt, // phContext (NULL on first call, phNewCtxt on subsequent calls).
  317. NULL, // pszTargetName (not used)
  318. fContextReq , // fContextReq (auth from cache, prompt or auth using supplied creds)(not used)
  319. 0, // Reserved1 (not used)
  320. 0, // TargetDataRep (not used)
  321. &sbdIn, // PSecBufDesc (input buffer descriptor)
  322. 0, // Reserved2 (not used)
  323. phNewCtxt, // phNewContext (should be passed back as phCtxt on subsequent calls)
  324. &sbdOut, // pOutput (output buffer descriptor)
  325. NULL, // pfContextAttr (not used)
  326. NULL); // ptsExpiry (not used)
  327. #ifdef _DEBUG
  328. fprintf(stderr,"ISC returned result : %s(%d), buffer : \n %s \n",
  329. issperr2str(ssResult),ssResult,sbOut[0].pvBuffer );
  330. #endif
  331. return ssResult;
  332. }
  333. VOID PrimeCredCache(CredHandle CredHandle, LPSTR szRealm, LPSTR szUser, LPSTR szPass)
  334. {
  335. DWORD ssResult;
  336. CtxtHandle hCtxt;
  337. SecBufferDesc sbdIn;
  338. SecBuffer sbIn[3];
  339. hCtxt.dwLower = CredHandle.dwLower;
  340. hCtxt.dwUpper = CredHandle.dwUpper;
  341. sbIn[0].pvBuffer = szRealm;
  342. sbIn[0].cbBuffer = strlen(szRealm);
  343. sbIn[1].pvBuffer = szUser;
  344. sbIn[1].cbBuffer = strlen(szUser);
  345. sbIn[2].pvBuffer = szPass;
  346. sbIn[2].cbBuffer = strlen(szPass);
  347. sbdIn.cBuffers = 3;
  348. sbdIn.pBuffers = sbIn;
  349. ssResult = (*(g_pFuncTbl->ApplyControlToken))(&hCtxt, &sbdIn);
  350. }
  351. //----------------------------------------------------------------------------
  352. // main
  353. //----------------------------------------------------------------------------
  354. #ifdef UNIX
  355. #define main prog_main
  356. int _main(int argc, char **argv);
  357. int _WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR pszCmdLine, int nCmdShow) {
  358. extern int __argc;
  359. extern char **__argv;
  360. return main(__argc, __argv);
  361. }
  362. int _main(int argc, char **argv)
  363. #else
  364. INT _main()
  365. #endif
  366. {
  367. #define IDENTITY_1 "Alice"
  368. #define IDENTITY_2 "Bob"
  369. DWORD dwReturn = 0;
  370. SECURITY_STATUS ssResult;
  371. // Get (global) dispatch table.
  372. InitializeSecurityInterface(TRUE);
  373. // Check to see if we have digest.
  374. if (!HaveDigest())
  375. {
  376. dwReturn = 1;
  377. goto exit;
  378. }
  379. // Credential handle and pointer.
  380. CredHandle hCred1, hCred2, hCred3;
  381. CtxtHandle hCtxt1, hCtxt2, hCtxt3;
  382. // Three apps logon using the same keys (appctx, userctx, both NULL);
  383. // These sessions will be used for authentication.
  384. LogonToDigestPkg(NULL, IDENTITY_1, &hCred1);
  385. LogonToDigestPkg(NULL, IDENTITY_1, &hCred2);
  386. LogonToDigestPkg(NULL, IDENTITY_1, &hCred3);
  387. // Three more apps also logon using the same keys.
  388. // we will prime the password cache with credentials for these apps
  389. // and expect to be able to share the credentials via the auth dialog.
  390. CredHandle hCred4, hCred5, hCred6;
  391. LogonToDigestPkg(NULL, IDENTITY_1, &hCred4);
  392. LogonToDigestPkg(NULL, IDENTITY_1, &hCred5);
  393. LogonToDigestPkg(NULL, IDENTITY_1, &hCred6);
  394. PrimeCredCache(hCred4, "[email protected]", "Wilma", "password");
  395. PrimeCredCache(hCred5, "[email protected]", "Betty", "passwordxxxx");
  396. PrimeCredCache(hCred6, "[email protected]", "Pebbles", "passwordxxxxx");
  397. // Finally, three more apps also logon using a different logon key (identity)
  398. // we will prime the password cache with credentials for these apps
  399. // Because of the different logon key we should never see these creds.
  400. CredHandle hCred7, hCred8, hCred9;
  401. LogonToDigestPkg(NULL, IDENTITY_2, &hCred7);
  402. LogonToDigestPkg(NULL, IDENTITY_2, &hCred8);
  403. LogonToDigestPkg(NULL, IDENTITY_2, &hCred9);
  404. PrimeCredCache(hCred7, "[email protected]", "Fred", "password");
  405. PrimeCredCache(hCred8, "[email protected]", "Barney", "passwordxxxx");
  406. PrimeCredCache(hCred9, "[email protected]", "Bam Bam", "passwordxxxxxxxx");
  407. //-------------------------------------------------------------------------------------------------------------
  408. // App 1 makes a request from a server, does not have credentials and must prompt
  409. // before finally succeeding.
  410. // Challenge from server.
  411. LPSTR szChallenge;
  412. szChallenge = "realm=\"[email protected]\", stale = FALSE, qop=\"auth,auth-int\", nonce=\"dcd98b7102dd2f0e8b11d0f600bfb0c093\", opaque=\"5ccc069c403ebaf9f0171e9517f40e41\"";
  413. // Package will dump response into this buffer.
  414. CHAR szResponse[4096];
  415. // First try at authenticating.
  416. ssResult =
  417. DoAuthenticate( &hCred1, // Cred from logging on.
  418. NULL, // Ctxt not specified first time.
  419. &hCtxt1, // Output context.
  420. 0, // auth from cache.
  421. szChallenge, // Server challenge header.
  422. NULL, // no realm since not preauth.
  423. "www.foo.com", // Host.
  424. "/bar/baz/boz/bif.html", // Url.
  425. "GET", // Method.
  426. NULL, // no Username
  427. NULL, // no Password.
  428. NULL, // no nonce
  429. NULL, // don't need hwnd for auth.
  430. szResponse, // Response buffer.
  431. 4096);
  432. // Expect to not have credentials the first time - prompt.
  433. if (ssResult == SEC_E_NO_CREDENTIALS)
  434. {
  435. ssResult =
  436. DoAuthenticate( &hCred1, // Cred from logging on.
  437. &hCtxt1, // Ctxt from previous call
  438. &hCtxt1, // Output context (same as from previous).
  439. ISC_REQ_PROMPT_FOR_CREDS, // prompt
  440. szChallenge, // Server challenge
  441. NULL, // No realm
  442. "www.foo.com", // Host
  443. "/bar/baz/boz/bif.html", // Url
  444. "GET", // Method
  445. NULL, // no username
  446. NULL, // no password
  447. NULL, // no nonce
  448. GetDesktopWindow(), // desktop window
  449. szResponse, // Response buffer
  450. 4096);
  451. }
  452. // We now have credentials and this will generate the output string.
  453. if (ssResult == SEC_E_OK)
  454. {
  455. ssResult =
  456. DoAuthenticate( &hCred1, // Cred from logging on.
  457. &hCtxt1, // Ctxt not specified first time.
  458. &hCtxt1, // Output context.
  459. 0, // auth
  460. szChallenge, // Server challenge.
  461. NULL, // no realm
  462. "www.foo.com", // Host.
  463. "/bar/baz/boz/bif.html", // Url.
  464. "GET", // Method.
  465. NULL, // no username
  466. NULL, // no password
  467. NULL, // no nonce
  468. NULL, // no hwnd
  469. szResponse, // Should have the response buffer now.
  470. 4096);
  471. }
  472. //-------------------------------------------------------------------------------------------------------------
  473. // App 2 makes a request to the same server and gets challenged for the same realm. First auth attempt will
  474. // not be successful since this is the first challenge this session, so it will have to prompt for credentials.
  475. // When prompting, because it shares credentials with App1, the drop-down will contain App1's credentials.
  476. ssResult =
  477. DoAuthenticate( &hCred2, // Cred from logging on.
  478. NULL, // Ctxt not specified first time.
  479. &hCtxt2, // Output context.
  480. 0, // auth from cache.
  481. szChallenge, // Server challenge header.
  482. NULL, // no realm since not preauth.
  483. "www.foo.com", // Host.
  484. "/bar/baz/boz/bif.html", // Url.
  485. "GET", // Method.
  486. NULL, // no Username
  487. NULL, // no Password.
  488. NULL, // no nonce
  489. NULL, // don't need hwnd for auth.
  490. szResponse, // Response buffer.
  491. 4096);
  492. // Generate the confirmation dialog. User can choose App1's creds or enter new credentials.
  493. if (ssResult == SEC_E_NO_CREDENTIALS)
  494. {
  495. ssResult =
  496. DoAuthenticate( &hCred2, // Cred from logging on.
  497. &hCtxt2, // Ctxt from previous call
  498. &hCtxt2, // Output context (same as from previous).
  499. ISC_REQ_PROMPT_FOR_CREDS, // prompt
  500. szChallenge, // Server challenge
  501. NULL , // No realm
  502. "www.foo.com", // Host
  503. "/bar/baz/boz/bif.html", // Url
  504. "GET", // Method
  505. NULL, // no username
  506. NULL, // no password
  507. NULL, // no nonce
  508. GetDesktopWindow(), // desktop window
  509. szResponse, // Response buffer
  510. 4096);
  511. }
  512. // App 2 now has credentials and can authenticate successfully.
  513. if (ssResult == SEC_E_OK)
  514. {
  515. ssResult =
  516. DoAuthenticate( &hCred2, // Cred from logging on.
  517. &hCtxt2, // Ctxt not specified first time.
  518. &hCtxt2, // Output context.
  519. 0, // auth
  520. szChallenge, // Server challenge.
  521. NULL, // no realm
  522. "www.foo.com", // Host.
  523. "/bar/baz/boz/bif.html", // Url.
  524. "GET", // Method.
  525. NULL, // no username
  526. NULL, // no password
  527. NULL, // no nonce
  528. NULL, // no hwnd
  529. szResponse, // Should have the response buffer now.
  530. 4096);
  531. }
  532. //-------------------------------------------------------------------------------------------------------------
  533. // App 3 makes a request to the same server and gets challenged for the same realm. First auth attempt will
  534. // not be successful since this is the first challenge this session, so it will have to prompt for credentials.
  535. // When prompting, because it shares credentials with App1 and App2 the drop-down could show two choices if
  536. // App2 entered new credentials (or just one if App2 chose to use App1's credential).
  537. ssResult =
  538. DoAuthenticate( &hCred3, // Cred from logging on.
  539. NULL, // Ctxt not specified first time.
  540. &hCtxt3, // Output context.
  541. 0, // auth from cache.
  542. szChallenge, // Server challenge header.
  543. NULL, // no realm since not preauth.
  544. "www.foo.com", // Host.
  545. "/bar/baz/boz/bif.html", // Url.
  546. "GET", // Method.
  547. NULL, // no Username
  548. NULL, // no Password.
  549. NULL, // no nonce
  550. NULL, // don't need hwnd for auth.
  551. szResponse, // Response buffer.
  552. 4096);
  553. // Generate the confirmation dialog. User can choose App1's creds or enter new credentials.
  554. if (ssResult == SEC_E_NO_CREDENTIALS)
  555. {
  556. ssResult =
  557. DoAuthenticate( &hCred3, // Cred from logging on.
  558. &hCtxt3, // Ctxt from previous call
  559. &hCtxt3, // Output context (same as from previous).
  560. ISC_REQ_PROMPT_FOR_CREDS, // prompt
  561. szChallenge, // Server challenge
  562. NULL , // No realm
  563. "www.foo.com", // Host
  564. "/bar/baz/boz/bif.html", // Url
  565. "GET", // Method
  566. NULL, // no username
  567. NULL, // no password
  568. NULL, // no nonce
  569. GetDesktopWindow(), // desktop window
  570. szResponse, // Response buffer
  571. 4096);
  572. }
  573. // App 3 now has credentials and can authenticate successfully.
  574. if (ssResult == SEC_E_OK)
  575. {
  576. ssResult =
  577. DoAuthenticate( &hCred3, // Cred from logging on.
  578. &hCtxt3, // Ctxt not specified first time.
  579. &hCtxt3, // Output context.
  580. 0, // auth
  581. szChallenge, // Server challenge.
  582. NULL, // no realm
  583. "www.foo.com", // Host.
  584. "/bar/baz/boz/bif.html", // Url.
  585. "GET", // Method.
  586. NULL, // no username
  587. NULL, // no password
  588. NULL, // no nonce
  589. NULL, // no hwnd
  590. szResponse, // Should have the response buffer now.
  591. 4096);
  592. }
  593. //-------------------------------------------------------------------------------------------------------------
  594. // App2 preauthenticates to "[email protected]" for a new url. Note that the credential that will be used
  595. // for preauthentication is whatever App2 chose or entered previously. The same would be true for
  596. // App1 or App3.
  597. ssResult =
  598. DoAuthenticate( &hCred2, // Cred from logging on.
  599. NULL, // Ctxt not specified first time.
  600. &hCtxt2, // Output context.
  601. 0, // auth (preauth)
  602. NULL, // No challenge header
  603. "[email protected]", // Realm for preauth.
  604. "www.foo.com", // Host.
  605. "/bar/baz.gif", // Url
  606. "GET", // Method.
  607. NULL, // no sername
  608. NULL, // no password.
  609. NULL, // no nonce
  610. NULL, // no hwnd
  611. szResponse, // Response buffer.
  612. 4096);
  613. //-------------------------------------------------------------------------------------------------------------
  614. // App3 made another request to the same server but did not preauthenticate. It got challenged for the
  615. // same realm and can authenticate without prompting because it has credentials for that realm.
  616. szChallenge = "realm=\"[email protected]\", stale = TRUE, qop=\"auth,auth-int\", nonce=\"abcdefge8b11d0f600bfb0c093\", opaque=\"efghijklmnopc403ebaf9f0171e9517f40e41\"";
  617. ssResult =
  618. DoAuthenticate( &hCred3, // Cred from logging on.
  619. NULL, // Ctxt not specified first time.
  620. &hCtxt3, // Output context.
  621. 0, // auth
  622. szChallenge, // Challenge from server.
  623. NULL, // no realm
  624. "www.foo.com", // Host.
  625. "/bar/baz.htm", // Url
  626. "GET", // Method.
  627. NULL, // no username
  628. NULL, // no password
  629. NULL, // no nonce
  630. NULL, // no hwnd
  631. szResponse, // Response buffer.
  632. 4096);
  633. // Logoff all three sessions
  634. ssResult = LogoffOfDigestPkg(&hCred1);
  635. ssResult = LogoffOfDigestPkg(&hCred2);
  636. ssResult = LogoffOfDigestPkg(&hCred3);
  637. ssResult = LogoffOfDigestPkg(&hCred4);
  638. ssResult = LogoffOfDigestPkg(&hCred5);
  639. ssResult = LogoffOfDigestPkg(&hCred6);
  640. ssResult = LogoffOfDigestPkg(&hCred7);
  641. ssResult = LogoffOfDigestPkg(&hCred8);
  642. ssResult = LogoffOfDigestPkg(&hCred9);
  643. if (hSecLib)
  644. FreeLibrary(hSecLib);
  645. exit:
  646. return dwReturn;
  647. }
  648. LPSTR
  649. issperr2str( SECURITY_STATUS error )
  650. {
  651. #define CASE(x) if( x == error ) \
  652. return #x;
  653. // switch( error ) {
  654. CASE ( SEC_E_INSUFFICIENT_MEMORY )
  655. //
  656. // MessageId: SEC_E_INVALID_HANDLE
  657. //
  658. // MessageText:
  659. //
  660. // The handle specified is invalid
  661. //
  662. CASE ( SEC_E_INVALID_HANDLE )
  663. //
  664. // MessageId: SEC_E_UNSUPPORTED_FUNCTION
  665. //
  666. // MessageText:
  667. //
  668. // The function requested is not supported
  669. //
  670. CASE ( SEC_E_UNSUPPORTED_FUNCTION )
  671. //
  672. // MessageId: SEC_E_TARGET_UNKNOWN
  673. //
  674. // MessageText:
  675. //
  676. // The specified target is unknown or unreachable
  677. //
  678. CASE ( SEC_E_TARGET_UNKNOWN )
  679. //
  680. // MessageId: SEC_E_INTERNAL_ERROR
  681. //
  682. // MessageText:
  683. //
  684. // The Local Security Authority cannot be contacted
  685. //
  686. CASE ( SEC_E_INTERNAL_ERROR )
  687. //
  688. // MessageId: SEC_E_SECPKG_NOT_FOUND
  689. //
  690. // MessageText:
  691. //
  692. // The requested security package does not exist
  693. //
  694. CASE ( SEC_E_SECPKG_NOT_FOUND )
  695. //
  696. // MessageId: SEC_E_NOT_OWNER
  697. //
  698. // MessageText:
  699. //
  700. // The caller is not the owner of the desired credentials
  701. //
  702. CASE ( SEC_E_NOT_OWNER )
  703. //
  704. // MessageId: SEC_E_CANNOT_INSTALL
  705. //
  706. // MessageText:
  707. //
  708. // The security package failed to initialize, and cannot be installed
  709. //
  710. CASE ( SEC_E_CANNOT_INSTALL )
  711. //
  712. // MessageId: SEC_E_INVALID_TOKEN
  713. //
  714. // MessageText:
  715. //
  716. // The token supplied to the function is invalid
  717. //
  718. CASE ( SEC_E_INVALID_TOKEN )
  719. //
  720. // MessageId: SEC_E_CANNOT_PACK
  721. //
  722. // MessageText:
  723. //
  724. // The security package is not able to marshall the logon buffer,
  725. // so the logon attempt has failed
  726. //
  727. CASE ( SEC_E_CANNOT_PACK )
  728. //
  729. // MessageId: SEC_E_QOP_NOT_SUPPORTED
  730. //
  731. // MessageText:
  732. //
  733. // The per-message Quality of Protection is not supported by the
  734. // security package
  735. //
  736. CASE ( SEC_E_QOP_NOT_SUPPORTED )
  737. //
  738. // MessageId: SEC_E_NO_IMPERSONATION
  739. //
  740. // MessageText:
  741. //
  742. // The security context does not allow impersonation of the client
  743. //
  744. CASE ( SEC_E_NO_IMPERSONATION )
  745. //
  746. // MessageId: SEC_E_LOGON_DENIED
  747. //
  748. // MessageText:
  749. //
  750. // The logon attempt failed
  751. //
  752. CASE ( SEC_E_LOGON_DENIED )
  753. //
  754. // MessageId: SEC_E_UNKNOWN_CREDENTIALS
  755. //
  756. // MessageText:
  757. //
  758. // The credentials supplied to the package were not
  759. // recognized
  760. //
  761. CASE ( SEC_E_UNKNOWN_CREDENTIALS )
  762. //
  763. // MessageId: SEC_E_NO_CREDENTIALS
  764. //
  765. // MessageText:
  766. //
  767. // No credentials are available in the security package
  768. //
  769. CASE ( SEC_E_NO_CREDENTIALS )
  770. //
  771. // MessageId: SEC_E_MESSAGE_ALTERED
  772. //
  773. // MessageText:
  774. //
  775. // The message supplied for verification has been altered
  776. //
  777. CASE ( SEC_E_MESSAGE_ALTERED )
  778. //
  779. // MessageId: SEC_E_OUT_OF_SEQUENCE
  780. //
  781. // MessageText:
  782. //
  783. // The message supplied for verification is out of sequence
  784. //
  785. CASE ( SEC_E_OUT_OF_SEQUENCE )
  786. //
  787. // MessageId: SEC_E_NO_AUTHENTICATING_AUTHORITY
  788. //
  789. // MessageText:
  790. //
  791. // No authority could be contacted for authentication.
  792. //
  793. CASE ( SEC_E_NO_AUTHENTICATING_AUTHORITY )
  794. //
  795. // MessageId: SEC_I_CONTINUE_NEEDED
  796. //
  797. // MessageText:
  798. //
  799. // The function completed successfully, but must be called
  800. // again to complete the context
  801. //
  802. CASE ( SEC_I_CONTINUE_NEEDED )
  803. //
  804. // MessageId: SEC_I_COMPLETE_NEEDED
  805. //
  806. // MessageText:
  807. //
  808. // The function completed successfully, but CompleteToken
  809. // must be called
  810. //
  811. CASE ( SEC_I_COMPLETE_NEEDED )
  812. //
  813. // MessageId: SEC_I_COMPLETE_AND_CONTINUE
  814. //
  815. // MessageText:
  816. //
  817. // The function completed successfully, but both CompleteToken
  818. // and this function must be called to complete the context
  819. //
  820. CASE ( SEC_I_COMPLETE_AND_CONTINUE )
  821. //
  822. // MessageId: SEC_I_LOCAL_LOGON
  823. //
  824. // MessageText:
  825. //
  826. // The logon was completed, but no network authority was
  827. // available. The logon was made using locally known information
  828. //
  829. CASE ( SEC_I_LOCAL_LOGON )
  830. //
  831. // MessageId: SEC_E_BAD_PKGID
  832. //
  833. // MessageText:
  834. //
  835. // The requested security package does not exist
  836. //
  837. CASE ( SEC_E_BAD_PKGID )
  838. //
  839. // MessageId: SEC_E_CONTEXT_EXPIRED
  840. //
  841. // MessageText:
  842. //
  843. // The context has expired and can no longer be used.
  844. //
  845. CASE ( SEC_E_CONTEXT_EXPIRED )
  846. //
  847. // MessageId: SEC_E_INCOMPLETE_MESSAGE
  848. //
  849. // MessageText:
  850. //
  851. // The supplied message is incomplete. The signature was not verified.
  852. //
  853. CASE ( SEC_E_INCOMPLETE_MESSAGE )
  854. //
  855. // Provided for backwards compatibility
  856. //
  857. CASE ( SEC_E_NO_SPM )
  858. CASE ( SEC_E_NOT_SUPPORTED )
  859. // default:
  860. return "Unknown SSPI Error ";
  861. // break;
  862. // }
  863. }