diff --git a/CHANGES b/CHANGES index 2ae9114..15874ab 100644 --- a/CHANGES +++ b/CHANGES @@ -1,5 +1,10 @@ $Id$ +Changes in 0.25: + Fixed Sorcerer's Apprentice bug in both the client and the + server. These bugs were inherited from the original BSD code. + + Changes in 0.24: Fix bugs in both client and server dealing with block number wraparound, usually manifesting themselves as failure to diff --git a/tftp/tftp.c b/tftp/tftp.c index fe8a88d..46000d4 100644 --- a/tftp/tftp.c +++ b/tftp/tftp.c @@ -137,7 +137,7 @@ tftp_sendfile(int fd, char *name, char *mode) } timeout = 0; (void) sigsetjmp(timeoutbuf,1); -send_data: + if (trace) tpacket("sent", dp, size + 4); n = sendto(f, dp, size + 4, 0, @@ -184,9 +184,11 @@ send_data: printf("discarded %d packets\n", j); } - if (ap->th_block == (block-1)) { - goto send_data; - } + /* + * RFC1129/RFC1350: We MUST NOT re-send the DATA + * packet in response to an invalid ACK. Doing so + * would cause the Sorcerer's Apprentice bug. + */ } } if ( !is_request ) diff --git a/tftpd/tftpd.c b/tftpd/tftpd.c index c019591..4f700c9 100644 --- a/tftpd/tftpd.c +++ b/tftpd/tftpd.c @@ -978,7 +978,6 @@ tftp_sendfile(struct formats *pf, struct tftphdr *oap, int oacklen) timeout = 0; (void) sigsetjmp(timeoutbuf,1); - send_data: if (send(peer, dp, size + 4, 0) != size + 4) { syslog(LOG_ERR, "tftpd: write: %m"); goto abort; @@ -1005,9 +1004,11 @@ tftp_sendfile(struct formats *pf, struct tftphdr *oap, int oacklen) } /* Re-synchronize with the other side */ (void) synchnet(peer); - if (ap->th_block == (block -1)) { - goto send_data; - } + /* + * RFC1129/RFC1350: We MUST NOT re-send the DATA + * packet in response to an invalid ACK. Doing so + * would cause the Sorcerer's Apprentice bug. + */ } }