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.

528 lines
16 KiB

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