Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

422 lines
8.7 KiB

  1. /*++
  2. Copyright (c) 1987-1993 Microsoft Corporation
  3. Module Name:
  4. utility.cxx
  5. Abstract:
  6. Private NtLmSsp service utility routines.
  7. Author:
  8. Cliff Van Dyke (cliffv) 9-Jun-1993
  9. Environment:
  10. User mode only.
  11. Contains NT-specific code.
  12. Requires ANSI C extensions: slash-slash comments, long external names.
  13. Revision History:
  14. ChandanS 06-Aug-1996 Stolen from net\svcdlls\ntlmssp\common\utility.c
  15. --*/
  16. //
  17. // Common include files.
  18. //
  19. #include <global.h>
  20. //
  21. // Include files specific to this .c file
  22. //
  23. #include <netlib.h> // NetpMemoryFree()
  24. #include <secobj.h> // ACE_DATA ...
  25. #include <stdio.h> // vsprintf().
  26. #include <tstr.h> // TCHAR_ equates.
  27. #define SSP_TOKEN_ACCESS (READ_CONTROL |\
  28. WRITE_DAC |\
  29. TOKEN_DUPLICATE |\
  30. TOKEN_IMPERSONATE |\
  31. TOKEN_QUERY |\
  32. TOKEN_QUERY_SOURCE |\
  33. TOKEN_ADJUST_PRIVILEGES |\
  34. TOKEN_ADJUST_GROUPS |\
  35. TOKEN_ADJUST_DEFAULT)
  36. #if DBG
  37. SECURITY_STATUS
  38. SspNtStatusToSecStatus(
  39. IN NTSTATUS NtStatus,
  40. IN SECURITY_STATUS DefaultStatus
  41. )
  42. /*++
  43. Routine Description:
  44. Convert an NtStatus code to the corresponding Security status code. For
  45. particular errors that are required to be returned as is (for setup code)
  46. don't map the errors.
  47. Arguments:
  48. NtStatus - NT status to convert
  49. Return Value:
  50. Returns security status code.
  51. --*/
  52. {
  53. //
  54. // this routine is left here for DBG builds to enable the developer
  55. // to ASSERT on status codes, etc.
  56. //
  57. return(NtStatus);
  58. }
  59. #endif
  60. BOOLEAN
  61. SspTimeHasElapsed(
  62. IN LARGE_INTEGER StartTime,
  63. IN DWORD Timeout
  64. )
  65. /*++
  66. Routine Description:
  67. Determine if "Timeout" milliseconds have elapsed since StartTime.
  68. Arguments:
  69. StartTime - Specifies an absolute time when the event started (100ns units).
  70. Timeout - Specifies a relative time in milliseconds. 0xFFFFFFFF indicates
  71. that the time will never expire.
  72. Return Value:
  73. TRUE -- iff Timeout milliseconds have elapsed since StartTime.
  74. --*/
  75. {
  76. LARGE_INTEGER TimeNow;
  77. LARGE_INTEGER ElapsedTime;
  78. LARGE_INTEGER Period;
  79. //
  80. // If the period to too large to handle (i.e., 0xffffffff is forever),
  81. // just indicate that the timer has not expired.
  82. //
  83. // (0x7fffffff is a little over 24 days).
  84. //
  85. if ( Timeout> 0x7fffffff ) {
  86. return FALSE;
  87. }
  88. //
  89. // Compute the elapsed time
  90. //
  91. NtQuerySystemTime( &TimeNow );
  92. ElapsedTime.QuadPart = TimeNow.QuadPart - StartTime.QuadPart;
  93. //
  94. // Convert Timeout from milliseconds into 100ns units.
  95. //
  96. Period.QuadPart = Int32x32To64( (LONG)Timeout, 10000 );
  97. //
  98. // If the elapsed time is negative (totally bogus),
  99. // or greater than the maximum allowed,
  100. // indicate the period has elapsed.
  101. //
  102. if ( ElapsedTime.QuadPart < 0 || ElapsedTime.QuadPart > Period.QuadPart ) {
  103. return TRUE;
  104. }
  105. return FALSE;
  106. }
  107. SECURITY_STATUS
  108. SspDuplicateToken(
  109. IN HANDLE OriginalToken,
  110. IN SECURITY_IMPERSONATION_LEVEL ImpersonationLevel,
  111. OUT PHANDLE DuplicatedToken
  112. )
  113. /*++
  114. Routine Description:
  115. Duplicates a token
  116. Arguments:
  117. OriginalToken - Token to duplicate
  118. DuplicatedToken - Receives handle to duplicated token
  119. Return Value:
  120. Any error from NtDuplicateToken
  121. --*/
  122. {
  123. NTSTATUS Status;
  124. OBJECT_ATTRIBUTES ObjectAttributes;
  125. SECURITY_QUALITY_OF_SERVICE QualityOfService;
  126. InitializeObjectAttributes(
  127. &ObjectAttributes,
  128. NULL,
  129. 0,
  130. NULL,
  131. NULL
  132. );
  133. QualityOfService.Length = sizeof(SECURITY_QUALITY_OF_SERVICE);
  134. QualityOfService.EffectiveOnly = FALSE;
  135. QualityOfService.ContextTrackingMode = SECURITY_STATIC_TRACKING;
  136. QualityOfService.ImpersonationLevel = ImpersonationLevel;
  137. ObjectAttributes.SecurityQualityOfService = &QualityOfService;
  138. Status = NtDuplicateToken(
  139. OriginalToken,
  140. SSP_TOKEN_ACCESS,
  141. &ObjectAttributes,
  142. FALSE,
  143. TokenImpersonation,
  144. DuplicatedToken
  145. );
  146. return(SspNtStatusToSecStatus(Status, SEC_E_NO_IMPERSONATION));
  147. }
  148. LPWSTR
  149. SspAllocWStrFromWStr(
  150. IN LPWSTR Unicode
  151. )
  152. /*++
  153. Routine Description:
  154. Allocate and copy unicode string (wide character strdup)
  155. Arguments:
  156. Unicode - pointer to wide character string to make copy of
  157. Return Value:
  158. NULL - There was some error in the conversion.
  159. Otherwise, it returns a pointer to the zero terminated UNICODE string in
  160. an allocated buffer. The buffer must be freed using NtLmFree.
  161. --*/
  162. {
  163. DWORD Size;
  164. LPWSTR ptr;
  165. Size = WCSSIZE(Unicode);
  166. ptr = (LPWSTR)NtLmAllocate(Size);
  167. if ( ptr != NULL) {
  168. RtlCopyMemory(ptr, Unicode, Size);
  169. }
  170. return ptr;
  171. }
  172. VOID
  173. SspHidePassword(
  174. IN OUT PUNICODE_STRING Password
  175. )
  176. /*++
  177. Routine Description:
  178. Run-encodes the password so that it is not very visually
  179. distinguishable. This is so that if it makes it to a
  180. paging file, it wont be obvious.
  181. WARNING - This routine will use the upper portion of the
  182. password's length field to store the seed used in encoding
  183. password. Be careful you don't pass such a string to
  184. a routine that looks at the length (like and RPC routine).
  185. Arguments:
  186. Seed - The seed to use to hide the password.
  187. PasswordSource - Contains password to hide.
  188. Return Value:
  189. --*/
  190. {
  191. SspPrint((SSP_API_MORE, "Entering SspHidePassword\n"));
  192. if( (Password->Length != 0) && (Password->MaximumLength != 0) )
  193. {
  194. LsaFunctions->LsaProtectMemory( Password->Buffer, (ULONG)Password->MaximumLength );
  195. }
  196. SspPrint((SSP_API_MORE, "Leaving SspHidePassword\n"));
  197. }
  198. VOID
  199. SspRevealPassword(
  200. IN OUT PUNICODE_STRING HiddenPassword
  201. )
  202. /*++
  203. Routine Description
  204. Reveals a previously hidden password so that it
  205. is plain text once again.
  206. Arguments:
  207. HiddenPassword - Contains the password to reveal
  208. Return Value
  209. --*/
  210. {
  211. SspPrint((SSP_API_MORE, "Entering SspRevealPassword\n"));
  212. if( (HiddenPassword->Length != 0) && (HiddenPassword->MaximumLength != 0) )
  213. {
  214. LsaFunctions->LsaUnprotectMemory( HiddenPassword->Buffer, (ULONG)HiddenPassword->MaximumLength );
  215. }
  216. SspPrint((SSP_API_MORE, "Leaving SspRevealPassword\n"));
  217. }
  218. BOOLEAN
  219. SspGetTokenBuffer(
  220. IN PSecBufferDesc TokenDescriptor OPTIONAL,
  221. IN ULONG BufferIndex,
  222. OUT PSecBuffer * Token,
  223. IN BOOLEAN ReadonlyOK
  224. )
  225. /*++
  226. Routine Description:
  227. This routine parses a Token Descriptor and pulls out the useful
  228. information.
  229. Arguments:
  230. TokenDescriptor - Descriptor of the buffer containing (or to contain) the
  231. token. If not specified, TokenBuffer and TokenSize will be returned
  232. as NULL.
  233. TokenBuffer - Returns a pointer to the buffer for the token.
  234. TokenSize - Returns a pointer to the location of the size of the buffer.
  235. ReadonlyOK - TRUE if the token buffer may be readonly.
  236. Return Value:
  237. TRUE - If token buffer was properly found.
  238. --*/
  239. {
  240. ULONG i, Index = 0;
  241. //
  242. // If there is no TokenDescriptor passed in,
  243. // just pass out NULL to our caller.
  244. //
  245. ASSERT(*Token != NULL);
  246. if ( !ARGUMENT_PRESENT( TokenDescriptor) ) {
  247. return TRUE;
  248. }
  249. if (TokenDescriptor->ulVersion != SECBUFFER_VERSION)
  250. {
  251. return FALSE;
  252. }
  253. //
  254. // Loop through each described buffer.
  255. //
  256. for ( i=0; i<TokenDescriptor->cBuffers ; i++ ) {
  257. PSecBuffer Buffer = &TokenDescriptor->pBuffers[i];
  258. if ( (Buffer->BufferType & (~SECBUFFER_ATTRMASK)) == SECBUFFER_TOKEN ) {
  259. //
  260. // If the buffer is readonly and readonly isn't OK,
  261. // reject the buffer.
  262. //
  263. if (!ReadonlyOK && (Buffer->BufferType & SECBUFFER_READONLY))
  264. {
  265. return FALSE;
  266. }
  267. //
  268. // It is possible that there are > 1 buffers of type SECBUFFER_TOKEN
  269. // eg, the rdr
  270. //
  271. if (Index != BufferIndex)
  272. {
  273. Index++;
  274. continue;
  275. }
  276. //
  277. // Return the requested information
  278. //
  279. if (!NT_SUCCESS(LsaFunctions->MapBuffer(Buffer, Buffer)))
  280. {
  281. return FALSE;
  282. }
  283. *Token = Buffer;
  284. return TRUE;
  285. }
  286. }
  287. //
  288. // If we didn't have a buffer, fine.
  289. //
  290. SspPrint((SSP_API_MORE, "SspGetTokenBuffer: No token passed in\n"));
  291. return TRUE;
  292. }