Ignore:
Timestamp:
11/26/08 02:51:23 (3 years ago)
Author:
wd
Message:

Prevent data that shoots past the buffer limit in 1459-style protocols from
being treated as a new command.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • branches/ithildin-1.1/modules/ircd/protocols/shared/rfc1459_io.c

    r825 r828  
    2222    int ret = 0; 
    2323    char *s; 
     24    bool dirtybuffer; 
    2425 
    2526    /* If we were force-called (ep is NULL) we assume there is data in our 
     
    3536 
    3637        while (cp->buflen > 0) { 
     38            dirtybuffer = false; 
    3739            /* if the buffer is full but no terminating character (\n) is 
    3840               found, we cheat */ 
     
    4547                    s++; 
    4648 
     49                /* A command without a newline, add it and note that the 
     50                 * future contents of the buffer are dirty (handled below 
     51                 * when we pass out the data) */ 
    4752                if (s == cp->buf + cp->bufsize) { 
    4853                    cp->buf[cp->bufsize - 1] = '\n'; 
    4954                    s = cp->buf + cp->bufsize - 1; 
     55                    dirtybuffer = true; 
    5056                } 
    5157            } else { 
     
    5561                    break; /* no separator found, try reading some more */ 
    5662            } 
    57             /* make a local copy of the packet, then pass it off to the parser.  
    58              * Bump the rest of the contents of 'buf' down if we read more than 
    59              * we have parsed. */ 
     63 
    6064            /* null-terminate and get rid of the [\r]\n sequence. */ 
    6165            if (s > cp->buf && *(s - 1) == '\r') 
     
    6367            else 
    6468                *s = '\0'; 
     69 
    6570            log_debug("[%s] <%s< %s", ircd.me->name, 
    6671                    (cp->cli != NULL ? cp->cli->nick : 
    6772                     (cp->srv != NULL ? cp->srv->name : "")), cp->buf); 
    68             if ((ret = packet_parse(cp)) == IRCD_CONNECTION_CLOSED) 
    69                 return (void *)ret; /* connection closed, stop immediately */ 
     73            /* Don't parse the packet if the buffer is dirty, otherwise do 
     74             * call the parser. */ 
     75            if (!(cp->flags & IRCD_CONNFL_DIRTYBUFFER)) 
     76            { 
     77                if ((ret = packet_parse(cp)) == IRCD_CONNECTION_CLOSED) 
     78                    return (void *)ret; /* connection closed, stop immediately */ 
     79            } else 
     80                cp->flags &= ~IRCD_CONNFL_DIRTYBUFFER; 
     81 
    7082            s++; /* increment s, now we see if our packet contains more data */ 
    7183            if (s - cp->buf < cp->buflen) { 
     
    7789                *cp->buf = '\0'; /* zero it out */ 
    7890            } 
     91 
     92            /* If the buffer is marked dirty, set the flag now on the 
     93             * connection (since we have passed off the previous command) */ 
     94            if (dirtybuffer) 
     95                cp->flags |= IRCD_CONNFL_DIRTYBUFFER; 
    7996 
    8097            if (ret == IRCD_PROTOCOL_CHANGED) 
     
    128145            buf[sm.len++] = ' '; 
    129146 
    130         sm.len += vsnprintf(&buf[sm.len], MAX_PACKET_LEN - 3 - sm.len, msg, 
    131                 args); 
     147        sm.len += vsnprintf(&buf[sm.len], MAX_PACKET_LEN - sm.len, msg, args); 
    132148    } 
    133149 
     
    139155            (to != NULL ? to : ""), buf); 
    140156 
    141     strcpy(&buf[sm.len], "\r\n"); 
    142     sm.len += 2; 
     157    /* Terminate the command */ 
     158    if (sm.len > MAX_PACKET_LEN - 2) 
     159        sm.len = MAX_PACKET_LEN - 2; 
     160    buf[sm.len++] = '\r'; 
     161    buf[sm.len++] = '\n'; 
    143162 
    144163    return &sm; 
Note: See TracChangeset for help on using the changeset viewer.