summaryrefslogtreecommitdiffstats
path: root/contrib/pf/ftp-proxy/getline.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/pf/ftp-proxy/getline.c')
-rw-r--r--contrib/pf/ftp-proxy/getline.c259
1 files changed, 259 insertions, 0 deletions
diff --git a/contrib/pf/ftp-proxy/getline.c b/contrib/pf/ftp-proxy/getline.c
new file mode 100644
index 0000000..2be3883
--- /dev/null
+++ b/contrib/pf/ftp-proxy/getline.c
@@ -0,0 +1,259 @@
+/* $OpenBSD: getline.c,v 1.15 2003/06/28 01:04:57 deraadt Exp $ */
+
+/*
+ * Copyright (c) 1985, 1988 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)ftpcmd.y 5.24 (Berkeley) 2/25/91
+ */
+
+#include <sys/types.h>
+#include <sys/socket.h>
+
+#include <netinet/in.h>
+#include <arpa/telnet.h>
+
+#include <errno.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <sysexits.h>
+#include <syslog.h>
+#include <unistd.h>
+
+#include "util.h"
+
+int refill_buffer(struct csiob *iobp);
+
+/*
+ * Refill the io buffer if we KNOW that data is available
+ *
+ * Returns 1 if any new data was obtained, 0 otherwise.
+ */
+
+int
+refill_buffer(struct csiob *iobp)
+{
+ int rqlen, rlen;
+
+ if (!(iobp->data_available))
+ return(0);
+
+ if (iobp->got_eof)
+ return(0);
+
+ /*
+ * The buffer has been entirely consumed if next_byte == io_buffer_len.
+ * Otherwise, there is some still-to-be-used data in io_buffer.
+ * Shuffle it to the start of the buffer.
+ * Note that next_byte will never exceed io_buffer_len.
+ * Also, note that we MUST use bcopy because the two regions could
+ * overlap (memcpy isn't defined to work properly with overlapping
+ * regions).
+ */
+ if (iobp->next_byte < iobp->io_buffer_len) {
+ int dst_ix = 0;
+ int src_ix = iobp->next_byte;
+ int amount = iobp->io_buffer_len - iobp->next_byte;
+
+ bcopy(&iobp->io_buffer[src_ix], &iobp->io_buffer[dst_ix],
+ amount);
+ iobp->io_buffer_len = amount;
+ } else if (iobp->next_byte == iobp->io_buffer_len)
+ iobp->io_buffer_len = 0;
+ else {
+ syslog(LOG_ERR, "next_byte(%d) > io_buffer_len(%d)",
+ iobp->next_byte, iobp->io_buffer_len);
+ exit(EX_OSERR);
+ }
+
+ iobp->next_byte = 0;
+
+ /* don't do tiny reads, grow first if we need to */
+ rqlen = iobp->io_buffer_size - iobp->io_buffer_len;
+ if (rqlen <= 128) {
+ char *tmp;
+
+ iobp->io_buffer_size += 128;
+ tmp = realloc(iobp->io_buffer, iobp->io_buffer_size);
+ if (tmp == NULL) {
+ syslog(LOG_INFO, "Insufficient memory");
+ exit(EX_UNAVAILABLE);
+ }
+ iobp->io_buffer = tmp;
+ rqlen = iobp->io_buffer_size - iobp->io_buffer_len;
+ }
+
+ /*
+ * Always leave an unused byte at the end of the buffer
+ * because the debug output uses that byte from time to time
+ * to ensure that something that is being printed is \0 terminated.
+ */
+ rqlen -= 1;
+
+ doread:
+ rlen = read(iobp->fd, &iobp->io_buffer[iobp->io_buffer_len], rqlen);
+ iobp->data_available = 0;
+ switch (rlen) {
+ case -1:
+ if (errno == EAGAIN || errno == EINTR)
+ goto doread;
+ if (errno != ECONNRESET) {
+ syslog(LOG_INFO, "read() failed on socket from %s (%m)",
+ iobp->who);
+ exit(EX_DATAERR);
+ }
+ /* fall through to EOF case */
+ case 0:
+ iobp->got_eof = 1;
+ return(0);
+ break;
+ default:
+ iobp->io_buffer_len += rlen;
+ break;
+ }
+ return(1);
+}
+
+/*
+ * telnet_getline - a hacked up version of fgets to ignore TELNET escape codes.
+ *
+ * This code is derived from the getline routine found in the UC Berkeley
+ * ftpd code.
+ *
+ */
+
+int
+telnet_getline(struct csiob *iobp, struct csiob *telnet_passthrough)
+{
+ unsigned char ch;
+ int ix;
+ char tbuf[100];
+
+ iobp->line_buffer[0] = '\0';
+
+ /*
+ * If the buffer is empty then refill it right away.
+ */
+ if (iobp->next_byte == iobp->io_buffer_len)
+ if (!refill_buffer(iobp))
+ return(0);
+
+ /*
+ * Is there a telnet command in the buffer?
+ */
+ ch = iobp->io_buffer[iobp->next_byte];
+ if (ch == IAC) {
+ /*
+ * Yes - buffer must have at least three bytes in it
+ */
+ if (iobp->io_buffer_len - iobp->next_byte < 3) {
+ if (!refill_buffer(iobp))
+ return(0);
+ if (iobp->io_buffer_len - iobp->next_byte < 3)
+ return(0);
+ }
+
+ iobp->next_byte++;
+ ch = iobp->io_buffer[iobp->next_byte++];
+
+ switch (ch) {
+ case WILL:
+ case WONT:
+ case DO:
+ case DONT:
+ tbuf[0] = IAC;
+ tbuf[1] = ch;
+ tbuf[2] = iobp->io_buffer[iobp->next_byte++];
+ (void)send(telnet_passthrough->fd, tbuf, 3,
+ telnet_passthrough->send_oob_flags);
+ break;
+ case IAC:
+ break;
+ default:
+ break;
+ }
+ return(1);
+ } else {
+ int clen;
+
+ /*
+ * Is there a newline in the buffer?
+ */
+ for (ix = iobp->next_byte; ix < iobp->io_buffer_len;
+ ix += 1) {
+ if (iobp->io_buffer[ix] == '\n')
+ break;
+ if (iobp->io_buffer[ix] == '\0') {
+ syslog(LOG_INFO,
+ "got NUL byte from %s - bye!",
+ iobp->who);
+ exit(EX_DATAERR);
+ }
+ }
+
+ if (ix == iobp->io_buffer_len) {
+ if (!refill_buffer(iobp))
+ return(0);
+ /*
+ * Empty line returned
+ * will try again soon!
+ */
+ return(1);
+ }
+
+ /*
+ * Expand the line buffer if it isn't big enough. We
+ * use a fudge factor of 5 rather than trying to
+ * figure out exactly how to account for the '\0 \r\n' and
+ * such. The correct fudge factor is 0, 1 or 2 but
+ * anything higher also works. We also grow it by a
+ * bunch to avoid having to do this often. Yes this is
+ * nasty.
+ */
+ if (ix - iobp->next_byte > iobp->line_buffer_size - 5) {
+ char *tmp;
+
+ iobp->line_buffer_size = 256 + ix - iobp->next_byte;
+ tmp = realloc(iobp->line_buffer,
+ iobp->line_buffer_size);
+ if (tmp == NULL) {
+ syslog(LOG_INFO, "Insufficient memory");
+ exit(EX_UNAVAILABLE);
+ }
+ iobp->line_buffer = tmp;
+ }
+
+ /* +1 is for the newline */
+ clen = (ix+1) - iobp->next_byte;
+ memcpy(iobp->line_buffer, &iobp->io_buffer[iobp->next_byte],
+ clen);
+ iobp->next_byte += clen;
+ iobp->line_buffer[clen] = '\0';
+ return(1);
+ }
+}
OpenPOWER on IntegriCloud