Browse Source

[tftp] Process OACKs even if malformed

IBM Tivoli PXE Server 5.1.0.3 is reported to send trailing garbage
bytes at the end of the OACK packet, which causes gPXE to reject the
packet and abort the TFTP transfer.

Work around the problem by processing as much as possible of the OACK,
and treating name/value parsing errors as non-fatal.

Reported-by: Shao Miller <Shao.Miller@yrdsb.edu.on.ca>
tags/v0.9.8
Michael Brown 15 years ago
parent
commit
1958974d0a
1 changed files with 28 additions and 12 deletions
  1. 28
    12
      src/net/udp/tftp.c

+ 28
- 12
src/net/udp/tftp.c View File

@@ -672,6 +672,7 @@ static int tftp_rx_oack ( struct tftp_request *tftp, void *buf, size_t len ) {
672 672
 	char *end = buf + len;
673 673
 	char *name;
674 674
 	char *value;
675
+	char *next;
675 676
 	int rc = 0;
676 677
 
677 678
 	/* Sanity check */
@@ -681,26 +682,41 @@ static int tftp_rx_oack ( struct tftp_request *tftp, void *buf, size_t len ) {
681 682
 		rc = -EINVAL;
682 683
 		goto done;
683 684
 	}
684
-	if ( end[-1] != '\0' ) {
685
-		DBGC ( tftp, "TFTP %p received OACK missing final NUL\n",
686
-		       tftp );
687
-		rc = -EINVAL;
688
-		goto done;
689
-	}
690 685
 
691 686
 	/* Process each option in turn */
692
-	name = oack->data;
693
-	while ( name < end ) {
694
-		value = ( name + strlen ( name ) + 1 );
687
+	for ( name = oack->data ; name < end ; name = next ) {
688
+
689
+		/* Parse option name and value
690
+		 *
691
+		 * We treat parsing errors as non-fatal, because there
692
+		 * exists at least one TFTP server (IBM Tivoli PXE
693
+		 * Server 5.1.0.3) that has been observed to send
694
+		 * malformed OACKs containing trailing garbage bytes.
695
+		 */
696
+		value = ( name + strnlen ( name, ( end - name ) ) + 1 );
697
+		if ( value > end ) {
698
+			DBGC ( tftp, "TFTP %p received OACK with malformed "
699
+			       "option name:\n", tftp );
700
+			DBGC_HD ( tftp, oack, len );
701
+			break;
702
+		}
695 703
 		if ( value == end ) {
696 704
 			DBGC ( tftp, "TFTP %p received OACK missing value "
697 705
 			       "for option \"%s\"\n", tftp, name );
698
-			rc = -EINVAL;
699
-			goto done;
706
+			DBGC_HD ( tftp, oack, len );
707
+			break;
700 708
 		}
709
+		next = ( value + strnlen ( value, ( end - value ) ) + 1 );
710
+		if ( next > end ) {
711
+			DBGC ( tftp, "TFTP %p received OACK with malformed "
712
+			       "value for option \"%s\":\n", tftp, name );
713
+			DBGC_HD ( tftp, oack, len );
714
+			break;
715
+		}
716
+
717
+		/* Process option */
701 718
 		if ( ( rc = tftp_process_option ( tftp, name, value ) ) != 0 )
702 719
 			goto done;
703
-		name = ( value + strlen ( value ) + 1 );
704 720
 	}
705 721
 
706 722
 	/* Process tsize information, if available */

Loading…
Cancel
Save