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.

535 lines
12 KiB

  1. /*++
  2. Copyright (c) 1993 Microsoft Corporation
  3. Module Name:
  4. Util.c
  5. Abstract:
  6. This module contains utilities function for the netware redirector.
  7. Author:
  8. Manny Weiser [MannyW] 07-Jan-1994
  9. Revision History:
  10. --*/
  11. #include "Procs.h"
  12. //
  13. // The local debug trace level
  14. //
  15. #define Dbg (DEBUG_TRACE_CONVERT)
  16. #ifdef ALLOC_PRAGMA
  17. #ifndef QFE_BUILD
  18. #pragma alloc_text( PAGE1, CopyBufferToMdl )
  19. #endif
  20. #endif
  21. #if 0 // Not pageable
  22. // see ifndef QFE_BUILD above
  23. #endif
  24. VOID
  25. CopyBufferToMdl(
  26. PMDL DestinationMdl,
  27. ULONG DataOffset,
  28. PUCHAR SourceData,
  29. ULONG SourceByteCount
  30. )
  31. /*++
  32. Routine Description:
  33. This routine copies data from a buffer described by a pointer to a
  34. given offset in a buffer described by an MDL.
  35. Arguments:
  36. DestinationMdl - The MDL for the destination buffer.
  37. DataOffset - The offset into the destination buffer to copy the data.
  38. SourceData - A pointer to the source data buffer.
  39. SourceByteCount - The number of bytes to copy.
  40. Return Value:
  41. None.
  42. --*/
  43. {
  44. ULONG BufferOffset;
  45. ULONG PreviousBufferOffset;
  46. PMDL Mdl;
  47. ULONG BytesToCopy;
  48. ULONG MdlByteCount;
  49. PVOID pSystemVa;
  50. DebugTrace( +1, Dbg, "MdlMoveMemory...\n", 0 );
  51. DebugTrace( 0, Dbg, "Desitination MDL = %X\n", DestinationMdl );
  52. DebugTrace( 0, Dbg, "DataOffset = %d\n", DataOffset );
  53. DebugTrace( 0, Dbg, "SourceData = %X\n", SourceData );
  54. DebugTrace( 0, Dbg, "SourceByteCount = %d\n", SourceByteCount );
  55. BufferOffset = 0;
  56. Mdl = DestinationMdl;
  57. //
  58. // Truncate the response if it is too big.
  59. //
  60. MdlByteCount = MdlLength( Mdl );
  61. if ( SourceByteCount + DataOffset > MdlByteCount ) {
  62. SourceByteCount = MdlByteCount - DataOffset;
  63. }
  64. while ( Mdl != NULL && SourceByteCount != 0 ) {
  65. PreviousBufferOffset = BufferOffset;
  66. BufferOffset += MmGetMdlByteCount( Mdl );
  67. if ( DataOffset < BufferOffset ) {
  68. //
  69. // Copy the data to this buffer
  70. //
  71. while ( SourceByteCount > 0 ) {
  72. BytesToCopy = MIN( SourceByteCount,
  73. BufferOffset - DataOffset );
  74. pSystemVa = MmGetSystemAddressForMdlSafe( Mdl, NormalPagePriority );
  75. DebugTrace( 0, Dbg, "Copy to %X\n", (PUCHAR) pSystemVa +
  76. DataOffset -
  77. PreviousBufferOffset );
  78. DebugTrace( 0, Dbg, "Copy from %X\n", SourceData );
  79. DebugTrace( 0, Dbg, "Copy bytes %d\n", BytesToCopy );
  80. TdiCopyLookaheadData(
  81. (PUCHAR)pSystemVa + DataOffset - PreviousBufferOffset,
  82. SourceData,
  83. BytesToCopy,
  84. 0 );
  85. SourceData += BytesToCopy;
  86. DataOffset += BytesToCopy;
  87. SourceByteCount -= BytesToCopy;
  88. Mdl = Mdl->Next;
  89. if ( Mdl != NULL ) {
  90. PreviousBufferOffset = BufferOffset;
  91. BufferOffset += MmGetMdlByteCount( Mdl );
  92. } else {
  93. ASSERT( SourceByteCount == 0 );
  94. }
  95. }
  96. } else {
  97. Mdl = Mdl->Next;
  98. }
  99. }
  100. DebugTrace( -1, Dbg, "MdlMoveMemory -> VOID\n", 0 );
  101. }
  102. //
  103. // These parsing routines are used to do multiple credential
  104. // connects to a single server.
  105. //
  106. NTSTATUS
  107. GetCredentialFromServerName(
  108. IN PUNICODE_STRING puServerName,
  109. OUT PUNICODE_STRING puCredentialName
  110. )
  111. /*+++
  112. Description: Given a munged server(credential) name,
  113. this routine returns the credential.
  114. ---*/
  115. {
  116. DWORD NameLength = 0;
  117. BOOLEAN FoundFirstParen = FALSE;
  118. BOOLEAN FoundLastParen = FALSE;
  119. DebugTrace( 0, Dbg, "GetCredentialFromServerName: %wZ\n", puServerName );
  120. puCredentialName->Length = puServerName->Length;
  121. puCredentialName->Buffer = puServerName->Buffer;
  122. //
  123. // Find the first paren.
  124. //
  125. while ( ( puCredentialName->Length ) && !FoundFirstParen ) {
  126. if ( puCredentialName->Buffer[0] == L'(' ) {
  127. FoundFirstParen = TRUE;
  128. }
  129. puCredentialName->Buffer++;
  130. puCredentialName->Length -= sizeof( WCHAR );
  131. }
  132. if ( !FoundFirstParen ) {
  133. DebugTrace( 0, Dbg, "No opening paren for server(credential) name.\n", 0 );
  134. return STATUS_UNSUCCESSFUL;
  135. }
  136. //
  137. // Figure out the name length.
  138. //
  139. while ( ( puCredentialName->Length ) && !FoundLastParen ) {
  140. if ( puCredentialName->Buffer[NameLength] == L')' ) {
  141. FoundLastParen = TRUE;
  142. }
  143. NameLength++;
  144. puCredentialName->Length -= sizeof( WCHAR );
  145. }
  146. if ( !FoundLastParen ) {
  147. DebugTrace( 0, Dbg, "No closing paren for server(credential) name.\n", 0 );
  148. return STATUS_UNSUCCESSFUL;
  149. }
  150. //
  151. // Format the name and return. Don't count the closing paren.
  152. //
  153. NameLength--;
  154. if ( !NameLength ) {
  155. DebugTrace( 0, Dbg, "Null credential name.\n", 0 );
  156. return STATUS_UNSUCCESSFUL;
  157. }
  158. puCredentialName->Length = (USHORT) (NameLength * sizeof( WCHAR ));
  159. puCredentialName->MaximumLength = puCredentialName->Length;
  160. DebugTrace( 0, Dbg, "GetCredentialFromServerName --> %wZ\n", puCredentialName );
  161. return STATUS_SUCCESS;
  162. }
  163. NTSTATUS
  164. BuildExCredentialServerName(
  165. IN PUNICODE_STRING puServerName,
  166. IN PUNICODE_STRING puUserName,
  167. OUT PUNICODE_STRING puExCredServerName
  168. )
  169. /*+++
  170. Description:
  171. Takes a server name and a user name and makes an
  172. ExCredServerName, which is simply: server(user)
  173. This routine allocates memory for the credential
  174. server name and the caller is responsible for
  175. freeing the memory when it is no longer needed.
  176. ---*/
  177. {
  178. NTSTATUS Status;
  179. PBYTE pbCredNameBuffer;
  180. DebugTrace( 0, Dbg, "BuildExCredentialServerName\n", 0 );
  181. if ( ( !puExCredServerName ) ||
  182. ( !puServerName ) ||
  183. ( !puUserName ) ) {
  184. DebugTrace( 0, DEBUG_TRACE_ALWAYS, "BuildExCredentialServerName -> STATUS_INVALID_PARAMETER\n", 0 );
  185. return STATUS_INVALID_PARAMETER;
  186. }
  187. puExCredServerName->MaximumLength = puServerName->Length +
  188. puUserName->Length +
  189. ( 2 * sizeof( WCHAR ) );
  190. pbCredNameBuffer = ALLOCATE_POOL( PagedPool,
  191. puExCredServerName->MaximumLength );
  192. if ( pbCredNameBuffer == NULL ) {
  193. return STATUS_INSUFFICIENT_RESOURCES;
  194. }
  195. puExCredServerName->Buffer = (PWCHAR) pbCredNameBuffer;
  196. puExCredServerName->Length = puExCredServerName->MaximumLength;
  197. //
  198. // Copy over the server name.
  199. //
  200. RtlCopyMemory( pbCredNameBuffer,
  201. puServerName->Buffer,
  202. puServerName->Length );
  203. pbCredNameBuffer += puServerName->Length;
  204. //
  205. // Add the credential name in parenthesis.
  206. //
  207. *( (PWCHAR) pbCredNameBuffer ) = L'(';
  208. pbCredNameBuffer += sizeof( WCHAR );
  209. RtlCopyMemory( pbCredNameBuffer,
  210. puUserName->Buffer,
  211. puUserName->Length );
  212. pbCredNameBuffer += puUserName->Length;
  213. *( (PWCHAR) pbCredNameBuffer ) = L')';
  214. DebugTrace( 0, Dbg, "BuildExCredentialServerName: %wZ\n", puExCredServerName );
  215. return STATUS_SUCCESS;
  216. }
  217. NTSTATUS
  218. UnmungeCredentialName(
  219. IN PUNICODE_STRING puCredName,
  220. OUT PUNICODE_STRING puServerName
  221. )
  222. /*+++
  223. Description:
  224. Given server(username), return the server
  225. name portion.
  226. ---*/
  227. {
  228. USHORT Length = 0;
  229. DebugTrace( 0, Dbg, "UnmungeCredentialName: %wZ\n", puCredName );
  230. puServerName->Buffer = puCredName->Buffer;
  231. puServerName->MaximumLength = puCredName->MaximumLength;
  232. while ( Length < ( puCredName->Length / sizeof( WCHAR ) ) ) {
  233. //
  234. // Look for the opening paren.
  235. //
  236. if ( puCredName->Buffer[Length] == L'(' ) {
  237. break;
  238. }
  239. Length++;
  240. }
  241. puServerName->Length = Length * sizeof( WCHAR );
  242. DebugTrace( 0, Dbg, " -> %wZ\n", puServerName );
  243. return STATUS_SUCCESS;
  244. }
  245. BOOLEAN
  246. IsCredentialName(
  247. IN PUNICODE_STRING puObjectName
  248. )
  249. /*+++
  250. Description: This returns TRUE if the object is an extended
  251. credential munged name.
  252. ---*/
  253. {
  254. DWORD dwCurrent = 0;
  255. if ( !puObjectName ) {
  256. return FALSE;
  257. }
  258. while ( dwCurrent < ( puObjectName->Length ) / sizeof( WCHAR ) ) {
  259. if ( puObjectName->Buffer[dwCurrent] == L'(' ) {
  260. return TRUE;
  261. }
  262. dwCurrent++;
  263. }
  264. return FALSE;
  265. }
  266. NTSTATUS
  267. ExCreateReferenceCredentials(
  268. PIRP_CONTEXT pIrpContext,
  269. PUNICODE_STRING puResource
  270. )
  271. /*+++
  272. On an extended create this checks for credentials
  273. and, if they exist, references them and resets the
  274. last used time. If the credentials do not exist
  275. then a credential shell is created and referenced.
  276. This function is responsible for determining the
  277. tree name from the resource. The resource may be
  278. a server in the tree, or the name of the tree.
  279. ---*/
  280. {
  281. NTSTATUS Status;
  282. PLOGON pLogon;
  283. PSCB pScb;
  284. UNICODE_STRING TreeName;
  285. PNDS_SECURITY_CONTEXT pCredentials;
  286. UNICODE_STRING ExName;
  287. NwAcquireExclusiveRcb( &NwRcb, TRUE );
  288. pLogon = FindUser( &(pIrpContext->Specific.Create.UserUid), FALSE );
  289. NwReleaseRcb( &NwRcb );
  290. if ( !pLogon ) {
  291. DebugTrace( 0, Dbg, "Invalid client security context in ExCreateReferenceCredentials.\n", 0 );
  292. return STATUS_ACCESS_DENIED;
  293. }
  294. //
  295. // The resource name is either a server or a tree. We need the tree
  296. // name to create the credential. The following should work even if
  297. // there is a server and tree with the same name.
  298. //
  299. Status = CreateScb( &pScb,
  300. pIrpContext,
  301. puResource,
  302. NULL,
  303. NULL,
  304. NULL,
  305. TRUE,
  306. FALSE );
  307. if ( NT_SUCCESS( Status ) ) {
  308. //
  309. // This is a server, dig out the tree name.
  310. //
  311. TreeName.Length = pScb->NdsTreeName.Length;
  312. TreeName.MaximumLength = pScb->NdsTreeName.MaximumLength;
  313. TreeName.Buffer = pScb->NdsTreeName.Buffer;
  314. } else {
  315. //
  316. // This must already be the tree name.
  317. //
  318. TreeName.Length = puResource->Length;
  319. TreeName.MaximumLength = puResource->MaximumLength;
  320. TreeName.Buffer = puResource->Buffer;
  321. pScb = NULL;
  322. }
  323. //
  324. // Get/Create the credential shell and reference it.
  325. //
  326. if ( !IsCredentialName( &TreeName ) ) {
  327. Status = BuildExCredentialServerName(
  328. &TreeName,
  329. pIrpContext->Specific.Create.puCredentialName,
  330. &ExName );
  331. if ( !NT_SUCCESS( Status ) ) {
  332. goto ExitWithCleanup;
  333. }
  334. }
  335. else {
  336. ExName = TreeName ;
  337. }
  338. Status = NdsLookupCredentials( pIrpContext,
  339. &ExName,
  340. pLogon,
  341. &pCredentials,
  342. CREDENTIAL_WRITE,
  343. TRUE );
  344. if ( !NT_SUCCESS( Status ) ) {
  345. goto ExitWithCleanup;
  346. }
  347. //
  348. // Adjust the reference counts.
  349. //
  350. ASSERT( IsCredentialName( &pCredentials->NdsTreeName ) );
  351. pCredentials->SupplementalHandleCount += 1;
  352. KeQuerySystemTime( &pCredentials->LastUsedTime );
  353. pIrpContext->Specific.Create.pExCredentials = pCredentials;
  354. NwReleaseCredList( pLogon, pIrpContext );
  355. if (ExName.Buffer != TreeName.Buffer) {
  356. //
  357. // only free if we allocated it via BuildExCredentialServerName
  358. //
  359. FREE_POOL( ExName.Buffer );
  360. }
  361. ExitWithCleanup:
  362. if ( pScb ) {
  363. NwDereferenceScb( pScb->pNpScb );
  364. }
  365. return Status;
  366. }
  367. NTSTATUS
  368. ExCreateDereferenceCredentials(
  369. PIRP_CONTEXT pIrpContext,
  370. PNDS_SECURITY_CONTEXT pNdsCredentials
  371. )
  372. /*+++
  373. Dereferce extended credentials.
  374. ---*/
  375. {
  376. NwAcquireExclusiveCredList( pNdsCredentials->pOwningLogon, pIrpContext );
  377. pNdsCredentials->SupplementalHandleCount -= 1;
  378. KeQuerySystemTime( &pNdsCredentials->LastUsedTime );
  379. NwReleaseCredList( pNdsCredentials->pOwningLogon, pIrpContext );
  380. return STATUS_SUCCESS;
  381. }