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.

529 lines
16 KiB

  1. /*++
  2. Copyright (c) 1987-1999 Microsoft Corporation
  3. Module Name:
  4. 3connect.c
  5. Abstract:
  6. This module implements the tree connect SMB related routines. It also implements the
  7. three flavours of this routine ( user level and share level non NT server tree connect
  8. SMB construction and the tree connect SMB construction for SMB servers)
  9. --*/
  10. #include "precomp.h"
  11. #pragma hdrstop
  12. //
  13. // The order of these names should match the order in which the enumerated type
  14. // NET_ROOT_TYPE is defined. This facilitates easy access of share type names
  15. //
  16. #ifdef ALLOC_PRAGMA
  17. #pragma alloc_text(PAGE, BuildCanonicalNetRootInformation)
  18. #pragma alloc_text(PAGE, CoreBuildTreeConnectSmb)
  19. #pragma alloc_text(PAGE, LmBuildTreeConnectSmb)
  20. #pragma alloc_text(PAGE, NtBuildTreeConnectSmb)
  21. #endif
  22. PCHAR s_NetRootTypeName[] = {
  23. SHARE_TYPE_NAME_DISK,
  24. SHARE_TYPE_NAME_PIPE,
  25. SHARE_TYPE_NAME_COMM,
  26. SHARE_TYPE_NAME_PRINT,
  27. SHARE_TYPE_NAME_WILD
  28. };
  29. extern NTSTATUS
  30. BuildTreeConnectSecurityInformation(
  31. PSMB_EXCHANGE pExchange,
  32. PBYTE pBuffer,
  33. PBYTE pPasswordLength,
  34. PULONG pSmbBufferSize);
  35. NTSTATUS
  36. BuildCanonicalNetRootInformation(
  37. PUNICODE_STRING pServerName,
  38. PUNICODE_STRING pNetRootName,
  39. NET_ROOT_TYPE NetRootType,
  40. BOOLEAN fUnicode,
  41. BOOLEAN fPostPendServiceString,
  42. PBYTE *pBufferPointer,
  43. PULONG pBufferSize)
  44. /*++
  45. Routine Description:
  46. This routine builds the desired net root information for a tree connect SMB
  47. Arguments:
  48. pServerName - the server name
  49. pNetRootName - the net root name
  50. NetRootType - the net root type ( print,pipe,disk etc.,)
  51. fUnicode - TRUE if it is to be built in UNICODE
  52. pBufferPointer - the SMB buffer
  53. pBufferSize - the size on input. modified to the remaining size on output
  54. Return Value:
  55. RXSTATUS - The return status for the operation
  56. Notes:
  57. This routine relies upon the names being in certain formats to ensure that a
  58. valid UNC name can be formulated.
  59. 1) The RDBSS netroot names start with a \ and also include the server name as
  60. part of the net root name. This is mandated by the prefix table search requirements
  61. in RDBSS.
  62. --*/
  63. {
  64. NTSTATUS Status;
  65. PAGED_CODE();
  66. if (fUnicode) {
  67. // Align the buffer and adjust the size accordingly.
  68. PBYTE pBuffer = *pBufferPointer;
  69. RxDbgTrace( 0, (DEBUG_TRACE_CREATE),
  70. ("BuildCanonicalNetRootInformation -- tcstring as unicode %wZ\n", pNetRootName));
  71. pBuffer = ALIGN_SMB_WSTR(pBuffer);
  72. if(sizeof(WCHAR) + (ULONG)(pBuffer - *pBufferPointer) > *pBufferSize) {
  73. return STATUS_BUFFER_OVERFLOW;
  74. }
  75. *pBufferSize -= (ULONG)(pBuffer - *pBufferPointer) + sizeof(WCHAR);
  76. *((PWCHAR)pBuffer) = L'\\';
  77. pBuffer += sizeof(WCHAR);
  78. *pBufferPointer = pBuffer;
  79. Status = SmbPutUnicodeStringAndUpcase(pBufferPointer,pNetRootName,pBufferSize);
  80. } else {
  81. RxDbgTrace( 0, (DEBUG_TRACE_CREATE), ("BuildCanonicalNetRootInformation -- tcstring as ascii\n"));
  82. if(sizeof(CHAR) > *pBufferSize) {
  83. return STATUS_BUFFER_OVERFLOW;
  84. }
  85. *((PCHAR)*pBufferPointer) = '\\';
  86. *pBufferPointer += sizeof(CHAR);
  87. *pBufferSize -= sizeof(CHAR);
  88. Status = SmbPutUnicodeStringAsOemStringAndUpcase(pBufferPointer,pNetRootName,pBufferSize);
  89. }
  90. if (NT_SUCCESS(Status) && fPostPendServiceString) {
  91. // Put the desired service name in ASCII ( always )
  92. ULONG Length = strlen(s_NetRootTypeName[NetRootType]) + 1;
  93. if (*pBufferSize >= Length) {
  94. RtlCopyMemory(*pBufferPointer,s_NetRootTypeName[NetRootType],Length);
  95. *pBufferSize -= Length;
  96. } else {
  97. Status = STATUS_BUFFER_OVERFLOW;
  98. }
  99. }
  100. return Status;
  101. }
  102. NTSTATUS
  103. CoreBuildTreeConnectSmb(
  104. PSMB_EXCHANGE pExchange,
  105. PGENERIC_ANDX pAndXSmb,
  106. PULONG pAndXSmbBufferSize)
  107. /*++
  108. Routine Description:
  109. This routine builds the tree connect SMB for a pre NT server
  110. Arguments:
  111. pExchange - the exchange instance
  112. pAndXSmb - the tree connect to be filled in...it's not really a andX
  113. pAndXSmbBufferSize - the SMB buffer size on input modified to remaining size on
  114. output.
  115. Return Value:
  116. RXSTATUS - The return status for the operation
  117. --*/
  118. {
  119. NTSTATUS Status;
  120. USHORT PasswordLength;
  121. PMRX_NET_ROOT NetRoot;
  122. UNICODE_STRING ServerName;
  123. UNICODE_STRING NetRootName;
  124. PSMBCE_SERVER pServer;
  125. PREQ_TREE_CONNECT pTreeConnect = (PREQ_TREE_CONNECT)pAndXSmb;
  126. ULONG OriginalBufferSize = *pAndXSmbBufferSize;
  127. BOOLEAN AppendServiceString;
  128. PBYTE pBuffer;
  129. PCHAR ServiceName;
  130. ULONG Length;
  131. PAGED_CODE();
  132. NetRoot = pExchange->SmbCeContext.pVNetRoot->pNetRoot;
  133. RxDbgTrace( 0, (DEBUG_TRACE_ALWAYS),
  134. ("CoreBuildTreeConnectSmb buffer,remptr %08lx %08lx, nrt=%08lx\n",
  135. pAndXSmb,
  136. pAndXSmbBufferSize,
  137. NetRoot->Type));
  138. pServer = SmbCeGetExchangeServer(pExchange);
  139. SmbCeGetServerName(NetRoot->pSrvCall,&ServerName);
  140. SmbCeGetNetRootName(NetRoot,&NetRootName);
  141. ServiceName = s_NetRootTypeName[NetRoot->Type];
  142. Length = strlen(ServiceName) + 1;
  143. pTreeConnect->WordCount = 0;
  144. AppendServiceString = FALSE;
  145. if(*pAndXSmbBufferSize < FIELD_OFFSET(REQ_TREE_CONNECT,Buffer)+1) {
  146. return STATUS_BUFFER_OVERFLOW;
  147. }
  148. pBuffer = (PBYTE)pTreeConnect + FIELD_OFFSET(REQ_TREE_CONNECT,Buffer);
  149. *pBuffer = 0x04;
  150. pBuffer++;
  151. *pAndXSmbBufferSize -= (FIELD_OFFSET(REQ_TREE_CONNECT,Buffer)+1);
  152. // put in the netname
  153. //RxDbgTrace( 0, (DEBUG_TRACE_ALWAYS), ("CoreBuildTreeConnectSmb before bcnri buffer,rem %08lx %08lx\n",pBuffer,*pAndXSmbBufferSize));
  154. Status = BuildCanonicalNetRootInformation(
  155. &ServerName,
  156. &NetRootName,
  157. pExchange->SmbCeContext.pVNetRoot->pNetRoot->Type,
  158. (BOOLEAN)(pServer->Dialect >= NTLANMAN_DIALECT),
  159. AppendServiceString,
  160. &pBuffer,
  161. pAndXSmbBufferSize);
  162. if (!NT_SUCCESS(Status))
  163. return Status;
  164. if(*pAndXSmbBufferSize < 1) {
  165. return STATUS_BUFFER_OVERFLOW;
  166. }
  167. // put in the password
  168. pBuffer = (PBYTE)pTreeConnect + OriginalBufferSize - *pAndXSmbBufferSize;
  169. //RxDbgTrace( 0, (DEBUG_TRACE_ALWAYS), ("CoreBuildTreeConnectSmb88 buffer,rem %08lx %08lx\n",pBuffer,*pAndXSmbBufferSize));
  170. *pBuffer = 0x04;
  171. pBuffer++;
  172. *pAndXSmbBufferSize -= 1;
  173. if (pServer->SecurityMode == SECURITY_MODE_SHARE_LEVEL) {
  174. // The password information needs to be sent as part of the tree connect
  175. // SMB for share level servers.
  176. //RxDbgTrace( 0, (DEBUG_TRACE_ALWAYS), ("CoreBuildTreeConnectSmb before btcsi buffer,rem %08lx %08lx\n",pBuffer,*pAndXSmbBufferSize));
  177. Status = BuildTreeConnectSecurityInformation(
  178. pExchange,
  179. pBuffer,
  180. (PBYTE)&PasswordLength,
  181. pAndXSmbBufferSize);
  182. }
  183. if (!NT_SUCCESS(Status))
  184. return Status;
  185. if(*pAndXSmbBufferSize < 1) {
  186. return STATUS_BUFFER_OVERFLOW;
  187. }
  188. // string in the service string based on the netroot type
  189. //RxDbgTrace( 0, (DEBUG_TRACE_ALWAYS), ("CoreBuildTreeConnectSmb beforesscopy buffer,rem %08lx %08lx\n",pBuffer,*pAndXSmbBufferSize));
  190. pBuffer = (PBYTE)pTreeConnect + OriginalBufferSize - *pAndXSmbBufferSize;
  191. *pBuffer = 0x04;
  192. pBuffer++;
  193. *pAndXSmbBufferSize -= 1;
  194. if (*pAndXSmbBufferSize >= Length) {
  195. RtlCopyMemory(pBuffer,ServiceName,Length);
  196. *pAndXSmbBufferSize -= Length;
  197. } else {
  198. Status = STATUS_BUFFER_OVERFLOW;
  199. }
  200. //RxDbgTrace( 0, (DEBUG_TRACE_ALWAYS), ("CoreBuildTreeConnectSmb beforesscopy buffer,rem %08lx %08lx\n",pBuffer,*pAndXSmbBufferSize));
  201. SmbPutUshort(
  202. &pTreeConnect->ByteCount,
  203. (USHORT)(OriginalBufferSize
  204. - *pAndXSmbBufferSize
  205. - FIELD_OFFSET(REQ_TREE_CONNECT,Buffer)
  206. )
  207. );
  208. RxDbgTrace( 0, (DEBUG_TRACE_ALWAYS), ("CoreBuildTreeConnectSmb end buffer,rem %08lx %08lx\n",pBuffer,*pAndXSmbBufferSize));
  209. return Status;
  210. }
  211. NTSTATUS
  212. LmBuildTreeConnectSmb(
  213. PSMB_EXCHANGE pExchange,
  214. PGENERIC_ANDX pAndXSmb,
  215. PULONG pAndXSmbBufferSize)
  216. /*++
  217. Routine Description:
  218. This routine builds the tree connect SMB for a pre NT server
  219. Arguments:
  220. pExchange - the exchange instance
  221. pAndXSmb - the tree connect to be filled in...it's not really a andX
  222. pAndXSmbBufferSize - the SMB buffer size on input modified to remaining size on
  223. output.
  224. Return Value:
  225. RXSTATUS - The return status for the operation
  226. --*/
  227. {
  228. NTSTATUS Status;
  229. USHORT PasswordLength;
  230. PMRX_NET_ROOT NetRoot;
  231. UNICODE_STRING ServerName;
  232. UNICODE_STRING NetRootName;
  233. PSMBCE_SERVER pServer;
  234. PREQ_TREE_CONNECT_ANDX pTreeConnectAndX = (PREQ_TREE_CONNECT_ANDX)pAndXSmb;
  235. ULONG OriginalBufferSize = *pAndXSmbBufferSize;
  236. BOOLEAN AppendServiceString;
  237. PBYTE pBuffer;
  238. PCHAR ServiceName;
  239. ULONG Length;
  240. PAGED_CODE();
  241. NetRoot = pExchange->SmbCeContext.pVNetRoot->pNetRoot;
  242. RxDbgTrace( 0, (DEBUG_TRACE_ALWAYS),
  243. ("LmBuildTreeConnectSmb buffer,remptr %08lx %08lx, nrt=%08lx\n",
  244. pAndXSmb,
  245. pAndXSmbBufferSize,
  246. NetRoot->Type));
  247. if(OriginalBufferSize < FIELD_OFFSET(REQ_TREE_CONNECT_ANDX,Buffer)) {
  248. return STATUS_BUFFER_OVERFLOW;
  249. }
  250. pServer = SmbCeGetExchangeServer(pExchange);
  251. SmbCeGetServerName(NetRoot->pSrvCall,&ServerName);
  252. SmbCeGetNetRootName(NetRoot,&NetRootName);
  253. ServiceName = s_NetRootTypeName[NetRoot->Type];
  254. Length = strlen(ServiceName) + 1;
  255. AppendServiceString = TRUE;
  256. pTreeConnectAndX->WordCount = 4;
  257. SmbPutUshort(&pTreeConnectAndX->AndXReserved,0);
  258. SmbPutUshort(
  259. &pTreeConnectAndX->Flags,0);
  260. pBuffer = (PBYTE)pTreeConnectAndX + FIELD_OFFSET(REQ_TREE_CONNECT_ANDX,Buffer);
  261. *pAndXSmbBufferSize -= (FIELD_OFFSET(REQ_TREE_CONNECT_ANDX,Buffer));
  262. if (pServer->SecurityMode == SECURITY_MODE_SHARE_LEVEL) {
  263. // The password information needs to be sent as part of the tree connect
  264. // SMB for share level servers.
  265. //RxDbgTrace( 0, (DEBUG_TRACE_ALWAYS), ("LmBuildTreeConnectSmb before btcsi buffer,rem %08lx %08lx\n",pBuffer,*pAndXSmbBufferSize));
  266. Status = BuildTreeConnectSecurityInformation(
  267. pExchange,
  268. pBuffer,
  269. (PBYTE)&PasswordLength,
  270. pAndXSmbBufferSize);
  271. if (Status == STATUS_SUCCESS) {
  272. pBuffer += PasswordLength;
  273. SmbPutUshort(&pTreeConnectAndX->PasswordLength,PasswordLength);
  274. }
  275. } else {
  276. if(*pAndXSmbBufferSize < sizeof(CHAR)) {
  277. return STATUS_BUFFER_OVERFLOW;
  278. }
  279. // No password is required for user level security servers as part of tree
  280. // connect
  281. SmbPutUshort(&pTreeConnectAndX->PasswordLength,0x1);
  282. *((PCHAR)pBuffer) = '\0';
  283. pBuffer += sizeof(CHAR);
  284. *pAndXSmbBufferSize -= sizeof(CHAR);
  285. Status = STATUS_SUCCESS;
  286. }
  287. if (Status == STATUS_SUCCESS) {
  288. Status = BuildCanonicalNetRootInformation(
  289. &ServerName,
  290. &NetRootName,
  291. pExchange->SmbCeContext.pVNetRoot->pNetRoot->Type,
  292. (BOOLEAN)(pServer->Dialect >= NTLANMAN_DIALECT),
  293. AppendServiceString,
  294. &pBuffer,
  295. pAndXSmbBufferSize);
  296. //RxDbgTrace( 0, (DEBUG_TRACE_ALWAYS), ("LmBuildTreeConnectSmb beforesscopy buffer,rem %08lx %08lx\n",pBuffer,*pAndXSmbBufferSize));
  297. if (Status == STATUS_SUCCESS) {
  298. SmbPutUshort(
  299. &pTreeConnectAndX->ByteCount,
  300. (USHORT)(OriginalBufferSize
  301. - *pAndXSmbBufferSize
  302. - FIELD_OFFSET(REQ_TREE_CONNECT_ANDX,Buffer)
  303. )
  304. );
  305. }
  306. RxDbgTrace( 0, (DEBUG_TRACE_ALWAYS),
  307. ("LmBuildTreeConnectSmb end buffer,rem %08lx %08lx\n",
  308. pBuffer,
  309. *pAndXSmbBufferSize));
  310. }
  311. return Status;
  312. }
  313. NTSTATUS
  314. NtBuildTreeConnectSmb(
  315. PSMB_EXCHANGE pExchange,
  316. PGENERIC_ANDX pAndXSmb,
  317. PULONG pAndXSmbBufferSize)
  318. /*++
  319. Routine Description:
  320. This routine builds the tree connect SMB for a pre NT server
  321. Arguments:
  322. pExchange - the exchange instance
  323. pAndXSmb - the session setup to be filled in
  324. pAndXSmbBufferSize - the SMB buffer size on input modified to remaining size on
  325. output.
  326. Return Value:
  327. RXSTATUS - The return status for the operation
  328. --*/
  329. {
  330. NTSTATUS Status = STATUS_SUCCESS;
  331. UNICODE_STRING ServerName;
  332. UNICODE_STRING NetRootName;
  333. PSMBCE_SERVER pServer;
  334. PREQ_TREE_CONNECT_ANDX pTreeConnect = (PREQ_TREE_CONNECT_ANDX)pAndXSmb;
  335. ULONG OriginalBufferSize = *pAndXSmbBufferSize;
  336. PBYTE pBuffer;
  337. ULONG BufferSize;
  338. PAGED_CODE();
  339. BufferSize = OriginalBufferSize;
  340. if(BufferSize < FIELD_OFFSET(REQ_TREE_CONNECT_ANDX,Buffer) + 1) {
  341. return STATUS_BUFFER_OVERFLOW;
  342. }
  343. pServer = SmbCeGetExchangeServer(pExchange);
  344. SmbCeGetServerName(pExchange->SmbCeContext.pVNetRoot->pNetRoot->pSrvCall,&ServerName);
  345. SmbCeGetNetRootName(pExchange->SmbCeContext.pVNetRoot->pNetRoot,&NetRootName);
  346. pTreeConnect->AndXCommand = 0xff; // No ANDX
  347. pTreeConnect->AndXReserved = 0x00; // Reserved (MBZ)
  348. SmbPutUshort(&pTreeConnect->AndXOffset, 0x0000); // No AndX as of yet.
  349. pTreeConnect->WordCount = 4;
  350. SmbPutUshort( &pTreeConnect->Flags, 0 );
  351. pBuffer = (PBYTE)pTreeConnect + FIELD_OFFSET(REQ_TREE_CONNECT_ANDX,Buffer);
  352. BufferSize -= FIELD_OFFSET(REQ_TREE_CONNECT_ANDX,Buffer);
  353. if(pServer->SecurityMode == SECURITY_MODE_USER_LEVEL){
  354. // No password information is required as part of tree connect for user level
  355. // security servers. Therefore send a null string as the password.
  356. SmbPutUshort(&pTreeConnect->PasswordLength,0x1);
  357. *((PCHAR)pBuffer) = '\0';
  358. pBuffer += sizeof(CHAR);
  359. BufferSize -= sizeof(CHAR);
  360. } else {
  361. USHORT PasswordLength;
  362. //plug in the password for this server.....qweee
  363. Status = BuildTreeConnectSecurityInformation(
  364. pExchange,
  365. pBuffer,
  366. (PBYTE)&PasswordLength,
  367. &BufferSize);
  368. if (Status == STATUS_SUCCESS ) {
  369. pBuffer += PasswordLength;
  370. SmbPutUshort(&pTreeConnect->PasswordLength,PasswordLength);
  371. }
  372. }
  373. if (NT_SUCCESS(Status)) {
  374. Status = BuildCanonicalNetRootInformation(
  375. &ServerName,
  376. &NetRootName,
  377. NET_ROOT_WILD, //let the server tell us! pNetRoot->Type,
  378. BooleanFlagOn(pServer->DialectFlags,DF_UNICODE),
  379. TRUE, //postpend the service string
  380. &pBuffer,
  381. &BufferSize);
  382. }
  383. if (NT_SUCCESS(Status)) {
  384. SmbPutUshort(
  385. &pTreeConnect->ByteCount,
  386. (USHORT)(OriginalBufferSize -
  387. FIELD_OFFSET(REQ_TREE_CONNECT_ANDX,Buffer) -
  388. BufferSize));
  389. }
  390. // update the buffer size to reflect the amount consumed.
  391. *pAndXSmbBufferSize = BufferSize;
  392. return Status;
  393. }