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.

400 lines
8.6 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 ULONG TickStart,
  63. IN ULONG Timeout
  64. )
  65. /*++
  66. Routine Description:
  67. Determine if "Timeout" milliseconds have elapsed since TickStart.
  68. Arguments:
  69. TickStart - Specifies a tick count when the event started in milliseconds.
  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 TickStart.
  74. --*/
  75. {
  76. ULONG TickNow = 0;
  77. TickNow = GetTickCount();
  78. //
  79. // TickNow < TickStart means TickCount is wrapped around (happens very
  80. // 49.7 days)
  81. //
  82. // We assume the interim between the Init/Accept calls with the same
  83. // context can have at most one wrapping around
  84. //
  85. if ( (TickNow > TickStart && TickNow - TickStart > TickNow) ||
  86. (TickNow < TickStart && 0xFFFFFFFF - TickStart + TickNow > Timeout) ) {
  87. return TRUE;
  88. }
  89. return FALSE;
  90. }
  91. SECURITY_STATUS
  92. SspDuplicateToken(
  93. IN HANDLE OriginalToken,
  94. IN SECURITY_IMPERSONATION_LEVEL ImpersonationLevel,
  95. OUT PHANDLE DuplicatedToken
  96. )
  97. /*++
  98. Routine Description:
  99. Duplicates a token
  100. Arguments:
  101. OriginalToken - Token to duplicate
  102. DuplicatedToken - Receives handle to duplicated token
  103. Return Value:
  104. Any error from NtDuplicateToken
  105. --*/
  106. {
  107. NTSTATUS Status;
  108. OBJECT_ATTRIBUTES ObjectAttributes;
  109. SECURITY_QUALITY_OF_SERVICE QualityOfService;
  110. InitializeObjectAttributes(
  111. &ObjectAttributes,
  112. NULL,
  113. 0,
  114. NULL,
  115. NULL
  116. );
  117. QualityOfService.Length = sizeof(SECURITY_QUALITY_OF_SERVICE);
  118. QualityOfService.EffectiveOnly = FALSE;
  119. QualityOfService.ContextTrackingMode = SECURITY_STATIC_TRACKING;
  120. QualityOfService.ImpersonationLevel = ImpersonationLevel;
  121. ObjectAttributes.SecurityQualityOfService = &QualityOfService;
  122. Status = NtDuplicateToken(
  123. OriginalToken,
  124. SSP_TOKEN_ACCESS,
  125. &ObjectAttributes,
  126. FALSE,
  127. TokenImpersonation,
  128. DuplicatedToken
  129. );
  130. return(SspNtStatusToSecStatus(Status, SEC_E_NO_IMPERSONATION));
  131. }
  132. LPWSTR
  133. SspAllocWStrFromWStr(
  134. IN LPWSTR Unicode
  135. )
  136. /*++
  137. Routine Description:
  138. Allocate and copy unicode string (wide character strdup)
  139. Arguments:
  140. Unicode - pointer to wide character string to make copy of
  141. Return Value:
  142. NULL - There was some error in the conversion.
  143. Otherwise, it returns a pointer to the zero terminated UNICODE string in
  144. an allocated buffer. The buffer must be freed using NtLmFree.
  145. --*/
  146. {
  147. DWORD Size;
  148. LPWSTR ptr;
  149. Size = (DWORD) WCSSIZE(Unicode);
  150. ptr = (LPWSTR)NtLmAllocate(Size);
  151. if ( ptr != NULL) {
  152. RtlCopyMemory(ptr, Unicode, Size);
  153. }
  154. return ptr;
  155. }
  156. VOID
  157. SspHidePassword(
  158. IN OUT PUNICODE_STRING Password
  159. )
  160. /*++
  161. Routine Description:
  162. Run-encodes the password so that it is not very visually
  163. distinguishable. This is so that if it makes it to a
  164. paging file, it wont be obvious.
  165. WARNING - This routine will use the upper portion of the
  166. password's length field to store the seed used in encoding
  167. password. Be careful you don't pass such a string to
  168. a routine that looks at the length (like and RPC routine).
  169. Arguments:
  170. Seed - The seed to use to hide the password.
  171. PasswordSource - Contains password to hide.
  172. Return Value:
  173. --*/
  174. {
  175. SspPrint((SSP_API_MORE, "Entering SspHidePassword\n"));
  176. if( (Password->Length != 0) && (Password->MaximumLength != 0) )
  177. {
  178. LsaFunctions->LsaProtectMemory( Password->Buffer, (ULONG)Password->MaximumLength );
  179. }
  180. SspPrint((SSP_API_MORE, "Leaving SspHidePassword\n"));
  181. }
  182. VOID
  183. SspRevealPassword(
  184. IN OUT PUNICODE_STRING HiddenPassword
  185. )
  186. /*++
  187. Routine Description
  188. Reveals a previously hidden password so that it
  189. is plain text once again.
  190. Arguments:
  191. HiddenPassword - Contains the password to reveal
  192. Return Value
  193. --*/
  194. {
  195. SspPrint((SSP_API_MORE, "Entering SspRevealPassword\n"));
  196. if( (HiddenPassword->Length != 0) && (HiddenPassword->MaximumLength != 0) )
  197. {
  198. LsaFunctions->LsaUnprotectMemory( HiddenPassword->Buffer, (ULONG)HiddenPassword->MaximumLength );
  199. }
  200. SspPrint((SSP_API_MORE, "Leaving SspRevealPassword\n"));
  201. }
  202. BOOLEAN
  203. SspGetTokenBuffer(
  204. IN PSecBufferDesc TokenDescriptor OPTIONAL,
  205. IN ULONG BufferIndex,
  206. OUT PSecBuffer * Token,
  207. IN BOOLEAN ReadonlyOK
  208. )
  209. /*++
  210. Routine Description:
  211. This routine parses a Token Descriptor and pulls out the useful
  212. information.
  213. Arguments:
  214. TokenDescriptor - Descriptor of the buffer containing (or to contain) the
  215. token. If not specified, TokenBuffer and TokenSize will be returned
  216. as NULL.
  217. TokenBuffer - Returns a pointer to the buffer for the token.
  218. TokenSize - Returns a pointer to the location of the size of the buffer.
  219. ReadonlyOK - TRUE if the token buffer may be readonly.
  220. Return Value:
  221. TRUE - If token buffer was properly found.
  222. --*/
  223. {
  224. ULONG i, Index = 0;
  225. //
  226. // If there is no TokenDescriptor passed in,
  227. // just pass out NULL to our caller.
  228. //
  229. ASSERT(*Token != NULL);
  230. if ( !ARGUMENT_PRESENT( TokenDescriptor) ) {
  231. return TRUE;
  232. }
  233. if (TokenDescriptor->ulVersion != SECBUFFER_VERSION)
  234. {
  235. return FALSE;
  236. }
  237. //
  238. // Loop through each described buffer.
  239. //
  240. for ( i=0; i<TokenDescriptor->cBuffers ; i++ ) {
  241. PSecBuffer Buffer = &TokenDescriptor->pBuffers[i];
  242. if ( (Buffer->BufferType & (~SECBUFFER_ATTRMASK)) == SECBUFFER_TOKEN ) {
  243. //
  244. // If the buffer is readonly and readonly isn't OK,
  245. // reject the buffer.
  246. //
  247. if (!ReadonlyOK && (Buffer->BufferType & SECBUFFER_READONLY))
  248. {
  249. return FALSE;
  250. }
  251. //
  252. // It is possible that there are > 1 buffers of type SECBUFFER_TOKEN
  253. // eg, the rdr
  254. //
  255. if (Index != BufferIndex)
  256. {
  257. Index++;
  258. continue;
  259. }
  260. //
  261. // Return the requested information
  262. //
  263. if (!NT_SUCCESS(LsaFunctions->MapBuffer(Buffer, Buffer)))
  264. {
  265. return FALSE;
  266. }
  267. *Token = Buffer;
  268. return TRUE;
  269. }
  270. }
  271. //
  272. // If we didn't have a buffer, fine.
  273. //
  274. SspPrint((SSP_API_MORE, "SspGetTokenBuffer: No token passed in\n"));
  275. return TRUE;
  276. }