/** Copy all the data from an \c ibuf to an \c obuf. */ int iobuf_copy(ibuf* in, obuf* out) { if (ibuf_eof(in)) return 1; if (ibuf_error(in) || obuf_error(out)) return 0; for (;;) { if (!obuf_write_large(out, in->io.buffer+in->io.bufstart, in->io.buflen-in->io.bufstart)) return 0; in->io.bufstart = in->io.buflen; if (!ibuf_refill(in)) return ibuf_eof(in); } }
static int read_line(void) { const char** p; int matches; if (!ibuf_getstr(&inbuf, &last_line.line, LF)) { exitasap = exitoneof || seq_next == seq_send; if (!ibuf_eof(&inbuf)) error1sys("Could not read line from stdin"); stdin_eof = 1; return 0; } --last_line.line.len; /* Strip off the trailing LF */ if (patterns != 0) { matches = 1; for (p = patterns; *p != 0; ++p) { if (str_matchs(&last_line.line, (*p)+1)) matches = **p == '+'; } if (!matches) return 0; } gettimestamp(&last_line.timestamp); SET_SEQ(last_line.seq = seq_next++); if (last_line.line.len > MAX_LINE) { str_rcut(&last_line.line, last_line.line.len - MAX_LINE); memcpy(last_line.line.s + MAX_LINE - 17, "[...truncated...]", 17); } buffer->push(&last_line); return 1; }
static void inbuf_errmsg(void) { if (ibuf_timedout(&inbuf)) respond(421, 1, "Timed out waiting for command."); else if (!ibuf_eof(&inbuf)) respond_syserr(421, "I/O error"); }
/** Read a line from the \c ibuf into a dynamic string. */ int ibuf_getstr(ibuf* in, struct str* s, char boundary) { iobuf* io; int ch; io = &in->io; in->count = 0; str_truncate(s, 0); if (ibuf_eof(in) || ibuf_error(in) || ibuf_timedout(in)) return 0; for (;;) { if (io->bufstart >= io->buflen && !ibuf_refill(in)) { if (ibuf_eof(in)) break; return 0; } in->count++; ch = io->buffer[io->bufstart++]; if (!str_catc(s, ch)) return 0; if (ch == boundary) break; } return in->count > 0; }
static int mainloop(const struct command* commands) { if (!respond_line(220, 1, str_welcome.s, str_welcome.len)) return 0; while (ibuf_getstr_crlf(&inbuf, &line)) if (!smtp_dispatch(commands)) { if (ibuf_eof(&inbuf)) msg1("Connection dropped"); if (ibuf_timedout(&inbuf)) msg1("Timed out"); return 1; } return 0; }
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; }