diff options
author | Theo de Raadt <deraadt@cvs.openbsd.org> | 2005-11-24 17:12:52 +0000 |
---|---|---|
committer | Theo de Raadt <deraadt@cvs.openbsd.org> | 2005-11-24 17:12:52 +0000 |
commit | 833a31456d58ae6f389643d5a554258f30ee6b7a (patch) | |
tree | 0c90a27624cb6661453d3bbd3345d29cdb7fdfa5 | |
parent | 7b69e8c06a7f2c7806348dd3b4d22033479bbc11 (diff) |
code is not being used; toss into Attic
-rw-r--r-- | libexec/ftp-proxy/Makefile | 17 | ||||
-rw-r--r-- | libexec/ftp-proxy/ftp-proxy.8 | 294 | ||||
-rw-r--r-- | libexec/ftp-proxy/ftp-proxy.c | 1373 | ||||
-rw-r--r-- | libexec/ftp-proxy/getline.c | 260 | ||||
-rw-r--r-- | libexec/ftp-proxy/util.c | 306 | ||||
-rw-r--r-- | libexec/ftp-proxy/util.h | 68 |
6 files changed, 0 insertions, 2318 deletions
diff --git a/libexec/ftp-proxy/Makefile b/libexec/ftp-proxy/Makefile deleted file mode 100644 index 76eb9ec5a9e..00000000000 --- a/libexec/ftp-proxy/Makefile +++ /dev/null @@ -1,17 +0,0 @@ -# $OpenBSD: Makefile,v 1.4 2003/11/20 23:23:09 avsm Exp $ -# @(#)Makefile 8.2 (Berkeley) 4/4/94 - -PROG= ftp-proxy -CFLAGS+=-Wall -SRCS= ftp-proxy.c getline.c util.c -MAN= ftp-proxy.8 - -.include <bsd.own.mk> - -.if (${TCP_WRAPPERS:L} == "yes") -CFLAGS+= -DLIBWRAP -LDADD+= -lwrap -DPADD+= ${LIBWRAP} -.endif - -.include <bsd.prog.mk> diff --git a/libexec/ftp-proxy/ftp-proxy.8 b/libexec/ftp-proxy/ftp-proxy.8 deleted file mode 100644 index 57494ee3284..00000000000 --- a/libexec/ftp-proxy/ftp-proxy.8 +++ /dev/null @@ -1,294 +0,0 @@ -.\" $OpenBSD: ftp-proxy.8,v 1.43 2005/09/23 14:37:57 jmc Exp $ -.\" -.\" Copyright (c) 1996-2001 -.\" Obtuse Systems Corporation, 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 OBTUSE SYSTEMS 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 OBTUSE 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. -.\" -.Dd August 17, 2001 -.Dt FTP-PROXY 8 -.Os -.Sh NAME -.Nm ftp-proxy -.Nd Internet File Transfer Protocol proxy server -.Sh SYNOPSIS -.Nm ftp-proxy -.Bk -words -.Op Fl AnrVw -.Op Fl a Ar address -.Op Fl D Ar debuglevel -.Op Fl g Ar group -.Op Fl M Ar maxport -.Op Fl m Ar minport -.Op Fl R Ar address[:port] -.Op Fl S Ar address -.Op Fl t Ar timeout -.Op Fl u Ar user -.Ek -.Sh DESCRIPTION -.Nm -is a proxy for the Internet File Transfer Protocol. -The proxy uses -.Xr pf 4 -and expects to have the FTP control connection as described in -.Xr services 5 -redirected to it via a -.Xr pf 4 -.Em rdr -command. -An example of how to do that is further down in this document. -.Pp -The options are as follows: -.Bl -tag -width Ds -.It Fl A -Permit only anonymous FTP connections. -The proxy will allow connections to log in to other sites as the user -.Qq ftp -or -.Qq anonymous -only. -Any attempt to log in as another user will be blocked by the proxy. -.It Fl a Ar address -Specify the local IP address to use in -.Xr bind 2 -as the source for connections made by -.Nm ftp-proxy -when connecting to destination FTP servers. -This may be necessary if the interface address of -your default route is not reachable from the destinations -.Nm -is attempting connections to, or this address is different from the one -connections are being NATed to. -In the usual case this means that -.Ar address -should be a publicly visible IP address assigned to one of -the interfaces on the machine running -.Nm -and should be the same address to which you are translating traffic -if you are using the -.Fl n -option. -.It Fl D Ar debuglevel -Specify a debug level, where the proxy emits verbose debug output -into -.Xr syslogd 8 -at level -.Dv LOG_DEBUG . -Meaningful values of debuglevel are 0-3, where 0 is no debug output and -3 is lots of debug output, the default being 0. -.It Fl g Ar group -Specify the named group to drop group privileges to, after doing -.Xr pf 4 -lookups which require root. -By default, -.Nm -uses the default group of the user it drops privilege to. -.It Fl M Ar maxport -Specify the upper end of the port range the proxy will use for the -data connections it establishes. -The default is -.Dv IPPORT_HILASTAUTO -defined in -.Aq Pa netinet/in.h -as 65535. -.It Fl m Ar minport -Specify the lower end of the port range the proxy will use for all -data connections it establishes. -The default is -.Dv IPPORT_HIFIRSTAUTO -defined in -.Aq Pa netinet/in.h -as 49152. -.It Fl n -Activate network address translation -.Pq NAT -mode. -In this mode, the proxy will not attempt to proxy passive mode -.Pq PASV or EPSV -data connections. -In order for this to work, the machine running the proxy 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 -.Xr pf.conf 5 -for more details on NAT. -The proxy only ignores passive mode data connections when using this flag; -it will still proxy PORT and EPRT mode data connections. -Without this flag, -.Nm -does not require any IP forwarding or NAT beyond the -.Em rdr -necessary to capture the FTP control connection. -.It Fl R Ar address:[port] -Reverse proxy mode for FTP servers running behind a NAT gateway. -In this mode, no redirection is needed. -The proxy is run from -.Xr inetd 8 -on the port that external clients connect to (usually 21). -Control connections and passive data connections are forwarded -to the server. -.It Fl r -Use reverse host -.Pq reverse DNS -lookups for logging and libwrap use. -By default, -the proxy does not look up hostnames for libwrap or logging purposes. -.It Fl S Ar address -Source address to use for data connections made by the proxy. -Useful when there are multiple addresses (aliases) available -to the proxy. -Clients may expect data connections to have the same source -address as the control connections, and reject or drop other -connections. -.It Fl t Ar timeout -Specifies a timeout, in seconds. -The proxy will exit and close open connections if it sees no data -for the duration of the timeout. -The default is 0, which means the proxy will not time out. -.It Fl u Ar user -Specify the named user to drop privilege to, after doing -.Xr pf 4 -lookups which require root privilege. -By default, -.Nm -drops privilege to the user -.Em proxy . -.Pp -Running as root means that the source of data connections the proxy makes -for PORT and EPRT will be the RFC mandated port 20. -When running as a non-root user, the source of the data connections from -.Nm -will be chosen randomly from the range -.Ar minport -to -.Ar maxport -as described above. -.It Fl V -Be verbose. -With this option the proxy logs the control commands -sent by clients and the replies sent by the servers to -.Xr syslogd 8 . -.It Fl w -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 -.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 -be written based on the destination as well as the source of FTP connections. -.El -.Pp -.Nm ftp-proxy -is run from -.Xr inetd 8 -and requires that FTP connections are redirected to it using a -.Em rdr -rule. -A typical way to do this would be to use a -.Xr pf.conf 5 -rule such as -.Bd -literal -offset 2n -int_if = \&"xl0\&" -rdr pass on $int_if proto tcp from any to any port 21 -> 127.0.0.1 \e - port 8021 -.Ed -.Pp -.Xr inetd 8 -must then be configured to run -.Nm -on the port from above using -.Bd -literal -offset 2n -127.0.0.1:8021 stream tcp nowait root /usr/libexec/ftp-proxy ftp-proxy -.Ed -.Pp -in -.Xr inetd.conf 5 . -.Pp -.Nm -accepts the redirected control connections and forwards them -to the server. -The proxy replaces the address and port number that the client -sends through the control connection to the server with its own -address and proxy port, where it listens for the data connection. -When the server opens the data connection back to this port, the -proxy forwards it to the client. -The -.Xr pf.conf 5 -rules need to let pass connections to these proxy ports -(see options -.Fl u , m , -and -.Fl M -above) in on the external interface. -The following example allows only ports 49152 to 65535 to pass in -statefully: -.Bd -literal -offset indent -block in on $ext_if proto tcp all -pass in on $ext_if inet proto tcp from any to $ext_if \e - port > 49151 keep state -.Ed -.Pp -Alternatively, rules can make use of the fact that by default, -.Nm -runs as user -.Qq proxy -to allow the backchannel connections, as in the following example: -.Bd -literal -offset indent -block in on $ext_if proto tcp all -pass in on $ext_if inet proto tcp from any to $ext_if \e - user proxy keep state -.Ed -.Pp -These examples do not cover the connections from the proxy to the -foreign FTP server. -If one does not pass outgoing connections by default additional rules -are needed. -.Sh SEE ALSO -.Xr ftp 1 , -.Xr pf 4 , -.Xr hosts.allow 5 , -.Xr hosts.deny 5 , -.Xr inetd.conf 5 , -.Xr pf.conf 5 , -.Xr inetd 8 , -.Xr pfctl 8 , -.Xr syslogd 8 -.Sh BUGS -Extended Passive mode -.Pq 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 -to the client, hopefully forcing the client to revert to passive mode -.Pq PASV -which is supported. -EPSV will work in network address translation mode, assuming a -.Xr pf.conf 5 -setup which allows the EPSV connections through to their destinations. -.Pp -IPv6 is not yet supported. diff --git a/libexec/ftp-proxy/ftp-proxy.c b/libexec/ftp-proxy/ftp-proxy.c deleted file mode 100644 index dd0c654ee75..00000000000 --- a/libexec/ftp-proxy/ftp-proxy.c +++ /dev/null @@ -1,1373 +0,0 @@ -/* $OpenBSD: ftp-proxy.c,v 1.41 2005/03/05 23:11:19 cloder Exp $ */ - -/* - * Copyright (c) 1996-2001 - * Obtuse Systems Corporation. 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 Obtuse Systems 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 OBTUSE SYSTEMS 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 OBTUSE SYSTEMS CORPORATION 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. - * - */ - -/* - * ftp proxy, Originally based on juniper_ftp_proxy from the Obtuse - * Systems juniper firewall, written by Dan Boulet <danny@obtuse.com> - * and Bob Beck <beck@obtuse.com> - * - * This version basically passes everything through unchanged except - * for the PORT and the * "227 Entering Passive Mode" reply. - * - * A PORT command is handled by noting the IP address and port number - * specified and then configuring a listen port on some very high port - * number and telling the server about it using a PORT message. - * We then watch for an in-bound connection on the port from the server - * and connect to the client's port when it happens. - * - * A "227 Entering Passive Mode" reply is handled by noting the IP address - * and port number specified and then configuring a listen port on some - * very high port number and telling the client about it using a - * "227 Entering Passive Mode" reply. - * We then watch for an in-bound connection on the port from the client - * and connect to the server's port when it happens. - * - * 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 retrieved from pf - * - */ - -/* - * TODO: - * Plenty, this is very basic, with the idea to get it in clean first. - * - * - IPv6 and EPASV support - * - Content filter support - * - filename filter support - * - per-user rules perhaps. - */ - -#include <sys/param.h> -#include <sys/time.h> -#include <sys/socket.h> - -#include <net/if.h> -#include <netinet/in.h> - -#include <arpa/inet.h> - -#include <ctype.h> -#include <errno.h> -#include <grp.h> -#include <netdb.h> -#include <pwd.h> -#include <signal.h> -#include <stdarg.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <sysexits.h> -#include <syslog.h> -#include <unistd.h> - -#include "util.h" - -#ifdef LIBWRAP -#include <tcpd.h> -int allow_severity = LOG_INFO; -int deny_severity = LOG_NOTICE; -#endif /* LIBWRAP */ - -int min_port = IPPORT_HIFIRSTAUTO; -int max_port = IPPORT_HILASTAUTO; - -#define STARTBUFSIZE 1024 /* Must be at least 3 */ - -/* - * Variables used to support PORT mode connections. - * - * This gets a bit complicated. - * - * If PORT mode is on then client_listen_sa describes the socket that - * the real client is listening on and server_listen_sa describes the - * socket that we are listening on (waiting for the real server to connect - * with us). - * - * If PASV mode is on then client_listen_sa describes the socket that - * we are listening on (waiting for the real client to connect to us on) - * and server_listen_sa describes the socket that the real server is - * listening on. - * - * If the socket we are listening on gets a connection then we connect - * to the other side's socket. Similarly, if a connected socket is - * shutdown then we shutdown the other side's socket. - */ - -double xfer_start_time; - -struct sockaddr_in real_server_sa; -struct sockaddr_in client_listen_sa; -struct sockaddr_in server_listen_sa; -struct sockaddr_in proxy_sa; -struct in_addr src_addr; - -int client_listen_socket = -1; /* Only used in PASV mode */ -int client_data_socket = -1; /* Connected socket to real client */ -int server_listen_socket = -1; /* Only used in PORT mode */ -int server_data_socket = -1; /* Connected socket to real server */ -int client_data_bytes, server_data_bytes; - -int AnonFtpOnly; -int Verbose; -int NatMode; -int ReverseMode; - -char ClientName[NI_MAXHOST]; -char RealServerName[NI_MAXHOST]; -char OurName[NI_MAXHOST]; - -const char *User = "proxy"; -const char *Group; - -extern int Debug_Level; -extern int Use_Rdns; -extern in_addr_t Bind_Addr; -extern char *__progname; - -typedef enum { - UNKNOWN_MODE, - PORT_MODE, - PASV_MODE, - EPRT_MODE, - EPSV_MODE -} connection_mode_t; - -connection_mode_t connection_mode; - -extern void debuglog(int debug_level, const char *fmt, ...); -double wallclock_time(void); -void show_xfer_stats(void); -void log_control_command (char *cmd, int client); -int new_dataconn(int server); -void do_client_cmd(struct csiob *client, struct csiob *server); -void do_server_reply(struct csiob *server, struct csiob *client); -static void -usage(void) -{ - syslog(LOG_NOTICE, - "usage: %s [-AnrVw] [-a address] [-D debuglevel] [-g group]" - " [-M maxport] [-m minport] [-R address[:port]] [-S address]" - " [-t timeout] [-u user]", __progname); - exit(EX_USAGE); -} - -static void -close_client_data(void) -{ - if (client_data_socket >= 0) { - shutdown(client_data_socket, 2); - close(client_data_socket); - client_data_socket = -1; - } -} - -static void -close_server_data(void) -{ - if (server_data_socket >= 0) { - shutdown(server_data_socket, 2); - close(server_data_socket); - server_data_socket = -1; - } -} - -static void -drop_privs(void) -{ - struct passwd *pw; - struct group *gr; - uid_t uid = 0; - gid_t gid = 0; - - if (User != NULL) { - pw = getpwnam(User); - if (pw == NULL) { - syslog(LOG_ERR, "cannot find user %s", User); - exit(EX_USAGE); - } - uid = pw->pw_uid; - gid = pw->pw_gid; - } - - if (Group != NULL) { - gr = getgrnam(Group); - if (gr == NULL) { - syslog(LOG_ERR, "cannot find group %s", Group); - exit(EX_USAGE); - } - gid = gr->gr_gid; - } - - if (gid != 0 && (setegid(gid) == -1 || setgid(gid) == -1)) { - syslog(LOG_ERR, "cannot drop group privs (%m)"); - exit(EX_CONFIG); - } - - if (uid != 0 && (seteuid(uid) == -1 || setuid(uid) == -1)) { - syslog(LOG_ERR, "cannot drop root privs (%m)"); - exit(EX_CONFIG); - } -} - -#ifdef LIBWRAP -/* - * 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. - */ -static int -check_host(struct sockaddr_in *client_sin, struct sockaddr_in *server_sin) -{ - char cname[NI_MAXHOST]; - char sname[NI_MAXHOST]; - struct request_info request; - int i; - - 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. - */ - i = getnameinfo((struct sockaddr *) &client_sin->sin_addr, - sizeof(&client_sin->sin_addr), cname, sizeof(cname), - NULL, 0, NI_NAMEREQD); - - if (i != 0 && i != EAI_NONAME && i != EAI_AGAIN) - strlcpy(cname, STRING_UNKNOWN, sizeof(cname)); - - i = getnameinfo((struct sockaddr *)&server_sin->sin_addr, - sizeof(&server_sin->sin_addr), sname, sizeof(sname), - NULL, 0, NI_NAMEREQD); - - if (i != 0 && i != EAI_NONAME && i != EAI_AGAIN) - strlcpy(sname, STRING_UNKNOWN, sizeof(sname)); - } else { - /* - * ensure the TCP wrapper doesn't start doing - * reverse DNS lookups if we aren't supposed to. - */ - strlcpy(cname, STRING_UNKNOWN, sizeof(cname)); - 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); - - if (!hosts_access(&request)) { - syslog(LOG_NOTICE, "tcpwrappers rejected: %s -> %s", - ClientName, RealServerName); - return(0); - } - return(1); -} -#endif /* LIBWRAP */ - -double -wallclock_time(void) -{ - struct timeval tv; - - gettimeofday(&tv, NULL); - return(tv.tv_sec + tv.tv_usec / 1e6); -} - -/* - * Show the stats for this data transfer - */ -void -show_xfer_stats(void) -{ - char tbuf[1000]; - double delta; - size_t len; - int i = -1; - - if (!Verbose) - return; - - delta = wallclock_time() - xfer_start_time; - - if (delta < 0.001) - delta = 0.001; - - if (client_data_bytes == 0 && server_data_bytes == 0) { - syslog(LOG_INFO, - "data transfer complete (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 complete (%dh %dm %ds", - idelta / (60*60), (idelta % (60*60)) / 60, - idelta % 60); - if (i == -1 || i >= len) - goto logit; - len -= i; - } else { - i = snprintf(tbuf, len, - "data transfer complete (%dm %ds", idelta / 60, - idelta % 60); - if (i == -1 || i >= len) - goto logit; - len -= i; - } - } else { - i = snprintf(tbuf, len, "data transfer complete (%.1fs", - delta); - if (i == -1 || i >= len) - goto logit; - len -= i; - } - - if (client_data_bytes > 0) { - i = snprintf(&tbuf[strlen(tbuf)], len, - ", %d bytes to server) (%.1fKB/s", client_data_bytes, - (client_data_bytes / delta) / (double)1024); - if (i == -1 || i >= len) - goto logit; - len -= i; - } - if (server_data_bytes > 0) { - i = snprintf(&tbuf[strlen(tbuf)], len, - ", %d bytes to client) (%.1fKB/s", server_data_bytes, - (server_data_bytes / delta) / (double)1024); - if (i == -1 || i >= len) - goto logit; - len -= i; - } - strlcat(tbuf, ")", sizeof(tbuf)); - logit: - if (i != -1) - syslog(LOG_INFO, "%s", tbuf); -} - -void -log_control_command (char *cmd, int client) -{ - /* log an ftp control command or reply */ - const char *logstring; - int level = LOG_DEBUG; - - if (!Verbose) - return; - - /* don't log passwords */ - 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)) - level = LOG_INFO; - } - syslog(level, "%s %s", client ? "client:" : " server:", - 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; - } - close_client_data(); - - if (server_listen_socket != -1) { - close(server_listen_socket); - server_listen_socket = -1; - } - close_server_data(); - - 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); - - if (server_listen_socket == -1) { - syslog(LOG_INFO, "server socket bind() failed (%m)"); - exit(EX_OSERR); - } - if (listen(server_listen_socket, 5) != 0) { - syslog(LOG_INFO, "server socket listen() failed (%m)"); - exit(EX_OSERR); - } - } else { - 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); - - if (client_listen_socket == -1) { - syslog(LOG_NOTICE, - "cannot get client listen socket (%m)"); - exit(EX_OSERR); - } - if (listen(client_listen_socket, 5) != 0) { - syslog(LOG_NOTICE, - "cannot listen on client socket (%m)"); - exit(EX_OSERR); - } - } - return(0); -} - -static void -connect_pasv_backchannel(void) -{ - struct sockaddr_in listen_sa; - socklen_t salen; - - /* - * We are about to accept a connection from the client. - * This is a PASV data connection. - */ - debuglog(2, "client listen socket ready"); - - close_server_data(); - close_client_data(); - - salen = sizeof(listen_sa); - client_data_socket = accept(client_listen_socket, - (struct sockaddr *)&listen_sa, &salen); - - if (client_data_socket < 0) { - syslog(LOG_NOTICE, "accept() failed (%m)"); - exit(EX_OSERR); - } - close(client_listen_socket); - client_listen_socket = -1; - memset(&listen_sa, 0, sizeof(listen_sa)); - - server_data_socket = get_backchannel_socket(SOCK_STREAM, min_port, - max_port, -1, 1, &listen_sa); - if (server_data_socket < 0) { - syslog(LOG_NOTICE, "get_backchannel_socket() failed (%m)"); - exit(EX_OSERR); - } - if (connect(server_data_socket, (struct sockaddr *) &server_listen_sa, - sizeof(server_listen_sa)) != 0) { - syslog(LOG_NOTICE, "connect() failed (%m)"); - exit(EX_NOHOST); - } - client_data_bytes = 0; - server_data_bytes = 0; - xfer_start_time = wallclock_time(); -} - -static void -connect_port_backchannel(void) -{ - struct sockaddr_in listen_sa; - socklen_t salen; - - /* - * We are about to accept a connection from the server. - * This is a PORT or EPRT data connection. - */ - debuglog(2, "server listen socket ready"); - - close_server_data(); - close_client_data(); - - salen = sizeof(listen_sa); - server_data_socket = accept(server_listen_socket, - (struct sockaddr *)&listen_sa, &salen); - if (server_data_socket < 0) { - syslog(LOG_NOTICE, "accept() failed (%m)"); - exit(EX_OSERR); - } - close(server_listen_socket); - server_listen_socket = -1; - - if (getuid() != 0) { - /* - * We're not running as root, so we get a backchannel - * socket bound in our designated range, instead of - * getting one bound to port 20 - This is deliberately - * not RFC compliant. - */ - bcopy(&src_addr, &listen_sa.sin_addr, sizeof(struct in_addr)); - client_data_socket = get_backchannel_socket(SOCK_STREAM, - min_port, max_port, -1, 1, &listen_sa); - if (client_data_socket < 0) { - syslog(LOG_NOTICE, "get_backchannel_socket() failed (%m)"); - exit(EX_OSERR); - } - - } else { - - /* - * We're root, get our backchannel socket bound to port - * 20 here, so we're fully RFC compliant. - */ - client_data_socket = socket(AF_INET, SOCK_STREAM, 0); - - salen = 1; - listen_sa.sin_family = AF_INET; - bcopy(&src_addr, &listen_sa.sin_addr, sizeof(struct in_addr)); - listen_sa.sin_port = htons(20); - - if (setsockopt(client_data_socket, SOL_SOCKET, SO_REUSEADDR, - &salen, sizeof(salen)) == -1) { - syslog(LOG_NOTICE, "setsockopt() failed (%m)"); - exit(EX_OSERR); - } - - if (bind(client_data_socket, (struct sockaddr *)&listen_sa, - sizeof(listen_sa)) == - 1) { - syslog(LOG_NOTICE, "data channel bind() failed (%m)"); - exit(EX_OSERR); - } - } - - if (connect(client_data_socket, (struct sockaddr *) &client_listen_sa, - sizeof(client_listen_sa)) != 0) { - syslog(LOG_INFO, "cannot connect data channel (%m)"); - exit(EX_NOHOST); - } - - client_data_bytes = 0; - server_data_bytes = 0; - xfer_start_time = wallclock_time(); -} - -void -do_client_cmd(struct csiob *client, struct csiob *server) -{ - int i, j, rv; - char tbuf[100]; - 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. - */ - if (strlen((char *)client->line_buffer) > 512) { - syslog(LOG_NOTICE, "excessively long control command"); - exit(EX_DATAERR); - } - - /* - * Check the client user provided if needed - */ - if (AnonFtpOnly && strncasecmp((char *)client->line_buffer, "user ", - strlen("user ")) == 0) { - char *cp; - - cp = (char *) client->line_buffer + strlen("user "); - if ((strcasecmp(cp, "ftp\r\n") != 0) && - (strcasecmp(cp, "anonymous\r\n") != 0)) { - /* - * this isn't anonymous - give the client an - * error before they send a password - */ - 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 && - errno != EINTR) - break; - else if (rv != -1) - j += rv; - } while (j >= 0 && j < i); - sendbuf = NULL; - } else - sendbuf = (char *)client->line_buffer; - } else if ((strncasecmp((char *)client->line_buffer, "eprt ", - strlen("eprt ")) == 0)) { - - /* 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((char *)client->line_buffer+strlen("eprt ")); - if (line == NULL) { - syslog(LOG_ERR, "insufficient memory"); - exit(EX_UNAVAILABLE); - } - p = line; - delim = p[0]; - p++; - - memset(result,0, sizeof(result)); - for (i = 0; i < 3; i++) { - q = strchr(p, delim); - if (!q || *q != delim) - goto parsefail; - *q++ = '\0'; - result[i] = p; - p = q; - } - - proto = strtoul(result[0], &p, 10); - if (!*result[0] || *p) - goto protounsupp; - - memset(&hints, 0, sizeof(hints)); - if (proto != 1) /* 1 == AF_INET - all we support for now */ - goto protounsupp; - hints.ai_family = AF_INET; - hints.ai_socktype = SOCK_STREAM; - hints.ai_flags = AI_NUMERICHOST; /*no DNS*/ - if (getaddrinfo(result[1], result[2], &hints, &res)) - goto parsefail; - if (res->ai_next) - goto parsefail; - 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", - 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", - inet_ntoa(server->sa.sin_addr), - 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); - sendbuf = tbuf; - goto out; -parsefail: - snprintf(tbuf, sizeof(tbuf), - "500 Invalid argument; rejected\r\n"); - sendbuf = NULL; - goto out; -protounsupp: - /* we only support AF_INET for now */ - if (proto == 2) - snprintf(tbuf, sizeof(tbuf), - "522 Protocol not supported, use (1)\r\n"); - else - snprintf(tbuf, sizeof(tbuf), - "501 Protocol not supported\r\n"); - sendbuf = NULL; -out: - if (line) - free(line); - if (res) - freeaddrinfo(res); - if (sendbuf == NULL) { - debuglog(1, "to client (modified): %s", tbuf); - i = strlen(tbuf); - do { - rv = send(client->fd, tbuf + j, i - j, 0); - 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)) { - - /* - * If we aren't in NAT mode, deal with EPSV. - * EPSV is a problem - Unlike 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 - * additions/deletions in pf. - * - * 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), - "500 EPSV command not understood\r\n"); - debuglog(1, "to client (modified): %s", tbuf); - j = 0; - i = strlen(tbuf); - do { - rv = send(client->fd, tbuf + j, i - j, 0); - if (rv == -1 && errno != EAGAIN && errno != EINTR) - break; - else if (rv != -1) - j += rv; - } while (j >= 0 && j < i); - sendbuf = NULL; - } else if (strncasecmp((char *)client->line_buffer, "port ", - strlen("port ")) == 0) { - unsigned int values[6]; - char *tailptr; - - debuglog(1, "Got a PORT command"); - - tailptr = (char *)&client->line_buffer[strlen("port ")]; - values[0] = 0; - - i = sscanf(tailptr, "%u,%u,%u,%u,%u,%u", &values[0], - &values[1], &values[2], &values[3], &values[4], - &values[5]); - if (i != 6) { - syslog(LOG_INFO, "malformed PORT command (%s)", - client->line_buffer); - exit(EX_DATAERR); - } - - for (i = 0; i<6; i++) { - if (values[i] > 255) { - syslog(LOG_INFO, - "malformed PORT command (%s)", - client->line_buffer); - 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_port = htons((values[4] << 8) | - values[5]); - debuglog(1, "client wants us to use %u.%u.%u.%u:%u", - 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", - inet_ntoa(server->sa.sin_addr), - 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], - ((u_char *)&server->sa.sin_addr.s_addr)[2], - ((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); - - sendbuf = tbuf; - } else - sendbuf = (char *)client->line_buffer; - - /* - *send our (possibly modified) control command in sendbuf - * on it's way to the server - */ - if (sendbuf != NULL) { - j = 0; - i = strlen(sendbuf); - do { - rv = send(server->fd, sendbuf + j, i - j, 0); - if (rv == -1 && errno != EAGAIN && errno != EINTR) - break; - else if (rv != -1) - j += rv; - } while (j >= 0 && j < i); - } -} - -void -do_server_reply(struct csiob *server, struct csiob *client) -{ - int code, i, j, rv; - struct in_addr *iap; - static int continuing = 0; - char tbuf[100], *sendbuf, *p; - - 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 - * exit - we don't pass this on for fear of hurting - * our other end, which might be poorly implemented. - */ - syslog(LOG_NOTICE, "long FTP control reply"); - exit(EX_DATAERR); - } - - /* - * Watch out for "227 Entering Passive Mode ..." replies - */ - code = strtol((char *)server->line_buffer, &p, 10); - if (isspace(server->line_buffer[0])) - code = 0; - if (!*(server->line_buffer) || (*p != ' ' && *p != '-')) { - if (continuing) - goto sendit; - syslog(LOG_INFO, "malformed control reply"); - exit(EX_DATAERR); - } - if (code <= 0 || code > 999) { - if (continuing) - goto sendit; - syslog(LOG_INFO, "invalid server reply code %d", code); - exit(EX_DATAERR); - } - if (*p == '-') - continuing = 1; - else - continuing = 0; - if (code == 227 && !NatMode) { - unsigned int values[6]; - char *tailptr; - - debuglog(1, "Got a PASV reply"); - debuglog(1, "{%s}", (char *)server->line_buffer); - - tailptr = (char *)strchr((char *)server->line_buffer, '('); - if (tailptr == NULL) { - tailptr = strrchr((char *)server->line_buffer, ' '); - if (tailptr == NULL) { - syslog(LOG_NOTICE, "malformed 227 reply"); - exit(EX_DATAERR); - } - } - tailptr++; /* skip past space or ( */ - - values[0] = 0; - - i = sscanf(tailptr, "%u,%u,%u,%u,%u,%u", &values[0], - &values[1], &values[2], &values[3], &values[4], - &values[5]); - if (i != 6) { - syslog(LOG_INFO, "malformed PASV reply (%s)", - client->line_buffer); - exit(EX_DATAERR); - } - for (i = 0; i<6; i++) - if (values[i] > 255) { - syslog(LOG_INFO, "malformed PASV reply(%s)", - client->line_buffer); - 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) | - values[5]); - - debuglog(1, "server wants us to use %s:%u", - inet_ntoa(server_listen_sa.sin_addr), (values[4] << 8) | - values[5]); - - new_dataconn(0); - connection_mode = PASV_MODE; - if (ReverseMode) - iap = &(proxy_sa.sin_addr); - else - iap = &(server->sa.sin_addr); - - debuglog(1, "we want client to use %s:%u", 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", tbuf); - sendbuf = tbuf; - } else { - sendit: - sendbuf = (char *)server->line_buffer; - } - - /* - * send our (possibly modified) control command in sendbuf - * on it's way to the client - */ - j = 0; - i = strlen(sendbuf); - do { - rv = send(client->fd, sendbuf + j, i - j, 0); - if (rv == -1 && errno != EAGAIN && errno != EINTR) - break; - else if (rv != -1) - j += rv; - } while (j >= 0 && j < i); - -} - -int -main(int argc, char *argv[]) -{ - struct csiob client_iob, server_iob; - struct sigaction new_sa, old_sa; - int sval, ch, flags, i; - socklen_t salen; - int one = 1; - long timeout_seconds = 0; - struct timeval tv; -#ifdef LIBWRAP - int use_tcpwrapper = 0; -#endif /* LIBWRAP */ - - while ((ch = getopt(argc, argv, "a:D:g:m:M:R:S:t:u:AnVwr")) != -1) { - char *p; - switch (ch) { - case 'a': - if (!*optarg) - usage(); - if ((Bind_Addr = inet_addr(optarg)) == INADDR_NONE) { - syslog(LOG_NOTICE, - "%s: invalid address", optarg); - usage(); - } - break; - case 'A': - AnonFtpOnly = 1; /* restrict to anon usernames only */ - break; - case 'D': - Debug_Level = strtol(optarg, &p, 10); - if (!*optarg || *p) - usage(); - break; - case 'g': - Group = optarg; - break; - case 'm': - min_port = strtol(optarg, &p, 10); - if (!*optarg || *p) - usage(); - if (min_port < 0 || min_port > USHRT_MAX) - usage(); - break; - case 'M': - max_port = strtol(optarg, &p, 10); - if (!*optarg || *p) - usage(); - if (max_port < 0 || max_port > USHRT_MAX) - usage(); - break; - case 'n': - NatMode = 1; /* pass all passives, we're using NAT */ - break; - case 'r': - Use_Rdns = 1; /* look up hostnames */ - break; - case 'R': { - char *s, *t; - - if (!*optarg) - usage(); - if ((s = strdup(optarg)) == NULL) { - syslog (LOG_NOTICE, - "Insufficient memory (malloc failed)"); - exit(EX_UNAVAILABLE); - } - memset(&real_server_sa, 0, sizeof(real_server_sa)); - real_server_sa.sin_len = sizeof(struct sockaddr_in); - real_server_sa.sin_family = AF_INET; - t = strchr(s, ':'); - if (t == NULL) - real_server_sa.sin_port = htons(21); - else { - long port = strtol(t + 1, &p, 10); - - if (*p || port <= 0 || port > 65535) - usage(); - real_server_sa.sin_port = htons(port); - *t = 0; - } - real_server_sa.sin_addr.s_addr = inet_addr(s); - if (real_server_sa.sin_addr.s_addr == INADDR_NONE) - usage(); - free(s); - ReverseMode = 1; - break; - } - case 'S': - if (!inet_aton(optarg, &src_addr)) - usage(); - break; - case 't': - timeout_seconds = strtol(optarg, &p, 10); - if (!*optarg || *p) - usage(); - break; - case 'u': - User = optarg; - break; - case 'V': - Verbose = 1; - break; -#ifdef LIBWRAP - case 'w': - use_tcpwrapper = 1; /* do the libwrap thing */ - break; -#endif /* LIBWRAP */ - default: - usage(); - /* NOTREACHED */ - } - } - argc -= optind; - argv += optind; - - 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, - &proxy_sa) == -1) - exit(EX_PROTOCOL); - - /* - * We may now drop root privs, as we have done our ioctl for - * pf. If we do drop root, we can't make backchannel connections - * for PORT and EPRT come from port 20, which is not strictly - * RFC compliant. This shouldn't cause problems for all but - * the stupidest ftp clients and the stupidest packet filters. - */ - drop_privs(); - - /* - * 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) - flags = 0; - else - flags = NI_NUMERICHOST | NI_NUMERICSERV; - - i = getnameinfo((struct sockaddr *)&client_iob.sa, - sizeof(client_iob.sa), ClientName, sizeof(ClientName), NULL, 0, - flags); - - if (i != 0 && i != EAI_NONAME && i != EAI_AGAIN) { - debuglog(2, "name resolution failure (client)"); - exit(EX_OSERR); - } - - i = getnameinfo((struct sockaddr *)&real_server_sa, - sizeof(real_server_sa), RealServerName, sizeof(RealServerName), - NULL, 0, flags); - - if (i != 0 && i != EAI_NONAME && i != EAI_AGAIN) { - debuglog(2, "name resolution failure (server)"); - exit(EX_OSERR); - } - -#ifdef LIBWRAP - if (use_tcpwrapper && !check_host(&client_iob.sa, &real_server_sa)) - exit(EX_NOPERM); -#endif - - client_iob.fd = 0; - - syslog(LOG_INFO, "accepted connection from %s:%u to %s:%u", ClientName, - ntohs(client_iob.sa.sin_port), 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, "cannot 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. - */ - salen = sizeof(server_iob.sa); - getsockname(server_iob.fd, (struct sockaddr *)&server_iob.sa, &salen); - - i = getnameinfo((struct sockaddr *)&server_iob.sa, - sizeof(server_iob.sa), OurName, sizeof(OurName), NULL, 0, flags); - - if (i != 0 && i != EAI_NONAME && i != EAI_AGAIN) { - debuglog(2, "name resolution failure (local)"); - exit(EX_OSERR); - } - - debuglog(1, "local socket is %s:%u", OurName, - ntohs(server_iob.sa.sin_port)); - - /* 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)"); - exit(EX_OSERR); - } - - if (setsockopt(client_iob.fd, SOL_SOCKET, SO_OOBINLINE, (char *)&one, - sizeof(one)) == -1) { - syslog(LOG_NOTICE, "cannot set SO_OOBINLINE (%m)"); - 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; - client_iob.io_buffer = malloc(client_iob.io_buffer_size); - client_iob.next_byte = 0; - client_iob.io_buffer_len = 0; - client_iob.alive = 1; - 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 = malloc(server_iob.io_buffer_size); - server_iob.next_byte = 0; - server_iob.io_buffer_len = 0; - server_iob.alive = 1; - server_iob.who = "server"; - 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) { - syslog (LOG_NOTICE, "insufficient memory"); - exit(EX_UNAVAILABLE); - } - - while (client_iob.alive || server_iob.alive) { - int maxfd = 0; - fd_set *fdsp; - - if (client_iob.fd > maxfd) - maxfd = client_iob.fd; - if (client_listen_socket > maxfd) - maxfd = client_listen_socket; - if (client_data_socket > maxfd) - maxfd = client_data_socket; - if (server_iob.fd > maxfd) - maxfd = server_iob.fd; - if (server_listen_socket > maxfd) - maxfd = server_listen_socket; - if (server_data_socket > maxfd) - maxfd = server_data_socket; - - debuglog(3, "client is %s; server is %s", - client_iob.alive ? "alive" : "dead", - server_iob.alive ? "alive" : "dead"); - - fdsp = (fd_set *)calloc(howmany(maxfd + 1, NFDBITS), - sizeof(fd_mask)); - if (fdsp == NULL) { - syslog(LOG_NOTICE, "insufficient memory"); - exit(EX_UNAVAILABLE); - } - - if (client_iob.alive && telnet_getline(&client_iob, - &server_iob)) { - debuglog(3, "client line buffer is \"%s\"", - (char *)client_iob.line_buffer); - 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\"", - (char *)server_iob.line_buffer); - if (server_iob.line_buffer[0] != '\0') - do_server_reply(&server_iob, &client_iob); - } else { - if (client_iob.alive) { - FD_SET(client_iob.fd, fdsp); - if (client_listen_socket >= 0) - FD_SET(client_listen_socket, fdsp); - if (client_data_socket >= 0) - FD_SET(client_data_socket, fdsp); - } - if (server_iob.alive) { - FD_SET(server_iob.fd, fdsp); - if (server_listen_socket >= 0) - FD_SET(server_listen_socket, fdsp); - if (server_data_socket >= 0) - FD_SET(server_data_socket, fdsp); - } - tv.tv_sec = timeout_seconds; - tv.tv_usec = 0; - - doselect: - sval = select(maxfd + 1, fdsp, NULL, NULL, - (tv.tv_sec == 0) ? NULL : &tv); - if (sval == 0) { - /* - * This proxy has timed out. Expire it - * quietly with an obituary in the syslogs - * for any passing mourners. - */ - syslog(LOG_INFO, - "timeout: no data for %ld seconds", - timeout_seconds); - exit(EX_OK); - } - if (sval == -1) { - if (errno == EINTR || errno == EAGAIN) - goto doselect; - syslog(LOG_NOTICE, - "select() failed (%m)"); - exit(EX_OSERR); - } - if (client_data_socket >= 0 && - FD_ISSET(client_data_socket, fdsp)) { - int rval; - - debuglog(3, "transfer: client to server"); - rval = xfer_data("client to server", - client_data_socket, - server_data_socket, - client_iob.sa.sin_addr, - real_server_sa.sin_addr); - if (rval <= 0) { - close_client_data(); - close_server_data(); - show_xfer_stats(); - } else - client_data_bytes += rval; - } - if (server_data_socket >= 0 && - FD_ISSET(server_data_socket, fdsp)) { - int rval; - - debuglog(3, "transfer: server to client"); - rval = xfer_data("server to client", - server_data_socket, - client_data_socket, - real_server_sa.sin_addr, - client_iob.sa.sin_addr); - if (rval <= 0) { - close_client_data(); - close_server_data(); - show_xfer_stats(); - } else - server_data_bytes += rval; - } - if (server_listen_socket >= 0 && - FD_ISSET(server_listen_socket, fdsp)) { - connect_port_backchannel(); - } - if (client_listen_socket >= 0 && - FD_ISSET(client_listen_socket, fdsp)) { - connect_pasv_backchannel(); - } - if (client_iob.alive && - FD_ISSET(client_iob.fd, fdsp)) { - client_iob.data_available = 1; - } - if (server_iob.alive && - FD_ISSET(server_iob.fd, fdsp)) { - server_iob.data_available = 1; - } - } - free(fdsp); - if (client_iob.got_eof) { - 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); - server_iob.got_eof = 0; - server_iob.alive = 0; - } - } - - if (Verbose) - syslog(LOG_INFO, "session ended"); - - exit(EX_OK); -} diff --git a/libexec/ftp-proxy/getline.c b/libexec/ftp-proxy/getline.c deleted file mode 100644 index 7779fbcf4a6..00000000000 --- a/libexec/ftp-proxy/getline.c +++ /dev/null @@ -1,260 +0,0 @@ -/* $OpenBSD: getline.c,v 1.17 2005/08/17 07:55:24 espie 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) { - unsigned 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; - unsigned 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: - case IP: - 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) { - unsigned 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); - } -} diff --git a/libexec/ftp-proxy/util.c b/libexec/ftp-proxy/util.c deleted file mode 100644 index 61c9f1f1bc8..00000000000 --- a/libexec/ftp-proxy/util.c +++ /dev/null @@ -1,306 +0,0 @@ -/* $OpenBSD: util.c,v 1.19 2004/07/06 19:49:11 dhartmei Exp $ */ - -/* - * Copyright (c) 1996-2001 - * Obtuse Systems Corporation. 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 Obtuse Systems 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 OBTUSE SYSTEMS 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 OBTUSE - * SYSTEMS CORPORATION 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. - * - */ - -#include <sys/types.h> -#include <sys/socket.h> -#include <sys/ioctl.h> -#include <sys/file.h> -#include <netinet/in.h> -#include <netinet/in_systm.h> -#include <net/if.h> -#include <net/pfvar.h> - -#include <arpa/inet.h> - -#include <ctype.h> -#include <errno.h> -#include <netdb.h> -#include <signal.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <stdarg.h> -#include <sysexits.h> -#include <syslog.h> -#include <unistd.h> - -#include "util.h" - -extern int ReverseMode; - -int Debug_Level; -int Use_Rdns; -in_addr_t Bind_Addr = INADDR_NONE; - -void debuglog(int debug_level, const char *fmt, ...); - -void -debuglog(int debug_level, const char *fmt, ...) -{ - va_list ap; - va_start(ap, fmt); - - if (Debug_Level >= debug_level) - vsyslog(LOG_DEBUG, fmt, ap); - va_end(ap); -} - -int -get_proxy_env(int connected_fd, struct sockaddr_in *real_server_sa_ptr, - struct sockaddr_in *client_sa_ptr, struct sockaddr_in *proxy_sa_ptr) -{ - struct pfioc_natlook natlook; - socklen_t slen; - int fd; - - slen = sizeof(*proxy_sa_ptr); - if (getsockname(connected_fd, (struct sockaddr *)proxy_sa_ptr, - &slen) != 0) { - syslog(LOG_ERR, "getsockname() failed (%m)"); - return(-1); - } - slen = sizeof(*client_sa_ptr); - if (getpeername(connected_fd, (struct sockaddr *)client_sa_ptr, - &slen) != 0) { - syslog(LOG_ERR, "getpeername() failed (%m)"); - return(-1); - } - - if (ReverseMode) - return(0); - - /* - * Build up the pf natlook structure. - * Just for IPv4 right now - */ - memset((void *)&natlook, 0, sizeof(natlook)); - natlook.af = AF_INET; - natlook.saddr.addr32[0] = client_sa_ptr->sin_addr.s_addr; - natlook.daddr.addr32[0] = proxy_sa_ptr->sin_addr.s_addr; - natlook.proto = IPPROTO_TCP; - natlook.sport = client_sa_ptr->sin_port; - natlook.dport = proxy_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. - */ - fd = open("/dev/pf", O_RDWR); - if (fd == -1) { - syslog(LOG_ERR, "cannot open /dev/pf (%m)"); - exit(EX_UNAVAILABLE); - } - - if (ioctl(fd, DIOCNATLOOK, &natlook) == -1) { - syslog(LOG_INFO, - "pf nat lookup failed %s:%hu (%m)", - inet_ntoa(client_sa_ptr->sin_addr), - 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. - */ - memset((void *)real_server_sa_ptr, 0, sizeof(struct sockaddr_in)); - real_server_sa_ptr->sin_port = natlook.rdport; - real_server_sa_ptr->sin_addr.s_addr = natlook.rdaddr.addr32[0]; - real_server_sa_ptr->sin_len = sizeof(struct sockaddr_in); - real_server_sa_ptr->sin_family = AF_INET; - return(0); -} - - -/* - * Transfer one unit of data across a pair of sockets - * - * 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]; - - /* - * Are we at the OOB mark? - */ - if (ioctl(from_fd, SIOCATMARK, &mark) < 0) { - xerrno = errno; - syslog(LOG_ERR, "cannot ioctl(SIOCATMARK) socket from %s (%m)", - what_read); - errno = xerrno; - return(-1); - } - if (mark) - flags = MSG_OOB; /* Yes - at the OOB mark */ - -snarf: - rlen = recv(from_fd, tbuf, sizeof(tbuf), flags); - if (rlen == -1 && flags == MSG_OOB && errno == EINVAL) { - /* OOB didn't work */ - flags = 0; - rlen = recv(from_fd, tbuf, sizeof(tbuf), flags); - } - if (rlen == 0) { - debuglog(3, "EOF on read socket"); - return(0); - } else if (rlen == -1) { - if (errno == EAGAIN || errno == EINTR) - goto snarf; - xerrno = errno; - syslog(LOG_ERR, "xfer_data (%s): failed (%m) with flags 0%o", - what_read, flags); - errno = xerrno; - return(-1); - } else { - offset = 0; - debuglog(3, "got %d bytes from socket", rlen); - - while (offset < rlen) { - int wlen; - fling: - wlen = send(to_fd, &tbuf[offset], rlen - offset, - flags); - if (wlen == 0) { - debuglog(3, "zero-length write"); - goto fling; - } else if (wlen == -1) { - if (errno == EAGAIN || errno == EINTR) - goto fling; - xerrno = errno; - syslog(LOG_INFO, "write failed (%m)"); - errno = xerrno; - return(-1); - } else { - debuglog(3, "wrote %d bytes to socket",wlen); - offset += wlen; - } - } - return(offset); - } -} - -/* - * 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. - */ - if (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. - * 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. - */ - 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) { - struct sockaddr_in sa; - int one, fd; - - fd = socket(AF_INET, type, 0); - - bzero(&sa, sizeof sa); - sa.sin_family = AF_INET; - if (Bind_Addr == INADDR_NONE) - if (sap == NULL) - sa.sin_addr.s_addr = INADDR_ANY; - else - sa.sin_addr.s_addr = sap->sin_addr.s_addr; - else - sa.sin_addr.s_addr = Bind_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, - sizeof(one)) == -1) - return(-1); - - sa.sin_port = htons(start_port); - - if (bind(fd, (struct sockaddr *)&sa, sizeof(sa)) == 0) { - if (sap != NULL) - *sap = sa; - return(fd); - } - - if (errno != EADDRINUSE) - return(-1); - - /* if it's in use, try the next port */ - close(fd); - - start_port += direction; - if (start_port < min_port) - start_port = max_port; - else if (start_port > max_port) - start_port = min_port; - } - errno = EAGAIN; - return(-1); -} diff --git a/libexec/ftp-proxy/util.h b/libexec/ftp-proxy/util.h deleted file mode 100644 index ce1e9159393..00000000000 --- a/libexec/ftp-proxy/util.h +++ /dev/null @@ -1,68 +0,0 @@ -/* $OpenBSD: util.h,v 1.5 2005/02/24 15:49:08 dhartmei Exp $ */ - -/* - * Copyright (c) 1996-2001 - * Obtuse Systems Corporation. 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. - * 4. Neither the name of the Obtuse Systems 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 OBTUSE SYSTEMS CORPORATION 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. - */ - -struct proxy_channel { - int pc_to_fd, pc_from_fd; - int pc_alive; - int pc_nextbyte; - int pc_flags; - int pc_length; - int pc_size; - struct sockaddr_in pc_from_sa, pc_to_sa; - int (*pc_filter)( void ** databuf, int datalen); - char *pc_buffer; -}; - -struct csiob { - int fd; - int line_buffer_size, io_buffer_size, io_buffer_len, next_byte; - unsigned char *io_buffer, *line_buffer; - struct sockaddr_in sa, real_sa; - const char *who; - char alive, got_eof, data_available; - int send_oob_flags; -}; - -extern int telnet_getline(struct csiob *iobp, - struct csiob *telnet_passthrough); - -extern int get_proxy_env(int fd, struct sockaddr_in *server_sa_ptr, - struct sockaddr_in *client_sa_ptr, struct sockaddr_in *proxy_sa_ptr); - -extern int get_backchannel_socket(int type, int min_port, int max_port, - int start_port, int direction, struct sockaddr_in *sap); - -extern int xfer_data(const char *what_read, int from_fd, int to_fd, - struct in_addr from, struct in_addr to); - -extern char *ProgName; - - |