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.

628 lines
22 KiB

  1. /*++
  2. Copyright (c) 2001 Microsoft Corporation
  3. Module Name:
  4. read.c
  5. Abstract:
  6. This module contains functions to manage TFTP read requests
  7. to the service from a client.
  8. Author:
  9. Jeffrey C. Venable, Sr. (jeffv) 01-Jun-2001
  10. Revision History:
  11. --*/
  12. #include "precomp.h"
  13. PTFTPD_BUFFER
  14. TftpdReadSendData(PTFTPD_BUFFER buffer) {
  15. PTFTPD_CONTEXT context = buffer->internal.context;
  16. TFTPD_DEBUG((TFTPD_TRACE_PROCESS,
  17. "TftpdReadSendData(buffer = %p, context = %p).\n",
  18. buffer, context));
  19. // Build the DATA packet.
  20. buffer->message.opcode = htons(TFTPD_DATA);
  21. buffer->message.data.block = htons((USHORT)(context->block + 1));
  22. // Complete the operation so we can receive the next ACK packet
  23. // if the client responds faster than we can exit sending the DATA.
  24. if (!TftpdProcessComplete(buffer))
  25. goto exit_send_data;
  26. // Send the DATA packet.
  27. buffer = TftpdIoSendPacket(buffer);
  28. exit_send_data :
  29. return (buffer);
  30. } // TftpdReadSendData()
  31. void
  32. TftpdReadTranslateText(PTFTPD_BUFFER buffer, DWORD bytes) {
  33. PTFTPD_CONTEXT context = buffer->internal.context;
  34. char *start, *end, *p, *q;
  35. TFTPD_DEBUG((TFTPD_TRACE_PROCESS, "TftpdReadTranslateText(buffer = %p, context = %p).\n", buffer, context));
  36. // NOTE: 'context' must be referenced before this call!
  37. ASSERT(context != NULL);
  38. //
  39. // Text (translated) mode :
  40. // The data is sent in NVT-ASCII format.
  41. // Cases to worry about:
  42. // (a) CR + non-LF -> CR + '\0' + non-LF (insert '\0')
  43. // (b) non-CR + LF -> non-CR + CR + LF (insert CR)
  44. // (b) Dangling CR at the end of a previously converted buffer which affects
  45. // the output of the first character of the following buffer.
  46. // We can do the conversion in-place.
  47. //
  48. // Convert the data in-place.
  49. start = (char *)&buffer->message.data.data;
  50. end = (start + bytes);
  51. p = q = start;
  52. context->translationOffset.QuadPart = 0;
  53. if (start == end)
  54. return;
  55. if (context->danglingCR) {
  56. context->danglingCR = FALSE;
  57. if (*p != '\n') {
  58. *q++ = '\0'; // This is a CR + non-LF combination, insert '\0' (case a).
  59. context->translationOffset.QuadPart++; // Count the added byte.
  60. } else
  61. *q++ = *p++; // Copy the LF.
  62. }
  63. while (TRUE) {
  64. while ((q < end) && (*p != '\r') && (*p != '\n')) { *q++ = *p++; }
  65. if (q == end)
  66. break;
  67. if (*p == '\r') {
  68. *q++ = *p++; // Copy the CR.
  69. if (q < end) {
  70. if (*p != '\n') {
  71. *q++ = '\0'; // This is a CR + non-LF combination, insert '\0' (case a).
  72. context->translationOffset.QuadPart++; // Count the added byte.
  73. } else
  74. *q++ = *p++; // Copy the LF.
  75. continue;
  76. } else
  77. break;
  78. }
  79. *q++ = '\r'; // This is a solitary LF, insert a CR (case b).
  80. context->translationOffset.QuadPart++; // Count the added byte.
  81. if (q < end)
  82. *q++ = *p++; // Copy the solitary LF.
  83. else
  84. break;
  85. } // while (true)
  86. if (*(end - 1) == '\r')
  87. context->danglingCR = TRUE;
  88. } // TftpdReadTranslateText()
  89. void CALLBACK
  90. TftpdReadOverlappedCompletion(PTFTPD_BUFFER buffer, BOOLEAN timedOut) {
  91. PTFTPD_CONTEXT context = buffer->internal.context;
  92. TFTPD_DEBUG((TFTPD_TRACE_PROCESS,
  93. "TftpdReadOverlappedCompletion(buffer = %p, context = %p).\n",
  94. buffer, context));
  95. ASSERT(context != NULL);
  96. if (InterlockedCompareExchangePointer(&context->wWait,
  97. INVALID_HANDLE_VALUE,
  98. NULL) == NULL)
  99. return;
  100. ASSERT(context->wWait != NULL);
  101. if (!UnregisterWait(context->wWait)) {
  102. DWORD error;
  103. if ((error = GetLastError()) != ERROR_IO_PENDING) {
  104. TFTPD_DEBUG((TFTPD_DBG_PROCESS,
  105. "TftpdReadOverlappedCompletion(buffer = %p, context = %p): "
  106. "UnregisterWait() failed, error 0x%08X.\n",
  107. buffer, context, error));
  108. TftpdContextKill(context);
  109. TftpdIoSendErrorPacket(buffer, TFTPD_ERROR_UNDEFINED, "Out of memory");
  110. goto exit_read_completion;
  111. }
  112. }
  113. context->wWait = NULL;
  114. if (context->state & TFTPD_STATE_DEAD)
  115. goto exit_read_completion;
  116. if (context->mode == TFTPD_MODE_TEXT)
  117. TftpdReadTranslateText(buffer, TFTPD_DATA_AMOUNT_RECEIVED(buffer));
  118. buffer = TftpdReadSendData(buffer);
  119. exit_read_completion :
  120. if (buffer != NULL)
  121. TftpdIoPostReceiveBuffer(buffer->internal.socket, buffer);
  122. TftpdContextRelease(context);
  123. } // TftpdReadOverlappedCompletion()
  124. PTFTPD_BUFFER
  125. TftpdReadResume(PTFTPD_BUFFER buffer) {
  126. PTFTPD_CONTEXT context = buffer->internal.context;
  127. DWORD error = NO_ERROR, size = 0;
  128. TFTPD_DEBUG((TFTPD_TRACE_PROCESS,
  129. "TftpdReadResume(buffer = %p, context = %p).\n",
  130. buffer, context));
  131. // NOTE: 'context' must be referenced before this call!
  132. ASSERT(context != NULL);
  133. // If we need to start the transfer with an OACK, do so now.
  134. if (context->options) {
  135. buffer = TftpdUtilSendOackPacket(buffer);
  136. goto exit_resume_read;
  137. }
  138. // Do we need to allocate a non-default buffer for transmitting
  139. // the file to the client?
  140. if (buffer->internal.socket == &globals.io.master) {
  141. buffer = TftpdIoSwapBuffer(buffer, context->socket);
  142. if (buffer == NULL) {
  143. TftpdContextKill(context);
  144. TftpdIoSendErrorPacket(buffer, TFTPD_ERROR_UNDEFINED, "Out of memory");
  145. goto exit_resume_read;
  146. }
  147. } // if (buffer->message.opcode == TFTPD_RRQ)
  148. // Is there more data to send from the soure file?
  149. if (context->fileOffset.QuadPart < context->filesize.QuadPart) {
  150. // Determine size.
  151. size = __min((DWORD)context->blksize,
  152. (DWORD)(context->filesize.QuadPart - context->fileOffset.QuadPart));
  153. // Prepare the overlapped read.
  154. buffer->internal.io.overlapped.OffsetHigh = context->fileOffset.HighPart;
  155. buffer->internal.io.overlapped.Offset = context->fileOffset.LowPart;
  156. buffer->internal.io.overlapped.hEvent = context->hWait;
  157. TFTPD_DEBUG((TFTPD_TRACE_PROCESS,
  158. "TftpdReadResume(buffer = %p): "
  159. "ReadFile(bytes = %d, offset = %d).\n",
  160. buffer, size, context->fileOffset.LowPart));
  161. // Perform the read operation.
  162. if (!ReadFile(context->hFile,
  163. &buffer->message.data.data,
  164. size,
  165. NULL,
  166. &buffer->internal.io.overlapped))
  167. error = GetLastError();
  168. if ((error != NO_ERROR) && (error != ERROR_IO_PENDING)) {
  169. TFTPD_DEBUG((TFTPD_DBG_PROCESS,
  170. "TftpdReadResume(context = %p, buffer = %p): "
  171. "ReadFile() failed, error 0x%08X.\n",
  172. context, buffer, error));
  173. TftpdContextKill(context);
  174. TftpdIoSendErrorPacket(buffer, TFTPD_ERROR_FILE_NOT_FOUND, "Access violation");
  175. goto exit_resume_read;
  176. }
  177. } else {
  178. ASSERT(context->fileOffset.QuadPart == context->filesize.QuadPart);
  179. ASSERT(size == 0);
  180. } // if (context->fileOffset.QuadPart < context->filesize.QuadPart)
  181. buffer->internal.io.bytes = (TFTPD_MIN_RECEIVED_DATA + size);
  182. if (error == ERROR_IO_PENDING) {
  183. HANDLE wait = NULL;
  184. TFTPD_DEBUG((TFTPD_TRACE_PROCESS,
  185. "TftpdReadResume(buffer = %p): ERROR_IO_PENDING.\n",
  186. buffer));
  187. // Keep an overlapped-operation reference to the context.
  188. TftpdContextAddReference(context);
  189. // Register a wait for completion.
  190. ASSERT(context->wWait == NULL);
  191. if (!RegisterWaitForSingleObject(&wait,
  192. context->hWait,
  193. (WAITORTIMERCALLBACKFUNC)TftpdReadOverlappedCompletion,
  194. buffer,
  195. INFINITE,
  196. (WT_EXECUTEINIOTHREAD | WT_EXECUTEONLYONCE))) {
  197. TFTPD_DEBUG((TFTPD_DBG_PROCESS,
  198. "TftpdReadResume(context = %p, buffer = %p): "
  199. "RegisterWaitForSingleObject() failed, error 0x%08X.\n",
  200. context, buffer, GetLastError()));
  201. // Reclaim the overlapped operation reference.
  202. TftpdContextKill(context);
  203. TftpdContextRelease(context);
  204. TftpdIoSendErrorPacket(buffer, TFTPD_ERROR_UNDEFINED, "Out of memory");
  205. // Buffer will get leaked.
  206. buffer = NULL; // Buffer is being used for overlapped operation.
  207. goto exit_resume_read;
  208. }
  209. // Did the completion callback already fire before we could save the wait handle
  210. // into the context so it cannot deregister the wait?
  211. if (InterlockedExchangePointer(&context->wWait, wait) != INVALID_HANDLE_VALUE) {
  212. buffer = NULL; // Buffer is being used for overlapped operation.
  213. goto exit_resume_read;
  214. }
  215. // Reclaim the overlapped operation reference.
  216. TftpdContextRelease(context);
  217. if (!UnregisterWait(context->wWait)) {
  218. if ((error = GetLastError()) != ERROR_IO_PENDING) {
  219. TFTPD_DEBUG((TFTPD_DBG_PROCESS,
  220. "TftpdReadResume(context = %p, buffer = %p): "
  221. "UnregisterWait() failed, error 0x%08X.\n",
  222. context, buffer, error));
  223. TftpdContextKill(context);
  224. TftpdIoSendErrorPacket(buffer, TFTPD_ERROR_UNDEFINED, "Out of memory");
  225. // TftpdContextLeak(context);
  226. buffer = NULL; // Buffer is being used for overlapped operation.
  227. goto exit_resume_read;
  228. }
  229. }
  230. context->wWait = NULL;
  231. // Whoever deregisters the wait proceeds with the operation.
  232. } // if (error == ERROR_IO_PENDING)
  233. //
  234. // Read file completed immediately.
  235. //
  236. if (context->mode == TFTPD_MODE_TEXT)
  237. TftpdReadTranslateText(buffer, size);
  238. buffer = TftpdReadSendData(buffer);
  239. exit_resume_read :
  240. return (buffer);
  241. } // TftpdReadResume()
  242. PTFTPD_BUFFER
  243. TftpdReadAck(PTFTPD_BUFFER buffer) {
  244. PTFTPD_CONTEXT context = NULL;
  245. DWORD state, newState;
  246. // Ensure that an ACK isn't send to the master socket.
  247. if (buffer->internal.socket == &globals.io.master) {
  248. TftpdIoSendErrorPacket(buffer, TFTPD_ERROR_ILLEGAL_OPERATION, "Illegal TFTP operation");
  249. goto exit_ack;
  250. }
  251. TFTPD_DEBUG((TFTPD_TRACE_PROCESS, "TftpdReadAck(buffer = %p).\n", buffer));
  252. //
  253. // Validate context.
  254. //
  255. context = TftpdContextAquire(&buffer->internal.io.peer);
  256. if (context == NULL) {
  257. TFTPD_DEBUG((TFTPD_TRACE_PROCESS,
  258. "TftpdReadAck(buffer = %p): Received ACK for non-existant context.\n",
  259. buffer));
  260. TftpdIoSendErrorPacket(buffer, TFTPD_ERROR_UNKNOWN_TRANSFER_ID, "Unknown transfer ID");
  261. goto exit_ack;
  262. }
  263. // Is this a RRQ context?
  264. if (context->type != TFTPD_RRQ) {
  265. TFTPD_DEBUG((TFTPD_TRACE_PROCESS,
  266. "TftpdReadAck(buffer = %p): Received ACK for non-RRQ context.\n",
  267. buffer));
  268. TftpdIoSendErrorPacket(buffer, TFTPD_ERROR_UNKNOWN_TRANSFER_ID, "Unknown transfer ID");
  269. goto exit_ack;
  270. }
  271. //
  272. // Validate ACK packet.
  273. //
  274. // If we sent an OACK, it must be ACK'd with block 0.
  275. if (context->options && (buffer->message.ack.block != 0)) {
  276. TFTPD_DEBUG((TFTPD_TRACE_PROCESS,
  277. "TftpdReadAck: Ignoring ACK buffer = %p, "
  278. "expected block 0 for acknowledgement of issued OACK.\n",
  279. buffer));
  280. goto exit_ack;
  281. }
  282. //
  283. // Aquire busy-sending state.
  284. //
  285. do {
  286. USHORT block = context->block;
  287. if (context->state & (TFTPD_STATE_BUSY | TFTPD_STATE_DEAD))
  288. goto exit_ack;
  289. // Is it for the correct block? The client can ACK the DATA packet
  290. // we just sent, or it could re-ACK the previous DATA packet meaning
  291. // it never saw the DATA packet we just sent in which case we need to
  292. // resend it. If the ACK is equal to our internal block number, we
  293. // just need to resend. If the ACK is equal to our internal block
  294. // number plus one, it's acking DATA we just sent so increment
  295. // our internal block number and send the next chunk. Note that an
  296. // ACK to our OACK is with block 0, so it will just slip through
  297. // this code.
  298. if ((buffer->message.ack.block != block) &&
  299. (buffer->message.ack.block != (USHORT)(block + 1)))
  300. goto exit_ack;
  301. } while (InterlockedCompareExchange(&context->state, TFTPD_STATE_BUSY, 0) != 0);
  302. //
  303. // Update state.
  304. //
  305. // Prevent the transmission of an OACK.
  306. context->options = 0;
  307. // Client has responded to us with acceptable ACK packet, reset timeout counter.
  308. context->retransmissions = 0;
  309. // Update block and offsets if necessary.
  310. if (buffer->message.ack.block == (USHORT)(context->block + 1)) {
  311. context->block++;
  312. context->fileOffset.QuadPart += (context->blksize - context->translationOffset.QuadPart);
  313. context->sorcerer = buffer->message.ack.block;
  314. } else {
  315. // RFC 1123. This is an ACK for the previous block number.
  316. // Our DATA packet may have been lost, or is merely taking the
  317. // scenic route through the network. Go ahead and resend a
  318. // DATA packet in response to this ACK, however record the
  319. // block number for which this occurred as a form of history
  320. // tracking. Should this occur again in the following block
  321. // number, we've fallen into the "Sorcerer's Apprentice" bug,
  322. // and we will break it by ignoring the secondary ACK of the
  323. // sequence. However, we must be careful not to break
  324. // authentic resend requests, so after dropping an ACK in
  325. // an attempt to break the "Sorcerer's Apprentice" bug, we
  326. // will resume sending DATA packets in response and then
  327. // revert back to watching for the bug again.
  328. if (buffer->message.ack.block == context->sorcerer) {
  329. #if defined(DBG)
  330. InterlockedIncrement(&globals.performance.sorcerersApprentice);
  331. #endif // defined(DBG)
  332. context->sorcerer--;
  333. // Do NOT send the DATA this time.
  334. buffer->internal.context = context;
  335. TftpdProcessComplete(buffer);
  336. goto exit_ack;
  337. } else {
  338. context->sorcerer = buffer->message.ack.block;
  339. }
  340. } // if (buffer->message.ack.block == (USHORT)(context->block + 1))
  341. //
  342. // Send DATA.
  343. //
  344. // Is there any more data to send, including a zero-length
  345. // DATA packet if (filesize % blksize) is zero to terminate
  346. // the transfer?
  347. if (context->fileOffset.QuadPart > context->filesize.QuadPart) {
  348. TFTPD_DEBUG((TFTPD_TRACE_PROCESS,
  349. "TftpdReadAck(buffer = %p, context = %p: RRQ complete.\n",
  350. buffer, context));
  351. TftpdContextKill(context);
  352. goto exit_ack;
  353. }
  354. // Keep track of the context for the pending DATA we need to issue.
  355. buffer->internal.context = context;
  356. buffer = TftpdReadResume(buffer);
  357. exit_ack :
  358. if (context != NULL)
  359. TftpdContextRelease(context);
  360. return (buffer);
  361. } // TftpdReadAck()
  362. PTFTPD_BUFFER
  363. TftpdReadRequest(PTFTPD_BUFFER buffer) {
  364. PTFTPD_CONTEXT context = NULL;
  365. NTSTATUS status;
  366. // Ensure that a RRQ is from the master socket only.
  367. if (buffer->internal.socket != &globals.io.master) {
  368. TftpdIoSendErrorPacket(buffer, TFTPD_ERROR_ILLEGAL_OPERATION,
  369. "Illegal TFTP operation");
  370. goto exit_read_request;
  371. }
  372. // Is this a duplicate request? Do we ignore it or send an error?
  373. if ((context = TftpdContextAquire(&buffer->internal.io.peer)) != NULL) {
  374. if (context->block > 0)
  375. TftpdIoSendErrorPacket(buffer, TFTPD_ERROR_ILLEGAL_OPERATION,
  376. "Illegal TFTP operation");
  377. TftpdContextRelease(context);
  378. context = NULL;
  379. goto exit_read_request;
  380. }
  381. // Allocate a context for this request (this gives us a reference to it as well).
  382. if ((context = (PTFTPD_CONTEXT)TftpdContextAllocate()) == NULL)
  383. goto exit_read_request;
  384. TFTPD_DEBUG((TFTPD_TRACE_PROCESS,
  385. "TftpdReadRequest(buffer = %p): context = %p.\n",
  386. buffer, context));
  387. // Initialize the context.
  388. context->type = TFTPD_RRQ;
  389. CopyMemory(&context->peer, &buffer->internal.io.peer, sizeof(context->peer));
  390. context->state = TFTPD_STATE_BUSY;
  391. // Obtain and validate the requested filename, mode, and options.
  392. if (!TftpdUtilGetFileModeAndOptions(context, buffer)) {
  393. TFTPD_DEBUG((TFTPD_DBG_PROCESS,
  394. "TftpdReadRequest(buffer = %p): "
  395. "Invalid file mode = %d.\n",
  396. buffer, context->mode));
  397. goto exit_read_request;
  398. }
  399. // Figure out which socket to use for this request (based on blksize).
  400. if (!TftpdIoAssignSocket(context, buffer)) {
  401. TFTPD_DEBUG((TFTPD_DBG_PROCESS,
  402. "TftpdReadRequest(buffer = %p): "
  403. "TftpdIoAssignSocket() failed.\n",
  404. buffer));
  405. goto exit_read_request;
  406. }
  407. // Check whether access is permitted.
  408. if (!TftpdUtilMatch(globals.parameters.validClients, inet_ntoa(context->peer.sin_addr)) ||
  409. !TftpdUtilMatch(globals.parameters.validReadFiles, context->filename)) {
  410. TFTPD_DEBUG((TFTPD_DBG_PROCESS,
  411. "TftpdReadRequest(buffer = %p): Access denied.\n",
  412. buffer));
  413. TftpdIoSendErrorPacket(buffer, TFTPD_ERROR_ACCESS_VIOLATION,
  414. "Access violation");
  415. goto exit_read_request;
  416. }
  417. // Open the file.
  418. context->hFile = CreateFile(context->filename, GENERIC_READ,
  419. FILE_SHARE_READ, NULL, OPEN_EXISTING,
  420. FILE_FLAG_SEQUENTIAL_SCAN | FILE_FLAG_OVERLAPPED, NULL);
  421. if (context->hFile == INVALID_HANDLE_VALUE) {
  422. TFTPD_DEBUG((TFTPD_DBG_PROCESS,
  423. "TftpdReadRequest(buffer = %p): "
  424. "CreateFile() for filename = %s not found, error 0x%08X.\n",
  425. buffer, context->filename, GetLastError()));
  426. TftpdIoSendErrorPacket(buffer, TFTPD_ERROR_FILE_NOT_FOUND,
  427. "File not found");
  428. context->hFile = NULL;
  429. goto exit_read_request;
  430. }
  431. if (!GetFileSizeEx(context->hFile, &context->filesize)) {
  432. TFTPD_DEBUG((TFTPD_DBG_PROCESS,
  433. "TftpdReadRequest(buffer = %p): "
  434. "Invalid file size for file name = %s.\n",
  435. buffer, context->filename));
  436. TftpdIoSendErrorPacket(buffer, TFTPD_ERROR_ACCESS_VIOLATION,
  437. "Access violation");
  438. goto exit_read_request;
  439. }
  440. // Create the ReadFile() wait event.
  441. if ((context->hWait = CreateEvent(NULL, FALSE, FALSE, NULL)) == NULL) {
  442. TFTPD_DEBUG((TFTPD_DBG_PROCESS,
  443. "TftpdReadRequest(buffer = %p): "
  444. "CreateEvent() failed, error = %d.\n",
  445. buffer, GetLastError()));
  446. TftpdIoSendErrorPacket(buffer, TFTPD_ERROR_UNDEFINED, "Out of memory");
  447. goto exit_read_request;
  448. }
  449. // Insert the context into the hash-table.
  450. if (!TftpdContextAdd(context)) {
  451. TFTPD_DEBUG((TFTPD_TRACE_PROCESS,
  452. "TftpdReadRequest(buffer = %p): "
  453. "Dropping request as we're already servicing it.\n",
  454. buffer));
  455. TftpdIoSendErrorPacket(buffer, TFTPD_ERROR_UNDEFINED,
  456. "Illegal TFTP operation");
  457. goto exit_read_request;
  458. }
  459. // Start the retransmission timer.
  460. if (!CreateTimerQueueTimer(&context->hTimer,
  461. globals.io.hTimerQueue,
  462. (WAITORTIMERCALLBACKFUNC)TftpdProcessTimeout,
  463. context,
  464. context->timeout,
  465. 720000,
  466. WT_EXECUTEINIOTHREAD)) {
  467. TftpdContextKill(context);
  468. context = NULL;
  469. TftpdIoSendErrorPacket(buffer, TFTPD_ERROR_UNDEFINED,
  470. "Unable to initiate timeout timer.");
  471. goto exit_read_request;
  472. } // if (NT_SUCCESS(status))
  473. // Add our own reference to the context.
  474. TftpdContextAddReference(context);
  475. // If 'context->options' is non-zero, TftpdReadResume() will issue an OACK
  476. // instead of a DATA packet. The subsquent ACK to the OACK will clear the
  477. // flags which will allow it to begin issuing subsequent DATA packets.
  478. buffer->internal.context = context;
  479. buffer = TftpdReadResume(buffer);
  480. // Free our own reference to the context.
  481. TftpdContextRelease(context);
  482. // If buffer != NULL, it gets recycled if possible.
  483. return (buffer);
  484. exit_read_request :
  485. if (context != NULL)
  486. TftpdContextFree(context);
  487. // If buffer != NULL, it gets recycled if possible.
  488. return (buffer);
  489. } // TftpdReadRequest()