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.

1455 lines
44 KiB

  1. // Test.cpp : Defines the entry point for the console application.
  2. //
  3. #include "testglobal.h"
  4. #include <stdio.h> // printf
  5. #include <security.h> // General definition of a Security Support Provider
  6. #define AUTH_USERNAME "test1"
  7. #define AUTH_USERNAME_W L"test1"
  8. #define AUTH_REALM "simple_digest"
  9. #define AUTH_REALM_W L"simple_digest\"_widechar"
  10. #define AUTH_NONCE "9b38dce631309cc25a653ebaad5b18ee01c8bf385260b26db0574a302be4c11367"
  11. #define AUTH_METHOD "GET"
  12. #define AUTH_ALGORITHM "md5-sess"
  13. #define AUTH_QOP "auth"
  14. #define AUTH_PASSWD "secret"
  15. #define AUTH_CNONCE "34c52218425a779f41d5075931fe6c93"
  16. #define AUTH_URI "/dir/index.html"
  17. #define AUTH_URI_W L"/dir/index.html"
  18. #define AUTH_URI2 "/simple_digest/progress.html"
  19. #define AUTH_URI2_W L"/simple_digest/progress.html"
  20. #define AUTH_NC "0000000b"
  21. #define AUTH_NC1 "00000001"
  22. #define AUTH_NC2 "00000002"
  23. #define AUTH_NC3 "00000003"
  24. #define AUTH_NC4 "00000004"
  25. #define AUTH_REQDIGEST "60cac55049f9887c9fb853f485128368"
  26. #define STR_BUF_SIZE 4000
  27. // Prototypes
  28. void PrintStatus(SECURITY_STATUS NetStatus);
  29. void MyPrintTime(LPSTR Comment,TimeStamp ConvertTime);
  30. int __cdecl
  31. main(int argc, char* argv[])
  32. {
  33. int bPass = 1;
  34. SECURITY_STATUS Status = STATUS_SUCCESS;
  35. char cTemp[STR_BUF_SIZE]; // temp buffer for scratch data
  36. char cOutputTemp[STR_BUF_SIZE];
  37. char szOutSecBuf[STR_BUF_SIZE];
  38. char szChallenge[STR_BUF_SIZE];
  39. char szISCChallengeResponse[STR_BUF_SIZE]; // Output buffer from ISC
  40. char szASCChallengeResponse[STR_BUF_SIZE]; // Output buffer from ASC
  41. // SSPI Interface tests
  42. ULONG PackageCount = 0;
  43. int i = 0;
  44. PSecPkgInfo pPackageInfo = NULL;
  45. PSecPkgInfo pPackageTmp = NULL;
  46. SECURITY_STATUS TmpStatus = STATUS_SUCCESS;
  47. HANDLE hClientToken = NULL;
  48. CredHandle ServerCred;
  49. CredHandle ClientCred;
  50. TimeStamp Lifetime;
  51. BOOL bServerCred = FALSE;
  52. BOOL bClientCred = FALSE;
  53. BOOL bRC = FALSE;
  54. ULONG ContextReqFlags = 0;
  55. ULONG ContextFlagsUtilized = 0;
  56. ULONG TargetDataRep = 0;
  57. ULONG ContextAttributes = 0;
  58. CtxtHandle OldContextHandle;
  59. CtxtHandle ServerCtxtHandle;
  60. CtxtHandle ClientCtxtHandle;
  61. SecBufferDesc InputBuffers;
  62. SecBufferDesc OutputBuffers;
  63. SecBuffer TempTokensIn[6];
  64. SecBuffer TempTokensOut[6];
  65. SecPkgContext_Names SecServerName;
  66. SecPkgCredentials_Names SecCredClientName;
  67. SecPkgContext_StreamSizes StreamSizes;
  68. TimeStamp SecContextExpiry;
  69. PCHAR pcPtr = NULL;
  70. int iLen = 0;
  71. STRING strChallenge;
  72. STRING strMethod;
  73. STRING strURL;
  74. STRING strHEntity;
  75. STRING strOutBuffer;
  76. UNICODE_STRING ustrUsername;
  77. UNICODE_STRING ustrPassword;
  78. UNICODE_STRING ustrDomain;
  79. STRING strTemp;
  80. ULONG ulMessSeqNo = 0;
  81. ULONG ulQOP = 0;
  82. SEC_WINNT_AUTH_IDENTITY_W AuthData;
  83. printf("Begining TESTB...\n");
  84. ZeroMemory(&ClientCred, sizeof(CredHandle));
  85. ZeroMemory(&ServerCred, sizeof(CredHandle));
  86. ZeroMemory(&OldContextHandle, sizeof(CtxtHandle));
  87. ZeroMemory(&ServerCtxtHandle, sizeof(CtxtHandle));
  88. ZeroMemory(&ClientCtxtHandle, sizeof(CtxtHandle));
  89. ZeroMemory(&SecServerName, sizeof(SecPkgContext_Names));
  90. ZeroMemory(&SecCredClientName, sizeof(SecPkgCredentials_Names));
  91. ZeroMemory(&SecContextExpiry, sizeof(SecContextExpiry));
  92. ZeroMemory(&ustrUsername, sizeof(ustrUsername));
  93. ZeroMemory(&ustrPassword, sizeof(ustrPassword));
  94. ZeroMemory(&ustrDomain, sizeof(ustrDomain));
  95. ZeroMemory(&strTemp, sizeof(strTemp));
  96. ZeroMemory(&StreamSizes, sizeof(StreamSizes));
  97. // Pull out any command line args
  98. if (argc > 1)
  99. {
  100. for (i = 1; i < argc; i++)
  101. {
  102. pcPtr = argv[i];
  103. if (*pcPtr == '-')
  104. {
  105. iLen = strlen(pcPtr);
  106. if (iLen >= 2)
  107. {
  108. switch (*(pcPtr + 1))
  109. {
  110. case 'u':
  111. Status = RtlCreateUnicodeStringFromAsciiz(&ustrUsername, (pcPtr + 2));
  112. break;
  113. case 'd':
  114. Status = RtlCreateUnicodeStringFromAsciiz(&ustrDomain, (pcPtr + 2));
  115. break;
  116. case 'p':
  117. Status = RtlCreateUnicodeStringFromAsciiz(&ustrPassword, (pcPtr + 2));
  118. break;
  119. case '?':
  120. default:
  121. printf("Usage: %s -uUsername -pPassword -ddomain\n", argv[0]);
  122. return(-1);
  123. break;
  124. }
  125. }
  126. }
  127. }
  128. }
  129. //
  130. // Get info about the security packages.
  131. //
  132. Status = EnumerateSecurityPackages( &PackageCount, &pPackageInfo );
  133. TmpStatus = GetLastError();
  134. if (!NT_SUCCESS(Status)) {
  135. printf( "FAILED: EnumerateSecurityPackages failed: 0x%x\n", Status);
  136. PrintStatus( Status );
  137. bPass = 0;
  138. goto CleanUp;
  139. }
  140. printf( "PackageCount: %ld\n", PackageCount );
  141. for ( i= 0; i< (int)PackageCount; i++)
  142. {
  143. pPackageTmp = (pPackageInfo + i);
  144. printf( "Name: %ws Comment: %ws\n", pPackageTmp->Name, pPackageTmp->Comment );
  145. printf( "Cap: %ld Version: %ld RPCid: %ld MaxToken: %ld\n\n",
  146. pPackageTmp->fCapabilities,
  147. pPackageTmp->wVersion,
  148. pPackageTmp->wRPCID,
  149. pPackageTmp->cbMaxToken );
  150. }
  151. //
  152. // Get info about the security packages.
  153. //
  154. Status = QuerySecurityPackageInfo( WDIGEST_SP_NAME, &pPackageInfo );
  155. TmpStatus = GetLastError();
  156. if (!NT_SUCCESS(Status)) {
  157. printf( "FAILED: QuerySecurityPackageInfo failed: status 0x%x\n", Status);
  158. PrintStatus( Status );
  159. bPass = 0;
  160. goto CleanUp;
  161. }
  162. printf( "Name: %ws Comment: %ws\n", pPackageInfo->Name, pPackageInfo->Comment );
  163. printf( "Cap: %ld Version: %ld RPCid: %ld MaxToken: %ld\n\n",
  164. pPackageInfo->fCapabilities,
  165. pPackageInfo->wVersion,
  166. pPackageInfo->wRPCID,
  167. pPackageInfo->cbMaxToken );
  168. //
  169. // Acquire a credential handle for the server side
  170. //
  171. printf("Server AcquireCredentialHandle\n");
  172. Status = AcquireCredentialsHandle(
  173. NULL, // New principal
  174. WDIGEST_SP_NAME, // Package Name
  175. SECPKG_CRED_INBOUND,
  176. NULL,
  177. NULL,
  178. NULL,
  179. NULL,
  180. &ServerCred,
  181. &Lifetime );
  182. if (!NT_SUCCESS(Status)) {
  183. printf( "FAILED: AcquireCredentialsHandle failed: status 0x%x\n", Status);
  184. // TmpStatus = GetLastError();
  185. PrintStatus( Status );
  186. bPass = 0;
  187. ZeroMemory(&ServerCred, sizeof(CredHandle));
  188. goto CleanUp;
  189. }
  190. bServerCred = TRUE;
  191. MyPrintTime("Server ACH LifeTime: ", Lifetime);
  192. //
  193. // Acquire a credential handle for the client side
  194. //
  195. printf("Client AcquireCredentialHandle\n");
  196. if (ustrUsername.Length || ustrPassword.Length || ustrDomain.Length)
  197. {
  198. printf("ACH Using supplied credentials\n");
  199. printf(" Username %wZ Domain %wZ Password %wZ\n",
  200. &ustrUsername, &ustrDomain, &ustrPassword);
  201. ZeroMemory(&AuthData, sizeof(SEC_WINNT_AUTH_IDENTITY_W));
  202. AuthData.Domain = ustrDomain.Buffer;
  203. AuthData.DomainLength = ustrDomain.Length / sizeof(WCHAR);
  204. AuthData.Password = ustrPassword.Buffer;
  205. AuthData.PasswordLength = ustrPassword.Length / sizeof(WCHAR);
  206. AuthData.User = ustrUsername.Buffer;
  207. AuthData.UserLength = ustrUsername.Length / sizeof(WCHAR);
  208. AuthData.Flags = SEC_WINNT_AUTH_IDENTITY_UNICODE;
  209. Status = AcquireCredentialsHandle(
  210. NULL, // AUTH_USERNAME_W, // get the creds for user digest
  211. WDIGEST_SP_NAME, // Package Name
  212. SECPKG_CRED_OUTBOUND,
  213. NULL,
  214. &AuthData, // Make NULL not to use any AuthData for cred
  215. NULL,
  216. NULL,
  217. &ClientCred,
  218. &Lifetime );
  219. }
  220. else
  221. {
  222. printf("ACH Using default credentials\n");
  223. Status = AcquireCredentialsHandle(
  224. NULL, // AUTH_USERNAME_W, // get the creds for user digest
  225. WDIGEST_SP_NAME, // Package Name
  226. SECPKG_CRED_OUTBOUND,
  227. NULL,
  228. NULL,
  229. NULL,
  230. NULL,
  231. &ClientCred,
  232. &Lifetime );
  233. }
  234. if (!NT_SUCCESS(Status)) {
  235. printf( "FAILED: AcquireCredentialsHandle failed: status 0x%x\n", Status);
  236. // TmpStatus = GetLastError();
  237. PrintStatus( Status );
  238. bPass = 0;
  239. // ZeroMemory(&ClientCred, sizeof(CredHandle));
  240. goto CleanUp;
  241. }
  242. else
  243. bClientCred = TRUE;
  244. printf( "ClientCred: 0x%lx 0x%lx ",
  245. ClientCred.dwLower, ClientCred.dwUpper );
  246. printf( "ServerCred: 0x%lx 0x%lx \n",
  247. ServerCred.dwLower, ServerCred.dwUpper );
  248. MyPrintTime( "Client ACH Lifetime: ", Lifetime );
  249. // Big time - call Accept with no parameters to get a challenge
  250. StringAllocate(&strChallenge, 1);
  251. StringCharDuplicate(&strMethod, "GET");
  252. StringCharDuplicate(&strURL, AUTH_URI);
  253. StringAllocate(&strHEntity, NULL);
  254. Status = StringAllocate(&strOutBuffer, 4000);
  255. if (!NT_SUCCESS(Status))
  256. {
  257. printf("FAILED: Outputbuffer allocate: status 0x%x\n", Status);
  258. PrintStatus( Status );
  259. bPass = 0;
  260. goto CleanUp;
  261. }
  262. // ZeroMemory(TempTokensIn, sizeof(TempTokensIn));
  263. // ZeroMemory(TempTokensOut, sizeof(TempTokensOut));
  264. ZeroMemory(&InputBuffers, sizeof(InputBuffers));
  265. ZeroMemory(&OutputBuffers, sizeof(OutputBuffers));
  266. InputBuffers.ulVersion = SECBUFFER_VERSION;
  267. InputBuffers.cBuffers = 5;
  268. InputBuffers.pBuffers = TempTokensIn;
  269. TempTokensIn[0].BufferType = SECBUFFER_TOKEN;
  270. TempTokensIn[0].cbBuffer = 0; // for NULL
  271. TempTokensIn[0].pvBuffer = NULL;
  272. TempTokensIn[1].BufferType = SECBUFFER_PKG_PARAMS;
  273. TempTokensIn[1].cbBuffer = 0; // for NULL
  274. TempTokensIn[1].pvBuffer = NULL;
  275. TempTokensIn[2].BufferType = SECBUFFER_PKG_PARAMS;
  276. TempTokensIn[2].cbBuffer = 0; // for NULL
  277. TempTokensIn[2].pvBuffer = NULL;
  278. TempTokensIn[3].BufferType = SECBUFFER_PKG_PARAMS;
  279. TempTokensIn[3].cbBuffer = 0; // strHEntity.Length + 1; // for NULL
  280. TempTokensIn[3].pvBuffer = NULL; // strHEntity.Buffer;
  281. TempTokensIn[4].BufferType = SECBUFFER_PKG_PARAMS;
  282. TempTokensIn[4].cbBuffer = 0; // (wcslen(AUTH_REALM_W) + 1) * sizeof(WCHAR); // Realm size count to use for this challenge
  283. TempTokensIn[4].pvBuffer = NULL; // AUTH_REALM_W; // Realm to use for this challenge
  284. OutputBuffers.ulVersion = SECBUFFER_VERSION;
  285. OutputBuffers.cBuffers = 1;
  286. OutputBuffers.pBuffers = TempTokensOut;
  287. TempTokensOut[0].BufferType = SECBUFFER_TOKEN;
  288. TempTokensOut[0].cbBuffer = 0; // strOutBuffer.MaximumLength; // use any space here
  289. TempTokensOut[0].pvBuffer = NULL; // strOutBuffer.Buffer;
  290. ContextReqFlags = ASC_REQ_REPLAY_DETECT | ASC_REQ_CONNECTION | ASC_REQ_ALLOCATE_MEMORY;
  291. printf("ASC will create the output buffer\n");
  292. Status = AcceptSecurityContext(
  293. &ServerCred,
  294. NULL,
  295. &InputBuffers,
  296. ContextReqFlags,
  297. TargetDataRep,
  298. &ServerCtxtHandle,
  299. &OutputBuffers,
  300. &ContextAttributes,
  301. &Lifetime);
  302. if ((Status != SEC_I_CONTINUE_NEEDED) &&
  303. (Status != STATUS_SUCCESS)) // Indicates that this is the challenge
  304. {
  305. printf("FAILED: SpAcceptLsaModeContext error status 0x%x\n", Status);
  306. PrintStatus( Status );
  307. bPass = 0;
  308. goto CleanUp;
  309. }
  310. if (!OutputBuffers.pBuffers[0].pvBuffer && OutputBuffers.pBuffers[0].cbBuffer)
  311. {
  312. printf("FAILED: SpAcceptLsaModeContext invalid output buffer pointer with length provided\n");
  313. Status = SEC_E_INTERNAL_ERROR;
  314. PrintStatus( Status );
  315. bPass = 0;
  316. goto CleanUp;
  317. }
  318. ZeroMemory(cOutputTemp, STR_BUF_SIZE); // contains the output buffer
  319. ZeroMemory(szChallenge, STR_BUF_SIZE); // contains the output buffer
  320. strncpy(cOutputTemp, (char *)OutputBuffers.pBuffers[0].pvBuffer, OutputBuffers.pBuffers[0].cbBuffer);
  321. cOutputTemp[OutputBuffers.pBuffers[0].cbBuffer] = '\0';
  322. strncpy(szChallenge, (char *)OutputBuffers.pBuffers[0].pvBuffer, OutputBuffers.pBuffers[0].cbBuffer);
  323. szChallenge[OutputBuffers.pBuffers[0].cbBuffer] = '\0';
  324. Status = FreeContextBuffer(OutputBuffers.pBuffers[0].pvBuffer);
  325. if (!NT_SUCCESS(Status))
  326. {
  327. printf("FAILED: FreeContextBuffer error: status 0x%x\n", Status);
  328. TmpStatus = GetLastError();
  329. PrintStatus( Status );
  330. bPass = 0;
  331. goto CleanUp;
  332. }
  333. printf("Context Flags Req 0x%lx Ret 0x%lx\n", ContextReqFlags, ContextAttributes);
  334. printf("Challenge Output Buffer is:\n%s\n\n", cOutputTemp);
  335. MyPrintTime("Server ASC LifeTime: ", Lifetime);
  336. printf("Now call the SSPI InitializeSecCtxt to generate the ChallengeResponse\n");
  337. InputBuffers.ulVersion = SECBUFFER_VERSION;
  338. InputBuffers.cBuffers = 3;
  339. InputBuffers.pBuffers = TempTokensIn;
  340. TempTokensIn[0].BufferType = SECBUFFER_TOKEN;
  341. TempTokensIn[0].cbBuffer = strlen(szChallenge) + 1; // for NULL
  342. TempTokensIn[0].pvBuffer = szChallenge;
  343. TempTokensIn[1].BufferType = SECBUFFER_PKG_PARAMS;
  344. TempTokensIn[1].cbBuffer = strMethod.Length + 1; // for NULL
  345. TempTokensIn[1].pvBuffer = strMethod.Buffer;
  346. TempTokensIn[2].BufferType = SECBUFFER_PKG_PARAMS;
  347. TempTokensIn[2].cbBuffer = 0; // strHEntity.Length + 1; // for NULL
  348. TempTokensIn[2].pvBuffer = NULL; // strHEntity.Buffer;
  349. OutputBuffers.ulVersion = SECBUFFER_VERSION;
  350. OutputBuffers.cBuffers = 1;
  351. OutputBuffers.pBuffers = TempTokensOut;
  352. TempTokensOut[0].BufferType = SECBUFFER_TOKEN;
  353. TempTokensOut[0].cbBuffer = strOutBuffer.MaximumLength; // use any space here
  354. TempTokensOut[0].pvBuffer = strOutBuffer.Buffer;
  355. ContextReqFlags = ISC_REQ_REPLAY_DETECT | ISC_REQ_CONNECTION;
  356. Status = InitializeSecurityContext(&ClientCred,
  357. NULL,
  358. AUTH_URI_W,
  359. ContextReqFlags,
  360. NULL,
  361. SECURITY_NATIVE_DREP,
  362. &InputBuffers,
  363. NULL,
  364. &ClientCtxtHandle,
  365. &OutputBuffers,
  366. &ContextFlagsUtilized,
  367. &Lifetime);
  368. if (!NT_SUCCESS(Status))
  369. {
  370. printf("FAILED: InitializeSecurityContext error: status 0x%x\n", Status);
  371. TmpStatus = GetLastError();
  372. PrintStatus( Status );
  373. bPass = 0;
  374. goto CleanUp;
  375. }
  376. printf("InitializeSecurityContext SUCCEEDED with Context Handle (0x%x,0x%x)\n",
  377. ClientCtxtHandle.dwLower, ClientCtxtHandle.dwUpper );
  378. printf("Context Flags Req 0x%lx Ret 0x%lx\n", ContextReqFlags, ContextFlagsUtilized);
  379. MyPrintTime("Client ISC LifeTime: ", Lifetime);
  380. ZeroMemory(cOutputTemp, STR_BUF_SIZE); // contains the output buffer
  381. ZeroMemory(szChallenge, STR_BUF_SIZE); // contains the output buffer
  382. strncpy(cOutputTemp, (char *)OutputBuffers.pBuffers[0].pvBuffer, OutputBuffers.pBuffers[0].cbBuffer);
  383. cOutputTemp[OutputBuffers.pBuffers[0].cbBuffer] = '\0';
  384. strncpy(szISCChallengeResponse, (char *)OutputBuffers.pBuffers[0].pvBuffer, OutputBuffers.pBuffers[0].cbBuffer);
  385. szISCChallengeResponse[OutputBuffers.pBuffers[0].cbBuffer] = '\0';
  386. printf("\nISC: Challenge Response Output Buffer is\n%s\n\n", szISCChallengeResponse);
  387. InputBuffers.ulVersion = SECBUFFER_VERSION;
  388. InputBuffers.cBuffers = 5;
  389. InputBuffers.pBuffers = TempTokensIn;
  390. TempTokensIn[0].BufferType = SECBUFFER_TOKEN;
  391. TempTokensIn[0].cbBuffer = strlen(cOutputTemp) + 1; // for NULL
  392. TempTokensIn[0].pvBuffer = cOutputTemp;
  393. TempTokensIn[1].BufferType = SECBUFFER_PKG_PARAMS;
  394. TempTokensIn[1].cbBuffer = strMethod.Length + 1; // for NULL
  395. TempTokensIn[1].pvBuffer = strMethod.Buffer;
  396. TempTokensIn[2].BufferType = SECBUFFER_PKG_PARAMS;
  397. TempTokensIn[2].cbBuffer = strURL.Length + 1; // for NULL
  398. TempTokensIn[2].pvBuffer = strURL.Buffer;
  399. TempTokensIn[3].BufferType = SECBUFFER_PKG_PARAMS;
  400. TempTokensIn[3].cbBuffer = 0; // strHEntity.Length + 1; // for NULL
  401. TempTokensIn[3].pvBuffer = NULL; // strHEntity.Buffer;
  402. TempTokensIn[4].BufferType = SECBUFFER_PKG_PARAMS;
  403. TempTokensIn[4].cbBuffer = 0; // Realm not used for challengeresponse
  404. TempTokensIn[4].pvBuffer = NULL; // not used for challengeresponse
  405. OutputBuffers.ulVersion = SECBUFFER_VERSION;
  406. OutputBuffers.cBuffers = 1;
  407. OutputBuffers.pBuffers = TempTokensOut;
  408. TempTokensOut[0].BufferType = SECBUFFER_TOKEN;
  409. TempTokensOut[0].cbBuffer = 0; // strOutBuffer.MaximumLength; // use any space here
  410. TempTokensOut[0].pvBuffer = NULL; // strOutBuffer.Buffer;
  411. ContextReqFlags = ASC_REQ_REPLAY_DETECT | ASC_REQ_CONNECTION | ASC_REQ_ALLOCATE_MEMORY;
  412. printf("Calling the AcceptSC with a ChallengeResponse (should talk to the DC)!\n");
  413. Status = AcceptSecurityContext(
  414. &ServerCred,
  415. NULL,
  416. &InputBuffers,
  417. ContextReqFlags,
  418. TargetDataRep,
  419. &ServerCtxtHandle,
  420. &OutputBuffers,
  421. &ContextAttributes,
  422. &Lifetime);
  423. if (!NT_SUCCESS(Status))
  424. {
  425. printf("FAILED: AcceptSecurityContext 2nd Call: status 0x%x\n", Status);
  426. PrintStatus( Status );
  427. bPass = 0;
  428. goto CleanUp;
  429. }
  430. strcpy(szASCChallengeResponse, (char *)InputBuffers.pBuffers[0].pvBuffer);
  431. printf("ASC has accepted the Challenge Resposne\n");
  432. printf("Now have a valid Security Context handle from ISC and ASC\n\n");
  433. printf("Context Flags Req 0x%lx Ret 0x%lx\n", ContextReqFlags, ContextAttributes);
  434. MyPrintTime("Server ASC LifeTime: ", Lifetime);
  435. Status = FreeContextBuffer(OutputBuffers.pBuffers[0].pvBuffer);
  436. if (!NT_SUCCESS(Status))
  437. {
  438. printf("FAILED: FreeContextBuffer error: status 0x%x\n", Status);
  439. TmpStatus = GetLastError();
  440. PrintStatus( Status );
  441. bPass = 0;
  442. goto CleanUp;
  443. }
  444. // Now get some info on the securitycontexts
  445. Status = QueryContextAttributes(&ServerCtxtHandle, SECPKG_ATTR_NAMES, &SecServerName);
  446. if (!NT_SUCCESS(Status))
  447. {
  448. printf("FAILED: QueryContextAttributes error: status 0x%x\n", Status);
  449. PrintStatus( Status );
  450. bPass = 0;
  451. goto CleanUp;
  452. }
  453. if (SecServerName.sUserName)
  454. {
  455. printf("QueryContextAttributes reports that Username is %S\n", SecServerName.sUserName);
  456. }
  457. // Now get some info on the securitycontexts
  458. Status = QueryContextAttributes(&ServerCtxtHandle, SECPKG_ATTR_PASSWORD_EXPIRY, &SecContextExpiry);
  459. if (!NT_SUCCESS(Status))
  460. {
  461. printf("FAILED: QueryContextAttributes error: status 0x%x\n", Status);
  462. PrintStatus( Status );
  463. bPass = 0;
  464. goto CleanUp;
  465. }
  466. MyPrintTime("QueryContextAttributes reports server context expires: ", SecContextExpiry);
  467. // Now get some info on the securitycontexts
  468. Status = QueryContextAttributes(&ServerCtxtHandle, SECPKG_ATTR_STREAM_SIZES, &StreamSizes);
  469. if (!NT_SUCCESS(Status))
  470. {
  471. printf("FAILED: QueryContextAttributes SECPKG_ATTR_STREAM_SIZES error: status 0x%x\n", Status);
  472. PrintStatus( Status );
  473. bPass = 0;
  474. goto CleanUp;
  475. }
  476. printf("Server Context(StreamSizes): MaxBuf %lu Blocksize %lu\n",
  477. StreamSizes.cbMaximumMessage, StreamSizes.cbBlockSize);
  478. // Now get some info on the securitycontexts
  479. Status = QueryCredentialsAttributes(&ClientCred, SECPKG_CRED_ATTR_NAMES, &SecCredClientName);
  480. if (!NT_SUCCESS(Status))
  481. {
  482. printf("FAILED: QueryCredentialAttributes error: status 0x%x\n", Status);
  483. PrintStatus( Status );
  484. bPass = 0;
  485. goto CleanUp;
  486. }
  487. if (SecCredClientName.sUserName)
  488. {
  489. printf("QueryCredentialAttributes reports that Username is %S\n", SecCredClientName.sUserName);
  490. }
  491. InputBuffers.ulVersion = SECBUFFER_VERSION;
  492. InputBuffers.cBuffers = 5;
  493. InputBuffers.pBuffers = TempTokensIn;
  494. // The first call to MakeSignature this represents the SECOND request on this Nonce!
  495. TempTokensIn[0].BufferType = SECBUFFER_TOKEN;
  496. TempTokensIn[0].cbBuffer = 0; // strlen(szISCChallengeResponse) + 1; // for NULL
  497. TempTokensIn[0].pvBuffer = NULL; // szISCChallengeResponse;
  498. TempTokensIn[1].BufferType = SECBUFFER_PKG_PARAMS;
  499. TempTokensIn[1].cbBuffer = strMethod.Length + 1; // for NULL
  500. TempTokensIn[1].pvBuffer = strMethod.Buffer;
  501. TempTokensIn[2].BufferType = SECBUFFER_PKG_PARAMS;
  502. TempTokensIn[2].cbBuffer = (strlen(AUTH_URI2) + 1) * sizeof(CHAR); // Realm size count to use for this challenge
  503. TempTokensIn[2].pvBuffer = AUTH_URI2; // Realm to use for this challenge
  504. TempTokensIn[3].BufferType = SECBUFFER_PKG_PARAMS;
  505. TempTokensIn[3].cbBuffer = 0; // strHEntity.Length + 1; // for NULL
  506. TempTokensIn[3].pvBuffer = NULL; // strHEntity.Buffer;
  507. TempTokensIn[4].BufferType = SECBUFFER_PKG_PARAMS; // There is no OutputBuffers
  508. TempTokensIn[4].cbBuffer = 4000; // So tack on another bufffer on end for output
  509. TempTokensIn[4].pvBuffer = szOutSecBuf;
  510. Status = MakeSignature(&ClientCtxtHandle,
  511. ulQOP,
  512. &InputBuffers,
  513. 0);
  514. if (!NT_SUCCESS(Status))
  515. {
  516. printf("FAILED: MakeSignature error: status 0x%x\n", Status);
  517. PrintStatus( Status );
  518. bPass = 0;
  519. goto CleanUp;
  520. }
  521. printf("\nMakeSig: Challenge Response Output Buffer for 2nd message is\n%s\n", szOutSecBuf);
  522. // You now send Output buffer to Server - in this case the buffer is szOutSecBuf
  523. printf("Now verify that the 2nd message is Authenticate\n");
  524. // The First message to VerifySignature is the Input to the final call of ASC
  525. strcpy(cOutputTemp, szOutSecBuf);
  526. TempTokensIn[0].BufferType = SECBUFFER_TOKEN;
  527. TempTokensIn[0].cbBuffer = strlen(cOutputTemp) + 1; // for NULL
  528. TempTokensIn[0].pvBuffer = cOutputTemp;
  529. Status = VerifySignature(&ServerCtxtHandle,
  530. &InputBuffers,
  531. ulMessSeqNo,
  532. &ulQOP);
  533. if (!NT_SUCCESS(Status))
  534. {
  535. printf("FAILED: VerifySignature 1st Call error : status 0x%x\n", Status);
  536. PrintStatus( Status );
  537. bPass = 0;
  538. goto CleanUp;
  539. }
  540. printf("Now have a authenticated 1st message under context 0x%x !\n", ServerCtxtHandle);
  541. printf("VerifySig: Check if still OK: Output Buffer (Verify should not have modified it) is\n%s\n\n", cOutputTemp);
  542. Status = VerifySignature(&ServerCtxtHandle,
  543. &InputBuffers,
  544. ulMessSeqNo,
  545. &ulQOP);
  546. if (NT_SUCCESS(Status))
  547. {
  548. printf("FAILED: VerifySignature 2nd Call should not have succeeded status 0x%x\n", Status);
  549. bPass = 0;
  550. goto CleanUp;
  551. }
  552. printf("Verified that replay does not work!!\n");
  553. goto CleanUp;
  554. CleanUp:
  555. printf("Leaving NT Digest testb\n\n\n");
  556. if (pPackageInfo)
  557. {
  558. FreeContextBuffer(pPackageInfo);
  559. }
  560. if (SecServerName.sUserName)
  561. {
  562. FreeContextBuffer(SecServerName.sUserName);
  563. }
  564. if (SecCredClientName.sUserName)
  565. {
  566. FreeContextBuffer(SecCredClientName.sUserName);
  567. }
  568. printf("About to call deletesecuritycontext\n");
  569. //
  570. // Free the security context handle
  571. //
  572. if (ServerCtxtHandle.dwLower || ServerCtxtHandle.dwUpper)
  573. {
  574. Status = DeleteSecurityContext(&ServerCtxtHandle);
  575. if (!NT_SUCCESS(Status))
  576. {
  577. printf("ERROR: DeleteSecurityContext ServerCtxtHandle failed: ");
  578. PrintStatus(Status);
  579. }
  580. }
  581. if (ClientCtxtHandle.dwLower || ClientCtxtHandle.dwUpper)
  582. {
  583. Status = DeleteSecurityContext(&ClientCtxtHandle);
  584. if (!NT_SUCCESS(Status))
  585. {
  586. printf("ERROR: DeleteSecurityContext ClientCtxtHandle failed: ");
  587. PrintStatus(Status);
  588. }
  589. }
  590. //
  591. // Free the credential handles
  592. //
  593. printf("Now calling to Free the ServerCred\n");
  594. if (bServerCred)
  595. {
  596. Status = FreeCredentialsHandle( &ServerCred );
  597. if (!NT_SUCCESS(Status))
  598. {
  599. printf( "FreeCredentialsHandle failed for ServerCred: " );
  600. PrintStatus(Status);
  601. }
  602. }
  603. printf("Now calling to Free the ServerCred\n");
  604. if (bClientCred)
  605. {
  606. Status = FreeCredentialsHandle(&ClientCred);
  607. if (!NT_SUCCESS(Status))
  608. {
  609. printf( "FreeCredentialsHandle failed for ClientCred: " );
  610. PrintStatus( Status );
  611. }
  612. }
  613. StringFree(&strChallenge);
  614. StringFree(&strMethod);
  615. StringFree(&strURL);
  616. StringFree(&strHEntity);
  617. StringFree(&strOutBuffer);
  618. if (bPass != 1)
  619. {
  620. printf("FAILED test run with one or more tests failing.\n");
  621. }
  622. else
  623. {
  624. printf("All tests passed.\n");
  625. }
  626. return 0;
  627. }
  628. void
  629. PrintStatus(
  630. SECURITY_STATUS NetStatus
  631. )
  632. /*++
  633. Routine Description:
  634. Print a net status code.
  635. Arguments:
  636. NetStatus - The net status code to print.
  637. Return Value:
  638. None
  639. --*/
  640. {
  641. printf( "Status = 0x%lx",NetStatus );
  642. switch (NetStatus) {
  643. case ERROR_LOGON_FAILURE:
  644. printf( " ERROR_LOGON_FAILURE" );
  645. break;
  646. case ERROR_ACCESS_DENIED:
  647. printf( " ERROR_ACCESS_DENIED" );
  648. break;
  649. case ERROR_NOT_SUPPORTED:
  650. printf( " ERROR_NOT_SUPPORTED" );
  651. break;
  652. case ERROR_NO_LOGON_SERVERS:
  653. printf( " ERROR_NO_LOGON_SERVERS" );
  654. break;
  655. case ERROR_NO_SUCH_DOMAIN:
  656. printf( " ERROR_NO_SUCH_DOMAIN" );
  657. break;
  658. case ERROR_NO_TRUST_LSA_SECRET:
  659. printf( " ERROR_NO_TRUST_LSA_SECRET" );
  660. break;
  661. case ERROR_NO_TRUST_SAM_ACCOUNT:
  662. printf( " ERROR_NO_TRUST_SAM_ACCOUNT" );
  663. break;
  664. case ERROR_DOMAIN_TRUST_INCONSISTENT:
  665. printf( " ERROR_DOMAIN_TRUST_INCONSISTENT" );
  666. break;
  667. case ERROR_BAD_NETPATH:
  668. printf( " ERROR_BAD_NETPATH" );
  669. break;
  670. case ERROR_FILE_NOT_FOUND:
  671. printf( " ERROR_FILE_NOT_FOUND" );
  672. break;
  673. case SEC_E_NO_SPM:
  674. printf( " SEC_E_NO_SPM" );
  675. break;
  676. case SEC_E_BAD_PKGID:
  677. printf( " SEC_E_BAD_PKGID" ); break;
  678. case SEC_E_NOT_OWNER:
  679. printf( " SEC_E_NOT_OWNER" ); break;
  680. case SEC_E_CANNOT_INSTALL:
  681. printf( " SEC_E_CANNOT_INSTALL" ); break;
  682. case SEC_E_INVALID_TOKEN:
  683. printf( " SEC_E_INVALID_TOKEN" ); break;
  684. case SEC_E_CANNOT_PACK:
  685. printf( " SEC_E_CANNOT_PACK" ); break;
  686. case SEC_E_QOP_NOT_SUPPORTED:
  687. printf( " SEC_E_QOP_NOT_SUPPORTED" ); break;
  688. case SEC_E_NO_IMPERSONATION:
  689. printf( " SEC_E_NO_IMPERSONATION" ); break;
  690. case SEC_E_LOGON_DENIED:
  691. printf( " SEC_E_LOGON_DENIED" ); break;
  692. case SEC_E_UNKNOWN_CREDENTIALS:
  693. printf( " SEC_E_UNKNOWN_CREDENTIALS" ); break;
  694. case SEC_E_NO_CREDENTIALS:
  695. printf( " SEC_E_NO_CREDENTIALS" ); break;
  696. case SEC_E_MESSAGE_ALTERED:
  697. printf( " SEC_E_MESSAGE_ALTERED" ); break;
  698. case SEC_E_OUT_OF_SEQUENCE:
  699. printf( " SEC_E_OUT_OF_SEQUENCE" ); break;
  700. case SEC_E_INSUFFICIENT_MEMORY:
  701. printf( " SEC_E_INSUFFICIENT_MEMORY" ); break;
  702. case SEC_E_INVALID_HANDLE:
  703. printf( " SEC_E_INVALID_HANDLE" ); break;
  704. case SEC_E_NOT_SUPPORTED:
  705. printf( " SEC_E_NOT_SUPPORTED" ); break;
  706. case SEC_I_CONTINUE_NEEDED:
  707. printf( " SEC_I_CONTINUE_NEEDED" ); break;
  708. }
  709. printf( "\n" );
  710. }
  711. void
  712. MyPrintTime(
  713. LPSTR Comment,
  714. TimeStamp ConvertTime
  715. )
  716. /*++
  717. Routine Description:
  718. Print the specified time
  719. Arguments:
  720. Comment - Comment to print in front of the time
  721. Time - Local time to print
  722. Return Value:
  723. None
  724. --*/
  725. {
  726. LARGE_INTEGER LocalTime;
  727. NTSTATUS Status;
  728. printf( "%s High/low 0x%x/0x%x: ", Comment, ConvertTime.HighPart, ConvertTime.LowPart);
  729. //
  730. // If the time is infinite,
  731. // just say so.
  732. //
  733. if ( (ConvertTime.HighPart == 0x7FFFFFFF) && (ConvertTime.LowPart == 0xFFFFFFFF) ) {
  734. printf( "Infinite\n" );
  735. //
  736. // Otherwise print it more clearly
  737. //
  738. } else {
  739. LocalTime.HighPart = 0;
  740. LocalTime.LowPart = 0;
  741. Status = RtlSystemTimeToLocalTime( &ConvertTime, &LocalTime );
  742. if (!NT_SUCCESS( Status )) {
  743. printf( "Can't convert time from GMT to Local time\n" );
  744. LocalTime = ConvertTime;
  745. }
  746. TIME_FIELDS TimeFields;
  747. RtlTimeToTimeFields( &LocalTime, &TimeFields );
  748. printf( "%ld/%ld/%ld %ld:%2.2ld:%2.2ld\n",
  749. TimeFields.Month,
  750. TimeFields.Day,
  751. TimeFields.Year,
  752. TimeFields.Hour,
  753. TimeFields.Minute,
  754. TimeFields.Second );
  755. }
  756. }
  757. // Support Routines
  758. //+-------------------------------------------------------------------------
  759. //
  760. // Function: StringAllocate
  761. //
  762. // Synopsis: Allocates cb chars to STRING Buffer
  763. //
  764. // Arguments: pString - pointer to String to allocate memory to
  765. //
  766. // Returns: STATUS_SUCCESS - Normal completion
  767. //
  768. // Requires:
  769. //
  770. // Effects: allocates memory and sets STRING sizes
  771. //
  772. // Notes: Must call StringFree() to release memory
  773. //
  774. //--------------------------------------------------------------------------
  775. NTSTATUS
  776. StringAllocate(
  777. IN PSTRING pString,
  778. IN USHORT cb
  779. )
  780. {
  781. // DebugLog((DEB_TRACE, "NTDigest:Entering StringAllocate\n"));
  782. NTSTATUS Status = STATUS_SUCCESS;
  783. cb = cb + 1; // Add in extra room for the terminating NULL
  784. if (ARGUMENT_PRESENT(pString))
  785. {
  786. pString->Length = 0;
  787. pString->Buffer = (char *)DigestAllocateMemory((ULONG)(cb * sizeof(CHAR)));
  788. if (pString->Buffer)
  789. {
  790. pString->MaximumLength = cb;
  791. }
  792. else
  793. {
  794. pString->MaximumLength = 0;
  795. Status = STATUS_NO_MEMORY;
  796. goto CleanUp;
  797. }
  798. }
  799. else
  800. {
  801. Status = STATUS_INVALID_PARAMETER;
  802. goto CleanUp;
  803. }
  804. CleanUp:
  805. // DebugLog((DEB_TRACE, "NTDigest: Leaving StringAllocate\n"));
  806. return(Status);
  807. }
  808. //+-------------------------------------------------------------------------
  809. //
  810. // Function: StringFree
  811. //
  812. // Synopsis: Clears a String and releases the memory
  813. //
  814. // Arguments: pString - pointer to String to clear
  815. //
  816. // Returns: SEC_E_OK - released memory succeeded
  817. //
  818. // Requires:
  819. //
  820. // Effects: de-allocates memory with LsaFunctions.AllocateLsaHeap
  821. //
  822. // Notes:
  823. //
  824. //--------------------------------------------------------------------------
  825. NTSTATUS
  826. StringFree(
  827. IN PSTRING pString
  828. )
  829. {
  830. // DebugLog((DEB_TRACE, "NTDigest:Entering StringFree\n"));
  831. NTSTATUS Status = STATUS_SUCCESS;
  832. if (ARGUMENT_PRESENT(pString) &&
  833. (pString->Buffer != NULL))
  834. {
  835. DigestFreeMemory(pString->Buffer);
  836. pString->Length = 0;
  837. pString->MaximumLength = 0;
  838. pString->Buffer = NULL;
  839. }
  840. // DebugLog((DEB_TRACE, "NTDigest: Leaving StringFree\n"));
  841. return(Status);
  842. }
  843. //+-------------------------------------------------------------------------
  844. //
  845. // Function: StringCharDuplicate
  846. //
  847. // Synopsis: Duplicates a NULL terminated char. If the source string buffer is
  848. // NULL the destionation will be too.
  849. //
  850. // Arguments: Destination - Receives a copy of the source NULL Term char *
  851. // czSource - String to copy
  852. //
  853. // Returns: SEC_E_OK - the copy succeeded
  854. // SEC_E_INSUFFICIENT_MEMORY - the call to allocate
  855. // memory failed.
  856. //
  857. // Requires:
  858. //
  859. // Effects: allocates memory with LsaFunctions.AllocateLsaHeap
  860. //
  861. // Notes:
  862. //
  863. //
  864. //--------------------------------------------------------------------------
  865. NTSTATUS
  866. StringCharDuplicate(
  867. OUT PSTRING DestinationString,
  868. IN OPTIONAL char *czSource
  869. )
  870. {
  871. // DebugLog((DEB_TRACE, "NTDigest: Entering StringCharDuplicate\n"));
  872. NTSTATUS Status = STATUS_SUCCESS;
  873. USHORT cbSourceCz = 0;
  874. DestinationString->Buffer = NULL;
  875. DestinationString->Length = 0;
  876. DestinationString->MaximumLength = 0;
  877. if ((ARGUMENT_PRESENT(czSource)) &&
  878. ((cbSourceCz = strlen(czSource)) != 0))
  879. {
  880. DestinationString->Buffer = (LPSTR) DigestAllocateMemory(cbSourceCz + sizeof(CHAR));
  881. if (DestinationString->Buffer != NULL)
  882. {
  883. DestinationString->Length = cbSourceCz;
  884. DestinationString->MaximumLength = cbSourceCz + sizeof(CHAR);
  885. RtlCopyMemory(
  886. DestinationString->Buffer,
  887. czSource,
  888. cbSourceCz
  889. );
  890. DestinationString->Buffer[cbSourceCz/sizeof(CHAR)] = '\0';
  891. }
  892. else
  893. {
  894. Status = STATUS_NO_MEMORY;
  895. // DebugLog((DEB_ERROR, "NTDigest: StringCharDuplicate, DigestAllocateMemory returns NULL\n"));
  896. goto CleanUp;
  897. }
  898. }
  899. CleanUp:
  900. // DebugLog((DEB_TRACE, "NTDigest: Leaving StringCharDuplicate\n"));
  901. return(Status);
  902. }
  903. //+-------------------------------------------------------------------------
  904. //
  905. // Function: DigestAllocateMemory
  906. //
  907. // Synopsis: Allocate memory in either lsa mode or user mode
  908. //
  909. // Effects: Allocated chunk is zeroed out
  910. //
  911. // Arguments:
  912. //
  913. // Requires:
  914. //
  915. // Returns:
  916. //
  917. // Notes:
  918. //
  919. //
  920. //--------------------------------------------------------------------------
  921. PVOID
  922. DigestAllocateMemory(
  923. IN ULONG BufferSize
  924. )
  925. {
  926. PVOID Buffer = NULL;
  927. // DebugLog((DEB_TRACE, "Entering DigestAllocateMemory\n"));
  928. Buffer = LocalAlloc(LPTR, BufferSize);
  929. // DebugLog((DEB_TRACE, "Leaving DigestAllocateMemory\n"));
  930. return Buffer;
  931. }
  932. //+-------------------------------------------------------------------------
  933. //
  934. // Function: NtLmFree
  935. //
  936. // Synopsis: Free memory in either lsa mode or user mode
  937. //
  938. // Effects:
  939. //
  940. // Arguments:
  941. //
  942. // Requires:
  943. //
  944. // Returns:
  945. //
  946. // Notes:
  947. //
  948. //
  949. //--------------------------------------------------------------------------
  950. VOID
  951. DigestFreeMemory(
  952. IN PVOID Buffer
  953. )
  954. {
  955. // DebugLog((DEB_TRACE, "Entering DigestFreeMemory\n"));
  956. LocalFree(Buffer);
  957. // DebugLog((DEB_TRACE, "Leaving DigestFreeMemory\n"));
  958. }
  959. /*
  960. //+-------------------------------------------------------------------------
  961. //
  962. // Function: DecodeUnicodeString
  963. //
  964. // Synopsis: Convert an encoded string into Unicode
  965. //
  966. // Arguments: pstrSource - pointer to String with encoded input
  967. //
  968. // pustrDestination - pointer to a destination Unicode string
  969. //
  970. // Returns: STATUS_SUCCESS - Normal completion
  971. //
  972. // Requires:
  973. //
  974. // Effects: allocates memory and sets UNICODE_STRING sizes
  975. //
  976. // Notes: Must call UnicodeStringFree() to release memory
  977. //
  978. //--------------------------------------------------------------------------
  979. NTSTATUS
  980. DecodeUnicodeString(
  981. IN PSTRING pstrSource,
  982. IN UINT CodePage,
  983. OUT PUNICODE_STRING pustrDestination
  984. )
  985. {
  986. NTSTATUS Status = STATUS_SUCCESS;
  987. int cNumWChars = 0; // number of wide characters
  988. int cb = 0; // number of bytes to allocate
  989. int iRC = 0; // return code
  990. DWORD dwError = 0;
  991. // Handle case if there is no characters to convert
  992. if (!pstrSource->Length)
  993. {
  994. pustrDestination->Length = 0;
  995. pustrDestination->MaximumLength = 0;
  996. pustrDestination->Buffer = NULL;
  997. goto CleanUp;
  998. }
  999. // Determine number of characters needed in unicode string
  1000. cNumWChars = MultiByteToWideChar(CodePage,
  1001. 0,
  1002. pstrSource->Buffer,
  1003. pstrSource->Length,
  1004. NULL,
  1005. 0);
  1006. if (cNumWChars <= 0)
  1007. {
  1008. Status = E_FAIL;
  1009. dwError = GetLastError();
  1010. goto CleanUp;
  1011. }
  1012. Status = UnicodeStringAllocate(pustrDestination, (USHORT)cNumWChars);
  1013. if (!NT_SUCCESS(Status))
  1014. {
  1015. goto CleanUp;
  1016. }
  1017. // We now have the space allocated so convert encoded unicode
  1018. iRC = MultiByteToWideChar(CodePage,
  1019. 0,
  1020. pstrSource->Buffer,
  1021. pstrSource->Length,
  1022. pustrDestination->Buffer,
  1023. cNumWChars);
  1024. if (iRC == 0)
  1025. {
  1026. UnicodeStringFree(pustrDestination); // Free up allocation on error
  1027. Status = E_FAIL;
  1028. dwError = GetLastError();
  1029. goto CleanUp;
  1030. }
  1031. // decoding successful set size of unicode string
  1032. pustrDestination->Length = (USHORT)(iRC * sizeof(WCHAR));
  1033. CleanUp:
  1034. return Status;
  1035. }
  1036. //+-------------------------------------------------------------------------
  1037. //
  1038. // Function: UnicodeStringDuplicate
  1039. //
  1040. // Synopsis: Duplicates a UNICODE_STRING. If the source string buffer is
  1041. // NULL the destionation will be too. Assumes Destination has
  1042. // no string info (called ClearUnicodeString)
  1043. //
  1044. // Arguments: DestinationString - Receives a copy of the source string
  1045. // SourceString - String to copy
  1046. //
  1047. // Returns: SEC_E_OK - the copy succeeded
  1048. // SEC_E_INSUFFICIENT_MEMORY - the call to allocate
  1049. // memory failed.
  1050. //
  1051. // Requires:
  1052. //
  1053. // Effects: allocates memory with DigestAllocateMemory
  1054. //
  1055. // Notes: will add a NULL character to resulting UNICODE_STRING
  1056. //
  1057. //--------------------------------------------------------------------------
  1058. NTSTATUS
  1059. UnicodeStringDuplicate(
  1060. OUT PUNICODE_STRING DestinationString,
  1061. IN OPTIONAL PUNICODE_STRING SourceString
  1062. )
  1063. {
  1064. // DebugLog((DEB_TRACE, "NTDigest:Entering DuplicateUnicodeString\n"));
  1065. NTSTATUS Status = STATUS_SUCCESS;
  1066. DestinationString->Buffer = NULL;
  1067. DestinationString->Length = 0;
  1068. DestinationString->MaximumLength = 0;
  1069. if ((ARGUMENT_PRESENT(SourceString)) &&
  1070. (SourceString->Buffer != NULL))
  1071. {
  1072. DestinationString->Buffer = (LPWSTR) DigestAllocateMemory(SourceString->Length + sizeof(WCHAR));
  1073. if (DestinationString->Buffer != NULL)
  1074. {
  1075. DestinationString->Length = SourceString->Length;
  1076. DestinationString->MaximumLength = SourceString->Length + sizeof(WCHAR);
  1077. RtlCopyMemory(
  1078. DestinationString->Buffer,
  1079. SourceString->Buffer,
  1080. SourceString->Length
  1081. );
  1082. DestinationString->Buffer[SourceString->Length/sizeof(WCHAR)] = L'\0';
  1083. }
  1084. else
  1085. {
  1086. Status = SEC_E_INSUFFICIENT_MEMORY;
  1087. goto CleanUp;
  1088. }
  1089. }
  1090. CleanUp:
  1091. // DebugLog((DEB_TRACE, "NTDigest: Leaving UnicodeStringDuplicate\n"));
  1092. return(Status);
  1093. }
  1094. //+-------------------------------------------------------------------------
  1095. //
  1096. // Function: UnicodeStringAllocate
  1097. //
  1098. // Synopsis: Allocates cb wide chars to STRING Buffer
  1099. //
  1100. // Arguments: pString - pointer to String to allocate memory to
  1101. //
  1102. // Returns: STATUS_SUCCESS - Normal completion
  1103. //
  1104. // Requires:
  1105. //
  1106. // Effects: allocates memory and sets STRING sizes
  1107. //
  1108. // Notes: Must call StringFree() to release memory
  1109. //
  1110. //--------------------------------------------------------------------------
  1111. NTSTATUS
  1112. UnicodeStringAllocate(
  1113. IN PUNICODE_STRING pString,
  1114. IN USHORT cNumWChars
  1115. )
  1116. {
  1117. // DebugLog((DEB_TRACE, "Entering UnicodeStringAllocate\n"));
  1118. NTSTATUS Status = STATUS_SUCCESS;
  1119. USHORT cb = 0;
  1120. cb = cNumWChars + 1; // Add in extra room for the terminating NULL
  1121. cb = cb * sizeof(WCHAR); // now convert to wide characters
  1122. if (ARGUMENT_PRESENT(pString))
  1123. {
  1124. pString->Length = 0;
  1125. pString->Buffer = (PWSTR)DigestAllocateMemory((ULONG)(cb));
  1126. if (pString->Buffer)
  1127. {
  1128. pString->MaximumLength = cb; // this value is in terms of bytes not WCHAR count
  1129. }
  1130. else
  1131. {
  1132. pString->MaximumLength = 0;
  1133. Status = SEC_E_INSUFFICIENT_MEMORY;
  1134. goto CleanUp;
  1135. }
  1136. }
  1137. else
  1138. {
  1139. Status = STATUS_INVALID_PARAMETER;
  1140. goto CleanUp;
  1141. }
  1142. CleanUp:
  1143. return(Status);
  1144. }
  1145. //+-------------------------------------------------------------------------
  1146. //
  1147. // Function: UnicodeStringClear
  1148. //
  1149. // Synopsis: Clears a UnicodeString and releases the memory
  1150. //
  1151. // Arguments: pString - pointer to UnicodeString to clear
  1152. //
  1153. // Returns: SEC_E_OK - released memory succeeded
  1154. //
  1155. // Requires:
  1156. //
  1157. // Effects: de-allocates memory with LsaFunctions.AllocateLsaHeap
  1158. //
  1159. // Notes:
  1160. //
  1161. //--------------------------------------------------------------------------
  1162. NTSTATUS
  1163. UnicodeStringFree(
  1164. OUT PUNICODE_STRING pString
  1165. )
  1166. {
  1167. NTSTATUS Status = STATUS_SUCCESS;
  1168. if (ARGUMENT_PRESENT(pString) &&
  1169. (pString->Buffer != NULL))
  1170. {
  1171. DigestFreeMemory(pString->Buffer);
  1172. pString->Length = 0;
  1173. pString->MaximumLength = 0;
  1174. pString->Buffer = NULL;
  1175. }
  1176. return(Status);
  1177. }
  1178. */