1 /* $KAME: ftp.c,v 1.24 2005/03/16 05:05:48 itojun Exp $ */
4 * Copyright (C) 1997 and 1998 WIDE Project.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the project nor the names of its contributors
16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission.
19 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 #include <sys/param.h>
35 #include <sys/types.h>
36 #include <sys/socket.h>
37 #include <sys/ioctl.h>
51 #include <netinet/in.h>
52 #include <arpa/inet.h>
57 static char rbuf
[MSS
];
58 static char sbuf
[MSS
];
59 static int passivemode
= 0;
60 static int wport4
= -1; /* listen() to active */
61 static int wport6
= -1; /* listen() to passive */
62 static int port4
= -1; /* active: inbound passive: outbound */
63 static int port6
= -1; /* active: outbound passive: inbound */
64 static struct sockaddr_storage data4
; /* server data address */
65 static struct sockaddr_storage data6
; /* client data address */
66 static int epsvall
= 0;
68 enum state
{ NONE
, LPRT
, EPRT
, LPSV
, EPSV
};
70 static int ftp_activeconn(void);
71 static int ftp_passiveconn(void);
72 static int ftp_copy(int, int);
73 static int ftp_copyresult(int, int, enum state
);
74 static int ftp_copycommand(int, int, enum state
*);
77 ftp_relay(int ctl6
, int ctl4
)
85 enum state state
= NONE
;
88 syslog(LOG_INFO
, "starting ftp control connection");
93 pfd
[0].events
= POLLIN
;
95 pfd
[1].events
= POLLIN
;
98 pfd
[2].events
= POLLIN
;
103 pfd
[3].events
= POLLIN
;
109 pfd
[4].events
= POLLIN
;
114 pfd
[5].events
= POLLIN
;
118 pfd
[4].fd
= pfd
[5].fd
= -1;
119 pfd
[4].events
= pfd
[5].events
= 0;
125 if (ctl4
>= FD_SETSIZE
)
126 exit_failure("descriptor too big");
127 FD_SET(ctl4
, &readfds
);
129 if (ctl6
>= FD_SETSIZE
)
130 exit_failure("descriptor too big");
131 FD_SET(ctl6
, &readfds
);
132 maxfd
= (ctl6
> maxfd
) ? ctl6
: maxfd
;
134 if (port4
>= FD_SETSIZE
)
135 exit_failure("descriptor too big");
136 FD_SET(port4
, &readfds
);
137 maxfd
= (port4
> maxfd
) ? port4
: maxfd
;
140 if (port6
>= FD_SETSIZE
)
141 exit_failure("descriptor too big");
142 FD_SET(port6
, &readfds
);
143 maxfd
= (port6
> maxfd
) ? port6
: maxfd
;
147 if (wport4
>= FD_SETSIZE
)
148 exit_failure("descriptor too big");
149 FD_SET(wport4
, &readfds
);
150 maxfd
= (wport4
> maxfd
) ? wport4
: maxfd
;
153 if (wport6
>= FD_SETSIZE
)
154 exit_failure("descriptor too big");
155 FD_SET(wport6
, &readfds
);
156 maxfd
= (wport6
> maxfd
) ? wport6
: maxfd
;
160 tv
.tv_sec
= FAITH_TIMEOUT
;
164 error
= poll(pfd
, sizeof(pfd
)/sizeof(pfd
[0]), tv
.tv_sec
* 1000);
166 error
= select(maxfd
+ 1, &readfds
, NULL
, NULL
, &tv
);
170 exit_failure("poll: %s", strerror(errno
));
172 exit_failure("select: %s", strerror(errno
));
176 exit_failure("connection timeout");
179 * The order of the following checks does (slightly) matter.
180 * It is important to visit all checks (do not use "continue"),
181 * otherwise some of the pipe may become full and we cannot
185 if (pfd
[1].revents
& POLLIN
)
187 if (FD_ISSET(ctl6
, &readfds
))
191 * copy control connection from the client.
192 * command translation is necessary.
194 error
= ftp_copycommand(ctl6
, ctl4
, &state
);
198 else if (error
== 0) {
201 exit_success("terminating ftp control connection");
206 if (pfd
[0].revents
& POLLIN
)
208 if (FD_ISSET(ctl4
, &readfds
))
212 * copy control connection from the server
213 * translation of result code is necessary.
215 error
= ftp_copyresult(ctl4
, ctl6
, state
);
219 else if (error
== 0) {
222 exit_success("terminating ftp control connection");
227 if (0 <= port4
&& 0 <= port6
&& (pfd
[2].revents
& POLLIN
))
229 if (0 <= port4
&& 0 <= port6
&& FD_ISSET(port4
, &readfds
))
233 * copy data connection.
234 * no special treatment necessary.
237 if (pfd
[2].revents
& POLLIN
)
239 if (FD_ISSET(port4
, &readfds
))
241 error
= ftp_copy(port4
, port6
);
249 syslog(LOG_INFO
, "terminating data connection");
256 if (0 <= port4
&& 0 <= port6
&& (pfd
[3].revents
& POLLIN
))
258 if (0 <= port4
&& 0 <= port6
&& FD_ISSET(port6
, &readfds
))
262 * copy data connection.
263 * no special treatment necessary.
266 if (pfd
[3].revents
& POLLIN
)
268 if (FD_ISSET(port6
, &readfds
))
270 error
= ftp_copy(port6
, port4
);
278 syslog(LOG_INFO
, "terminating data connection");
286 if (wport4
&& (pfd
[4].revents
& POLLIN
))
288 if (wport4
&& FD_ISSET(wport4
, &readfds
))
292 * establish active data connection from the server.
297 if (wport4
&& (pfd
[5].revents
& POLLIN
))
299 if (wport6
&& FD_ISSET(wport6
, &readfds
))
303 * establish passive data connection from the client.
311 exit_failure("%s", strerror(errno
));
320 struct pollfd pfd
[1];
324 struct timeval timeout
;
327 /* get active connection from server */
330 pfd
[0].events
= POLLIN
;
333 if (wport4
>= FD_SETSIZE
)
334 exit_failure("descriptor too big");
335 FD_SET(wport4
, &set
);
337 timeout
.tv_sec
= 120;
341 if (poll(pfd
, sizeof(pfd
)/sizeof(pfd
[0]), timeout
.tv_sec
* 1000) == 0 ||
342 (port4
= accept(wport4
, (struct sockaddr
*)&data4
, &n
)) < 0)
344 if (select(wport4
+ 1, &set
, NULL
, NULL
, &timeout
) == 0 ||
345 (port4
= accept(wport4
, (struct sockaddr
*)&data4
, &n
)) < 0)
350 syslog(LOG_INFO
, "active mode data connection failed");
354 /* ask active connection to client */
355 sa
= (struct sockaddr
*)&data6
;
356 port6
= socket(sa
->sa_family
, SOCK_STREAM
, 0);
361 syslog(LOG_INFO
, "active mode data connection failed");
364 error
= connect(port6
, sa
, sa
->sa_len
);
369 port6
= port4
= wport4
= -1;
370 syslog(LOG_INFO
, "active mode data connection failed");
374 syslog(LOG_INFO
, "active mode data connection established");
384 struct pollfd pfd
[1];
388 struct timeval timeout
;
391 /* get passive connection from client */
394 pfd
[0].events
= POLLIN
;
397 if (wport6
>= FD_SETSIZE
)
398 exit_failure("descriptor too big");
399 FD_SET(wport6
, &set
);
401 timeout
.tv_sec
= 120;
405 if (poll(pfd
, sizeof(pfd
)/sizeof(pfd
[0]), timeout
.tv_sec
* 1000) == 0 ||
406 (port6
= accept(wport6
, (struct sockaddr
*)&data6
, &len
)) < 0)
408 if (select(wport6
+ 1, &set
, NULL
, NULL
, &timeout
) == 0 ||
409 (port6
= accept(wport6
, (struct sockaddr
*)&data6
, &len
)) < 0)
414 syslog(LOG_INFO
, "passive mode data connection failed");
418 /* ask passive connection to server */
419 sa
= (struct sockaddr
*)&data4
;
420 port4
= socket(sa
->sa_family
, SOCK_STREAM
, 0);
425 syslog(LOG_INFO
, "passive mode data connection failed");
428 error
= connect(port4
, sa
, sa
->sa_len
);
433 wport6
= port4
= port6
= -1;
434 syslog(LOG_INFO
, "passive mode data connection failed");
438 syslog(LOG_INFO
, "passive mode data connection established");
443 ftp_copy(int src
, int dst
)
445 int error
, atmark
, n
;
447 /* OOB data handling */
448 error
= ioctl(src
, SIOCATMARK
, &atmark
);
449 if (error
!= -1 && atmark
== 1) {
450 n
= read(src
, rbuf
, 1);
453 send(dst
, rbuf
, n
, MSG_OOB
);
455 n
= read(src
, rbuf
, sizeof(rbuf
));
463 n
= read(src
, rbuf
, sizeof(rbuf
));
474 exit_failure("%s", strerror(errno
));
476 return 0; /* to make gcc happy */
480 ftp_copyresult(int src
, int dst
, enum state state
)
482 int error
, atmark
, n
;
489 /* OOB data handling */
490 error
= ioctl(src
, SIOCATMARK
, &atmark
);
491 if (error
!= -1 && atmark
== 1) {
492 n
= read(src
, rbuf
, 1);
495 send(dst
, rbuf
, n
, MSG_OOB
);
497 n
= read(src
, rbuf
, sizeof(rbuf
));
505 n
= read(src
, rbuf
, sizeof(rbuf
));
514 for (i
= 0; i
< 3; i
++) {
529 /* param points to first non-command token, if any */
530 while (*param
&& isspace(*param
))
537 if (!passivemode
&& rbuf
[0] == '1') {
538 if (ftp_activeconn() < 0) {
539 n
= snprintf(rbuf
, sizeof(rbuf
),
540 "425 Cannot open data connetion\r\n");
541 if (n
< 0 || n
>= sizeof(rbuf
))
550 /* expecting "200 PORT command successful." */
552 p
= strstr(rbuf
, "PORT");
554 p
[0] = (state
== LPRT
) ? 'L' : 'E';
566 * expecting "227 Entering Passive Mode (x,x,x,x,x,x,x)"
567 * (in some cases result comes without paren)
578 unsigned int ho
[4], po
[2];
579 struct sockaddr_in
*sin
;
580 struct sockaddr_in6
*sin6
;
584 * PASV result -> LPSV/EPSV result
587 while (*p
&& *p
!= '(' && !isdigit(*p
)) /*)*/
590 goto passivefail0
; /*XXX*/
593 n
= sscanf(p
, "%u,%u,%u,%u,%u,%u",
594 &ho
[0], &ho
[1], &ho
[2], &ho
[3], &po
[0], &po
[1]);
596 goto passivefail0
; /*XXX*/
598 /* keep PORT parameter */
599 memset(&data4
, 0, sizeof(data4
));
600 sin
= (struct sockaddr_in
*)&data4
;
601 sin
->sin_len
= sizeof(*sin
);
602 sin
->sin_family
= AF_INET
;
603 sin
->sin_addr
.s_addr
= 0;
604 for (n
= 0; n
< 4; n
++) {
605 sin
->sin_addr
.s_addr
|=
606 htonl((ho
[n
] & 0xff) << ((3 - n
) * 8));
608 sin
->sin_port
= htons(((po
[0] & 0xff) << 8) | (po
[1] & 0xff));
610 /* get ready for passive data connection */
611 memset(&data6
, 0, sizeof(data6
));
612 sin6
= (struct sockaddr_in6
*)&data6
;
613 sin6
->sin6_len
= sizeof(*sin6
);
614 sin6
->sin6_family
= AF_INET6
;
615 wport6
= socket(sin6
->sin6_family
, SOCK_STREAM
, 0);
618 n
= snprintf(sbuf
, sizeof(sbuf
),
619 "500 could not translate from PASV\r\n");
620 if (n
< 0 || n
>= sizeof(sbuf
))
629 error
= setsockopt(wport6
, IPPROTO_IPV6
, IPV6_FAITH
,
632 exit_failure("setsockopt(IPV6_FAITH): %s", strerror(errno
));
635 error
= bind(wport6
, (struct sockaddr
*)sin6
, sin6
->sin6_len
);
641 error
= listen(wport6
, 1);
648 /* transmit LPSV or EPSV */
650 * addr from dst, port from wport6
653 error
= getsockname(wport6
, (struct sockaddr
*)&data6
, &len
);
659 sin6
= (struct sockaddr_in6
*)&data6
;
660 port
= sin6
->sin6_port
;
663 error
= getsockname(dst
, (struct sockaddr
*)&data6
, &len
);
669 sin6
= (struct sockaddr_in6
*)&data6
;
670 sin6
->sin6_port
= port
;
673 a
= (char *)&sin6
->sin6_addr
;
674 p
= (char *)&sin6
->sin6_port
;
675 n
= snprintf(sbuf
, sizeof(sbuf
),
676 "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",
677 6, 16, UC(a
[0]), UC(a
[1]), UC(a
[2]), UC(a
[3]),
678 UC(a
[4]), UC(a
[5]), UC(a
[6]), UC(a
[7]),
679 UC(a
[8]), UC(a
[9]), UC(a
[10]), UC(a
[11]),
680 UC(a
[12]), UC(a
[13]), UC(a
[14]), UC(a
[15]),
681 2, UC(p
[0]), UC(p
[1]));
682 if (n
< 0 || n
>= sizeof(sbuf
))
689 n
= snprintf(sbuf
, sizeof(sbuf
),
690 "229 Entering Extended Passive Mode (|||%d|)\r\n",
691 ntohs(sin6
->sin6_port
));
692 if (n
< 0 || n
>= sizeof(sbuf
))
703 exit_failure("%s", strerror(errno
));
705 return 0; /* to make gcc happy */
709 ftp_copycommand(int src
, int dst
, enum state
*state
)
711 int error
, atmark
, n
;
713 unsigned int af
, hal
, ho
[16], pal
, po
[2];
716 struct sockaddr_in
*sin
;
717 struct sockaddr_in6
*sin6
;
722 /* OOB data handling */
723 error
= ioctl(src
, SIOCATMARK
, &atmark
);
724 if (error
!= -1 && atmark
== 1) {
725 n
= read(src
, rbuf
, 1);
728 send(dst
, rbuf
, n
, MSG_OOB
);
730 n
= read(src
, rbuf
, sizeof(rbuf
));
738 n
= read(src
, rbuf
, sizeof(rbuf
));
753 for (i
= 0; i
< 4; i
++) {
755 /* invalid command */
759 *q
++ = islower(*p
) ? toupper(*p
) : *p
;
763 /* invalid command */
769 /* param points to first non-command token, if any */
770 while (*param
&& isspace(*param
))
777 if (strcmp(cmd
, "LPRT") == 0 && param
) {
787 wport4
= wport6
= port4
= port6
= -1;
790 n
= snprintf(sbuf
, sizeof(sbuf
), "501 %s disallowed in EPSV ALL\r\n",
792 if (n
< 0 || n
>= sizeof(sbuf
))
800 "%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u",
801 &af
, &hal
, &ho
[0], &ho
[1], &ho
[2], &ho
[3],
802 &ho
[4], &ho
[5], &ho
[6], &ho
[7],
803 &ho
[8], &ho
[9], &ho
[10], &ho
[11],
804 &ho
[12], &ho
[13], &ho
[14], &ho
[15],
805 &pal
, &po
[0], &po
[1]);
806 if (n
!= 21 || af
!= 6 || hal
!= 16|| pal
!= 2) {
807 n
= snprintf(sbuf
, sizeof(sbuf
),
808 "501 illegal parameter to LPRT\r\n");
809 if (n
< 0 || n
>= sizeof(sbuf
))
816 /* keep LPRT parameter */
817 memset(&data6
, 0, sizeof(data6
));
818 sin6
= (struct sockaddr_in6
*)&data6
;
819 sin6
->sin6_len
= sizeof(*sin6
);
820 sin6
->sin6_family
= AF_INET6
;
821 for (n
= 0; n
< 16; n
++)
822 sin6
->sin6_addr
.s6_addr
[n
] = ho
[n
];
823 sin6
->sin6_port
= htons(((po
[0] & 0xff) << 8) | (po
[1] & 0xff));
826 /* get ready for active data connection */
828 error
= getsockname(dst
, (struct sockaddr
*)&data4
, &len
);
831 n
= snprintf(sbuf
, sizeof(sbuf
),
832 "500 could not translate to PORT\r\n");
833 if (n
< 0 || n
>= sizeof(sbuf
))
839 if (((struct sockaddr
*)&data4
)->sa_family
!= AF_INET
)
841 sin
= (struct sockaddr_in
*)&data4
;
843 wport4
= socket(sin
->sin_family
, SOCK_STREAM
, 0);
846 error
= bind(wport4
, (struct sockaddr
*)sin
, sin
->sin_len
);
852 error
= listen(wport4
, 1);
861 error
= getsockname(wport4
, (struct sockaddr
*)&data4
, &len
);
867 if (((struct sockaddr
*)&data4
)->sa_family
!= AF_INET
) {
872 sin
= (struct sockaddr_in
*)&data4
;
873 a
= (char *)&sin
->sin_addr
;
874 p
= (char *)&sin
->sin_port
;
875 n
= snprintf(sbuf
, sizeof(sbuf
), "PORT %d,%d,%d,%d,%d,%d\r\n",
876 UC(a
[0]), UC(a
[1]), UC(a
[2]), UC(a
[3]),
878 if (n
< 0 || n
>= sizeof(sbuf
))
885 } else if (strcmp(cmd
, "EPRT") == 0 && param
) {
889 char *afp
, *hostp
, *portp
;
890 struct addrinfo hints
, *res
;
898 wport4
= wport6
= port4
= port6
= -1;
901 n
= snprintf(sbuf
, sizeof(sbuf
), "501 %s disallowed in EPSV ALL\r\n",
903 if (n
< 0 || n
>= sizeof(sbuf
))
911 ch
= *p
++; /* boundary character */
913 while (*p
&& *p
!= ch
)
917 n
= snprintf(sbuf
, sizeof(sbuf
),
918 "501 illegal parameter to EPRT\r\n");
919 if (n
< 0 || n
>= sizeof(sbuf
))
927 while (*p
&& *p
!= ch
)
933 while (*p
&& *p
!= ch
)
939 n
= sscanf(afp
, "%d", &af
);
940 if (n
!= 1 || af
!= 2) {
941 n
= snprintf(sbuf
, sizeof(sbuf
),
942 "501 unsupported address family to EPRT\r\n");
943 if (n
< 0 || n
>= sizeof(sbuf
))
949 memset(&hints
, 0, sizeof(hints
));
950 hints
.ai_family
= AF_UNSPEC
;
951 hints
.ai_socktype
= SOCK_STREAM
;
952 hints
.ai_protocol
= IPPROTO_TCP
;
953 error
= getaddrinfo(hostp
, portp
, &hints
, &res
);
955 n
= snprintf(sbuf
, sizeof(sbuf
),
956 "501 EPRT: %s\r\n", gai_strerror(error
));
957 if (n
< 0 || n
>= sizeof(sbuf
))
964 n
= snprintf(sbuf
, sizeof(sbuf
),
965 "501 EPRT: %s resolved to multiple addresses\r\n", hostp
);
966 if (n
< 0 || n
>= sizeof(sbuf
))
974 memcpy(&data6
, res
->ai_addr
, res
->ai_addrlen
);
978 } else if (strcmp(cmd
, "LPSV") == 0 && !param
) {
988 wport4
= wport6
= port4
= port6
= -1;
991 n
= snprintf(sbuf
, sizeof(sbuf
), "501 %s disallowed in EPSV ALL\r\n",
993 if (n
< 0 || n
>= sizeof(sbuf
))
1001 n
= snprintf(sbuf
, sizeof(sbuf
), "PASV\r\n");
1002 if (n
< 0 || n
>= sizeof(sbuf
))
1005 write(dst
, sbuf
, n
);
1007 passivemode
= 0; /* to be set to 1 later */
1009 } else if (strcmp(cmd
, "EPSV") == 0 && !param
) {
1017 wport4
= wport6
= port4
= port6
= -1;
1019 n
= snprintf(sbuf
, sizeof(sbuf
), "PASV\r\n");
1020 if (n
< 0 || n
>= sizeof(sbuf
))
1023 write(dst
, sbuf
, n
);
1025 passivemode
= 0; /* to be set to 1 later */
1027 } else if (strcmp(cmd
, "EPSV") == 0 && param
1028 && strncasecmp(param
, "ALL", 3) == 0 && isspace(param
[3])) {
1033 n
= snprintf(sbuf
, sizeof(sbuf
), "200 EPSV ALL command successful.\r\n");
1034 if (n
< 0 || n
>= sizeof(sbuf
))
1037 write(src
, sbuf
, n
);
1039 } else if (strcmp(cmd
, "PORT") == 0 || strcmp(cmd
, "PASV") == 0) {
1043 n
= snprintf(sbuf
, sizeof(sbuf
), "502 %s not implemented.\r\n", cmd
);
1044 if (n
< 0 || n
>= sizeof(sbuf
))
1047 write(src
, sbuf
, n
);
1049 } else if (passivemode
1050 && (strcmp(cmd
, "STOR") == 0
1051 || strcmp(cmd
, "STOU") == 0
1052 || strcmp(cmd
, "RETR") == 0
1053 || strcmp(cmd
, "LIST") == 0
1054 || strcmp(cmd
, "NLST") == 0
1055 || strcmp(cmd
, "APPE") == 0)) {
1057 * commands with data transfer. need to care about passive
1058 * mode data connection.
1061 if (ftp_passiveconn() < 0) {
1062 n
= snprintf(sbuf
, sizeof(sbuf
), "425 Cannot open data connetion\r\n");
1063 if (n
< 0 || n
>= sizeof(sbuf
))
1066 write(src
, sbuf
, n
);
1068 /* simply relay the command */
1069 write(dst
, rbuf
, n
);
1075 /* simply relay it */
1077 write(dst
, rbuf
, n
);
1082 exit_failure("%s", strerror(errno
));
1084 return 0; /* to make gcc happy */