示例#1
0
/*
 * Determines from the first five bytes of a potential SLP header
 * if the following message is really an SLP message. Returns 1 if
 * it is a real SLP message, 0 if not.
 */
int valid_slp(unsigned char *slphdr, int len) {
	struct slpv1_hdr slp1;
	struct slpv2_hdr slp2;

	len -= (8 /* udp */ + 20 /* IP */ + 14 /* ether */);
	/* a valid version will be 1 or 2 */
	switch (*slphdr) {
	case 1:
	    memcpy(&slp1, slphdr, 5);
	    /* valid function? */
	    if (slp1.function > V1_MAX_FUNCTION) {
		return (0);
	    }
	    /* valid length heuristic */
	    if (slp1.length > len) {
		return (0);
	    }
	    return (1);
	case 2:
	    memcpy(&slp2, slphdr, 5);
	    /* valid function? */
	    if (slp2.function > V2_MAX_FUNCTION) {
		return (0);
	    }
	    /* valid length heuristic */
	    get_int24(&(slp2.l1));
	    if (netval > len) {
		return (0);
	    }
	    return (1);
	default:
	    return (0);
	}
}
/* Return > 0 Total packet length.in bytes
 *        = 0 Length unknown, need more data.
 *        < 0 Error, invalid format.
 */
