1 /*
2 * Copyright (C) 2008 Edwin Groothuis. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
14 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16 * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
17 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
23 * SUCH DAMAGE.
24 */
25
26 #include <sys/cdefs.h>
27 __FBSDID("$FreeBSD: stable/10/libexec/tftpd/tftp-io.c 339060 2018-10-01 16:09:20Z asomers $");
28
29 #include <sys/stat.h>
30 #include <sys/types.h>
31 #include <sys/socket.h>
32
33 #include <netinet/in.h>
34 #include <arpa/tftp.h>
35 #include <arpa/inet.h>
36
37 #include <assert.h>
38 #include <errno.h>
39 #include <setjmp.h>
40 #include <signal.h>
41 #include <stddef.h>
42 #include <stdio.h>
43 #include <stdlib.h>
44 #include <string.h>
45 #include <syslog.h>
46 #include <unistd.h>
47
48 #include "tftp-file.h"
49 #include "tftp-io.h"
50 #include "tftp-utils.h"
51 #include "tftp-options.h"
52
53 struct sockaddr_storage peer_sock;
54 struct sockaddr_storage me_sock;
55
56 static int send_packet(int peer, uint16_t block, char *pkt, int size);
57
58 static struct errmsg {
59 int e_code;
60 const char *e_msg;
61 } errmsgs[] = {
62 { EUNDEF, "Undefined error code" },
63 { ENOTFOUND, "File not found" },
64 { EACCESS, "Access violation" },
65 { ENOSPACE, "Disk full or allocation exceeded" },
66 { EBADOP, "Illegal TFTP operation" },
67 { EBADID, "Unknown transfer ID" },
68 { EEXISTS, "File already exists" },
69 { ENOUSER, "No such user" },
70 { EOPTNEG, "Option negotiation" },
71 { -1, NULL }
72 };
73
74 #define DROPPACKET(s) \
75 if (packetdroppercentage != 0 && \
76 random()%100 < packetdroppercentage) { \
77 tftp_log(LOG_DEBUG, "Artificial packet drop in %s", s); \
78 return; \
79 }
80 #define DROPPACKETn(s,n) \
81 if (packetdroppercentage != 0 && \
82 random()%100 < packetdroppercentage) { \
83 tftp_log(LOG_DEBUG, "Artificial packet drop in %s", s); \
84 return (n); \
85 }
86
87 const char *
errtomsg(int error)88 errtomsg(int error)
89 {
90 static char ebuf[40];
91 struct errmsg *pe;
92
93 if (error == 0)
94 return ("success");
95 for (pe = errmsgs; pe->e_code >= 0; pe++)
96 if (pe->e_code == error)
97 return (pe->e_msg);
98 snprintf(ebuf, sizeof(ebuf), "error %d", error);
99 return (ebuf);
100 }
101
102 static int
send_packet(int peer,uint16_t block,char * pkt,int size)103 send_packet(int peer, uint16_t block, char *pkt, int size)
104 {
105 int i;
106 int t = 1;
107
108 for (i = 0; i < 12 ; i++) {
109 DROPPACKETn("send_packet", 0);
110
111 if (sendto(peer, pkt, size, 0, (struct sockaddr *)&peer_sock,
112 peer_sock.ss_len) == size) {
113 if (i)
114 tftp_log(LOG_ERR,
115 "%s block %d, attempt %d successful",
116 packettype(ntohs(((struct tftphdr *)
117 (pkt))->th_opcode)), block, i);
118 return (0);
119 }
120 tftp_log(LOG_ERR,
121 "%s block %d, attempt %d failed (Error %d: %s)",
122 packettype(ntohs(((struct tftphdr *)(pkt))->th_opcode)),
123 block, i, errno, strerror(errno));
124 sleep(t);
125 if (t < 32)
126 t <<= 1;
127 }
128 tftp_log(LOG_ERR, "send_packet: %s", strerror(errno));
129 return (1);
130 }
131
132 /*
133 * Send an ERROR packet (error message).
134 * Error code passed in is one of the
135 * standard TFTP codes, or a UNIX errno
136 * offset by 100.
137 */
138 void
send_error(int peer,int error)139 send_error(int peer, int error)
140 {
141 struct tftphdr *tp;
142 int length;
143 struct errmsg *pe;
144 char buf[MAXPKTSIZE];
145
146 if (debug&DEBUG_PACKETS)
147 tftp_log(LOG_DEBUG, "Sending ERROR %d", error);
148
149 DROPPACKET("send_error");
150
151 tp = (struct tftphdr *)buf;
152 tp->th_opcode = htons((u_short)ERROR);
153 tp->th_code = htons((u_short)error);
154 for (pe = errmsgs; pe->e_code >= 0; pe++)
155 if (pe->e_code == error)
156 break;
157 if (pe->e_code < 0) {
158 pe->e_msg = strerror(error - 100);
159 tp->th_code = EUNDEF; /* set 'undef' errorcode */
160 }
161 strcpy(tp->th_msg, pe->e_msg);
162 length = strlen(pe->e_msg);
163 tp->th_msg[length] = '\0';
164 length += 5;
165
166 if (debug&DEBUG_PACKETS)
167 tftp_log(LOG_DEBUG, "Sending ERROR %d: %s", error, tp->th_msg);
168
169 if (sendto(peer, buf, length, 0,
170 (struct sockaddr *)&peer_sock, peer_sock.ss_len) != length)
171 tftp_log(LOG_ERR, "send_error: %s", strerror(errno));
172 }
173
174 /*
175 * Send an WRQ packet (write request).
176 */
177 int
send_wrq(int peer,char * filename,char * mode)178 send_wrq(int peer, char *filename, char *mode)
179 {
180 int n;
181 struct tftphdr *tp;
182 char *bp;
183 char buf[MAXPKTSIZE];
184 int size;
185
186 if (debug&DEBUG_PACKETS)
187 tftp_log(LOG_DEBUG, "Sending WRQ: filename: '%s', mode '%s'",
188 filename, mode
189 );
190
191 DROPPACKETn("send_wrq", 1);
192
193 tp = (struct tftphdr *)buf;
194 tp->th_opcode = htons((u_short)WRQ);
195 size = offsetof(struct tftphdr, th_stuff);
196
197 bp = tp->th_stuff;
198 strlcpy(bp, filename, sizeof(buf) - size);
199 bp += strlen(filename);
200 *bp = 0;
201 bp++;
202 size += strlen(filename) + 1;
203
204 strlcpy(bp, mode, sizeof(buf) - size);
205 bp += strlen(mode);
206 *bp = 0;
207 bp++;
208 size += strlen(mode) + 1;
209
210 if (options_rfc_enabled)
211 size += make_options(peer, bp, sizeof(buf) - size);
212
213 n = sendto(peer, buf, size, 0,
214 (struct sockaddr *)&peer_sock, peer_sock.ss_len);
215 if (n != size) {
216 tftp_log(LOG_ERR, "send_wrq: %s", strerror(errno));
217 return (1);
218 }
219 return (0);
220 }
221
222 /*
223 * Send an RRQ packet (write request).
224 */
225 int
send_rrq(int peer,char * filename,char * mode)226 send_rrq(int peer, char *filename, char *mode)
227 {
228 int n;
229 struct tftphdr *tp;
230 char *bp;
231 char buf[MAXPKTSIZE];
232 int size;
233
234 if (debug&DEBUG_PACKETS)
235 tftp_log(LOG_DEBUG, "Sending RRQ: filename: '%s', mode '%s'",
236 filename, mode
237 );
238
239 DROPPACKETn("send_rrq", 1);
240
241 tp = (struct tftphdr *)buf;
242 tp->th_opcode = htons((u_short)RRQ);
243 size = offsetof(struct tftphdr, th_stuff);
244
245 bp = tp->th_stuff;
246 strlcpy(bp, filename, sizeof(buf) - size);
247 bp += strlen(filename);
248 *bp = 0;
249 bp++;
250 size += strlen(filename) + 1;
251
252 strlcpy(bp, mode, sizeof(buf) - size);
253 bp += strlen(mode);
254 *bp = 0;
255 bp++;
256 size += strlen(mode) + 1;
257
258 if (options_rfc_enabled) {
259 options[OPT_TSIZE].o_request = strdup("0");
260 size += make_options(peer, bp, sizeof(buf) - size);
261 }
262
263 n = sendto(peer, buf, size, 0,
264 (struct sockaddr *)&peer_sock, peer_sock.ss_len);
265 if (n != size) {
266 tftp_log(LOG_ERR, "send_rrq: %d %s", n, strerror(errno));
267 return (1);
268 }
269 return (0);
270 }
271
272 /*
273 * Send an OACK packet (option acknowledgement).
274 */
275 int
send_oack(int peer)276 send_oack(int peer)
277 {
278 struct tftphdr *tp;
279 int size, i, n;
280 char *bp;
281 char buf[MAXPKTSIZE];
282
283 if (debug&DEBUG_PACKETS)
284 tftp_log(LOG_DEBUG, "Sending OACK");
285
286 DROPPACKETn("send_oack", 0);
287
288 /*
289 * Send back an options acknowledgement (only the ones with
290 * a reply for)
291 */
292 tp = (struct tftphdr *)buf;
293 bp = buf + 2;
294 size = sizeof(buf) - 2;
295 tp->th_opcode = htons((u_short)OACK);
296 for (i = 0; options[i].o_type != NULL; i++) {
297 if (options[i].o_reply != NULL) {
298 n = snprintf(bp, size, "%s%c%s", options[i].o_type,
299 0, options[i].o_reply);
300 bp += n+1;
301 size -= n+1;
302 if (size < 0) {
303 tftp_log(LOG_ERR, "oack: buffer overflow");
304 exit(1);
305 }
306 }
307 }
308 size = bp - buf;
309
310 if (sendto(peer, buf, size, 0,
311 (struct sockaddr *)&peer_sock, peer_sock.ss_len) != size) {
312 tftp_log(LOG_INFO, "send_oack: %s", strerror(errno));
313 return (1);
314 }
315
316 return (0);
317 }
318
319 /*
320 * Send an ACK packet (acknowledgement).
321 */
322 int
send_ack(int fp,uint16_t block)323 send_ack(int fp, uint16_t block)
324 {
325 struct tftphdr *tp;
326 int size;
327 char buf[MAXPKTSIZE];
328
329 if (debug&DEBUG_PACKETS)
330 tftp_log(LOG_DEBUG, "Sending ACK for block %d", block);
331
332 DROPPACKETn("send_ack", 0);
333
334 tp = (struct tftphdr *)buf;
335 size = sizeof(buf) - 2;
336 tp->th_opcode = htons((u_short)ACK);
337 tp->th_block = htons((u_short)block);
338 size = 4;
339
340 if (sendto(fp, buf, size, 0,
341 (struct sockaddr *)&peer_sock, peer_sock.ss_len) != size) {
342 tftp_log(LOG_INFO, "send_ack: %s", strerror(errno));
343 return (1);
344 }
345
346 return (0);
347 }
348
349 /*
350 * Send a DATA packet
351 */
352 int
send_data(int peer,uint16_t block,char * data,int size)353 send_data(int peer, uint16_t block, char *data, int size)
354 {
355 char buf[MAXPKTSIZE];
356 struct tftphdr *pkt;
357 int n;
358
359 if (debug&DEBUG_PACKETS)
360 tftp_log(LOG_DEBUG, "Sending DATA packet %d of %d bytes",
361 block, size);
362
363 DROPPACKETn("send_data", 0);
364
365 pkt = (struct tftphdr *)buf;
366
367 pkt->th_opcode = htons((u_short)DATA);
368 pkt->th_block = htons((u_short)block);
369 memcpy(pkt->th_data, data, size);
370
371 n = send_packet(peer, block, (char *)pkt, size + 4);
372 return (n);
373 }
374
375
376 /*
377 * Receive a packet
378 */
379 static jmp_buf timeoutbuf;
380
381 static void
timeout(int sig __unused)382 timeout(int sig __unused)
383 {
384
385 /* tftp_log(LOG_DEBUG, "Timeout\n"); Inside a signal handler... */
386 longjmp(timeoutbuf, 1);
387 }
388
389 int
receive_packet(int peer,char * data,int size,struct sockaddr_storage * from,int thistimeout)390 receive_packet(int peer, char *data, int size, struct sockaddr_storage *from,
391 int thistimeout)
392 {
393 struct tftphdr *pkt;
394 struct sockaddr_storage from_local;
395 struct sockaddr_storage *pfrom;
396 socklen_t fromlen;
397 int n;
398 static int timed_out;
399
400 if (debug&DEBUG_PACKETS)
401 tftp_log(LOG_DEBUG,
402 "Waiting %d seconds for packet", timeoutpacket);
403
404 pkt = (struct tftphdr *)data;
405
406 signal(SIGALRM, timeout);
407 timed_out = setjmp(timeoutbuf);
408 alarm(thistimeout);
409
410 if (timed_out != 0) {
411 tftp_log(LOG_ERR, "receive_packet: timeout");
412 alarm(0);
413 return (RP_TIMEOUT);
414 }
415
416 pfrom = (from == NULL) ? &from_local : from;
417 fromlen = sizeof(*pfrom);
418 n = recvfrom(peer, data, size, 0, (struct sockaddr *)pfrom, &fromlen);
419
420 alarm(0);
421
422 DROPPACKETn("receive_packet", RP_TIMEOUT);
423
424 if (n < 0) {
425 tftp_log(LOG_ERR, "receive_packet: timeout");
426 return (RP_TIMEOUT);
427 }
428
429 if (n < 0) {
430 /* No idea what could have happened if it isn't a timeout */
431 tftp_log(LOG_ERR, "receive_packet: %s", strerror(errno));
432 return (RP_RECVFROM);
433 }
434 if (n < 4) {
435 tftp_log(LOG_ERR,
436 "receive_packet: packet too small (%d bytes)", n);
437 return (RP_TOOSMALL);
438 }
439
440 pkt->th_opcode = ntohs((u_short)pkt->th_opcode);
441 if (pkt->th_opcode == DATA ||
442 pkt->th_opcode == ACK)
443 pkt->th_block = ntohs((u_short)pkt->th_block);
444
445 if (pkt->th_opcode == DATA && n > pktsize) {
446 tftp_log(LOG_ERR, "receive_packet: packet too big");
447 return (RP_TOOBIG);
448 }
449
450 if (((struct sockaddr_in *)(pfrom))->sin_addr.s_addr !=
451 ((struct sockaddr_in *)(&peer_sock))->sin_addr.s_addr) {
452 tftp_log(LOG_ERR,
453 "receive_packet: received packet from wrong source");
454 return (RP_WRONGSOURCE);
455 }
456
457 if (pkt->th_opcode == ERROR) {
458 tftp_log(pkt->th_code == EUNDEF ? LOG_DEBUG : LOG_ERR,
459 "Got ERROR packet: %s", pkt->th_msg);
460 return (RP_ERROR);
461 }
462
463 if (debug&DEBUG_PACKETS)
464 tftp_log(LOG_DEBUG, "Received %d bytes in a %s packet",
465 n, packettype(pkt->th_opcode));
466
467 return n - 4;
468 }
469