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, pipe01[2], pipe02[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
main(int argc,char * argv[])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)
service_execution_thread(LPDWORD param)134 DWORD service_execution_thread(LPDWORD param) {
135 return main2(serv_param.argc, serv_param.argv);
136 }
137 #endif
138
main2(int argc,char * argv[])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(pipe01)) sys_err("pipe01");
274 if (pipe(pipe02)) sys_err("pipe02");
275
276 if ( (childpid = fork()) == 0) {
277 close(pipe01[1]);
278 close(pipe02[0]);
279 dns_helper(pipe01[0], pipe02[1]);
280 } else {
281 close(pipe01[0]);
282 close(pipe02[1]);
283 }
284
285 dns_write_pipe = pipe01[1];
286 dns_read_pipe = pipe02[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 pipe01[0] = setup_connect("127.0.0.1", port, &lport, &conn_res);
299 if (conn_res == 0) { /* connected OK */
300 if ((pipe01[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(pipe01[0], &wset)) {
307 if (FD_ISSET(temp_sock, &rset)) {
308 if ((pipe01[1] = accept(temp_sock, NULL, NULL)) == INVALID_SOCKET){
309 printf("setup error for fake pipe01: %d\n", WSAGetLastError());
310 exit(0);
311 }
312 } else sys_err("could not connect to local pipe 1");
313
314
315 pipe02[1] = setup_connect("127.0.0.1", port, &lport, &conn_res);
316 if (conn_res == 0) { /* connected OK */
317 if ((pipe02[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 ((pipe02[0] = accept(temp_sock, NULL, NULL)) == INVALID_SOCKET) {
325 printf("setup error for fake pipe02: %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 = pipe01[1];
334 dns_read_pipe = pipe02[0];
335
336 /* Turn off non-blocking for sockets to be used in the DNS helper */
337
338 sockarg = 0;
339
340 if (ioctlsocket(pipe01[0], FIONBIO, &sockarg) == SOCKET_ERROR) {
341 printf("ioctlsocket 1 failed because %d\n", WSAGetLastError());
342 exit(-1);
343 }
344
345 if (ioctlsocket(pipe02[1], FIONBIO, &sockarg) == SOCKET_ERROR) {
346 printf("ioctlsocket 2 failed because %d\n", WSAGetLastError());
347 exit(-1);
348 }
349 arg[0] = pipe01[0];
350 arg[1] = pipe02[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
1142