1 /* $NetBSD: ftp.c,v 1.17 2006/05/24 21:47:25 christos Exp $ */
2 /* $KAME: ftp.c,v 1.23 2003/08/19 21:20:33 itojun Exp $ */
5 * Copyright (C) 1997 and 1998 WIDE Project.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. Neither the name of the project nor the names of its contributors
17 * may be used to endorse or promote products derived from this software
18 * without specific prior written permission.
20 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 #include <sys/param.h>
34 #include <sys/types.h>
35 #include <sys/socket.h>
36 #include <sys/ioctl.h>
48 #include <netinet/in.h>
49 #include <arpa/inet.h>
54 static char rbuf
[MSS
];
55 static char sbuf
[MSS
];
56 static int passivemode
= 0;
57 static int wport4
= -1; /* listen() to active */
58 static int wport6
= -1; /* listen() to passive */
59 static int port4
= -1; /* active: inbound passive: outbound */
60 static int port6
= -1; /* active: outbound passive: inbound */
61 static struct sockaddr_storage data4
; /* server data address */
62 static struct sockaddr_storage data6
; /* client data address */
63 static int epsvall
= 0;
65 enum state
{ NONE
, LPRT
, EPRT
, LPSV
, EPSV
};
67 static int ftp_activeconn
__P((void));
68 static int ftp_passiveconn
__P((void));
69 static int ftp_copy
__P((int, int));
70 static int ftp_copyresult
__P((int, int, enum state
));
71 static int ftp_copycommand
__P((int, int, enum state
*));
74 ftp_relay(int ctl6
, int ctl4
)
78 enum state state
= NONE
;
81 syslog(LOG_INFO
, "starting ftp control connection");
85 pfd
[0].events
= POLLIN
;
87 pfd
[1].events
= POLLIN
;
90 pfd
[2].events
= POLLIN
;
95 pfd
[3].events
= POLLIN
;
101 pfd
[4].events
= POLLIN
;
106 pfd
[5].events
= POLLIN
;
110 pfd
[4].fd
= pfd
[5].fd
= -1;
111 pfd
[4].events
= pfd
[5].events
= 0;
113 tv
.tv_sec
= FAITH_TIMEOUT
;
116 error
= poll(pfd
, sizeof(pfd
)/sizeof(pfd
[0]), tv
.tv_sec
* 1000);
118 exit_failure("poll: %s", strerror(errno
));
121 exit_failure("connection timeout");
124 * The order of the following checks does (slightly) matter.
125 * It is important to visit all checks (do not use "continue"),
126 * otherwise some of the pipe may become full and we cannot
129 if (pfd
[1].revents
& POLLIN
)
132 * copy control connection from the client.
133 * command translation is necessary.
135 error
= ftp_copycommand(ctl6
, ctl4
, &state
);
139 else if (error
== 0) {
142 exit_success("terminating ftp control connection");
146 if (pfd
[0].revents
& POLLIN
)
149 * copy control connection from the server
150 * translation of result code is necessary.
152 error
= ftp_copyresult(ctl4
, ctl6
, state
);
156 else if (error
== 0) {
159 exit_success("terminating ftp control connection");
163 if (0 <= port4
&& 0 <= port6
&& (pfd
[2].revents
& POLLIN
))
166 * copy data connection.
167 * no special treatment necessary.
169 if (pfd
[2].revents
& POLLIN
)
170 error
= ftp_copy(port4
, port6
);
183 syslog(LOG_INFO
, "terminating data connection");
189 if (0 <= port4
&& 0 <= port6
&& (pfd
[3].revents
& POLLIN
))
192 * copy data connection.
193 * no special treatment necessary.
195 if (pfd
[3].revents
& POLLIN
)
196 error
= ftp_copy(port6
, port4
);
209 syslog(LOG_INFO
, "terminating data connection");
216 if (wport4
&& (pfd
[4].revents
& POLLIN
))
219 * establish active data connection from the server.
223 if (wport4
&& (pfd
[5].revents
& POLLIN
))
226 * establish passive data connection from the client.
234 exit_failure("%s", strerror(errno
));
242 struct pollfd pfd
[1];
243 struct timeval timeout
;
246 /* get active connection from server */
248 pfd
[0].events
= POLLIN
;
249 timeout
.tv_sec
= 120;
252 if (poll(pfd
, sizeof(pfd
)/sizeof(pfd
[0]), timeout
.tv_sec
* 1000) == 0 ||
253 (port4
= accept(wport4
, (struct sockaddr
*)&data4
, &n
)) < 0)
257 syslog(LOG_INFO
, "active mode data connection failed");
261 /* ask active connection to client */
262 sa
= (struct sockaddr
*)&data6
;
263 port6
= socket(sa
->sa_family
, SOCK_STREAM
, 0);
268 syslog(LOG_INFO
, "active mode data connection failed");
271 error
= connect(port6
, sa
, sa
->sa_len
);
276 port6
= port4
= wport4
= -1;
277 syslog(LOG_INFO
, "active mode data connection failed");
281 syslog(LOG_INFO
, "active mode data connection established");
290 struct pollfd pfd
[1];
291 struct timeval timeout
;
294 /* get passive connection from client */
296 pfd
[0].events
= POLLIN
;
297 timeout
.tv_sec
= 120;
300 if (poll(pfd
, sizeof(pfd
)/sizeof(pfd
[0]), timeout
.tv_sec
* 1000) == 0 ||
301 (port6
= accept(wport6
, (struct sockaddr
*)&data6
, &len
)) < 0)
305 syslog(LOG_INFO
, "passive mode data connection failed");
309 /* ask passive connection to server */
310 sa
= (struct sockaddr
*)&data4
;
311 port4
= socket(sa
->sa_family
, SOCK_STREAM
, 0);
316 syslog(LOG_INFO
, "passive mode data connection failed");
319 error
= connect(port4
, sa
, sa
->sa_len
);
324 wport6
= port4
= port6
= -1;
325 syslog(LOG_INFO
, "passive mode data connection failed");
329 syslog(LOG_INFO
, "passive mode data connection established");
334 ftp_copy(int src
, int dst
)
336 int error
, atmark
, n
;
338 /* OOB data handling */
339 error
= ioctl(src
, SIOCATMARK
, &atmark
);
340 if (error
!= -1 && atmark
== 1) {
341 n
= read(src
, rbuf
, 1);
344 send(dst
, rbuf
, n
, MSG_OOB
);
346 n
= read(src
, rbuf
, sizeof(rbuf
));
354 n
= read(src
, rbuf
, sizeof(rbuf
));
365 exit_failure("%s", strerror(errno
));
367 return 0; /* to make gcc happy */
371 ftp_copyresult(int src
, int dst
, enum state state
)
373 int error
, atmark
, n
;
380 /* OOB data handling */
381 error
= ioctl(src
, SIOCATMARK
, &atmark
);
382 if (error
!= -1 && atmark
== 1) {
383 n
= read(src
, rbuf
, 1);
386 send(dst
, rbuf
, n
, MSG_OOB
);
388 n
= read(src
, rbuf
, sizeof(rbuf
));
396 n
= read(src
, rbuf
, sizeof(rbuf
));
405 for (i
= 0; i
< 3; i
++) {
406 if (!isdigit((unsigned char)*p
)) {
413 if (!isspace((unsigned char)*p
)) {
420 /* param points to first non-command token, if any */
421 while (*param
&& isspace((unsigned char)*param
))
428 if (!passivemode
&& rbuf
[0] == '1') {
429 if (ftp_activeconn() < 0) {
430 n
= snprintf(rbuf
, sizeof(rbuf
),
431 "425 Cannot open data connetion\r\n");
432 if (n
< 0 || n
>= (int)sizeof(rbuf
))
441 /* expecting "200 PORT command successful." */
443 p
= strstr(rbuf
, "PORT");
445 p
[0] = (state
== LPRT
) ? 'L' : 'E';
457 * expecting "227 Entering Passive Mode (x,x,x,x,x,x,x)"
458 * (in some cases result comes without paren)
469 unsigned int ho
[4], po
[2];
470 struct sockaddr_in
*sin
;
471 struct sockaddr_in6
*sin6
;
475 * PASV result -> LPSV/EPSV result
478 while (*p
&& *p
!= '(' && !isdigit((unsigned char)*p
)) /*)*/
481 goto passivefail0
; /*XXX*/
484 n
= sscanf(p
, "%u,%u,%u,%u,%u,%u",
485 &ho
[0], &ho
[1], &ho
[2], &ho
[3], &po
[0], &po
[1]);
487 goto passivefail0
; /*XXX*/
489 /* keep PORT parameter */
490 memset(&data4
, 0, sizeof(data4
));
491 sin
= (struct sockaddr_in
*)&data4
;
492 sin
->sin_len
= sizeof(*sin
);
493 sin
->sin_family
= AF_INET
;
494 sin
->sin_addr
.s_addr
= 0;
495 for (n
= 0; n
< 4; n
++) {
496 sin
->sin_addr
.s_addr
|=
497 htonl((ho
[n
] & 0xff) << ((3 - n
) * 8));
499 sin
->sin_port
= htons(((po
[0] & 0xff) << 8) | (po
[1] & 0xff));
501 /* get ready for passive data connection */
502 memset(&data6
, 0, sizeof(data6
));
503 sin6
= (struct sockaddr_in6
*)&data6
;
504 sin6
->sin6_len
= sizeof(*sin6
);
505 sin6
->sin6_family
= AF_INET6
;
506 wport6
= socket(sin6
->sin6_family
, SOCK_STREAM
, 0);
509 n
= snprintf(sbuf
, sizeof(sbuf
),
510 "500 could not translate from PASV\r\n");
511 if (n
< 0 || n
>= (int)sizeof(sbuf
))
520 error
= setsockopt(wport6
, IPPROTO_IPV6
, IPV6_FAITH
,
523 exit_failure("setsockopt(IPV6_FAITH): %s", strerror(errno
));
526 error
= bind(wport6
, (struct sockaddr
*)sin6
, sin6
->sin6_len
);
532 error
= listen(wport6
, 1);
539 /* transmit LPSV or EPSV */
541 * addr from dst, port from wport6
544 error
= getsockname(wport6
, (struct sockaddr
*)&data6
, &len
);
550 sin6
= (struct sockaddr_in6
*)&data6
;
551 port
= sin6
->sin6_port
;
554 error
= getsockname(dst
, (struct sockaddr
*)&data6
, &len
);
560 sin6
= (struct sockaddr_in6
*)&data6
;
561 sin6
->sin6_port
= port
;
564 a
= (char *)&sin6
->sin6_addr
;
565 p
= (char *)&sin6
->sin6_port
;
566 n
= snprintf(sbuf
, sizeof(sbuf
),
567 "228 Entering Long Passive Mode (%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d)\r\n",
568 6, 16, UC(a
[0]), UC(a
[1]), UC(a
[2]), UC(a
[3]),
569 UC(a
[4]), UC(a
[5]), UC(a
[6]), UC(a
[7]),
570 UC(a
[8]), UC(a
[9]), UC(a
[10]), UC(a
[11]),
571 UC(a
[12]), UC(a
[13]), UC(a
[14]), UC(a
[15]),
572 2, UC(p
[0]), UC(p
[1]));
573 if (n
< 0 || n
>= (int)sizeof(sbuf
))
580 n
= snprintf(sbuf
, sizeof(sbuf
),
581 "229 Entering Extended Passive Mode (|||%d|)\r\n",
582 ntohs(sin6
->sin6_port
));
583 if (n
< 0 || n
>= (int)sizeof(sbuf
))
594 exit_failure("%s", strerror(errno
));
596 return 0; /* to make gcc happy */
600 ftp_copycommand(int src
, int dst
, enum state
*state
)
602 int error
, atmark
, n
;
604 unsigned int af
, hal
, ho
[16], pal
, po
[2];
607 struct sockaddr_in
*sin
;
608 struct sockaddr_in6
*sin6
;
613 /* OOB data handling */
614 error
= ioctl(src
, SIOCATMARK
, &atmark
);
615 if (error
!= -1 && atmark
== 1) {
616 n
= read(src
, rbuf
, 1);
619 send(dst
, rbuf
, n
, MSG_OOB
);
621 n
= read(src
, rbuf
, sizeof(rbuf
));
629 n
= read(src
, rbuf
, sizeof(rbuf
));
644 for (i
= 0; i
< 4; i
++) {
645 if (!isalpha((unsigned char)*p
)) {
646 /* invalid command */
650 *q
++ = islower((unsigned char)*p
) ? toupper((unsigned char)*p
) : *p
;
653 if (!isspace((unsigned char)*p
)) {
654 /* invalid command */
660 /* param points to first non-command token, if any */
661 while (*param
&& isspace((unsigned char)*param
))
668 if (strcmp(cmd
, "LPRT") == 0 && param
) {
678 wport4
= wport6
= port4
= port6
= -1;
681 n
= snprintf(sbuf
, sizeof(sbuf
), "501 %s disallowed in EPSV ALL\r\n",
683 if (n
< 0 || n
>= (int)sizeof(sbuf
))
691 "%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u",
692 &af
, &hal
, &ho
[0], &ho
[1], &ho
[2], &ho
[3],
693 &ho
[4], &ho
[5], &ho
[6], &ho
[7],
694 &ho
[8], &ho
[9], &ho
[10], &ho
[11],
695 &ho
[12], &ho
[13], &ho
[14], &ho
[15],
696 &pal
, &po
[0], &po
[1]);
697 if (n
!= 21 || af
!= 6 || hal
!= 16|| pal
!= 2) {
698 n
= snprintf(sbuf
, sizeof(sbuf
),
699 "501 illegal parameter to LPRT\r\n");
700 if (n
< 0 || n
>= (int)sizeof(sbuf
))
707 /* keep LPRT parameter */
708 memset(&data6
, 0, sizeof(data6
));
709 sin6
= (struct sockaddr_in6
*)&data6
;
710 sin6
->sin6_len
= sizeof(*sin6
);
711 sin6
->sin6_family
= AF_INET6
;
712 for (n
= 0; n
< 16; n
++)
713 sin6
->sin6_addr
.s6_addr
[n
] = ho
[n
];
714 sin6
->sin6_port
= htons(((po
[0] & 0xff) << 8) | (po
[1] & 0xff));
717 /* get ready for active data connection */
719 error
= getsockname(dst
, (struct sockaddr
*)&data4
, &len
);
722 n
= snprintf(sbuf
, sizeof(sbuf
),
723 "500 could not translate to PORT\r\n");
724 if (n
< 0 || n
>= (int)sizeof(sbuf
))
730 if (((struct sockaddr
*)&data4
)->sa_family
!= AF_INET
)
732 sin
= (struct sockaddr_in
*)&data4
;
734 wport4
= socket(sin
->sin_family
, SOCK_STREAM
, 0);
737 error
= bind(wport4
, (struct sockaddr
*)sin
, sin
->sin_len
);
743 error
= listen(wport4
, 1);
752 error
= getsockname(wport4
, (struct sockaddr
*)&data4
, &len
);
758 if (((struct sockaddr
*)&data4
)->sa_family
!= AF_INET
) {
763 sin
= (struct sockaddr_in
*)&data4
;
764 a
= (char *)&sin
->sin_addr
;
765 p
= (char *)&sin
->sin_port
;
766 n
= snprintf(sbuf
, sizeof(sbuf
), "PORT %d,%d,%d,%d,%d,%d\r\n",
767 UC(a
[0]), UC(a
[1]), UC(a
[2]), UC(a
[3]),
769 if (n
< 0 || n
>= (int)sizeof(sbuf
))
776 } else if (strcmp(cmd
, "EPRT") == 0 && param
) {
780 char *afp
, *hostp
, *portp
;
781 struct addrinfo hints
, *res
;
789 wport4
= wport6
= port4
= port6
= -1;
792 n
= snprintf(sbuf
, sizeof(sbuf
), "501 %s disallowed in EPSV ALL\r\n",
794 if (n
< 0 || n
>= (int)sizeof(sbuf
))
802 ch
= *p
++; /* boundary character */
804 while (*p
&& *p
!= ch
)
808 n
= snprintf(sbuf
, sizeof(sbuf
),
809 "501 illegal parameter to EPRT\r\n");
810 if (n
< 0 || n
>= (int)sizeof(sbuf
))
818 while (*p
&& *p
!= ch
)
824 while (*p
&& *p
!= ch
)
830 n
= sscanf(afp
, "%d", &af
);
831 if (n
!= 1 || af
!= 2) {
832 n
= snprintf(sbuf
, sizeof(sbuf
),
833 "501 unsupported address family to EPRT\r\n");
834 if (n
< 0 || n
>= (int)sizeof(sbuf
))
840 memset(&hints
, 0, sizeof(hints
));
841 hints
.ai_family
= AF_UNSPEC
;
842 hints
.ai_socktype
= SOCK_STREAM
;
843 hints
.ai_protocol
= IPPROTO_TCP
;
844 error
= getaddrinfo(hostp
, portp
, &hints
, &res
);
846 n
= snprintf(sbuf
, sizeof(sbuf
),
847 "501 EPRT: %s\r\n", gai_strerror(error
));
848 if (n
< 0 || n
>= (int)sizeof(sbuf
))
855 n
= snprintf(sbuf
, sizeof(sbuf
),
856 "501 EPRT: %s resolved to multiple addresses\r\n", hostp
);
857 if (n
< 0 || n
>= (int)sizeof(sbuf
))
865 memcpy(&data6
, res
->ai_addr
, res
->ai_addrlen
);
869 } else if (strcmp(cmd
, "LPSV") == 0 && !param
) {
879 wport4
= wport6
= port4
= port6
= -1;
882 n
= snprintf(sbuf
, sizeof(sbuf
), "501 %s disallowed in EPSV ALL\r\n",
884 if (n
< 0 || n
>= (int)sizeof(sbuf
))
892 n
= snprintf(sbuf
, sizeof(sbuf
), "PASV\r\n");
893 if (n
< 0 || n
>= (int)sizeof(sbuf
))
898 passivemode
= 0; /* to be set to 1 later */
900 } else if (strcmp(cmd
, "EPSV") == 0 && !param
) {
908 wport4
= wport6
= port4
= port6
= -1;
910 n
= snprintf(sbuf
, sizeof(sbuf
), "PASV\r\n");
911 if (n
< 0 || n
>= (int)sizeof(sbuf
))
916 passivemode
= 0; /* to be set to 1 later */
918 } else if (strcmp(cmd
, "EPSV") == 0 && param
919 && strncasecmp(param
, "ALL", 3) == 0 && isspace((unsigned char)param
[3])) {
924 n
= snprintf(sbuf
, sizeof(sbuf
), "200 EPSV ALL command successful.\r\n");
925 if (n
< 0 || n
>= (int)sizeof(sbuf
))
930 } else if (strcmp(cmd
, "PORT") == 0 || strcmp(cmd
, "PASV") == 0) {
934 n
= snprintf(sbuf
, sizeof(sbuf
), "502 %s not implemented.\r\n", cmd
);
935 if (n
< 0 || n
>= (int)sizeof(sbuf
))
940 } else if (passivemode
941 && (strcmp(cmd
, "STOR") == 0
942 || strcmp(cmd
, "STOU") == 0
943 || strcmp(cmd
, "RETR") == 0
944 || strcmp(cmd
, "LIST") == 0
945 || strcmp(cmd
, "NLST") == 0
946 || strcmp(cmd
, "APPE") == 0)) {
948 * commands with data transfer. need to care about passive
949 * mode data connection.
952 if (ftp_passiveconn() < 0) {
953 n
= snprintf(sbuf
, sizeof(sbuf
), "425 Cannot open data connetion\r\n");
954 if (n
< 0 || n
>= (int)sizeof(sbuf
))
959 /* simply relay the command */
966 /* simply relay it */
973 exit_failure("%s", strerror(errno
));
975 return 0; /* to make gcc happy */