This patch was provided by Maciej Pyszka, mpyszka {at} rekord {dot} com {dot} pl. It has been placed in the public domain. It adds another option to sftpd, -u, which specifies which data port to bind when initiating active (PORT command) transfers. To apply this patch: % cd sftpd-1.46 % patch < bind-specified-active-port.txt % make distclean % ./configure && make (then copy the new binaries over the old ones) diff -c sftpd-1.46/sftpd.cpp mpsafetp/sftpd.cpp *** sftpd-1.46/sftpd.cpp Wed Nov 22 15:44:55 2000 --- mpsafetp/sftpd.cpp Tue Nov 6 14:54:15 2001 *************** *** 159,164 **** --- 159,166 ---- // if that member doesn't actually need an initialization SFTPD::SFTPD() : // ------ socket state ------ + // UOF + ourDataPort(8100), useStdinStream(false), client_control(INVALID_SOCKET), clientControlStream(NULL), *************** *** 398,404 **** artificialDelay = atoi(argString); break; ! case 's': // stdin stream useStdinStream = true; break; --- 400,411 ---- artificialDelay = atoi(argString); break; ! //UOF ! case 'u': ! ourDataPort = atoi(argString); ! break; ! ! case 's': // stdin stream useStdinStream = true; break; *************** *** 584,589 **** --- 591,597 ---- " -f: contact ftpd at another host (ADDR) and port N;\n" " (this is potentially INSECURE -- see sftpd.html)\n" " data channel:\n" + " -u port number server tries to bind for data channel (default: 8100)\n" " -c require all data transfers to be encrypted\n" " -r- restrict ports used for PASV to range [low,high]\n" " logging:\n" *************** *** 897,903 **** diagnostic("received connection from ftpd, trying to connect to client"); relayDataConnection( server_listen, server_data, ! relayClientAddress, relayClientPort, client_data); } // --- client connects to me --- --- 905,911 ---- diagnostic("received connection from ftpd, trying to connect to client"); relayDataConnection( server_listen, server_data, ! relayClientAddress, relayClientPort, client_data, ourDataPort); } // --- client connects to me --- *************** *** 1100,1106 **** // peerB_data - socket to connect to other peer, "B" bool SFTPD::relayDataConnection( SOCKET &peerA_listen, SOCKET &peerA_data, ! IPAddress addrB, int portB, SOCKET &peerB_data) { // for errors and diagnostics, we need to determine // who is client and who is server --- 1109,1115 ---- // peerB_data - socket to connect to other peer, "B" bool SFTPD::relayDataConnection( SOCKET &peerA_listen, SOCKET &peerA_data, ! IPAddress addrB, int portB, SOCKET &peerB_data, int ourport) { // for errors and diagnostics, we need to determine // who is client and who is server *************** *** 1125,1131 **** diagnostic("trying to connect to " << B << " at " << formatAddress(addrB) << ", port " << portB); ! peerB_data = connect_socket(addrB, portB); addEntropy(); } --- 1134,1140 ---- diagnostic("trying to connect to " << B << " at " << formatAddress(addrB) << ", port " << portB); ! peerB_data = connect_socket(addrB, portB, ourport); addEntropy(); } Only in sftpd-1.46: sftpd.dsp diff -c sftpd-1.46/sftpd.h mpsafetp/sftpd.h *** sftpd-1.46/sftpd.h Wed Nov 22 15:44:55 2000 --- mpsafetp/sftpd.h Tue Nov 6 12:35:40 2001 *************** *** 54,59 **** --- 54,61 ---- private: // data // ------ socket state ------ + // UOF - our port for data + int ourDataPort; // control connection to the client bool useStdinStream; // true if client_control is stdin SOCKET client_control; // send, select *************** *** 235,241 **** // and connect to the other bool relayDataConnection( SOCKET &peerA_listen, SOCKET &peerA_data, ! IPAddress addrB, int portB, SOCKET &peerB_data); // copy data from one socket to another, until no more is waiting void relaySocketData(SOCKET &dest, SOCKET &src); --- 237,243 ---- // and connect to the other bool relayDataConnection( SOCKET &peerA_listen, SOCKET &peerA_data, ! IPAddress addrB, int portB, SOCKET &peerB_data, int ourport=0); // copy data from one socket to another, until no more is waiting void relaySocketData(SOCKET &dest, SOCKET &src); diff -c sftpd-1.46/sockutil.cpp mpsafetp/sockutil.cpp *** sftpd-1.46/sockutil.cpp Wed Nov 22 15:44:55 2000 --- mpsafetp/sockutil.cpp Tue Nov 6 14:58:13 2001 *************** *** 502,508 **** // initiate a connection ! SOCKET connect_socket(IPAddress ipaddr, int port) { // create address structure sockaddr_in saddr; // address of receiver --- 502,508 ---- // initiate a connection ! SOCKET connect_socket(IPAddress ipaddr, int port, int ourport) { // create address structure sockaddr_in saddr; // address of receiver *************** *** 518,523 **** --- 518,545 ---- } incOpenSockets(); + //UOF + if( ourport && ( s != INVALID_SOCKET ) ) { + int buffer,i; + + buffer=1; + i=sizeof( int ); + + setsockopt( s, SOL_SOCKET, SO_REUSEADDR, (char *)&buffer, i); + + sockaddr_in ouraddr; + memset((char *)&ouraddr, 0, sizeof( ouraddr)); + ouraddr.sin_family = AF_INET; + ouraddr.sin_port = htons((short)ourport); + ouraddr.sin_addr.s_addr = htonl(INADDR_ANY); + + int ourp = ourport; + while( bind( s, (sockaddr *)&ouraddr, sizeof(ouraddr))) { + ourp++; + ouraddr.sin_port = htons((short)ourp); + } + } + // connect the socket to the resolved address and port (sockaddr) if (connect(s, (sockaddr *)&saddr, sizeof(saddr)) == SOCKET_ERROR) { diff -c sftpd-1.46/sockutil.h mpsafetp/sockutil.h *** sftpd-1.46/sockutil.h Wed Nov 22 15:44:55 2000 --- mpsafetp/sockutil.h Tue Nov 6 12:22:10 2001 *************** *** 186,192 **** SOCKET accept_socket(SOCKET s); // accept a connection on the given listening socket ! SOCKET connect_socket(IPAddress ipaddr, int port); // create a socket and connect it to a remote host/port void close_socket(SOCKET s); --- 186,192 ---- SOCKET accept_socket(SOCKET s); // accept a connection on the given listening socket ! SOCKET connect_socket(IPAddress ipaddr, int port, int ourport=0); // create a socket and connect it to a remote host/port void close_socket(SOCKET s);