diff options
author | Theo de Raadt <deraadt@cvs.openbsd.org> | 2001-08-19 13:43:10 +0000 |
---|---|---|
committer | Theo de Raadt <deraadt@cvs.openbsd.org> | 2001-08-19 13:43:10 +0000 |
commit | 3b2924bd18a8a1671da1f0ebfc650f87f71d2cf2 (patch) | |
tree | c7790a0775e9e51dfdaf86a3bb3d22eaf4554782 /libexec | |
parent | a6a38350f779ddf3a6febf67dda7714fe368e492 (diff) |
1564 lines of cleanup
Diffstat (limited to 'libexec')
-rw-r--r-- | libexec/ftp-proxy/ftp-proxy.8 | 45 | ||||
-rw-r--r-- | libexec/ftp-proxy/ftp-proxy.c | 492 | ||||
-rw-r--r-- | libexec/ftp-proxy/getline.c | 6 | ||||
-rw-r--r-- | libexec/ftp-proxy/util.c | 118 |
4 files changed, 294 insertions, 367 deletions
diff --git a/libexec/ftp-proxy/ftp-proxy.8 b/libexec/ftp-proxy/ftp-proxy.8 index 0282888e909..d0a83a64bce 100644 --- a/libexec/ftp-proxy/ftp-proxy.8 +++ b/libexec/ftp-proxy/ftp-proxy.8 @@ -1,4 +1,4 @@ -.\" $OpenBSD: ftp-proxy.8,v 1.1 2001/08/19 04:11:11 beck Exp $ +.\" $OpenBSD: ftp-proxy.8,v 1.2 2001/08/19 13:43:09 deraadt Exp $ .\" .\" Copyright (c) 1996-2001 .\" Obtuse Systems Corporation, All rights reserved. @@ -44,7 +44,7 @@ Internet File Transfer Protocol proxy server. .Sh DESCRIPTION .Nm is a proxy for the Internet file transfer protocol. -The proxy uses +The proxy uses .Xr pf 4 and expects to have the ftp control connection as described in .Xr services 5 @@ -58,7 +58,7 @@ to log in to other sites as the user "ftp" or "anonymous" only. Any attempt to log in as another user will be blocked by the proxy. .It Fl n Activate network address translation mode. in this mode, the proxy -will not attempt to proxy passive mode (PASV or EPSV) data connections, +will not attempt to proxy passive mode (PASV or EPSV) data connections, for this to work on a gateway you will need to be forwarding packets and doing network address translation to allow the outbound passive connections from the client to reach the server. See @@ -68,17 +68,17 @@ when using this flag, it will still proxy PORT and EPRT mode data connections. Without this flag, .Nm ftp-proxy does not require any ip forwarding or NAT beyond the rdr necessary to -capture the ftp control connection. +capture the ftp control connection. .It Fl V Be verbose. With this option the proxy logs the control commands -sent by clients and the replies send by the servers to -.Xr syslog 8 +sent by clients and the replies send by the servers to +.Xr syslog 8 .It Fl w -Use the tcp wrapper access control library +Use the tcp wrapper access control library .Xr hosts_access 3 allowing connections to be allowed or denied based on the tcp wrapper's .Xr hosts.allow 5 -and +and .Xr hosts.deny 5 files. The proxy does libwrap operations after determining the destination of the captured control connection, so that tcp wrapper rules may @@ -92,33 +92,33 @@ specify the lower end of the port range the proxy will use for all data connections it establishes. The default is .Ev IPPORT_HIFIRSTAUTO defined in <netinet/in.h> -as 49152 +as 49152. .It Fl M maxport specify the upper end of the port range the proxy will use for the data connections it establishes. The default is .Ev IPPORT_HILASTAUTO defined in <netinet/in.h> -as 65535 +as 65535. .It Fl t timeout specifies a timeout, in seconds. The proxy will exit and close open connections if it sees no data the duration of the timeout. The default is 0, which means the proxy will not time out. .It Fl D debuglevel specify a debug level, where the proxy emits verbose debug output -into +into .Xr syslog 8 at level LOG_DEBUG. meaningful values of debuglevel are 0-3, where 0 -is no debug output and 3 is lots of debug output. the default is 0 +is no debug output and 3 is lots of debug output, the default being 0. .El .Pp -ftp-proxy is run from +ftp-proxy is run from .Xr inetd 8 and requires that ftp connections are redirected to it using an rdr rule. A typical way to do this would be to use a rule such as .Pp rdr on xl0 from any to any port 21 -> 127.0.0.1 port 8081 .Pp -In +In .Xr nat.conf 5 (this assumes you are on a gateway where xl0 would be your inside interface). You would then need to configure @@ -128,8 +128,8 @@ using .Pp 8081 stream tcp nowait root /usr/libexec/ftp-proxy ftp-proxy .Pp -in -.Xr inetd.conf 5 +in +.Xr inetd.conf 5 . .Sh SEE ALSO .Xr ftp 1 , .Xr host.allow 5 , @@ -141,14 +141,13 @@ in .Pp Extended Passive mode (EPSV) is not supported by the proxy and will not work unless the proxy is run in network address translation mode. -When not in network address translation mode, The proxy returns an error +When not in network address translation mode, the proxy returns an error to the client, hopefully forcing the client to revert to Passive mode (PASV) which is supported. EPSV will work in network address translation mode, -assuming a -.Xr nat.conf 5 -setup which allows the EPSV connections through to their destinations. +assuming a +.Xr nat.conf 5 +setup which allows the EPSV connections through to their destinations. .Pp IPv6 is not yet supported. This will have to wait for corresponding -support from -.Xr pf 4 - +support from +.Xr pf 4 . diff --git a/libexec/ftp-proxy/ftp-proxy.c b/libexec/ftp-proxy/ftp-proxy.c index 26e3f6873dd..5bc04026b9f 100644 --- a/libexec/ftp-proxy/ftp-proxy.c +++ b/libexec/ftp-proxy/ftp-proxy.c @@ -1,4 +1,5 @@ -/* $OpenBSD: ftp-proxy.c,v 1.3 2001/08/19 05:50:50 beck Exp $ */ +/* $OpenBSD: ftp-proxy.c,v 1.4 2001/08/19 13:43:09 deraadt Exp $ */ + /* * Copyright (c) 1996-2001 * Obtuse Systems Corporation. All rights reserved. @@ -19,14 +20,14 @@ * 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 OBTUSE SYSTEMS CORPORATION OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * 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 + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * + * */ /* @@ -53,14 +54,14 @@ * supports tcp wrapper lookups/access control with the -w flag using * the real destination address - the tcp wrapper stuff is done after * the real destination address is retreived from pf - * + * */ -/* +/* * TODO: * Plenty, this is very basic, with the idea to get it in clean first. - * - * - Ipv6 and EPASV support + * + * - Ipv6 and EPASV support * - Content filter support * - filename filter support * - per-user rules perhaps. @@ -134,7 +135,6 @@ int AnonFtpOnly; int Verbose; int NatMode; - char ClientName[NI_MAXHOST]; char RealServerName[NI_MAXHOST]; char OurName[NI_MAXHOST]; @@ -166,7 +166,7 @@ usage() exit(EX_USAGE); } -/* +/* * Check a connection against the tcpwrapper, log if we're going to * reject it, returns: 0 -> reject, 1 -> accept. We add in hostnames * if we are set to do reverse DNS, otherwise no. @@ -181,30 +181,28 @@ check_host(struct sockaddr_in *client_sin, struct sockaddr_in *server_sin) struct request_info request; int i; - request_init(&request, RQ_DAEMON, __progname, RQ_CLIENT_SIN, + request_init(&request, RQ_DAEMON, __progname, RQ_CLIENT_SIN, client_sin, RQ_SERVER_SIN, server_sin, RQ_CLIENT_ADDR, inet_ntoa(client_sin->sin_addr), 0); if (Use_Rdns) { - /* * We already looked these up, but we have to do it again * for tcp wrapper, to ensure that we get the DNS name, since * the tcp wrapper cares about these things, and we don't * want to pass in a printed address as a name. */ - if (Use_Rdns) { i = getnameinfo( (struct sockaddr *) &client_sin->sin_addr, - sizeof(&client_sin->sin_addr), cname, + sizeof(&client_sin->sin_addr), cname, sizeof(cname), NULL, 0, NI_NAMEREQD); if (i == -1) strlcpy(cname, STRING_UNKNOWN, sizeof(cname)); i = getnameinfo( - (struct sockaddr *)&server_sin->sin_addr, - sizeof(&server_sin->sin_addr), sname, + (struct sockaddr *)&server_sin->sin_addr, + sizeof(&server_sin->sin_addr), sname, sizeof(sname), NULL, 0, NI_NAMEREQD); if (i == -1) strlcpy(sname, STRING_UNKNOWN, sizeof(sname)); @@ -217,7 +215,7 @@ check_host(struct sockaddr_in *client_sin, struct sockaddr_in *server_sin) strlcpy(sname, STRING_UNKNOWN, sizeof(sname)); } } - + request_set(&request, RQ_SERVER_ADDR, inet_ntoa(server_sin->sin_addr), 0); request_set(&request, RQ_CLIENT_NAME, cname, RQ_SERVER_NAME, sname, 0); @@ -234,7 +232,7 @@ double wallclock_time() { struct timeval tv; - + gettimeofday(&tv,NULL); return(tv.tv_sec + tv.tv_usec / 1e6); } @@ -250,13 +248,13 @@ show_xfer_stats() double delta; size_t len; int i; - + if (!Verbose) return; delta = wallclock_time() - xfer_start_time; - - if (delta < 0.001) + + if (delta < 0.001) delta = 0.001; if (client_data_bytes == 0 && server_data_bytes == 0) { @@ -264,24 +262,23 @@ show_xfer_stats() "data transfer completed (no bytes transferred)"); return; } - + len = sizeof(tbuf); if (delta >= 60) { int idelta; - + idelta = delta + 0.5; if (idelta >= 60*60) { i = snprintf(tbuf, len, "data transfer completed (%dh %dm %ds", - idelta / (60*60), (idelta % (60*60)) / 60, + idelta / (60*60), (idelta % (60*60)) / 60, idelta % 60); if (i >= len) goto logit; len -= i; - } else { - i = snprintf(tbuf, len, + i = snprintf(tbuf, len, "data transfer completed (%dm %ds", idelta / 60, idelta % 60); if (i >= len) @@ -297,7 +294,7 @@ show_xfer_stats() } if (client_data_bytes > 0) { - i = snprintf(&tbuf[strlen(tbuf)], len, + i = snprintf(&tbuf[strlen(tbuf)], len, ", %d (%.1fKB/s) to server", client_data_bytes, (client_data_bytes / delta) / (double)1024); if (i >= len) @@ -312,56 +309,54 @@ show_xfer_stats() goto logit; len -= i; } - strlcat(tbuf,")", len); - logit: - syslog(LOG_INFO,"%s",tbuf); + strlcat(tbuf, ")", len); + logit: + syslog(LOG_INFO, "%s", tbuf); } /* * Are we in PORT mode, PASV mode or unknown mode? */ -void -log_control_command (char * cmd, int client) +void +log_control_command (char *cmd, int client) { /* log an ftp control command or reply */ - char * logstring; + char *logstring; int level = LOG_DEBUG; - if (!Verbose) + if (!Verbose) return; /* don't log passwords */ - if (strncasecmp(cmd,"pass ",5) == 0) + if (strncasecmp(cmd, "pass ", 5) == 0) logstring = "PASS XXXX"; else logstring = cmd; if (client) { /* log interesting stuff at LOG_INFO, rest at LOG_DEBUG */ - if ((strncasecmp(cmd,"user ",5) == 0) || - (strncasecmp(cmd,"retr ",5) == 0) || - (strncasecmp(cmd,"cwd ",4) == 0) || - (strncasecmp(cmd,"stor ",5) == 0)) + if ((strncasecmp(cmd, "user ", 5) == 0) || + (strncasecmp(cmd, "retr ", 5) == 0) || + (strncasecmp(cmd, "cwd ", 4) == 0) || + (strncasecmp(cmd, "stor " ,5) == 0)) level = LOG_INFO; } syslog(level, "%s %s", (client?"from client:":"server reply:"), logstring); } - /* * set ourselves up for a new data connection. Direction is toward client if * "server" is 0, towards server otherwise. */ - int new_dataconn(int server) { - + /* * Close existing data conn. */ - + if (client_listen_socket != -1) { close(client_listen_socket); client_listen_socket = -1; @@ -380,30 +375,22 @@ new_dataconn(int server) close(server_data_socket); server_data_socket = -1; } - + if (server) { bzero (&server_listen_sa, sizeof(server_listen_sa)); - - server_listen_socket = get_backchannel_socket( - SOCK_STREAM, - min_port, - max_port, - -1, - 1, - &server_listen_sa); - + server_listen_socket = get_backchannel_socket(SOCK_STREAM, + min_port, max_port, -1, 1, &server_listen_sa); + if (server_listen_socket == -1) { - syslog(LOG_INFO,"bind of server socket failed (%m)"); + syslog(LOG_INFO, "bind of server socket failed (%m)"); exit(EX_OSERR); } if (listen(server_listen_socket, 5) != 0) { - syslog(LOG_INFO,"listen on server socket failed (%m)"); + syslog(LOG_INFO, "listen on server socket failed (%m)"); exit(EX_OSERR); } - } else { - bzero(&client_listen_sa, sizeof(client_listen_sa)); - + bzero(&client_listen_sa, sizeof(client_listen_sa)); client_listen_socket = get_backchannel_socket(SOCK_STREAM, min_port, max_port, -1, 1, &client_listen_sa); @@ -426,16 +413,15 @@ do_client_cmd(struct csiob *client, struct csiob *server) { int i,j,rv; char tbuf[100]; - char *sendbuf = NULL; + char *sendbuf = NULL; log_control_command((char *)client->line_buffer, 1); - + /* client->line_buffer is an ftp control command. * There is no reason for these to be very long. * In the interest of limiting buffer overrun attempts, - * we catch them here. + * we catch them here. */ - if (strlen((char *)client->line_buffer) > 512) { syslog(LOG_NOTICE, "excessively long control command"); exit(EX_DATAERR); @@ -444,45 +430,40 @@ do_client_cmd(struct csiob *client, struct csiob *server) /* * Check the client user provided if needed */ - - if (AnonFtpOnly && strncasecmp((char *)client->line_buffer,"user ", + if (AnonFtpOnly && strncasecmp((char *)client->line_buffer, "user ", strlen("user ")) == 0) { - char * cp; + char *cp; + cp = client->line_buffer + strlen("user "); - if ((strcasecmp(cp,"ftp\r\n") != 0) - && (strcasecmp(cp, "anonymous\r\n") != 0)) { + if ((strcasecmp(cp, "ftp\r\n") != 0) && + (strcasecmp(cp, "anonymous\r\n") != 0)) { /* - * this isn't anonymous - give the client an + * this isn't anonymous - give the client an * error before they send a password */ - snprintf(tbuf, sizeof(tbuf), + snprintf(tbuf, sizeof(tbuf), "500 Only anonymous ftp is allowed\r\n"); j = 0; i = strlen(tbuf); do { rv = send(client->fd, tbuf + j, i - j, 0); - if (rv == -1 && errno != EAGAIN && + if (rv == -1 && errno != EAGAIN && errno != EINTR) break; else if (rv != -1) j += rv; } while (j >= 0 && j < i); sendbuf = NULL; - } else + } else sendbuf = client->line_buffer; - } else if ((strncasecmp((char *)client->line_buffer,"eprt ", - strlen("eprt ")) == 0)) { - - /* Watch out for EPRT commands */ + } else if ((strncasecmp((char *)client->line_buffer, "eprt ", + strlen("eprt ")) == 0)) { - char *line = NULL; - char *q, *p; - char *result[3]; - char delim; - struct addrinfo hints; - struct addrinfo *res = NULL; + /* Watch out for EPRT commands */ + char *line = NULL, *q, *p, *result[3], delim; + struct addrinfo hints, *res = NULL; unsigned long proto; - + j = 0; line = strdup(client->line_buffer+strlen("eprt ")); if (line == NULL) { @@ -520,41 +501,39 @@ do_client_cmd(struct csiob *client, struct csiob *server) if (sizeof(client_listen_sa) < res->ai_addrlen) goto parsefail; memcpy(&client_listen_sa, res->ai_addr, res->ai_addrlen); - - debuglog(1,"client wants us to use %s:%u\n", - inet_ntoa(client_listen_sa.sin_addr), + + debuglog(1, "client wants us to use %s:%u\n", + inet_ntoa(client_listen_sa.sin_addr), htons(client_listen_sa.sin_port)); /* * Configure our own listen socket and tell the server about it */ - new_dataconn(1); - connection_mode = EPRT_MODE; - debuglog(1,"we want server to use %s:%u\n", + debuglog(1, "we want server to use %s:%u\n", inet_ntoa(server->sa.sin_addr), - ntohs(server_listen_sa.sin_port)); + ntohs(server_listen_sa.sin_port)); snprintf(tbuf, sizeof(tbuf), "EPRT |%d|%s|%u|\r\n", 1, - inet_ntoa(server->sa.sin_addr), - ntohs(server_listen_sa.sin_port)); - debuglog(1,"to server(modified): %s",tbuf); + inet_ntoa(server->sa.sin_addr), + ntohs(server_listen_sa.sin_port)); + debuglog(1, "to server(modified): %s", tbuf); sendbuf = tbuf; goto out; parsefail: - snprintf(tbuf, sizeof(tbuf), + snprintf(tbuf, sizeof(tbuf), "500 Invalid argument, rejected\r\n"); sendbuf = NULL; goto out; -protounsupp: +protounsupp: /* we only support AF_INET for now */ if (proto == 2) - snprintf(tbuf, sizeof(tbuf), + snprintf(tbuf, sizeof(tbuf), "522 Protocol not supported, use (1)\r\n"); else - snprintf(tbuf, sizeof(tbuf), + snprintf(tbuf, sizeof(tbuf), "501 Protocol not supported\r\n"); sendbuf = NULL; out: @@ -563,37 +542,36 @@ out: if (res) freeaddrinfo(res); if (sendbuf == NULL) { - debuglog(1, "to client(modified): %s\n",tbuf); + debuglog(1, "to client(modified): %s\n", tbuf); i = strlen(tbuf); do { rv = send(client->fd, tbuf + j, i - j, 0); - if (rv == -1 && errno != EAGAIN && + if (rv == -1 && errno != EAGAIN && errno != EINTR) break; else if (rv != -1) j += rv; } while (j >= 0 && j < i); } - } else if (!NatMode && (strncasecmp((char *)client->line_buffer,"epsv", - strlen("epsv")) == 0)) { + } else if (!NatMode && (strncasecmp((char *)client->line_buffer, "epsv", + strlen("epsv")) == 0)) { /* * If we aren't in NAT mode, deal with EPSV. - * EPSV is a problem - Unliks PASV, the reply from the + * EPSV is a problem - Unliks PASV, the reply from the * server contains *only* a port, we can't modify the reply * to the client and get the client to connect to us without * resorting to using a dynamic rdr rule we have to add in * for the reply to this connection, and take away afterwards. * so this will wait until we have the right solution for rule - * addtions/deletions in pf. + * addtions/deletions in pf. * - * in the meantime we just tell the client we don't do it, + * in the meantime we just tell the client we don't do it, * and most clients should fall back to using PASV. */ - - snprintf(tbuf, sizeof(tbuf), + snprintf(tbuf, sizeof(tbuf), "500 EPSV command not understood\r\n"); - debuglog(1, "to client(modified): %s\n",tbuf); + debuglog(1, "to client(modified): %s\n", tbuf); j = 0; i = strlen(tbuf); do { @@ -604,14 +582,14 @@ out: j += rv; } while (j >= 0 && j < i); sendbuf = NULL; - } else if (strncasecmp((char *)client->line_buffer,"port ", - strlen("port ")) == 0) { + } else if (strncasecmp((char *)client->line_buffer, "port ", + strlen("port ")) == 0) { unsigned int values[6]; int byte_number; u_char *tailptr, ch; - debuglog(1,"Got a PORT command\n"); - + debuglog(1, "Got a PORT command\n"); + tailptr = &client->line_buffer[strlen("port ")]; byte_number = 0; values[0] = 0; @@ -645,30 +623,28 @@ out: "PORT command - session terminated"); exit(EX_DATAERR); } - + client_listen_sa.sin_family = AF_INET; - client_listen_sa.sin_addr.s_addr = htonl((values[0] << 24) - | (values[1] << 16) | (values[2] << 8) - | (values[3] << 0)); + client_listen_sa.sin_addr.s_addr = htonl((values[0] << 24) | + (values[1] << 16) | (values[2] << 8) | + (values[3] << 0)); - client_listen_sa.sin_port = htons((values[4] << 8) - | values[5]); - debuglog(1,"client wants us to use %u.%u.%u.%u:%u\n", + client_listen_sa.sin_port = htons((values[4] << 8) | + values[5]); + debuglog(1, "client wants us to use %u.%u.%u.%u:%u\n", values[0], values[1], values[2], values[3], (values[4] << 8) | values[5]); - + /* * Configure our own listen socket and tell the server about it */ - new_dataconn(1); - connection_mode = PORT_MODE; - - debuglog(1,"we want server to use %s:%u\n", + + debuglog(1, "we want server to use %s:%u\n", inet_ntoa(server->sa.sin_addr), - ntohs(server_listen_sa.sin_port)); - + ntohs(server_listen_sa.sin_port)); + snprintf(tbuf, sizeof(tbuf), "PORT %u,%u,%u,%u,%u,%u\r\n", ((u_char *)&server->sa.sin_addr.s_addr)[0], ((u_char *)&server->sa.sin_addr.s_addr)[1], @@ -676,14 +652,14 @@ out: ((u_char *)&server->sa.sin_addr.s_addr)[3], ((u_char *)&server_listen_sa.sin_port)[0], ((u_char *)&server_listen_sa.sin_port)[1]); - - debuglog(1,"to server(modified): %s",tbuf); - + + debuglog(1, "to server(modified): %s", tbuf); + sendbuf = tbuf; } else sendbuf = client->line_buffer; - - /* + + /* *send our (possibly modified) control command in sendbuf * on it's way to the server */ @@ -705,11 +681,10 @@ do_server_reply(struct csiob *server, struct csiob *client) { int code, i, j, rv; struct in_addr *iap; - char tbuf[100]; - char *sendbuf; - + char tbuf[100], *sendbuf; + log_control_command((char *)server->line_buffer, 0); - + if (strlen((char *)server->line_buffer) > 512) { /* * someone's playing games. Have a cow in the syslogs and @@ -719,31 +694,29 @@ do_server_reply(struct csiob *server, struct csiob *client) syslog(LOG_NOTICE, "Long (> 512 bytes) ftp control reply"); exit(EX_DATAERR); } - + /* * Watch out for "227 Entering Passive Mode ..." replies */ - code = atoi((char *)server->line_buffer); if (code <= 0 || code > 999) { - syslog(LOG_INFO,"invalid server reply code %d", code); + syslog(LOG_INFO, "invalid server reply code %d", code); exit(EX_DATAERR); } if (code == 227 && !NatMode) { - u_char ch; - u_char *tailptr; - int byte_number; unsigned int values[6]; - + u_char ch, *tailptr; + int byte_number; + debuglog(1, "Got a PASV reply\n"); - debuglog(1, "{%s}\n",(char *)server->line_buffer); - + debuglog(1, "{%s}\n", (char *)server->line_buffer); + tailptr = strchr((char *)server->line_buffer,'('); if (tailptr == NULL) { syslog(LOG_NOTICE, "malformed 227 reply"); exit(EX_DATAERR); } - + tailptr += 1; /* Move past the open-parentheses */ byte_number = 0; values[0] = 0; @@ -768,62 +741,55 @@ do_server_reply(struct csiob *server, struct csiob *client) } tailptr += 1; } - + /* * The PASV reply should be terminated by a closing * parentheses. */ - if (ch != ')') { - syslog(LOG_INFO,"malformed 227 reply, junk at end"); + syslog(LOG_INFO, "malformed 227 reply, junk at end"); exit(EX_DATAERR); } /* we need the righr number of bytes for ipv4 and port here */ - if (byte_number != 5) { syslog(LOG_NOTICE, "malformed 227 reply, missing bytes"); exit(EX_DATAERR); } - + server_listen_sa.sin_family = AF_INET; server_listen_sa.sin_addr.s_addr = htonl((values[0] << 24) | (values[1] << 16) | (values[2] << 8) | (values[3] << 0)); - server_listen_sa.sin_port = htons((values[4] << 8) | + server_listen_sa.sin_port = htons((values[4] << 8) | values[5]); - debuglog(1,"server wants us to use %s:%u\n", + debuglog(1, "server wants us to use %s:%u\n", inet_ntoa(server_listen_sa.sin_addr), (values[4] << 8) | values[5]); - + new_dataconn(0); - connection_mode = PASV_MODE; - iap = &(server->sa.sin_addr); - - debuglog(1,"we want client to use %s:%u\n", inet_ntoa(*iap), + + debuglog(1, "we want client to use %s:%u\n", inet_ntoa(*iap), htons(client_listen_sa.sin_port)); - + snprintf(tbuf, sizeof(tbuf), "227 Entering Passive Mode (%u,%u,%u,%u,%u,%u\r\n", ((u_char *)iap)[0], ((u_char *)iap)[1], ((u_char *)iap)[2], ((u_char *)iap)[3], ((u_char *)&client_listen_sa.sin_port)[0], ((u_char *)&client_listen_sa.sin_port)[1]); - - debuglog(1, "to client(modified): %s\n",tbuf); - + debuglog(1, "to client(modified): %s\n", tbuf); sendbuf = tbuf; - } else + } else sendbuf = server->line_buffer; - /* - *send our (possibly modified) control command in sendbuf + /* + * send our (possibly modified) control command in sendbuf * on it's way to the client */ - j = 0; i = strlen(sendbuf); do { @@ -843,7 +809,7 @@ main(int argc, char **argv) struct timeval tv; long timeout_seconds = 0; struct sigaction new_sa, old_sa; - int sval, ch, salen, flags, i; + int sval, ch, salen, flags, i; int use_tcpwrapper = 0; int one = 1; @@ -887,33 +853,31 @@ main(int argc, char **argv) } argc -= optind; argv += optind; - - if (max_port < min_port) + if (max_port < min_port) usage(); openlog(__progname, LOG_NDELAY|LOG_PID, LOG_DAEMON); - + setlinebuf(stdout); setlinebuf(stderr); - + memset(&client_iob, 0, sizeof(client_iob)); memset(&server_iob, 0, sizeof(server_iob)); - - if (get_proxy_env(0, &real_server_sa, &client_iob.sa) == -1) + + if (get_proxy_env(0, &real_server_sa, &client_iob.sa) == -1) exit(EX_PROTOCOL); - + /* - * We check_host after get_proxy_env so that checks are done + * We check_host after get_proxy_env so that checks are done * against the original destination endpoint, not the endpoint * of our side of the rdr. This allows the use of tcpwrapper * rules to restrict destinations as well as sources of connections * for ftp. */ - - if (Use_Rdns) + if (Use_Rdns) flags = NI_NUMERICHOST | NI_NUMERICSERV; - else + else flags = 0; i = getnameinfo((struct sockaddr *)&client_iob.sa, @@ -923,83 +887,77 @@ main(int argc, char **argv) if (i == -1) { syslog (LOG_ERR, "getnameinfo failed (%m)"); exit(EX_OSERR); - } + } - i = getnameinfo((struct sockaddr *)&real_server_sa, + i = getnameinfo((struct sockaddr *)&real_server_sa, sizeof(real_server_sa), RealServerName, sizeof(RealServerName), NULL, 0, flags); if (i == -1) { syslog (LOG_ERR, "getnameinfo failed (%m)"); exit(EX_OSERR); - } + } if (use_tcpwrapper && !check_host(&client_iob.sa, &real_server_sa)) exit(EX_NOPERM); client_iob.fd = 0; - - - /* Check to see if we have a timeout defined, if so, - * set a timeout for this select call to that value, so + + /* Check to see if we have a timeout defined, if so, + * set a timeout for this select call to that value, so * we may time out if don't see any data in timeout - * seconds. + * seconds. */ - tv.tv_sec = timeout_seconds; - tv.tv_usec = 0; - + tv.tv_usec = 0; timeout_seconds=tv.tv_sec; - - + debuglog(1, "client is %s:%u\n", ClientName, ntohs(client_iob.sa.sin_port)); - + debuglog(1, "target server is %s:%u\n", RealServerName, ntohs(real_server_sa.sin_port)); - + server_iob.fd = get_backchannel_socket(SOCK_STREAM, min_port, max_port, -1, 1, &server_iob.sa); - + if (connect(server_iob.fd, (struct sockaddr *)&real_server_sa, sizeof(real_server_sa)) != 0) { syslog(LOG_INFO, "Can't connect to %s:%u (%m)", RealServerName, ntohs(real_server_sa.sin_port)); exit(EX_NOHOST); } - + /* * Now that we are connected to the real server, get the name * of our end of the server socket so we know our IP address - * from the real server's perspective. + * from the real server's perspective. */ - - i = getnameinfo((struct sockaddr *)&client_iob.sa, + i = getnameinfo((struct sockaddr *)&client_iob.sa, sizeof(client_iob.sa), OurName, sizeof(OurName), NULL, 0, flags); - + salen = sizeof(server_iob.sa); getsockname(server_iob.fd, (struct sockaddr *)&server_iob.sa, &salen); - + debuglog(1, "our end of socket to server is %s:%u\n", OurName, ntohs(server_iob.sa.sin_port)); - - /* ignore sigpipe */ - + + /* ignore SIGPIPE */ + bzero(&new_sa, sizeof(new_sa)); new_sa.sa_handler = SIG_IGN; (void)sigemptyset(&new_sa.sa_mask); new_sa.sa_flags = SA_RESTART; - if (sigaction(SIGPIPE, &new_sa, &old_sa) != 0) { - syslog(LOG_ERR,"sigaction failed (%m)"); + syslog(LOG_ERR, "sigaction failed (%m)"); exit(EX_OSERR); } - + if (setsockopt(client_iob.fd, SOL_SOCKET, SO_OOBINLINE, (char *)&one, sizeof(one)) == -1) { - syslog(LOG_NOTICE,"Can't set SO_OOBINLINE (%m) - exiting"); + syslog(LOG_NOTICE, "Can't set SO_OOBINLINE (%m) - exiting"); exit(EX_OSERR); } - + client_iob.line_buffer_size = STARTBUFSIZE; client_iob.line_buffer = malloc(client_iob.line_buffer_size); client_iob.io_buffer_size = STARTBUFSIZE; @@ -1010,11 +968,10 @@ main(int argc, char **argv) client_iob.who = "client"; client_iob.send_oob_flags = 0; client_iob.real_sa = client_iob.sa; - - + server_iob.line_buffer_size = STARTBUFSIZE; server_iob.line_buffer = malloc(server_iob.line_buffer_size); - server_iob.io_buffer_size = STARTBUFSIZE; + server_iob.io_buffer_size = STARTBUFSIZE; server_iob.io_buffer = malloc(server_iob.io_buffer_size); server_iob.next_byte = 0; server_iob.io_buffer_len = 0; @@ -1023,14 +980,12 @@ main(int argc, char **argv) server_iob.send_oob_flags = MSG_OOB; server_iob.real_sa = real_server_sa; - if (client_iob.line_buffer == NULL || client_iob.io_buffer == NULL - || server_iob.line_buffer == NULL || server_iob.io_buffer == NULL) - { + if (client_iob.line_buffer == NULL || client_iob.io_buffer == NULL || + server_iob.line_buffer == NULL || server_iob.io_buffer == NULL) { syslog (LOG_NOTICE, "Insufficient memory (malloc failed)"); exit(EX_UNAVAILABLE); - } - - + } + while (client_iob.alive || server_iob.alive) { fd_set fds; @@ -1040,72 +995,71 @@ main(int argc, char **argv) * many open files for FD_SETSIZE - we deal here only * with one ftp connection */ - - debuglog(3,"client is %s, server is %s\n", - client_iob.alive ? "alive" : "dead", - server_iob.alive ? "alive" : "dead"); + debuglog(3, "client is %s, server is %s\n", + client_iob.alive ? "alive" : "dead", + server_iob.alive ? "alive" : "dead"); FD_ZERO(&fds); - - if (client_iob.alive && telnet_getline(&client_iob, + + if (client_iob.alive && telnet_getline(&client_iob, &server_iob)) { debuglog(3, "client line buffer is \"%s\"\n", (char *)client_iob.line_buffer); - if (client_iob.line_buffer[0] != '\0') + if (client_iob.line_buffer[0] != '\0') do_client_cmd(&client_iob, &server_iob); } else if (server_iob.alive && telnet_getline(&server_iob, &client_iob)) { - debuglog(3,"server line buffer is \"%s\"\n", + debuglog(3, "server line buffer is \"%s\"\n", (char *)server_iob.line_buffer); - if (server_iob.line_buffer[0] != '\0') + if (server_iob.line_buffer[0] != '\0') do_server_reply(&server_iob, &client_iob); } else { if (client_iob.alive) { FD_SET(client_iob.fd, &fds); - if (client_listen_socket >= 0) + if (client_listen_socket >= 0) FD_SET(client_listen_socket, &fds); if (client_data_socket >= 0) FD_SET(client_data_socket, &fds); } if (server_iob.alive) { - FD_SET(server_iob.fd, &fds); + FD_SET(server_iob.fd, &fds); if (server_listen_socket >= 0) FD_SET(server_listen_socket, &fds); - if (server_data_socket >= 0) + if (server_data_socket >= 0) FD_SET(server_data_socket, &fds); } - tv.tv_sec = timeout_seconds; - tv.tv_usec = 0; + tv.tv_usec = 0; doselect: switch (sval = select(FD_SETSIZE, &fds, NULL, NULL, (tv.tv_sec == 0) ? NULL : &tv)) { case 0: - /* - * This proxy has timed out. Expire it - * quietly with an obituary in the syslogs + /* + * This proxy has timed out. Expire it + * quietly with an obituary in the syslogs * for any passing mourners. */ - syslog(LOG_INFO, + syslog(LOG_INFO, "timeout, no data for %ld seconds", timeout_seconds); - exit(EX_OK); + exit(EX_OK); break; - + case -1: - if (errno == EINTR || errno == EAGAIN) + if (errno == EINTR || errno == EAGAIN) goto doselect; syslog(LOG_NOTICE, "select failed (%m) - exiting"); exit(EX_OSERR); break; - + default: if (client_data_socket >= 0 && FD_ISSET(client_data_socket,&fds)) { int rval; - debuglog(3,"xfer client to server\n"); + + debuglog(3, "xfer client to server\n"); rval = xfer_data("client to server", client_data_socket, server_data_socket, @@ -1119,14 +1073,14 @@ main(int argc, char **argv) close(server_data_socket); server_data_socket = -1; show_xfer_stats(); - } else + } else client_data_bytes += rval; } if (server_data_socket >= 0 && FD_ISSET(server_data_socket,&fds)) { int rval; - - debuglog(3,"xfer server to client\n"); + + debuglog(3, "xfer server to client\n"); rval = xfer_data("server to client", server_data_socket, client_data_socket, @@ -1140,23 +1094,21 @@ main(int argc, char **argv) close(server_data_socket); server_data_socket = -1; show_xfer_stats(); - } else + } else server_data_bytes += rval; } if (server_listen_socket >= 0 && FD_ISSET(server_listen_socket,&fds)) { struct sockaddr_in listen_sa; - + /* - * We are about to accept a + * We are about to accept a * connection from the server. * This is a PORT or EPRT data * connection. */ - - debuglog(2, - "server listen socket ready\n"); - + debuglog(2, "server listen socket ready\n"); + if (server_data_socket >= 0) { shutdown(server_data_socket,2); close(server_data_socket); @@ -1184,26 +1136,26 @@ main(int argc, char **argv) salen = 1; listen_sa.sin_family = AF_INET; - + bzero(&listen_sa.sin_addr, sizeof(struct in_addr)); - - debuglog(2,"setting sin_addr to %s\n", + + debuglog(2, "setting sin_addr to %s\n", inet_ntoa(client_iob.sa.sin_addr)); - + listen_sa.sin_port = htons(20); salen = 1; setsockopt(client_data_socket, SOL_SOCKET, SO_REUSEADDR, &salen, sizeof(salen)); - if (bind(client_data_socket, - (struct sockaddr *)&listen_sa, - sizeof(listen_sa)) < 0) { + if (bind(client_data_socket, + (struct sockaddr *)&listen_sa, + sizeof(listen_sa)) < 0) { syslog(LOG_NOTICE, "bind to 20 failed (%m)"); exit(EX_OSERR); } - + if (connect(client_data_socket, (struct sockaddr *) &client_listen_sa, @@ -1220,17 +1172,16 @@ main(int argc, char **argv) FD_ISSET(client_listen_socket,&fds)) { struct sockaddr_in listen_sa; int salen; - + /* * We are about to accept a * connection from the client. * This is a PASV data - * connection. + * connection. */ - debuglog(2, "client listen socket ready\n"); - + if (server_data_socket >= 0) { shutdown(server_data_socket,2); close(server_data_socket); @@ -1242,16 +1193,16 @@ main(int argc, char **argv) client_data_socket = -1; } salen = sizeof(listen_sa); - client_data_socket = + client_data_socket = accept(client_listen_socket, (struct sockaddr *)&listen_sa, &salen); if (client_data_socket < 0) { - syslog(LOG_NOTICE, + syslog(LOG_NOTICE, "accept failed (%m)"); exit(EX_OSERR); } - + close(client_listen_socket); client_listen_socket = -1; memset(&listen_sa, 0, @@ -1281,29 +1232,28 @@ main(int argc, char **argv) FD_ISSET(client_iob.fd,&fds)) { client_iob.data_available = 1; } - + if (server_iob.alive && FD_ISSET(server_iob.fd,&fds)) { server_iob.data_available = 1; } - + } } - + if (client_iob.got_eof) { - shutdown(server_iob.fd,1); - shutdown(client_iob.fd,0); + shutdown(server_iob.fd, 1); + shutdown(client_iob.fd, 0); client_iob.got_eof = 0; client_iob.alive = 0; } - + if (server_iob.got_eof) { - shutdown(client_iob.fd,1); - shutdown(server_iob.fd,0); + shutdown(client_iob.fd, 1); + shutdown(server_iob.fd, 0); server_iob.got_eof = 0; server_iob.alive = 0; } - } exit(EX_OK); } diff --git a/libexec/ftp-proxy/getline.c b/libexec/ftp-proxy/getline.c index f1eb1deb504..bf70a1b5fc2 100644 --- a/libexec/ftp-proxy/getline.c +++ b/libexec/ftp-proxy/getline.c @@ -35,7 +35,7 @@ /* * RCS information: - * $Id: getline.c,v 1.1 2001/08/19 04:11:12 beck Exp $ + * $Id: getline.c,v 1.2 2001/08/19 13:43:09 deraadt Exp $ */ #include <sys/types.h> @@ -95,8 +95,8 @@ refill_buffer(register struct csiob *iobp) } 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)\n", - iobp->next_byte,iobp->io_buffer_len); + syslog(LOG_ERR, "next_byte(%d) > io_buffer_len(%d)\n", + iobp->next_byte, iobp->io_buffer_len); exit(EX_OSERR); } diff --git a/libexec/ftp-proxy/util.c b/libexec/ftp-proxy/util.c index e553b5cf3dc..ddacd35e6a9 100644 --- a/libexec/ftp-proxy/util.c +++ b/libexec/ftp-proxy/util.c @@ -1,4 +1,5 @@ -/* $OpenBSD: util.c,v 1.1 2001/08/19 04:11:12 beck Exp $ */ +/* $OpenBSD: util.c,v 1.2 2001/08/19 13:43:09 deraadt Exp $ */ + /* * Copyright (c) 1996-2001 * Obtuse Systems Corporation. All rights reserved. @@ -30,13 +31,12 @@ * */ - #include <sys/types.h> #include <sys/socket.h> -#include <netinet/in.h> #include <sys/ioctl.h> #include <sys/file.h> #include <netinet/in.h> +#include <netinet/in.h> #include <netinet/in_systm.h> #include <net/if.h> #include <net/pfvar.h> @@ -64,25 +64,21 @@ int Use_Rdns; void debuglog(int debug_level, const char *fmt, ...) { - va_list ap; - va_start(ap,fmt); + va_list ap; + va_start(ap,fmt); - if (Debug_Level >= debug_level) { - vsyslog(LOG_DEBUG, fmt, ap); - } + if (Debug_Level >= debug_level) + vsyslog(LOG_DEBUG, fmt, ap); } - int get_proxy_env(int connected_fd, struct sockaddr_in *real_server_sa_ptr, struct sockaddr_in *client_sa_ptr) { - struct pf_natlook natlook; - struct pf_natlook *natlookp; - char * client; + struct pf_natlook natlook, *natlookp; + char *client; int slen, fd; - - + slen = sizeof(*real_server_sa_ptr); if (getsockname(connected_fd, (struct sockaddr *)real_server_sa_ptr, &slen) != 0) { @@ -95,12 +91,10 @@ get_proxy_env(int connected_fd, struct sockaddr_in *real_server_sa_ptr, syslog(LOG_ERR,"getpeername failed (%m)"); return(-1); } - - + /* * Build up the pf natlook structure. */ - memset((void *)&natlook, 0, sizeof(natlook)); natlook.saddr = client_sa_ptr->sin_addr.s_addr; natlook.daddr = real_server_sa_ptr->sin_addr.s_addr; @@ -108,39 +102,37 @@ get_proxy_env(int connected_fd, struct sockaddr_in *real_server_sa_ptr, natlook.sport = client_sa_ptr->sin_port; natlook.dport = real_server_sa_ptr->sin_port; natlook.direction = PF_OUT; - + /* * Open the pf device and lookup the mapping pair to find - * the original address we were supposed to connect to. + * the original address we were supposed to connect to. */ - client = strdup(inet_ntoa(client_sa_ptr->sin_addr)); if (client == NULL) { errno = ENOMEM; return(-1); } - + fd = open("/dev/pf", O_RDWR); if (fd == -1) { syslog(LOG_ERR, "Can't open /dev/pf (%m)"); exit(EX_UNAVAILABLE); } - + natlookp = &natlook; if (ioctl(fd, DIOCNATLOOK, natlookp) == -1) { syslog(LOG_INFO, - "pf nat lookup failed (%m), connection from %s:%hu", + "pf nat lookup failed (%m), connection from %s:%hu", client, ntohs(client_sa_ptr->sin_port)); close(fd); return(-1); } close(fd); - + /* - * Now jam the original address and port back into the into - * destination sockaddr_in for the proxy to deal with. + * Now jam the original address and port back into the into + * destination sockaddr_in for the proxy to deal with. */ - memset((void *)real_server_sa_ptr, 0, sizeof(struct sockaddr_in)); real_server_sa_ptr->sin_port = natlookp->rdport; real_server_sa_ptr->sin_addr.s_addr = natlookp->rdaddr; @@ -156,19 +148,16 @@ get_proxy_env(int connected_fd, struct sockaddr_in *real_server_sa_ptr, * A unit of data is as much as we get with a single read(2) call. * */ - int xfer_data(const char *what_read,int from_fd, int to_fd, struct in_addr from, struct in_addr to) { + int rlen, offset, xerrno, mark, flags = 0; char tbuf[4096]; - int rlen, offset, xerrno; - int mark, flags; - + /* * Are we at the OOB mark? */ - if (ioctl(from_fd, SIOCATMARK, &mark) < 0) { xerrno = errno; syslog(LOG_ERR,"can't ioctl(SIOCATMARK) socket from %s (%m)", @@ -176,11 +165,8 @@ xfer_data(const char *what_read,int from_fd, int to_fd, struct in_addr from, errno = xerrno; return(-1); } - - if (mark) + if (mark) flags = MSG_OOB; /* Yes - at the OOB mark */ - else - flags = 0; snarf: rlen = recv(from_fd,tbuf,sizeof(tbuf), flags); @@ -190,7 +176,7 @@ snarf: rlen = recv(from_fd,tbuf,sizeof(tbuf), flags); } if (rlen == 0) { - debuglog(3, "xfer_data - eof on read socket"); + debuglog(3, "xfer_data - eof on read socket"); return(0); } else if (rlen == -1) { if (errno == EAGAIN || errno == EINTR) @@ -202,8 +188,8 @@ snarf: return(-1); } else { offset = 0; - debuglog(3, "xfer got %d bytes from socket\n",rlen); - + debuglog(3, "xfer got %d bytes from socket\n", rlen); + while (offset < rlen) { int wlen; fling: @@ -228,94 +214,86 @@ snarf: } } - -/* +/* * get_backchannel_socket gets us a socket bound somewhere in a * particular range of ports */ - int get_backchannel_socket(int type, int min_port, int max_port, int start_port, int direction, struct sockaddr_in *sap) { int count; - + /* * Make sure that direction is 'defined' and that min_port is not * greater than max_port. */ - - /* by default we go up by one port until we find one */ if (direction != -1) - direction = 1; - + direction = 1; + + /* by default we go up by one port until we find one */ if (min_port > max_port) { errno = EINVAL; return(-1); } - + count = 1 + max_port - min_port; - + /* - * pick a port we can bind to from within the range we want. + * pick a port we can bind to from within the range we want. * If the caller specifies -1 as the starting port number then * we pick one somewhere in the range to try. * This is an optimization intended to speedup port selection and - * has NOTHING to do with security. + * has NOTHING to do with security. */ - if (start_port == -1) start_port = (arc4random() % count) + min_port; - + if (start_port < min_port || start_port > max_port) { errno = EINVAL; return(-1); } - + while (count-- > 0) { - int one; - int fd; + int one, fd; struct sockaddr_in sa; - + fd = socket(AF_INET, type, 0); - + sa.sin_family = AF_INET; - if (sap == NULL) + if (sap == NULL) sa.sin_addr.s_addr = INADDR_ANY; else sa.sin_addr.s_addr = sap->sin_addr.s_addr; - + /* * Indicate that we want to reuse a port if it happens that the * port in question was a listen port recently. */ - one = 1; - if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &one, + if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one)) == -1) return(-1); sa.sin_port = htons(start_port); - + if (bind(fd, (struct sockaddr *)&sa, sizeof(sa)) == 0) { - if (sap != NULL) + if (sap != NULL) *sap = sa; return(fd); } - if (errno != EADDRINUSE) + if (errno != EADDRINUSE) return(-1); - + /* if it's in use, try the next port */ - close(fd); start_port += direction; - if (start_port < min_port) + if (start_port < min_port) start_port = max_port; - else if (start_port > max_port) + else if (start_port > max_port) start_port = min_port; - } errno = EAGAIN; return(-1); |