int packet_get_length(enum PacketParseType htype,
                      const char* ptr, unsigned n, /* Bytes read so far */
                      unsigned max_plen,     /* Max packet length, 0=no limit */
                      unsigned trunc_len,    /* Truncate (lines) if longer, 0=no limit */
                      int*     statep)       /* Protocol specific state */
{
    unsigned hlen, plen;

    switch (htype) {
    case TCP_PB_RAW:
        if (n == 0) goto more;
        else {
            DEBUGF((" => nothing remain packet=%d\r\n", n));        
            return n;
        }

    case TCP_PB_1:
        /* TCP_PB_1:    [L0 | Data] */
        hlen = 1;
        if (n < hlen) goto more;
        plen = get_int8(ptr);
        goto remain;

    case TCP_PB_2:
        /* TCP_PB_2:    [L1,L0 | Data] */
        hlen = 2;
        if (n < hlen) goto more;
        plen = get_int16(ptr);
        goto remain;

    case TCP_PB_4:
        /* TCP_PB_4:    [L3,L2,L1,L0 | Data] */
        hlen = 4;
        if (n < hlen) goto more;
        plen = get_int32(ptr);
        goto remain;

    case TCP_PB_RM:
        /* TCP_PB_RM:    [L3,L2,L1,L0 | Data] 
        ** where MSB (bit) is used to signal end of record
        */
        hlen = 4;
        if (n < hlen) goto more;
        plen = get_int32(ptr) & 0x7fffffff;
        goto remain;

    case TCP_PB_LINE_LF: {
        /* TCP_PB_LINE_LF:  [Data ... \n]  */
        const char* ptr2;
        if ((ptr2 = memchr(ptr, '\n', n)) == NULL) {
            if (n > max_plen && max_plen != 0) { /* packet full */
                DEBUGF((" => packet full (no NL)=%d\r\n", n));
                goto error;
            }
            else if (n >= trunc_len && trunc_len!=0) { /* buffer full */
                DEBUGF((" => line buffer full (no NL)=%d\r\n", n));
                return trunc_len;
            }
            goto more;
        }
        else {
            int len = (ptr2 - ptr) + 1; /* including newline */
            if (len > max_plen && max_plen!=0) {
                DEBUGF((" => packet_size %d exceeded\r\n", max_plen));
                goto error;
            }
            if (len > trunc_len && trunc_len!=0) {
                DEBUGF((" => truncated line=%d\r\n", trunc_len));
                return trunc_len;
            }
            DEBUGF((" => nothing remain packet=%d\r\n", len));
            return len;
        }
    }

    case TCP_PB_ASN1: {
        /* TCP_PB_ASN1: handles long (4 bytes) or short length format */
        const char* tptr = ptr;
        int length;
        int nn = n;
        
        if (n < 2) goto more;
        nn--;
        if ((*tptr++ & 0x1f) == 0x1f) { /* Long tag format */
            while (nn && ((*tptr & 0x80) == 0x80)) {
                tptr++;
                nn--;
            }
            if (nn < 2) goto more;
            tptr++;
            nn--;
        }
        
        /* tptr now point to length field and nn characters remain */
        length = *tptr & 0x7f;
        if ((*tptr & 0x80) == 0x80) {   /* Long length format */
            tptr++;
            nn--;
            if (nn < length) goto more;
            switch (length) {
            case 0: plen = 0; break;
            case 1: plen = get_int8(tptr);  tptr += 1; break;
            case 2: plen = get_int16(tptr); tptr += 2; break;
            case 3: plen = get_int24(tptr); tptr += 3; break;
            case 4: plen = get_int32(tptr); tptr += 4; break;
            default: goto error; /* error */
            }
        }
        else {
            tptr++;
            plen = length;
        }
        hlen = (tptr-ptr);
        goto remain;
    }    
    
    case TCP_PB_CDR: {
        const struct cdr_head* hp;
        hlen = sizeof(struct cdr_head);
        if (n < hlen) goto more;
        hp = (struct cdr_head*) ptr;
        if (sys_memcmp(hp->magic, CDR_MAGIC, 4) != 0)
            goto error;
        if (hp->flags & 0x01) /* Byte ordering flag */
            plen = get_little_int32(hp->message_size);
        else
            plen = get_int32(hp->message_size);
        goto remain;
    }
    
    case TCP_PB_FCGI: {
        const struct fcgi_head* hp;
        hlen = sizeof(struct fcgi_head);
        if (n < hlen) goto more;
        hp = (struct fcgi_head*) ptr;
        if (hp->version != FCGI_VERSION_1)
                goto error;
        plen = ((hp->contentLengthB1 << 8) | hp->contentLengthB0)
               + hp->paddingLength;
        goto remain;
    }
    case TCP_PB_HTTPH:
    case TCP_PB_HTTPH_BIN:
        *statep = !0;
    case TCP_PB_HTTP:
    case TCP_PB_HTTP_BIN:
        /* TCP_PB_HTTP:  data \r\n(SP data\r\n)*  */
        plen = n;
        if (((plen == 1) && NL(ptr)) || ((plen == 2) && CRNL(ptr)))
            goto done;
        else {
            const char* ptr1 = ptr;
            int   len = plen;
            
	    if (!max_plen) {
		/* This is for backward compatibility with old user of decode_packet
		 * that might use option 'line_length' to limit accepted length of
		 * http lines.
		 */
		max_plen = trunc_len;
	    }

            while (1) {
                const char* ptr2 = memchr(ptr1, '\n', len);
                
                if (ptr2 == NULL) {
                    if (max_plen != 0) {
                        if (n >= max_plen) /* packet full */
                            goto error;
                    }
                    goto more;
                }
                else {
                    plen = (ptr2 - ptr) + 1;

                    if (*statep == 0) {
                        if (max_plen != 0 && plen > max_plen)
                            goto error;
                        goto done;
                    }

                    if (plen < n) {
                        if (SP(ptr2+1) && plen>2) {
                            /* header field value continue on next line */
                            ptr1 = ptr2+1;
                            len = n - plen;
                        }
                        else {
                            if (max_plen != 0 && plen > max_plen)
                                goto error;
                            goto done;
                        }
                    }
                    else {
                        if (max_plen != 0 && plen > max_plen)
                            goto error;
                        goto more;
                    }
                }
            }
        }
    case TCP_PB_TPKT: {
        const struct tpkt_head* hp;
        hlen = sizeof(struct tpkt_head);
        if (n < hlen)
            goto more;
        hp = (struct tpkt_head*) ptr;
        if (hp->vrsn == TPKT_VRSN) {
            plen = get_int16(hp->packet_length) - hlen;
        } else {
            goto error;
	}
        goto remain;
    }
    
    case TCP_PB_SSL_TLS:
        hlen = 5;
        if (n < hlen) goto more;        
        if ((ptr[0] & 0x80) && ptr[2] == 1) {
            /* Ssl-v2 Client hello <<1:1, Len:15, 1:8, Version:16>>  */
            plen = (get_int16(&ptr[0]) & 0x7fff) - 3;
        } 
        else {
            /* <<ContentType:8, Version:16, Length:16>> */
            plen = get_int16(&ptr[3]);
        }
        goto remain;
    
    default:
        DEBUGF((" => case error\r\n"));
        return -1;
    }

more:
    return 0;

remain:
    {
        int tlen = hlen + plen;
	if ((max_plen != 0 && plen > max_plen)
	    || tlen < (int)hlen) { /* wrap-around protection */
	    return -1;
	}
	return tlen;
    }		

done:
    return plen;

error:
    return -1;
}
示例#3
0
static int v2_finish(struct slpv2_hdr *slp, int flags) {
	unsigned int firstop;

	if (!(flags & F_DTAIL))
	    return (1);

	/* check for options */
	get_int24(&(slp->o1));
	firstop = netval;

	if (firstop) {
	    unsigned short op_id;
	    unsigned short nextop;
	    char *op_class;

	    for (;;) {
		unsigned short real_oplen;

		if (msglength < 4) {
		    sprintf(get_line(0, 0),
			    "Option expected but not present");
		    return (0);
		}

		nbtohs();
		op_id = netval;
		p += sizeof (unsigned short);
		msglength -= sizeof (unsigned short);
		nbtohs();
		nextop = netval;
		p += sizeof (unsigned short);
		msglength -= sizeof (unsigned short);

		real_oplen = nextop ? nextop : msglength;

		/* known options */
		switch (op_id) {
		case 1:
		    sprintf(get_line(0, 0),
			    "Option: Required Attribute Missing");
		    DOFIELD("Template IDVer", FIELD_DEFAULT);
		    DOFIELD("Required Attrs", FIELD_DEFAULT);
		    break;
		default:
		    sprintf(get_line(0, 0), "Option: Unknown");
		    p += (real_oplen - 4);
		    msglength -= (real_oplen - 4);
		    break;
		}

		if (op_id < 0x3fff)
		    op_class = "Standardized, optional";
		else if (op_id < 0x7fff)
		    op_class = "Standardized, mandatory";
		else if (op_id < 0x8fff)
		    op_class = "Not standardized, private";
		else if (op_id < 0xffff)
		    op_class = "Reserved";
		sprintf(get_line(0, 0), "Option ID = 0x%04x, %s",
			op_id, op_class);
		if (nextop &&
		    ((nextop - 4) > msglength) &&
		    !tcp_continuation) {
		    sprintf(get_line(0, 0),
			    "[Framing error: remaining pkt length = %u]",
			    msglength);
		    return (0);
		}

		sprintf(get_line(0, 0), "Option Length = %u", real_oplen);

		if (!nextop)
		    break;
	    }
	}

	return (1);
}
示例#4
0
static int v2_header(int flags,
			struct slpv2_hdr *slp,
			int *totallen,
			int fraglen) {
	extern int curr_proto, dst_port;
	char *prototag = (curr_proto == IPPROTO_TCP ? "/tcp" : "");

	if ((slp->flags & V2_OVERFLOW) == V2_OVERFLOW)
	    overflow = B_TRUE;

	/* summary mode header parsing */
	if (flags & F_SUM) {

	    /* make sure we have at least a header */
	    if (msglength < sizeof (*slp)) {
		sprintf(get_sum_line(), "SLP V2 [Incomplete Header]");
		return (0);
	    }

	    sprintf(msgbuf, "SLP V2 %s [%d%s] ",
		    slpv2_func(slp->function, B_TRUE),
		    ntohs(slp->xid), prototag);

	    /* skip to end of header */
	    msgend = msgbuf + strlen(msgbuf);
	    msglength -= sizeof (*slp);
	    p += sizeof (*slp);

	    /* skip language tag */
	    SKIPFIELD(FIELD_DEFAULT);
	} else if (flags & F_DTAIL) {
	    char *lang;
	    int len;

	    /* detailed mode header parsing */
	    show_header("SLP:  ", "Service Location Protocol (v2)", fraglen);
	    show_space();

	    if (msglength < sizeof (*slp)) {
		sprintf(get_line(0, 0), "==> Incomplete SLP header");
		return (0);
	    }

	    sprintf(get_line(0, 0), "Version = %d", slp->vers);
	    sprintf(get_line(0, 0), "Function = %d, %s",
		    slp->function, slpv2_func(slp->function, B_FALSE));
	    get_int24(&(slp->l1));
	    *totallen = netval;
	    sprintf(get_line(0, 0), "Message length = %u", *totallen);
	    /* check for TCP continuation */
	    if (curr_proto == IPPROTO_TCP &&
		*totallen > msglength &&
		!tcp_continuation) {
		tcp_continuation = B_TRUE;
		reg_tcp_cont((char *)slp, *totallen, msglength, dst_port);
	    }

	    if (!tcp_continuation && *totallen != msglength) {
		sprintf(get_line(0, 0),
			"  (Stated and on-the-wire lengths differ)");
	    }
	    /* flags */
	    sprintf(get_line(0, 0), "Flags = 0x%02x", slp->flags);
	    sprintf(get_line(0, 0), "      %s",
		    getflag(slp->flags, V2_OVERFLOW,
			    "overflow", "no overflow"));
	    sprintf(get_line(0, 0), "      %s",
		    getflag(slp->flags, V2_FRESH,
			    "fresh registration", "no fresh registration"));
	    sprintf(get_line(0, 0), "      %s",
		    getflag(slp->flags, V2_MCAST,
			    "request multicast / broadcast", "unicast"));
	    /* check reserved flags that must be zero */
	    if ((slp->flags & 7) != 0) {
		sprintf(get_line(0, 0),
			"      .... .xxx = %d (reserved flags nonzero)",
			slp->flags & 7);
	    }
	    /* end of flags */

	    /* language tag */
	    p = (char *)slp + sizeof (*slp);
	    msglength -= sizeof (*slp);
	    GETSHORT(len);
	    if (len > msglength) {
		sprintf(get_line(0, 0),
			"Language Tag Length = %u [CORRUPT MESSAGE]",
			len);
		return (0);
	    }

	    lang = get_line(0, 0);
	    strcpy(lang, "Language Tag = ");
	    strncat(lang,  p, len);
	    sprintf(get_line(0, 0), "XID = %u", ntohs(slp->xid));

	    /* set msglength to remaining length of SLP message */
	    p += len;
	    msglength -= len;
	}

	return (1);
}