"Fossies" - the Fresh Open Source Software Archive

Member "tlswrap-1.04/tlswrap.c" (29 Nov 2006, 34942 Bytes) of package /linux/privat/old/tlswrap-1.04.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "tlswrap.c" see the Fossies "Dox" file reference documentation.

    1 
    2 /*
    3  * Copyright (c) 2002-2006 Tomas Svensson <ts@codepix.com>
    4  * All rights reserved.
    5  *
    6  * Redistribution and use in source and binary forms, with or without
    7  * modification, are permitted provided that the following conditions
    8  * are met:
    9  * 1. Redistributions of source code must retain the above copyright
   10  *    notice, this list of conditions and the following disclaimer.
   11  * 2. Redistributions in binary form must reproduce the above copyright
   12  *    notice, this list of conditions and the following disclaimer in the
   13  *    documentation and/or other materials provided with the distribution.
   14  * 3. The name of the author may not be used to endorse or promote products
   15  *    derived from this software without specific prior written permission.
   16  *
   17  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
   18  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
   19  * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL
   20  * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
   21  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
   22  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
   23  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
   24  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
   25  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
   26  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   27  */
   28 
   29 #define _POSIX_PII_SOCKET /* for Tru64 UNIX 5.1 */
   30 
   31 #define TLSWRAP_VERSION_TEXT "v1.04"
   32 
   33 #ifdef WIN32
   34 #include "stdafx.h"
   35 #endif
   36 
   37 #include "conf.h"
   38 
   39 #include <sys/types.h>
   40 #include <sys/stat.h>
   41 #include <fcntl.h>
   42 #include <signal.h>
   43 #include <stdio.h>
   44 #include <stdlib.h>
   45 #include <string.h>
   46 
   47 #ifdef WIN32
   48 #define WIN32_LEAN_AND_MEAN     // Exclude rarely-used stuff from Windows headers
   49 #include <Winsock2.h>
   50 #include <windows.h>
   51 #include <process.h>    /* _beginthread, _endthread */
   52 #include <direct.h>
   53 #define snprintf _snprintf
   54 #define strcasecmp _stricmp
   55 #define strncasecmp _strnicmp
   56 #define chdir _chdir
   57 #define mkdir _mkdir
   58 #define getcwd _getcwd
   59 typedef int socklen_t;
   60 #ifdef WIN64
   61 typedef   __int64 ssize_t;
   62 #else
   63 typedef   __int32 ssize_t;
   64 #endif
   65 #define ECONNREFUSED WSAECONNREFUSED
   66 #define EINPROGRESS WSAEINPROGRESS
   67 #define EWOULDBLOCK WSAEWOULDBLOCK
   68 #define ECONNRESET WSAECONNRESET
   69 int write(SOCKET s, void *buf, int len);
   70 int read(SOCKET s, void *buf, int len);
   71 #define close closesocket
   72 char *srv_name = "TLSWrap";
   73 char *srv_name2 = "TLSWrap Service";
   74 char *srv_desc = "TLSWrap is a TLS/SSL FTP wrapper";
   75 #else
   76 #include <sys/resource.h>
   77 #include <sys/time.h>
   78 #include <sys/errno.h>
   79 #include <sys/socket.h>
   80 #include <netdb.h>
   81 #include <unistd.h>
   82 #endif
   83 
   84 #include "tlswrap.h"
   85 #include "network.h"
   86 #include "misc.h"
   87 #include "parse.h"
   88 #include "tls.h"
   89 #include "config.h"
   90 
   91 char    *cfg_tlsrsafile;
   92 char    *cfg_tlsciphers;
   93 
   94 int     debug;
   95 int     sec_mode;
   96 int     dns_write_pipe, dns_read_pipe, pipe1[2], pipe2[2];
   97 
   98 #ifdef WIN32
   99 int     in_service;
  100 struct  parm serv_param;
  101 #endif
  102 
  103 
  104 #ifdef HAVE_LIBWRAP
  105 #include <tcpd.h>
  106 
  107 int allow_severity;
  108 int deny_severity;
  109 #endif
  110 
  111 int main2(int argc, char *argv[]);
  112 
  113 int main(int argc, char *argv[])
  114 {
  115 #if defined(WIN32) && !defined(WIN98)
  116     SERVICE_TABLE_ENTRY servicetable[]=
  117     {
  118         {srv_name,(LPSERVICE_MAIN_FUNCTION)service_main},
  119         {NULL,NULL}
  120     };
  121     serv_param.argc = argc;
  122     serv_param.argv = argv;
  123     in_service = 0;
  124     if ((argc >= 2) && !strcmp(argv[1], "-S")) {
  125         in_service = 1;
  126         StartServiceCtrlDispatcher(servicetable);
  127     }
  128     else
  129 #endif
  130     return main2(argc, argv);
  131 }
  132 
  133 #if defined(WIN32) && !defined(WIN98)
  134 DWORD service_execution_thread(LPDWORD param) {
  135     return main2(serv_param.argc, serv_param.argv);
  136 }
  137 #endif
  138 
  139 int main2(int argc, char *argv[]) {
  140 #ifndef WIN32
  141     struct  sigaction sact;
  142     pid_t   childpid;
  143     struct  rlimit rlimit;
  144     int     flags;
  145 #ifndef __CYGWIN__
  146     char    fakebuf[1];
  147     int     sock_err;
  148     socklen_t sock_errlen;
  149 #endif
  150 #else
  151     WORD    wVersionRequested;
  152     WSADATA wsaData;
  153     char    port[6] ;//, tport[6];
  154     SOCKET  temp_sock;
  155     int     conn_res;
  156     unsigned int lport;
  157     SOCKET  arg[2];
  158     unsigned long sockarg;
  159 #endif
  160 #if defined(WIN32) || defined(__CYGWIN__)
  161     fd_set  eset;
  162 #endif
  163     char    buffer[NI_MAXHOST];
  164     int     listen_fd;
  165     int     idx;
  166     int     i, sel, newsock;
  167     int     remove_this,  serv_write;
  168     char    cfg_listenport[6];
  169     char    cfg_egdsock[NI_MAXHOST];
  170     char    cfg_listenhost[NI_MAXHOST];
  171     char    cfg_instopt[NI_MAXHOST];
  172     unsigned int cfg_max_users;
  173     fd_set  rset, wset;
  174     struct  sockaddr sockaddr;
  175     socklen_t   socklen;
  176     struct  user_data *ud;
  177     struct  dns_msg dns;
  178     unsigned int    tcpbufsize, tcpsndlowat;
  179     ssize_t bytes, bytesW;
  180     char    token[6];
  181     char    certspath[1024];
  182     char    ucertspath[1024];
  183     char    cfg_cafile[1024];
  184     char    crlfile[1024];
  185     int     conn_err, serv_remove, serv_install, key_wait;
  186     char remoteip[NI_MAXHOST];
  187     if ( (cfg_tlsciphers = (char*)malloc(1024)) == NULL)
  188         exit(1);
  189 
  190 #ifndef WIN32
  191     rlimit.rlim_cur = RLIM_INFINITY;
  192     rlimit.rlim_max = RLIM_INFINITY;
  193     setrlimit(RLIMIT_CORE, &rlimit);
  194 #else
  195     wVersionRequested = MAKEWORD(2,0);
  196  
  197     if (WSAStartup(wVersionRequested, &wsaData)) {
  198         MessageBox(NULL, "Can't initialize WinSock 2.0", "TLSWrap", MB_OK |
  199             MB_ICONERROR);
  200         exit(0);
  201     }
  202     if(!SetConsoleCtrlHandler((PHANDLER_ROUTINE)CtrlHandler, TRUE)) {
  203         printf("Can't set control handler\n");
  204     }       
  205 
  206 #endif
  207 
  208     read_config(argc, argv, &cfg_max_users, cfg_listenport, 
  209         sizeof(cfg_listenport), &debug,
  210         cfg_egdsock, sizeof(cfg_egdsock), cfg_tlsciphers,
  211         1024, &tcpbufsize, &tcpsndlowat, cfg_listenhost,
  212         sizeof(cfg_listenhost), token, sizeof(token), &sec_mode,
  213         certspath, sizeof(certspath), &serv_install, &serv_remove, &key_wait,
  214         cfg_instopt, sizeof(cfg_instopt), ucertspath, sizeof(ucertspath),
  215         cfg_cafile, sizeof(cfg_cafile), crlfile, sizeof(crlfile));
  216 
  217     if ( (ud = (struct user_data*)malloc(cfg_max_users *
  218             sizeof(struct user_data))) == NULL) {
  219         fprintf(stderr,"can't malloc user_data");
  220         exit(1);
  221     }
  222 
  223 #if defined(WIN32) && !defined(WIN98)
  224     if (serv_install) {
  225         if(_getcwd(buffer, NI_MAXHOST) == NULL )
  226             perror("_getcwd error" );
  227         install_service(buffer, cfg_instopt, key_wait);
  228     } else if (serv_remove)
  229         remove_service(key_wait);
  230 #endif
  231 
  232     if (1) { //if (sec_mode > 0) {
  233 #ifndef WIN32
  234         umask(077);
  235 #endif
  236         if (certspath[0] != '\0') {
  237             if (chdir(certspath))
  238                 sys_err("unable to access certs dir");
  239         } else {
  240             if (chdir("certs")) {
  241 #ifndef WIN32
  242                 if (mkdir("certs", 0700))
  243 #else
  244                 if (mkdir("certs"))
  245 #endif
  246                     sys_err("unable to create certs dir");
  247                 if (chdir("certs"))
  248                     sys_err("unable to access certs dir");
  249             }
  250             if (getcwd(certspath, sizeof(certspath)) == NULL)
  251                 sys_err("certspath getcwd");
  252         }
  253     }
  254     
  255     if (debug) {
  256         printf("certspath = %s\nucertspath = %s\n", certspath, ucertspath); 
  257     }
  258     tls_init(cfg_egdsock);
  259 
  260 #ifndef WIN32
  261     sact.sa_handler = SIG_IGN;
  262     sigemptyset(&sact.sa_mask);
  263     sact.sa_flags = 0;
  264     sigaction(SIGPIPE, &sact, NULL);
  265 #endif
  266 
  267 #ifdef HAVE_SETPROCTITLE
  268     setproctitle("tlswrap");
  269 #endif
  270 
  271 #ifndef WIN32
  272 
  273     if (pipe(pipe1)) sys_err("pipe1");
  274     if (pipe(pipe2)) sys_err("pipe2");
  275 
  276     if ( (childpid = fork()) == 0) {
  277         close(pipe1[1]);
  278         close(pipe2[0]);
  279         dns_helper(pipe1[0], pipe2[1]);
  280     } else {
  281         close(pipe1[0]);
  282         close(pipe2[1]);
  283     }
  284 
  285     dns_write_pipe = pipe1[1];
  286     dns_read_pipe  = pipe2[0];
  287 
  288     flags = fcntl(dns_write_pipe, F_GETFL);
  289     fcntl(dns_write_pipe, F_SETFL, flags | O_NONBLOCK);
  290     flags = fcntl(dns_read_pipe, F_GETFL);
  291     fcntl(dns_read_pipe, F_SETFL, flags | O_NONBLOCK);
  292 
  293 #else
  294     port[0] = '\0';
  295     temp_sock = setup_listen(5, "127.0.0.1", port, sizeof(port));
  296     if (debug)
  297         printf("listening to port %s for pipe setup\n", port);
  298     pipe1[0] = setup_connect("127.0.0.1", port, &lport, &conn_res);
  299     if (conn_res == 0) { /* connected OK */
  300         if ((pipe1[1] = accept(temp_sock, NULL, NULL)) == INVALID_SOCKET)
  301             sys_err("setup error for fake pipe");
  302     } else if (conn_res != 1) sys_err("local pipe connect1");
  303     FD_ZERO(&rset);
  304     FD_SET(temp_sock, &rset);
  305     select(1, &rset, NULL, NULL, NULL);
  306     //if (FD_ISSET(pipe1[0], &wset)) {
  307     if (FD_ISSET(temp_sock, &rset)) {
  308         if ((pipe1[1] = accept(temp_sock, NULL, NULL)) == INVALID_SOCKET){
  309             printf("setup error for fake pipe1: %d\n", WSAGetLastError());
  310             exit(0);
  311         }
  312     } else sys_err("could not connect to local pipe 1");
  313 
  314 
  315     pipe2[1] = setup_connect("127.0.0.1", port, &lport, &conn_res);
  316     if (conn_res == 0) { /* connected OK */
  317         if ((pipe2[0] = accept(temp_sock, NULL, NULL)) == INVALID_SOCKET)
  318             sys_err("setup error for fake pipe");
  319     } else if (conn_res != 1) sys_err("local pipe connect2");
  320     FD_ZERO(&rset);
  321     FD_SET(temp_sock, &rset);
  322     select(1, &rset, NULL, NULL, NULL);
  323     if (FD_ISSET(temp_sock, &rset)) {
  324         if ((pipe2[0] = accept(temp_sock, NULL, NULL)) == INVALID_SOCKET) {
  325             printf("setup error for fake pipe2: %d\n", WSAGetLastError());
  326             exit(0);
  327         }
  328     } else sys_err("could not connect to local pipe 2");
  329 
  330     if (closesocket(temp_sock) == SOCKET_ERROR)
  331         printf("error closing listening socket because %d\n", WSAGetLastError());
  332 
  333     dns_write_pipe = pipe1[1];
  334     dns_read_pipe  = pipe2[0];
  335 
  336     /* Turn off non-blocking for sockets to be used in the DNS helper */
  337 
  338     sockarg = 0;
  339 
  340     if (ioctlsocket(pipe1[0], FIONBIO, &sockarg) ==  SOCKET_ERROR) {
  341         printf("ioctlsocket 1 failed because %d\n", WSAGetLastError());
  342         exit(-1);
  343     }
  344 
  345     if (ioctlsocket(pipe2[1], FIONBIO, &sockarg) ==  SOCKET_ERROR) {
  346         printf("ioctlsocket 2 failed because %d\n", WSAGetLastError());
  347         exit(-1);
  348     }
  349     arg[0] = pipe1[0];
  350     arg[1] = pipe2[1];
  351 
  352     _beginthread((dns_helper), 0, &arg);
  353 
  354 #endif /* WIN32 */
  355 
  356     /* Do blocking DNS requests before this (if any) */
  357 
  358     init_ud(ud, cfg_max_users);
  359 
  360     listen_fd = setup_listen(5, cfg_listenhost, cfg_listenport, 0);
  361 
  362     fprintf(stderr,
  363         "TLSWrap %s (c) 2002-2006 Tomas Svensson <ts@codepix.com>\n", TLSWRAP_VERSION_TEXT);
  364     fprintf(stderr, "Servicing up to %u clients on %s:%s\n", cfg_max_users, cfg_listenhost, cfg_listenport);
  365 #if !defined __CYGWIN__ && !defined WIN32
  366 #ifdef __HAVE_DAEMON
  367     if (!debug)
  368         daemon(0 ,0);
  369 #else
  370     if (!debug) {
  371         if ( (childpid = fork()) < 0)
  372             sys_err("fork()");
  373         else if (childpid != 0) {
  374             fprintf(stderr, "Running as process %u\n", (unsigned int)childpid);
  375             exit(0); /* parent */
  376         }
  377         (void)setsid();
  378         if (certspath[0] == '\0')
  379             chdir("/"); 
  380     }
  381 #endif /* !HAVE_DAEMON */
  382 #endif /* !__CYGWIN__ */
  383 
  384     for(;;) {
  385         FD_ZERO(&rset);
  386         FD_ZERO(&wset);
  387 #if defined(WIN32) || defined(__CYGWIN__)
  388         FD_ZERO(&eset);
  389 #endif
  390         FD_SET(listen_fd, &rset);
  391         FD_SET(dns_read_pipe, &rset);
  392 
  393         for(i = 0; i < cfg_max_users ; i++) {
  394             if (ud[i].user_fd != -1) {
  395                 /* If there is room in the buffer, read from the user control connection */
  396                 if (ud[i].u2s_i < &ud[i].u2s_buf[U2S_SIZE]) {
  397                     FD_SET(ud[i].user_fd, &rset);
  398                 }
  399                 /* If there is room in the buffer and we are connected,
  400                     read from the server control connection */
  401                 if ((ud[i].connected == CONN_YES) &&
  402                     (ud[i].s2u_i < &ud[i].s2u_buf[S2U_SIZE])) {
  403                     FD_SET(ud[i].serv_fd, &rset);
  404                 }
  405                 else if (ud[i].connected == CONN_IN_PROG) {
  406 #if defined(WIN32) || defined(__CYGWIN__)
  407                     FD_SET(ud[i].serv_fd, &eset);
  408 #else
  409                     FD_SET(ud[i].serv_fd, &rset);
  410 #endif
  411                     FD_SET(ud[i].serv_fd, &wset);
  412                 }
  413                 if (ud[i].data_connected == CONN_IN_PROG) {
  414 #if defined(WIN32) || defined(__CYGWIN__)
  415                     FD_SET(ud[i].serv_data_fd, &eset);
  416 #else
  417                     FD_SET(ud[i].serv_data_fd, &rset);
  418 #endif
  419                     FD_SET(ud[i].serv_data_fd, &wset);
  420                 } else if (ud[i].data_connected == CONN_DATA_OK) {
  421                     if (ud[i].dc2s_i < 
  422                         &ud[i].dc2s_buf[DBUF_SIZE])
  423                         if (ud[i].user_data_close != CLOSE_READ)
  424                             FD_SET(ud[i].user_data_fd, &rset);
  425                     if (ud[i].ds2c_i <
  426                         &ud[i].ds2c_buf[DBUF_SIZE])
  427                         if  (ud[i].serv_data_close != CLOSE_READ)
  428                             FD_SET(ud[i].serv_data_fd, &rset);
  429                     if (ud[i].dc2s_i != ud[i].dc2s_o)
  430                         if (ud[i].serv_data_close != CLOSE_WRITE)
  431                             FD_SET(ud[i].serv_data_fd, &wset);
  432                     if (ud[i].ds2c_i != ud[i].ds2c_o)
  433                         if (ud[i].user_data_close != CLOSE_WRITE)
  434                             FD_SET(ud[i].user_data_fd, &wset);
  435                 } else if (ud[i].data_connected == CONN_DATA_LISTEN) {
  436                     FD_SET(ud[i].user_data_fd, &rset);
  437                     if (debug)
  438                         printf("setting fd %d for conn_data_listen\n",ud[i].user_data_fd);
  439                 }
  440                 
  441                 if ((ud[i].connected == CONN_YES) && (ud[i].u2s_i != ud[i].u2s_o)) {
  442                     FD_SET(ud[i].serv_fd, &wset);
  443                 }
  444                 if ((ud[i].u2s_i - ud[i].u2s_o) < 0)
  445                     sys_err("bug");
  446                 if (ud[i].s2u_i != ud[i].s2u_o) {
  447                     if ((memchr(ud[i].s2u_o, '\n', ud[i].s2u_i-ud[i].s2u_o) != NULL) ||
  448                         (ud[i].s2u_i == &ud[i].s2u_buf[S2U_SIZE]))
  449                         //(memchr(ud[i].s2u_o, '\n', ud[i].s2u_i-ud[i].s2u_o) != NULL)  /* should be? */
  450                         FD_SET(ud[i].user_fd, &wset); // memchr crap again
  451                 }
  452 
  453 
  454                 if (ud[i].retry)
  455                     FD_SET(ud[i].user_fd, &wset);
  456                 if (ud[i].retry_data)
  457                     FD_SET(ud[i].user_data_fd, &wset);
  458 
  459                 /* TLS connection negotiation */
  460 
  461                 if (ud[i].ssl_ctrl_fd_mode == TLS_READ) {
  462                     if (debug)
  463                         printf("TLS_READ: fd = %d\n", ud[i].serv_fd);
  464                     FD_SET(ud[i].serv_fd, &rset);
  465                     FD_CLR(ud[i].serv_fd, &wset);
  466                 } else if (ud[i].ssl_ctrl_fd_mode == TLS_WRITE) {
  467                     FD_SET(ud[i].serv_fd, &wset);
  468                     FD_CLR(ud[i].serv_fd, &rset);
  469                 }
  470 
  471                 if (ud[i].ssl_data_fd_mode == TLS_READ) {
  472                     if (debug)
  473                         printf("setting serv_data_fd (%d) in rset for TLS_READ\n", ud[i].serv_data_fd);
  474                     FD_SET(ud[i].serv_data_fd, &rset); 
  475                     FD_CLR(ud[i].serv_data_fd, &wset);
  476                 } else if (ud[i].ssl_data_fd_mode == TLS_WRITE) {
  477                     if (debug)
  478                         printf("setting serv_data_fd (%d) in wset for TLS_WRITE\n", ud[i].serv_data_fd);
  479                     FD_SET(ud[i].serv_data_fd, &wset);
  480                     FD_CLR(ud[i].serv_data_fd, &rset);
  481                 }
  482             } /* if fd */
  483 
  484         } /* for */
  485 
  486         /*
  487         max_fd = find_max_fd((dns_read_pipe > listen_fd) ?
  488             dns_read_pipe : listen_fd, ud, cfg_max_users);
  489          max_fd = find_max_fd(&rset, &wset);
  490 
  491         if (debug)
  492             printf("max_fd = %d\n",max_fd);
  493         */
  494 #if 0
  495         
  496         if (debug) {
  497             printf("listening for:\n");
  498             i = 0;
  499             if (FD_ISSET(ud[i].user_fd, &rset))
  500                 printf("user_fd readable\n");
  501             if (FD_ISSET(ud[i].user_fd, &wset))
  502                 printf("user_fd writable\n");
  503             if (FD_ISSET(ud[i].serv_fd, &rset))
  504                 printf("serv_fd readable\n");
  505             if (FD_ISSET(ud[i].serv_fd, &wset))
  506                 printf("serv_fd writable\n");
  507             if (FD_ISSET(ud[i].user_data_fd, &rset))
  508                 printf("user_data_fd (%d) readable\n", ud[i].user_data_fd);
  509             if (FD_ISSET(ud[i].user_data_fd, &wset))
  510                 printf("user_data_fd (%d) writable\n", ud[i].user_data_fd);
  511             if (FD_ISSET(ud[i].serv_data_fd, &rset))
  512                 printf("serv_data_fd (%d) readable\n", ud[i].serv_data_fd);
  513             if (FD_ISSET(ud[i].serv_data_fd, &wset))
  514                 printf("serv_data_fd (%d) writable\n", ud[i].serv_data_fd);
  515 #ifdef WIN32
  516             if (FD_ISSET(ud[i].serv_data_fd, &eset))
  517                 printf("serv_data_fd (%d) exception\n", ud[i].serv_data_fd);
  518             if (FD_ISSET(ud[i].serv_fd, &eset))
  519                 printf("serv_fd (%d) exception\n", ud[i].serv_fd);
  520 #endif
  521         }
  522 #endif
  523 
  524 #if defined(WIN32) || defined(__CYGWIN__)
  525         sel = select(FD_SETSIZE, &rset, &wset, &eset, NULL);
  526 #else
  527         sel = select(FD_SETSIZE, &rset, &wset, NULL, NULL);
  528 #endif
  529 #if 0
  530         if (debug) {
  531             printf("result is :\n");
  532             i = 0;
  533             if (FD_ISSET(ud[i].user_fd, &rset))
  534                 printf("user_fd readable\n");
  535             if (FD_ISSET(ud[i].user_fd, &wset))
  536                 printf("user_fd writable\n");
  537             if (FD_ISSET(ud[i].serv_fd, &rset))
  538                 printf("serv_fd readable\n");
  539             if (FD_ISSET(ud[i].serv_fd, &wset))
  540                 printf("serv_fd writable\n");
  541             if (FD_ISSET(ud[i].user_data_fd, &rset))
  542                 printf("user_fd readable\n");
  543             if (FD_ISSET(ud[i].user_data_fd, &wset))
  544                 printf("user_fd writable\n");
  545             if (FD_ISSET(ud[i].serv_data_fd, &rset))
  546                 printf("serv_fd readable\n");
  547             if (FD_ISSET(ud[i].serv_data_fd, &wset))
  548                 printf("serv_fd writable\n");
  549 #ifdef WIN32
  550             if (FD_ISSET(ud[i].serv_data_fd, &eset))
  551                 printf("serv_data_fd (%d) exception\n", ud[i].serv_data_fd);
  552             if (FD_ISSET(ud[i].serv_fd, &eset))
  553                 printf("serv_fd (%d) exception\n", ud[i].serv_fd);
  554 #endif
  555             if (FD_ISSET(dns_read_pipe, &rset))
  556                 printf("dns read pipe\n");
  557             if (FD_ISSET(listen_fd, &rset))
  558                 printf("listen_fd\n");
  559             printf("---------------------\n");
  560         } 
  561         if (sel == -1) {
  562 #ifdef WIN32
  563             printf("select failed because %d\n", WSAGetLastError());
  564 #endif
  565             sys_err("select");
  566         }   
  567 #endif
  568         if (debug)
  569             printf("selected\n");
  570         if (FD_ISSET(dns_read_pipe, &rset)) {
  571             if ( (bytes = read(dns_read_pipe, &dns, sizeof(dns)))
  572                 == sizeof(dns) ) {
  573                 if ((ud[dns.ud].user_fd != -1) && (ud[dns.ud].connected == CONN_DNS)) {
  574                     ud[dns.ud].serv_dns = dns; /* use for EPSV later */
  575                     setup_connect_2(&ud[dns.ud], &dns, 0);
  576                 }
  577             } else {
  578 #ifdef WIN32
  579                     printf("Exiting...\n");
  580                     WSACleanup();
  581                     if (in_service)
  582                         _endthread();
  583                     else
  584                         exit(0);
  585 #endif
  586                 sys_err("child died");
  587             }
  588         }
  589         if (FD_ISSET(listen_fd, &rset)) {
  590             memset(&sockaddr, 0, sizeof(sockaddr));
  591             socklen = sizeof(sockaddr);
  592             if ( (newsock = accept(listen_fd, &sockaddr, &socklen)) != -1) {
  593                 idx = find_free_slot(ud, cfg_max_users);
  594                 if (idx==-1) {
  595                     write(newsock, "No more users allowed.\r\n", 24);
  596                     close(newsock);
  597                 } else {
  598                     memset(&ud[idx], 0, sizeof(struct user_data));
  599                     ud[idx].u2s_i = ud[idx].u2s_o = ud[idx].u2s_buf;
  600                     ud[idx].s2u_i = ud[idx].s2u_o = ud[idx].s2u_buf;
  601                     ud[idx].user_ptr = ud[idx].user_input;
  602                     ud[idx].serv_ptr = ud[idx].serv_input;
  603                     ud[idx].connected = CONN_NO;
  604                     ud[idx].data_connected = CONN_NO;
  605                     ud[idx].serv_status = SERV_NONE;
  606                     ud[idx].serv_data_fd = -1;
  607                     ud[idx].user_fd = newsock;
  608                     ud[idx].ssl_data_fd_mode = TLS_NONE;
  609                     ud[idx].ssl_ctrl_fd_mode = TLS_NONE;
  610                     ud[idx].sec_level = sec_mode;
  611                     if (debug)
  612                         printf("connected to user\n");
  613                     snprintf(buffer, sizeof(buffer), "220 TLSWrap FTP Proxy Server (%s) ready.\r\n", TLSWRAP_VERSION_TEXT);
  614                     print_to_ud(&ud[idx], buffer);
  615                 }
  616             } /*else {
  617                 printf("accept failed\n");
  618             }*/
  619         }
  620         for(i = 0; i < cfg_max_users; i++) {
  621             remove_this = 0;
  622             serv_write = 0;
  623             if (ud[i].user_fd != -1) {
  624 
  625                 /* TLS section */
  626 
  627                 if (ud[i].serv_status == SERV_TLS) {
  628                     if (debug)
  629                         printf("checking TLS status\n");
  630                     if ( ((ud[i].ssl_ctrl_fd_mode == TLS_READ) && FD_ISSET(ud[i].serv_fd, &rset)) || 
  631                         ((ud[i].ssl_ctrl_fd_mode == TLS_WRITE) && FD_ISSET(ud[i].serv_fd, &wset)) ) {
  632                         tls_auth_cont(&ud[i], 0);
  633                         continue;
  634                     }
  635                 }
  636                 if (ud[i].data_connected == CONN_DATA_TLS) {
  637                     if (debug)
  638                         printf("checking conn_data_tls\n");
  639                     if ( ((ud[i].ssl_data_fd_mode == TLS_READ) && FD_ISSET(ud[i].serv_data_fd, &rset)) ||
  640                         ((ud[i].ssl_data_fd_mode == TLS_WRITE) && FD_ISSET(ud[i].serv_data_fd, &wset)) ) {
  641                         tls_auth_cont(&ud[i], 1);
  642                         continue;
  643                     }
  644                 }
  645 
  646                 /* TLS fd swapping */
  647 
  648                 if (ud[i].tls_status & TLS_CTRL) {
  649                     if (ud[i].ssl_ctrl_fd_mode == TLS_READ && FD_ISSET(ud[i].serv_fd, &rset) &&
  650                       ud[i].ssl_ctrl_func == TLS_WRITE) {
  651                         FD_SET(ud[i].serv_fd, &wset);
  652                         FD_CLR(ud[i].serv_fd, &rset);
  653                     } else if (ud[i].ssl_ctrl_fd_mode == TLS_WRITE && FD_ISSET(ud[i].serv_fd, &wset) &&
  654                      ud[i].ssl_ctrl_func == TLS_READ) {
  655                         FD_SET(ud[i].serv_fd, &rset);
  656                         FD_CLR(ud[i].serv_fd, &wset);
  657                     }
  658                 }
  659 
  660                 if (ud[i].tls_status & TLS_DATA) {
  661                     if (ud[i].ssl_data_fd_mode == TLS_READ && FD_ISSET(ud[i].serv_data_fd, &rset) &&
  662                       ud[i].ssl_data_func == TLS_WRITE) {
  663                         FD_SET(ud[i].serv_data_fd, &wset);
  664                         FD_CLR(ud[i].serv_data_fd, &rset);
  665                     } else if ( ud[i].ssl_data_fd_mode == TLS_WRITE && FD_ISSET(ud[i].serv_data_fd, &wset) &&
  666                         ud[i].ssl_data_func == TLS_READ) { 
  667                         FD_SET(ud[i].serv_data_fd, &rset);
  668                         FD_CLR(ud[i].serv_data_fd, &wset);
  669                     }       
  670                 }       
  671 
  672                 /* Read Section */
  673 
  674 
  675                 if (ud[i].connected == CONN_YES) {
  676                     if ((ud[i].retry && FD_ISSET(ud[i].user_fd,  &wset)) ||
  677                       FD_ISSET(ud[i].serv_fd, &rset)) {
  678                         if ((debug) && (ud[i].retry))
  679                             printf("retry set\n");
  680                         if (ud[i].tls_status & TLS_CTRL)
  681                             bytes = tls_read(&ud[i], ud[i].s2u_i, &ud[i].s2u_buf[S2U_SIZE] - ud[i].s2u_i,0);
  682                         else
  683                             bytes = read(ud[i].serv_fd, ud[i].s2u_i, &ud[i].s2u_buf[S2U_SIZE] - ud[i].s2u_i);
  684 
  685                         ud[i].retry = 0;
  686                         if (bytes < 0) {
  687 #ifdef WIN32
  688                             errno = WSAGetLastError();
  689 #endif 
  690                             if (errno != EWOULDBLOCK) {
  691                                 perror("server_read");
  692                                 user_close(&ud[i]); /* inte data_close! */
  693                             }
  694                             continue;
  695                         } else if ((bytes == 0) && ((&ud[i].s2u_buf[S2U_SIZE] - ud[i].s2u_i) > 0)){
  696                             FD_CLR(ud[i].serv_fd,&wset);
  697                             FD_CLR(ud[i].user_fd,&rset);
  698                             user_close(&ud[i]);
  699                             remove_this = 1;
  700                         } else {
  701                             if (bytes == (&ud[i].s2u_buf[S2U_SIZE] - ud[i].s2u_i)) {
  702                                 if (debug)
  703                                     printf("filled buffer - retrying\n");
  704                                 ud[i].retry = 1;
  705                             }
  706                             ud[i].s2u_i += bytes;
  707                             FD_SET(ud[i].user_fd, &wset); /* Try to write this data below */
  708                             if (debug) {
  709                                 printf("read %lu bytes from server control, trying to write later\n", (unsigned long)bytes);
  710                                 //printf("%s\n", (char*)(ud[i].s2u_i-bytes));
  711                             }
  712                         }
  713                     }
  714                 }
  715                 
  716                 if (ud[i].data_connected == CONN_DATA_OK)  {
  717                     if ((ud[i].retry_data && FD_ISSET(ud[i].user_data_fd,  &wset)) ||
  718                     FD_ISSET(ud[i].serv_data_fd, &rset)) {
  719                         if (ud[i].tls_status & TLS_DATA)
  720                             bytes = tls_read(&ud[i], ud[i].ds2c_i, 
  721                                 &ud[i].ds2c_buf[DBUF_SIZE] - ud[i].ds2c_i, 1);
  722                         else
  723                             bytes = read(ud[i].serv_data_fd, ud[i].ds2c_i,
  724                                 &ud[i].ds2c_buf[DBUF_SIZE] - ud[i].ds2c_i);
  725                         ud[i].retry_data = 0;
  726                         if (bytes < 0) {
  727 #ifdef WIN32
  728                             errno = WSAGetLastError();
  729 #endif
  730                             if (errno != EWOULDBLOCK) {
  731 #ifdef WIN32
  732                                 printf("bytes = %u, err = %d\n", bytes, WSAGetLastError());
  733 #endif
  734                                 perror("server_data_read1");
  735                                 data_close(&ud[i]);
  736                             }
  737                             continue;
  738                         } else if ((bytes == 0) && ((&ud[i].ds2c_buf[DBUF_SIZE] - ud[i].ds2c_i) > 0) ){
  739                                 ud[i].serv_data_close = CLOSE_READ;
  740                                 if (debug)
  741                                     printf("setting CLOSE_READ in serv_data_close\n");
  742                                 if (ud[i].serv_read_cnt > 0) /* va? */
  743                                     ud[i].user_data_close = CLOSE_READ;
  744                         } else {
  745                             if (bytes == (&ud[i].ds2c_buf[DBUF_SIZE] - ud[i].ds2c_i)) {
  746                                 if (debug)
  747                                     printf("filled data buffer - retrying\n");
  748                                 ud[i].retry_data = 1;
  749                             }
  750                             if (debug)
  751                                 printf("read %ld bytes from serv_data_fd\n", (long)bytes);
  752                             ud[i].ds2c_i += bytes;
  753                             ud[i].serv_read_cnt += bytes;
  754                             FD_SET(ud[i].user_data_fd, &wset); /* Try to write this data below */ 
  755                         }
  756                     }
  757 
  758                     if (FD_ISSET(ud[i].user_data_fd, &rset)) {
  759                         bytes = read(ud[i].user_data_fd, ud[i].dc2s_i,
  760                             &ud[i].dc2s_buf[DBUF_SIZE] - ud[i].dc2s_i);
  761                         if (bytes < 0) {
  762 #ifdef WIN32
  763                             errno = WSAGetLastError();
  764 #endif
  765                             if (errno != EWOULDBLOCK) {
  766 #ifdef WIN32
  767                                 printf("bytes = %u, err = %d\n", bytes, WSAGetLastError());
  768 #endif
  769                                 perror("server_data_read");
  770                                 data_close(&ud[i]);
  771                             }
  772                             continue;
  773                         } else if (bytes == 0) {
  774                                 ud[i].user_data_close = CLOSE_READ;
  775                                 if (ud[i].user_read_cnt > 0)
  776                                     ud[i].serv_data_close = CLOSE_READ;
  777                                 if (debug)
  778                                     printf("setting CLOSE_READ in user_data_close\n");
  779                         } else {
  780                             if (debug)
  781                                 printf("read %ld bytes from user_data_fd\n", (long)bytes);
  782                             ud[i].dc2s_i += bytes;
  783                             ud[i].user_read_cnt += bytes;
  784                             FD_SET(ud[i].serv_data_fd, &wset); /* Try to write this data below */
  785                         }
  786                     }
  787 
  788                 }
  789                 if (ud[i].connected == CONN_YES && ud[i].data_connected == CONN_DATA_LISTEN) {
  790                     if (debug)
  791                         printf("conn_data_listen\n");
  792                     if (FD_ISSET(ud[i].user_data_fd, &rset)) {
  793                             if (debug)
  794                                 printf("trying to accept user data connection\n");
  795                             if ( (newsock = accept(ud[i].user_data_fd, &sockaddr, &socklen)) != -1) {
  796                                 close(ud[i].user_data_fd);
  797                                 if (ud[i].active) {
  798                                     ud[i].user_data_fd = ud[i].serv_data_fd;
  799                                     ud[i].serv_data_fd = newsock;
  800                                     get_remote_ip(newsock, remoteip, sizeof(remoteip));
  801                                     strlcpy(ud[i].serv_data_host, remoteip, sizeof(ud[i].serv_data_host));
  802                                 } else
  803                                     ud[i].user_data_fd = newsock;
  804                                 ud[i].data_connected = CONN_DATA_OK;
  805                                 ud[i].ssl_data_fd_mode = TLS_NONE;
  806                                 ud[i].dc2s_i = ud[i].dc2s_o = ud[i].dc2s_buf;
  807                                 ud[i].ds2c_i = ud[i].ds2c_o = ud[i].ds2c_buf;
  808                                 ud[i].serv_data_close = CLOSE_NONE;
  809                                 ud[i].user_data_close = CLOSE_NONE;
  810                                 ud[i].user_read_cnt = 0;
  811                                 ud[i].serv_read_cnt = 0;
  812 /*  
  813                                 (void)setsockopt(ud[i].user_data_fd, SOL_SOCKET, SO_SNDLOWAT, 
  814                                     &tcpsndlowat, sizeof(tcpsndlowat));
  815                                 (void)setsockopt(ud[i].serv_data_fd, SOL_SOCKET, SO_SNDLOWAT,
  816                                     &tcpsndlowat, sizeof(tcpsndlowat));
  817                                 (void)setsockopt(ud[i].user_data_fd, SOL_SOCKET, SO_SNDBUF,
  818                                     &tcpbufsize, sizeof(tcpbufsize));
  819                                 (void)setsockopt(ud[i].serv_data_fd, SOL_SOCKET, SO_SNDBUF,
  820                                     &tcpbufsize, sizeof(tcpbufsize));
  821                                 (void)setsockopt(ud[i].user_data_fd, SOL_SOCKET, SO_RCVBUF,
  822                                     &tcpbufsize, sizeof(tcpbufsize));
  823                                 (void)setsockopt(ud[i].serv_data_fd, SOL_SOCKET, SO_RCVBUF,
  824                                     &tcpbufsize, sizeof(tcpbufsize));
  825 */
  826 
  827                                 ud[i].data_connected = CONN_DATA_TLS;
  828                                 if (debug)
  829                                     printf("accept'ed client data connection\n");
  830                                 tls_auth(&ud[i], 1, ucertspath, cfg_cafile);
  831                             } else
  832                                 printf("accept failed\n");
  833                     }
  834                 }
  835 
  836                 if (ud[i].user_fd != -1) {
  837                     if (FD_ISSET(ud[i].user_fd,&rset)) {
  838                         if ((bytes = read(ud[i].user_fd, ud[i].u2s_i, &ud[i].u2s_buf[U2S_SIZE]
  839                           - ud[i].u2s_i)) < 0) {
  840 #ifdef WIN32
  841                             errno = WSAGetLastError();
  842 #endif
  843                             if (errno != EWOULDBLOCK) {
  844                                 if (errno != ECONNRESET) {
  845                                     perror("user_read");
  846 #ifdef WIN32
  847                                     printf("WSAGETLastError = %d\n", errno);
  848 #endif
  849                                 }
  850                                 user_close(&ud[i]);
  851                             }
  852                         } else if (bytes==0) {
  853                             user_close(&ud[i]);
  854                         } else {
  855                             ud[i].u2s_i += bytes;
  856                             serv_write = 1;
  857                         }
  858                         if (ud[i].u2s_i - ud[i].u2s_o < 0)
  859                             sys_err("bug1");
  860                     }
  861                 }
  862 
  863                 /* Write Section */
  864 
  865                 if (ud[i].data_connected == CONN_DATA_OK)  {
  866                     if (FD_ISSET(ud[i].serv_data_fd, &wset) && ((bytes = ud[i].dc2s_i - ud[i].dc2s_o) > 0)) {
  867                         if (ud[i].tls_status & TLS_DATA)
  868                             bytesW = tls_write(&ud[i], ud[i].dc2s_o, bytes, 1);
  869                         else
  870                             bytesW = write(ud[i].serv_data_fd, ud[i].dc2s_o, bytes);
  871 #ifdef WIN32
  872                         errno = WSAGetLastError();
  873 #endif
  874                         if (bytesW < 0) {
  875                             if (errno == EPIPE) {
  876                                 ud[i].serv_data_close = CLOSE_WRITE;
  877                             }
  878                             else if (errno != EWOULDBLOCK) {
  879                                 perror("serv_data_fd_write");
  880                                 data_close(&ud[i]);
  881                             }
  882                             continue;
  883                         } else {
  884                             if (debug)
  885                                 printf("wrote %ld bytes to serv_data_fd (of %ld requested)\n", 
  886                                     (long)bytesW, (long)bytes);
  887                             ud[i].dc2s_o += bytesW;
  888                             if (ud[i].dc2s_o == ud[i].dc2s_i)
  889                                 ud[i].dc2s_o = ud[i].dc2s_i = ud[i].dc2s_buf;
  890                         }
  891                     }
  892                         
  893                     if (FD_ISSET(ud[i].user_data_fd, &wset) && ((bytes = ud[i].ds2c_i - ud[i].ds2c_o) > 0)) {
  894                         bytesW = write(ud[i].user_data_fd, ud[i].ds2c_o, bytes);
  895                         if (bytesW < 0) {
  896 #ifdef WIN32
  897                             errno = WSAGetLastError();
  898 #endif
  899                             if (errno == EPIPE) {
  900                                 ud[i].user_data_close = CLOSE_WRITE;
  901                             }
  902                             if (errno != EWOULDBLOCK) {
  903                                 perror("user_data_fd_write");
  904                                 data_close(&ud[i]);
  905                             }
  906                             continue;
  907                         } else {
  908                              if (debug)
  909                                 printf("wrote %ld bytes to user_data_fd (of %ld requested)\n",
  910                                     (long)bytesW, (long)bytes);
  911                             ud[i].ds2c_o += bytesW;
  912                             if (ud[i].ds2c_o == ud[i].ds2c_i)
  913                                 ud[i].ds2c_o = ud[i].ds2c_i = ud[i].ds2c_buf;
  914                         }
  915                     }
  916 
  917                     if ( ( (ud[i].data_direction == DATA_DOWN && ud[i].serv_data_close == CLOSE_READ) ||
  918                          (ud[i].data_direction == DATA_UP && ud[i].user_data_close == CLOSE_READ) || 
  919                          (ud[i].serv_data_close == CLOSE_READ && ud[i].user_data_close == CLOSE_READ) ) &&
  920                          (ud[i].ds2c_o == ud[i].ds2c_i && ud[i].dc2s_o == ud[i].dc2s_i) )  {
  921                         data_close(&ud[i]);
  922                         if (debug)
  923                             printf("data connection totally closed\n");
  924                     }
  925 /*
  926                     if ( ud[i].ctrl_close ) &&
  927                          (ud[i].u2s_o == ud[i].u2s_i && ud[i].s2u_o == ud[i].s2u_i) )  {
  928                         user_close(&ud[i]);
  929                         if (debug)
  930                             printf("user connection totally closed\n");
  931                     }
  932 */
  933                 } /* ud[i].data_connected == CONN_DATA_OK */
  934 
  935                 /*
  936                 if ((ud[i].connected == CONN_YES) || (ud[i].connected == CONN_IN_PROG)) {
  937                     if (FD_ISSET(ud[i].serv_fd, &wset) && ((bytes = ud[i].u2s_i - ud[i].u2s_o) > 0))
  938                         serv_write = 1;
  939                 } else
  940                 */
  941                 if ((bytes = ud[i].u2s_i - ud[i].u2s_o) > 0) 
  942                     serv_write = 1; /* OK? */
  943 
  944                 if (serv_write) {
  945                     if (ud[i].connected != CONN_YES) {
  946                         if ( (&ud[i].user_input[BUF_SIZE] - ud[i].user_ptr) >= bytes) {
  947                             /* There is room in the user buffer for this data */
  948                             memcpy(ud[i].user_ptr, ud[i].u2s_o, bytes);
  949                             ud[i].u2s_o += bytes;
  950                             ud[i].user_ptr += bytes;
  951                             if (ud[i].u2s_o == ud[i].u2s_i)
  952                                 ud[i].u2s_o = ud[i].u2s_i = ud[i].u2s_buf;
  953                         } else
  954                             printf("could not copy user input to user buffer\n");
  955                     } else {
  956                         if (ud[i].prot == 'P') {
  957                             intercept_user_buf(&ud[i], ud[i].u2s_o, &bytes);
  958                             if (bytes == 0)
  959                                 ud[i].u2s_i = ud[i].u2s_o;
  960                         }
  961                         if (ud[i].tls_status & TLS_CTRL) 
  962                             bytesW = tls_write(&ud[i], ud[i].u2s_o, bytes, 0);
  963                         else
  964                             bytesW = write(ud[i].serv_fd, ud[i].u2s_o, bytes);
  965                         if (bytesW < 0) {
  966 #ifdef WIN32
  967                             errno = WSAGetLastError();
  968 #endif
  969                             if (errno != EWOULDBLOCK) {
  970                                 perror("server_write");
  971                                 user_close(&ud[i]);
  972                             }
  973                             continue;
  974                         } else {
  975                             ud[i].u2s_o += bytesW;
  976                             if (ud[i].u2s_o == ud[i].u2s_i)
  977                                 ud[i].u2s_o = ud[i].u2s_i = ud[i].u2s_buf;
  978                         }
  979                     }
  980                 }
  981 
  982                 if ((bytes = ud[i].s2u_i - ud[i].s2u_o) > 0) {
  983                     if (debug) {
  984                         printf("there are %lu bytes to write", (unsigned long)bytes);
  985                         if ((ud[i].serv_status == SERV_FLOW || ud[i].connected != CONN_YES ) && FD_ISSET(ud[i].user_fd,&wset) && 
  986                         (memchr(ud[i].s2u_o, '\n', bytes) == NULL)) {
  987                             printf(", but didn't write them because memchr!");
  988                         }
  989                         printf("\n");
  990                     }
  991                     if ((ud[i].serv_status == SERV_FLOW || ud[i].connected != CONN_YES ) && FD_ISSET(ud[i].user_fd,&wset) && 
  992                         ((memchr(ud[i].s2u_o, '\n', bytes) != NULL) || (ud[i].s2u_i == &ud[i].s2u_buf[S2U_SIZE])) 
  993                         ) {
  994                             if (debug)
  995                                 printf("calling change_serv_buf\n");
  996                             if (change_serv_buf(&ud[i], ud[i].s2u_o)) {
  997                                 bytesW = bytes;
  998                             } else 
  999                                 bytesW = write(ud[i].user_fd, ud[i].s2u_o, bytes);
 1000 
 1001                         if (bytesW < 0) {
 1002 #ifdef WIN32
 1003                             errno = WSAGetLastError();
 1004 #endif
 1005                             if (errno != EWOULDBLOCK) {
 1006                                 perror("user_write");
 1007                                 user_close(&ud[i]);
 1008                             }
 1009                         } else {
 1010                             ud[i].s2u_o+=bytesW;
 1011                             if (debug) {
 1012                                 printf("wrote %lu bytes to user_fd\n", (unsigned long)bytesW);
 1013                                 //printf("%s\n", (char*)(ud[i].s2u_o-bytesW));
 1014                             }
 1015                             if (ud[i].s2u_o==ud[i].s2u_i)
 1016                                 ud[i].s2u_o = ud[i].s2u_i = ud[i].s2u_buf;
 1017                         }
 1018                     }  else if ( (ud[i].serv_status != SERV_FLOW) && (ud[i].connected==CONN_YES)) {
 1019                         if ( (&ud[i].serv_input[BUF_SIZE] - ud[i].serv_ptr) >= bytes) {
 1020                             /* There is room in the server buffer for this data */
 1021                             if (debug)
 1022                                 printf("eating server bytes\n");
 1023                             memcpy(ud[i].serv_ptr, ud[i].s2u_o, bytes);
 1024                             ud[i].s2u_o += bytes;
 1025                             ud[i].serv_ptr += bytes;
 1026                             if (ud[i].s2u_o==ud[i].s2u_i)
 1027                                 ud[i].s2u_o = ud[i].s2u_i = ud[i].s2u_buf;
 1028                         } else
 1029                             printf("could not copy server input to server buffer\n");
 1030                     } 
 1031                 }
 1032                 
 1033 
 1034                 /* Nonblocking connect to a remote data port gave a result */
 1035 
 1036 
 1037                 if (ud[i].data_connected == CONN_IN_PROG && ud[i].connected == CONN_YES) {
 1038 #if defined WIN32 || defined __CYGWIN__
 1039                     if (FD_ISSET(ud[i].serv_data_fd,&eset) || 
 1040 #else
 1041                     if (FD_ISSET(ud[i].serv_data_fd,&rset) ||
 1042 #endif
 1043                         FD_ISSET(ud[i].serv_data_fd,&wset)) {
 1044                         if (debug)
 1045                             printf("nonblocking data connect\n"); 
 1046 #if defined WIN32 || defined __CYGWIN__
 1047                         conn_err = FD_ISSET(ud[i].serv_data_fd,&eset);
 1048 #else
 1049                         sock_errlen = sizeof(sock_err);
 1050                         conn_err = 0;
 1051                         if (getsockopt(ud[i].serv_data_fd, SOL_SOCKET, SO_ERROR, &sock_err,
 1052                             &sock_errlen) < 0)
 1053                             conn_err = 1; /* Solaris pending error */
 1054                         else if (sock_err)
 1055                             conn_err = 1; /* BSD pending error */
 1056                         if (!conn_err) {
 1057                             if (read(ud[i].serv_data_fd, fakebuf, 0) < 0)
 1058                                 conn_err = 1; /* We are not connected */
 1059                         }
 1060 #endif                   
 1061                         if (debug)
 1062                             printf("checking if %d is connected\n", ud[i].serv_data_fd);
 1063 
 1064                         if (conn_err) {
 1065                             if (debug)
 1066                                 printf("data port connection failed\n");
 1067                             print_to_ud(&ud[i],"421 Connection failed.\r\n");
 1068                             data_close(&ud[i]);
 1069                         } else {
 1070                             ud[i].data_connected = CONN_YES;
 1071                             if (debug)
 1072                                 printf("data port connected\n");
 1073                             open_local_dataport(&ud[i]);
 1074                         }
 1075 
 1076                     }
 1077                 }
 1078 
 1079                 /* Nonblocking connect to remote server gave a result */
 1080 
 1081                 if (ud[i].connected == CONN_IN_PROG)
 1082 #if defined WIN32 || defined __CYGWIN__
 1083                     if (FD_ISSET(ud[i].serv_fd,&eset) ||
 1084 #else
 1085                     if (FD_ISSET(ud[i].serv_fd,&rset) ||
 1086 #endif
 1087                         FD_ISSET(ud[i].serv_fd,&wset)) {
 1088 #if defined WIN32 || defined __CYGWIN__
 1089                         conn_err = FD_ISSET(ud[i].serv_fd,&eset);
 1090 #else
 1091                         sock_errlen = sizeof(sock_err);
 1092                         conn_err = 0;
 1093                         if (getsockopt(ud[i].serv_fd, SOL_SOCKET, SO_ERROR, &sock_err,
 1094                             &sock_errlen) < 0)
 1095                             conn_err = 1; /* Solaris pending error */
 1096                         else if (sock_err)
 1097                             conn_err = 1; /* BSD pending error */
 1098 
 1099                         if (!conn_err) {
 1100                             if (read(ud[i].serv_fd, fakebuf, 0) < 0)
 1101                                 conn_err = 1; /* We are not connected */
 1102                         }
 1103 #endif
 1104                         if (conn_err) {
 1105                             print_to_ud(&ud[i],"421 Connection failed.\r\n");
 1106                             user_close(&ud[i]);
 1107                             if (debug)
 1108                                 printf("failed connecting to server\n");
 1109                         } else {
 1110                             if (ud[i].issl) {
 1111                             // Implicit SSL crap
 1112                                 ud[i].serv_status = SERV_TLS;
 1113                                 tls_auth(&ud[i], 0, ucertspath, cfg_cafile);
 1114                             } else {
 1115                                 ud[i].serv_status = SERV_CONN;
 1116                             }
 1117                             ud[i].connected = CONN_YES;
 1118                             if (debug)
 1119                                 printf("connected to server\n");
 1120                         }
 1121                     }
 1122             }
 1123             if (remove_this == 1)
 1124                     ud[i].user_fd = -1;
 1125             
 1126             else    {
 1127                 if (ud[i].user_input != ud[i].user_ptr) {
 1128                     /* if (debug)
 1129                         printf("parse_buf\n"); */
 1130                     while (parse_buf(&ud[i], i, dns_write_pipe, token) == 0);
 1131                 }
 1132                 if (ud[i].serv_input != ud[i].serv_ptr) {
 1133                     /* if (debug)
 1134                         printf("parse_serv_buf\n"); */
 1135                     while (parse_serv_buf(&ud[i], i, ucertspath, cfg_cafile) == 0);
 1136                 }
 1137             }
 1138         }
 1139     }
 1140 }
 1141