static int copy_body(void) { int sawcr = 0; /* Was the last character a CR */ unsigned linepos = 0; /* The number of bytes since the last LF */ int sawperiod = 0; /* True if the first character was a period */ char ch; data_start(); while (ibuf_getc(&inbuf, &ch)) { switch (ch) { case LF: if (sawperiod && linepos == 0) { message_end(); return 1; } data_byte(ch); sawperiod = sawcr = linepos = 0; break; case CR: if (sawcr) { data_byte(CR); ++linepos; } sawcr = 1; break; default: if (ch == PERIOD && !sawperiod && linepos == 0) sawperiod = 1; else { sawperiod = 0; if (sawcr) { data_byte(CR); ++linepos; sawcr = 0; } data_byte(ch); ++linepos; } } } return 0; }
static int read_request(void) /* Returns number of bytes read before the LF, or -1 for EOF */ { unsigned offset; int saw_esc; int saw_esc_respond; int saw_esc_ignore; char byte[1]; saw_esc = saw_esc_respond = saw_esc_ignore = 0; offset = 0; while (offset < sizeof request - 1) { if (!ibuf_getc(&inbuf, byte)) { inbuf_errmsg(); return -1; } if (saw_esc) { saw_esc = 0; switch (*byte) { case TELNET_DONT: case TELNET_WONT: saw_esc_ignore = *byte; break; case TELNET_WILL: saw_esc_respond = TELNET_DONT; break; case TELNET_DO : saw_esc_respond = TELNET_WONT; break; case TELNET_IAC : request[offset++] = TELNET_IAC; break; } } else if (saw_esc_ignore) { saw_esc_ignore = 0; } else if (saw_esc_respond) { obuf_putc(&outbuf, TELNET_IAC); obuf_putc(&outbuf, saw_esc_respond); obuf_putc(&outbuf, *byte); obuf_flush(&outbuf); saw_esc_respond = 0; } else if (*byte == TELNET_IAC) saw_esc = 1; else if (*byte == LF) break; else request[offset++] = *byte ? *byte : LF; } while (*byte != LF) if (!ibuf_getc(&inbuf, byte)) { inbuf_errmsg(); return -1; } return offset; }
/** Read an unsigned long from the \c ibuf */ int ibuf_getu(ibuf* in, unsigned long* data) { char ch; int chars; *data = 0; chars = 0; while (ibuf_peek(in, &ch) && ch >= '0' && ch <= '9') { *data = (*data * 10) + ch - '0'; ibuf_getc(in, &ch); chars = 1; } return chars; }
static int starttls(void) { int fd; char *fdstr; int extrachars = 0; char c; /* STARTTLS must be the last command in a pipeline, otherwise we can * create a security risk (see CVE-2011-0411). Close input and * check for any extra pipelined commands, so we can give an error * message. Note that this will cause an error on the filehandle, * since we have closed it. */ close(0); while (!ibuf_eof(&inbuf) && !ibuf_error(&inbuf)) { if (ibuf_getc(&inbuf, &c)) ++extrachars; } if (!(fdstr=getenv("SSLCTLFD"))) return 0; if ((fd = atoi(fdstr)) <= 0) return 0; if (write(fd, "y", 1) < 1) return 0; if (!(fdstr=getenv("SSLREADFD"))) return 0; if ((fd = atoi(fdstr)) <= 0) return 0; if (dup2(fd, 0) != 0) return 0; if (!(fdstr=getenv("SSLWRITEFD"))) return 0; if ((fd = atoi(fdstr)) <= 0) return 0; if (dup2(fd, 1) != 1) return 0; /* Re-initialize stdin and clear input buffer */ ibuf_init(&inbuf,0,0,IOBUF_NEEDSCLOSE, 4096); if (extrachars) respond(&resp_earlytalker); return 1; }