]> The Tcpdump Group git mirrors - tcpdump/blobdiff - print-tftp.c
CVE-2016-7983,7984/Don't use strchr() to scan packet data.
[tcpdump] / print-tftp.c
index 5519c686a416daf3bbc94243443cd8f3f74b01d8..69bc601fdda4ed8be3ac4f5e2bb9e24098be8ce8 100644 (file)
@@ -109,7 +109,8 @@ tftp_print(netdissect_options *ndo,
        register const struct tftphdr *tp;
        register const char *cp;
        register const u_char *p;
-       register int opcode, i;
+       register int opcode;
+       u_int ui;
 
        tp = (const struct tftphdr *)bp;
 
@@ -117,9 +118,12 @@ tftp_print(netdissect_options *ndo,
        ND_PRINT((ndo, " %d", length));
 
        /* Print tftp request type */
+       if (length < 2)
+               goto trunc;
        ND_TCHECK(tp->th_opcode);
        opcode = EXTRACT_16BITS(&tp->th_opcode);
        cp = tok2str(op2str, "tftp-#%d", opcode);
+       length -= 2;
        ND_PRINT((ndo, " %s", cp));
        /* Bail if bogus opcode */
        if (*cp == 't')
@@ -129,46 +133,80 @@ tftp_print(netdissect_options *ndo,
 
        case RRQ:
        case WRQ:
-       case OACK:
                p = (const u_char *)tp->th_stuff;
+               if (length == 0)
+                       goto trunc;
+               ND_PRINT((ndo, " "));
+               /* Print filename */
+               ND_PRINT((ndo, "\""));
+               ui = fn_printztn(ndo, p, length, ndo->ndo_snapend);
+               ND_PRINT((ndo, "\""));
+               if (ui == 0)
+                       goto trunc;
+               p += ui;
+               length -= ui;
+
+               /* Print the mode - RRQ and WRQ only */
+               if (length == 0)
+                       goto trunc;     /* no mode */
                ND_PRINT((ndo, " "));
-               /* Print filename or first option */
-               if (opcode != OACK)
-                       ND_PRINT((ndo, "\""));
-               i = fn_print(ndo, p, ndo->ndo_snapend);
-               if (opcode != OACK)
-                       ND_PRINT((ndo, "\""));
-
-               /* Print the mode (RRQ and WRQ only) and any options */
-               while ((p = (const u_char *)strchr((const char *)p, '\0')) != NULL) {
-                       if (length <= (u_int)(p - (const u_char *)&tp->th_block))
-                               break;
-                       p++;
-                       if (*p != '\0') {
+               ui = fn_printztn(ndo, p, length, ndo->ndo_snapend);
+               if (ui == 0)
+                       goto trunc;
+               p += ui;
+               length -= ui;
+
+               /* Print options, if any */
+               while (length != 0) {
+                       ND_TCHECK(*p);
+                       if (*p != '\0')
                                ND_PRINT((ndo, " "));
-                               fn_print(ndo, p, ndo->ndo_snapend);
-                       }
+                       ui = fn_printztn(ndo, p, length, ndo->ndo_snapend);
+                       if (ui == 0)
+                               goto trunc;
+                       p += ui;
+                       length -= ui;
                }
+               break;
 
-               if (i)
-                       goto trunc;
+       case OACK:
+               p = (const u_char *)tp->th_stuff;
+               /* Print options */
+               while (length != 0) {
+                       ND_TCHECK(*p);
+                       if (*p != '\0')
+                               ND_PRINT((ndo, " "));
+                       ui = fn_printztn(ndo, p, length, ndo->ndo_snapend);
+                       if (ui == 0)
+                               goto trunc;
+                       p += ui;
+                       length -= ui;
+               }
                break;
 
        case ACK:
        case DATA:
+               if (length < 2)
+                       goto trunc;     /* no block number */
                ND_TCHECK(tp->th_block);
                ND_PRINT((ndo, " block %d", EXTRACT_16BITS(&tp->th_block)));
                break;
 
        case TFTP_ERROR:
                /* Print error code string */
+               if (length < 2)
+                       goto trunc;     /* no error code */
                ND_TCHECK(tp->th_code);
-               ND_PRINT((ndo, " %s \"", tok2str(err2str, "tftp-err-#%d \"",
+               ND_PRINT((ndo, " %s", tok2str(err2str, "tftp-err-#%d \"",
                                       EXTRACT_16BITS(&tp->th_code))));
+               length -= 2;
                /* Print error message string */
-               i = fn_print(ndo, (const u_char *)tp->th_data, ndo->ndo_snapend);
+               if (length == 0)
+                       goto trunc;     /* no error message */
+               ND_PRINT((ndo, " \""));
+               ui = fn_printztn(ndo, (const u_char *)tp->th_data, length, ndo->ndo_snapend);
                ND_PRINT((ndo, "\""));
-               if (i)
+               if (ui == 0)
                        goto trunc;
                break;