2 Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003,
3 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
5 This file is part of GNU Wget.
7 GNU Wget is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
12 GNU Wget is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with Wget. If not, see <http://www.gnu.org/licenses/>.
20 In addition, as a special exception, the Free Software Foundation
21 gives permission to link the code of its release of Wget with the
22 OpenSSL project's "OpenSSL" library (or with modified versions of it
23 that use the same license as the "OpenSSL" library), and distribute
24 the linked executables. You must obey the GNU General Public License
25 in all respects for all of the code used other than "OpenSSL". If you
26 modify this file, you may extend this exception to your version of the
27 file, but you are not obligated to do so. If you do not wish to do
28 so, delete this exception statement from your version. */
47 char ftp_last_respline[128];
50 /* Get the response of FTP server and allocate enough room to handle
51 it. <CR> and <LF> characters are stripped from the line, and the
52 line is 0-terminated. All the response lines but the last one are
53 skipped. The last line is determined as described in RFC959.
55 If the line is successfully read, FTPOK is returned, and *ret_line
56 is assigned a freshly allocated line. Otherwise, FTPRERR is
57 returned, and the value of *ret_line should be ignored. */
60 ftp_response (int fd, char **ret_line)
65 char *line = fd_read_line (fd);
69 /* Strip trailing CRLF before printing the line, so that
70 escnonprint doesn't include bogus \012 and \015. */
71 p = strchr (line, '\0');
72 if (p > line && p[-1] == '\n')
74 if (p > line && p[-1] == '\r')
77 if (opt.server_response)
78 logprintf (LOG_NOTQUIET, "%s\n", escnonprint (line));
80 DEBUGP (("%s\n", escnonprint (line)));
82 /* The last line of output is the one that begins with "ddd ". */
83 if (c_isdigit (line[0]) && c_isdigit (line[1]) && c_isdigit (line[2])
86 strncpy (ftp_last_respline, line, sizeof (ftp_last_respline));
87 ftp_last_respline[sizeof (ftp_last_respline) - 1] = '\0';
95 /* Returns the malloc-ed FTP request, ending with <CR><LF>, printing
96 it if printing is required. If VALUE is NULL, just use
99 ftp_request (const char *command, const char *value)
104 /* Check for newlines in VALUE (possibly injected by the %0A URL
105 escape) making the callers inadvertently send multiple FTP
106 commands at once. Without this check an attacker could
107 intentionally redirect to ftp://server/fakedir%0Acommand.../
108 and execute arbitrary FTP command on a remote FTP server. */
109 if (strpbrk (value, "\r\n"))
111 /* Copy VALUE to the stack and modify CR/LF to space. */
113 STRDUP_ALLOCA (defanged, value);
114 for (p = defanged; *p; p++)
115 if (*p == '\r' || *p == '\n')
117 DEBUGP (("\nDetected newlines in %s \"%s\"; changing to %s \"%s\"\n",
118 command, escnonprint (value), command, escnonprint (defanged)));
119 /* Make VALUE point to the defanged copy of the string. */
122 res = concat_strings (command, " ", value, "\r\n", (char *) 0);
125 res = concat_strings (command, "\r\n", (char *) 0);
126 if (opt.server_response)
128 /* Hack: don't print out password. */
129 if (strncmp (res, "PASS", 4) != 0)
130 logprintf (LOG_ALWAYS, "--> %s\n", res);
132 logputs (LOG_ALWAYS, "--> PASS Turtle Power!\n\n");
135 DEBUGP (("\n--> %s\n", res));
139 /* Sends the USER and PASS commands to the server, to control
140 connection socket csock. */
142 ftp_login (int csock, const char *acc, const char *pass)
145 char *request, *respline;
149 err = ftp_response (csock, &respline);
152 if (*respline != '2')
158 /* Send USER username. */
159 request = ftp_request ("USER", acc);
160 nwritten = fd_write (csock, request, strlen (request), -1);
167 /* Get appropriate response. */
168 err = ftp_response (csock, &respline);
171 /* An unprobable possibility of logging without a password. */
172 if (*respline == '2')
177 /* Else, only response 3 is appropriate. */
178 if (*respline != '3')
181 return FTPLOGREFUSED;
185 static const char *skey_head[] = {
190 const char *seed = NULL;
192 for (i = 0; i < countof (skey_head); i++)
194 int l = strlen (skey_head[i]);
195 if (0 == strncasecmp (skey_head[i], respline, l))
203 int skey_sequence = 0;
205 /* Extract the sequence from SEED. */
206 for (; c_isdigit (*seed); seed++)
207 skey_sequence = 10 * skey_sequence + *seed - '0';
213 return FTPLOGREFUSED;
215 /* Replace the password with the SKEY response to the
217 pass = skey_response (skey_sequence, seed, pass);
220 #endif /* ENABLE_OPIE */
222 /* Send PASS password. */
223 request = ftp_request ("PASS", pass);
224 nwritten = fd_write (csock, request, strlen (request), -1);
231 /* Get appropriate response. */
232 err = ftp_response (csock, &respline);
235 if (*respline != '2')
246 ip_address_to_port_repr (const ip_address *addr, int port, char *buf,
251 assert (addr->family == AF_INET);
252 /* buf must contain the argument of PORT (of the form a,b,c,d,e,f). */
253 assert (buflen >= 6 * 4);
255 ptr = IP_INADDR_DATA (addr);
256 snprintf (buf, buflen, "%d,%d,%d,%d,%d,%d", ptr[0], ptr[1],
257 ptr[2], ptr[3], (port & 0xff00) >> 8, port & 0xff);
258 buf[buflen - 1] = '\0';
261 /* Bind a port and send the appropriate PORT command to the FTP
262 server. Use acceptport after RETR, to get the socket of data
265 ftp_port (int csock, int *local_sock)
268 char *request, *respline;
272 /* Must contain the argument of PORT (of the form a,b,c,d,e,f). */
273 char bytes[6 * 4 + 1];
275 /* Get the address of this side of the connection. */
276 if (!socket_ip_address (csock, &addr, ENDPOINT_LOCAL))
279 assert (addr.family == AF_INET);
281 /* Setting port to 0 lets the system choose a free port. */
285 *local_sock = bind_local (&addr, &port);
289 /* Construct the argument of PORT (of the form a,b,c,d,e,f). */
290 ip_address_to_port_repr (&addr, port, bytes, sizeof (bytes));
292 /* Send PORT request. */
293 request = ftp_request ("PORT", bytes);
294 nwritten = fd_write (csock, request, strlen (request), -1);
298 fd_close (*local_sock);
303 /* Get appropriate response. */
304 err = ftp_response (csock, &respline);
307 fd_close (*local_sock);
310 if (*respline != '2')
313 fd_close (*local_sock);
322 ip_address_to_lprt_repr (const ip_address *addr, int port, char *buf,
325 unsigned char *ptr = IP_INADDR_DATA (addr);
327 /* buf must contain the argument of LPRT (of the form af,n,h1,h2,...,hn,p1,p2). */
328 assert (buflen >= 21 * 4);
330 /* Construct the argument of LPRT (of the form af,n,h1,h2,...,hn,p1,p2). */
331 switch (addr->family)
334 snprintf (buf, buflen, "%d,%d,%d,%d,%d,%d,%d,%d,%d", 4, 4,
335 ptr[0], ptr[1], ptr[2], ptr[3], 2,
336 (port & 0xff00) >> 8, port & 0xff);
339 snprintf (buf, buflen,
340 "%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d",
342 ptr[0], ptr[1], ptr[2], ptr[3], ptr[4], ptr[5], ptr[6], ptr[7],
343 ptr[8], ptr[9], ptr[10], ptr[11], ptr[12], ptr[13], ptr[14], ptr[15],
344 2, (port & 0xff00) >> 8, port & 0xff);
351 /* Bind a port and send the appropriate PORT command to the FTP
352 server. Use acceptport after RETR, to get the socket of data
355 ftp_lprt (int csock, int *local_sock)
358 char *request, *respline;
362 /* Must contain the argument of LPRT (of the form af,n,h1,h2,...,hn,p1,p2). */
363 char bytes[21 * 4 + 1];
365 /* Get the address of this side of the connection. */
366 if (!socket_ip_address (csock, &addr, ENDPOINT_LOCAL))
369 assert (addr.family == AF_INET || addr.family == AF_INET6);
371 /* Setting port to 0 lets the system choose a free port. */
375 *local_sock = bind_local (&addr, &port);
379 /* Construct the argument of LPRT (of the form af,n,h1,h2,...,hn,p1,p2). */
380 ip_address_to_lprt_repr (&addr, port, bytes, sizeof (bytes));
382 /* Send PORT request. */
383 request = ftp_request ("LPRT", bytes);
384 nwritten = fd_write (csock, request, strlen (request), -1);
388 fd_close (*local_sock);
392 /* Get appropriate response. */
393 err = ftp_response (csock, &respline);
396 fd_close (*local_sock);
399 if (*respline != '2')
402 fd_close (*local_sock);
410 ip_address_to_eprt_repr (const ip_address *addr, int port, char *buf,
415 /* buf must contain the argument of EPRT (of the form |af|addr|port|).
416 * 4 chars for the | separators, INET6_ADDRSTRLEN chars for addr
417 * 1 char for af (1-2) and 5 chars for port (0-65535) */
418 assert (buflen >= 4 + INET6_ADDRSTRLEN + 1 + 5);
420 /* Construct the argument of EPRT (of the form |af|addr|port|). */
421 afnum = (addr->family == AF_INET ? 1 : 2);
422 snprintf (buf, buflen, "|%d|%s|%d|", afnum, print_address (addr), port);
423 buf[buflen - 1] = '\0';
426 /* Bind a port and send the appropriate PORT command to the FTP
427 server. Use acceptport after RETR, to get the socket of data
430 ftp_eprt (int csock, int *local_sock)
433 char *request, *respline;
437 /* Must contain the argument of EPRT (of the form |af|addr|port|).
438 * 4 chars for the | separators, INET6_ADDRSTRLEN chars for addr
439 * 1 char for af (1-2) and 5 chars for port (0-65535) */
440 char bytes[4 + INET6_ADDRSTRLEN + 1 + 5 + 1];
442 /* Get the address of this side of the connection. */
443 if (!socket_ip_address (csock, &addr, ENDPOINT_LOCAL))
446 /* Setting port to 0 lets the system choose a free port. */
450 *local_sock = bind_local (&addr, &port);
454 /* Construct the argument of EPRT (of the form |af|addr|port|). */
455 ip_address_to_eprt_repr (&addr, port, bytes, sizeof (bytes));
457 /* Send PORT request. */
458 request = ftp_request ("EPRT", bytes);
459 nwritten = fd_write (csock, request, strlen (request), -1);
463 fd_close (*local_sock);
467 /* Get appropriate response. */
468 err = ftp_response (csock, &respline);
471 fd_close (*local_sock);
474 if (*respline != '2')
477 fd_close (*local_sock);
485 /* Similar to ftp_port, but uses `PASV' to initiate the passive FTP
486 transfer. Reads the response from server and parses it. Reads the
487 host and port addresses and returns them. */
489 ftp_pasv (int csock, ip_address *addr, int *port)
491 char *request, *respline, *s;
494 unsigned char tmp[6];
496 assert (addr != NULL);
497 assert (port != NULL);
501 /* Form the request. */
502 request = ftp_request ("PASV", NULL);
504 nwritten = fd_write (csock, request, strlen (request), -1);
511 /* Get the server response. */
512 err = ftp_response (csock, &respline);
515 if (*respline != '2')
520 /* Parse the request. */
522 for (s += 4; *s && !c_isdigit (*s); s++)
526 for (i = 0; i < 6; i++)
529 for (; c_isdigit (*s); s++)
530 tmp[i] = (*s - '0') + 10 * tmp[i];
535 /* When on the last number, anything can be a terminator. */
542 addr->family = AF_INET;
543 memcpy (IP_INADDR_DATA (addr), tmp, 4);
544 *port = ((tmp[4] << 8) & 0xff00) + tmp[5];
550 /* Similar to ftp_lprt, but uses `LPSV' to initiate the passive FTP
551 transfer. Reads the response from server and parses it. Reads the
552 host and port addresses and returns them. */
554 ftp_lpsv (int csock, ip_address *addr, int *port)
556 char *request, *respline, *s;
557 int nwritten, i, af, addrlen, portlen;
559 unsigned char tmp[16];
560 unsigned char tmpprt[2];
562 assert (addr != NULL);
563 assert (port != NULL);
567 /* Form the request. */
568 request = ftp_request ("LPSV", NULL);
571 nwritten = fd_write (csock, request, strlen (request), -1);
579 /* Get the server response. */
580 err = ftp_response (csock, &respline);
583 if (*respline != '2')
589 /* Parse the response. */
591 for (s += 4; *s && !c_isdigit (*s); s++)
596 /* First, get the address family */
598 for (; c_isdigit (*s); s++)
599 af = (*s - '0') + 10 * af;
601 if (af != 4 && af != 6)
607 if (!*s || *s++ != ',')
613 /* Then, get the address length */
615 for (; c_isdigit (*s); s++)
616 addrlen = (*s - '0') + 10 * addrlen;
618 if (!*s || *s++ != ',')
630 if ((af == 4 && addrlen != 4)
631 || (af == 6 && addrlen != 16))
637 /* Now, we get the actual address */
638 for (i = 0; i < addrlen; i++)
641 for (; c_isdigit (*s); s++)
642 tmp[i] = (*s - '0') + 10 * tmp[i];
652 /* Now, get the port length */
654 for (; c_isdigit (*s); s++)
655 portlen = (*s - '0') + 10 * portlen;
657 if (!*s || *s++ != ',')
669 /* Finally, we get the port number */
671 for (; c_isdigit (*s); s++)
672 tmpprt[0] = (*s - '0') + 10 * tmpprt[0];
674 if (!*s || *s++ != ',')
681 for (; c_isdigit (*s); s++)
682 tmpprt[1] = (*s - '0') + 10 * tmpprt[1];
688 addr->family = AF_INET;
689 memcpy (IP_INADDR_DATA (addr), tmp, 4);
690 *port = ((tmpprt[0] << 8) & 0xff00) + tmpprt[1];
691 DEBUGP (("lpsv addr is: %s\n", print_address(addr)));
692 DEBUGP (("tmpprt[0] is: %d\n", tmpprt[0]));
693 DEBUGP (("tmpprt[1] is: %d\n", tmpprt[1]));
694 DEBUGP (("*port is: %d\n", *port));
699 addr->family = AF_INET6;
700 memcpy (IP_INADDR_DATA (addr), tmp, 16);
701 *port = ((tmpprt[0] << 8) & 0xff00) + tmpprt[1];
702 DEBUGP (("lpsv addr is: %s\n", print_address(addr)));
703 DEBUGP (("tmpprt[0] is: %d\n", tmpprt[0]));
704 DEBUGP (("tmpprt[1] is: %d\n", tmpprt[1]));
705 DEBUGP (("*port is: %d\n", *port));
712 /* Similar to ftp_eprt, but uses `EPSV' to initiate the passive FTP
713 transfer. Reads the response from server and parses it. Reads the
714 host and port addresses and returns them. */
716 ftp_epsv (int csock, ip_address *ip, int *port)
718 char *request, *respline, *start, delim, *s;
724 assert (port != NULL);
726 /* IP already contains the IP address of the control connection's
727 peer, so we don't need to call socket_ip_address here. */
729 /* Form the request. */
730 /* EPSV 1 means that we ask for IPv4 and EPSV 2 means that we ask for IPv6. */
731 request = ftp_request ("EPSV", (ip->family == AF_INET ? "1" : "2"));
734 nwritten = fd_write (csock, request, strlen (request), -1);
742 /* Get the server response. */
743 err = ftp_response (csock, &respline);
746 if (*respline != '2')
752 assert (respline != NULL);
754 DEBUGP(("respline is %s\n", respline));
756 /* Parse the response. */
759 /* Skip the useless stuff and get what's inside the parentheses */
760 start = strchr (respline, '(');
767 /* Skip the first two void fields */
770 if (delim < 33 || delim > 126)
776 for (i = 0; i < 2; i++)
785 /* Finally, get the port number */
787 for (i = 1; c_isdigit (*s); s++)
794 tport = (*s - '0') + 10 * tport;
797 /* Make sure that the response terminates correcty */
817 /* Sends the TYPE request to the server. */
819 ftp_type (int csock, int type)
821 char *request, *respline;
826 /* Construct argument. */
829 /* Send TYPE request. */
830 request = ftp_request ("TYPE", stype);
831 nwritten = fd_write (csock, request, strlen (request), -1);
838 /* Get appropriate response. */
839 err = ftp_response (csock, &respline);
842 if (*respline != '2')
845 return FTPUNKNOWNTYPE;
852 /* Changes the working directory by issuing a CWD command to the
855 ftp_cwd (int csock, const char *dir)
857 char *request, *respline;
861 /* Send CWD request. */
862 request = ftp_request ("CWD", dir);
863 nwritten = fd_write (csock, request, strlen (request), -1);
870 /* Get appropriate response. */
871 err = ftp_response (csock, &respline);
874 if (*respline == '5')
879 if (*respline != '2')
889 /* Sends REST command to the FTP server. */
891 ftp_rest (int csock, wgint offset)
893 char *request, *respline;
897 request = ftp_request ("REST", number_to_static_string (offset));
898 nwritten = fd_write (csock, request, strlen (request), -1);
905 /* Get appropriate response. */
906 err = ftp_response (csock, &respline);
909 if (*respline != '3')
919 /* Sends RETR command to the FTP server. */
921 ftp_retr (int csock, const char *file)
923 char *request, *respline;
927 /* Send RETR request. */
928 request = ftp_request ("RETR", file);
929 nwritten = fd_write (csock, request, strlen (request), -1);
936 /* Get appropriate response. */
937 err = ftp_response (csock, &respline);
940 if (*respline == '5')
945 if (*respline != '1')
955 /* Sends the LIST command to the server. If FILE is NULL, send just
956 `LIST' (no space). */
958 ftp_list (int csock, const char *file)
960 char *request, *respline;
965 /* Try `LIST -a' first and revert to `LIST' in case of failure. */
966 const char *list_commands[] = { "LIST -a",
971 request = ftp_request (list_commands[i], file);
972 nwritten = fd_write (csock, request, strlen (request), -1);
979 /* Get appropriate response. */
980 err = ftp_response (csock, &respline);
983 if (*respline == '5')
987 else if (*respline == '1')
999 } while (i < countof (list_commands) && !ok);
1004 /* Sends the SYST command to the server. */
1006 ftp_syst (int csock, enum stype *server_type)
1008 char *request, *respline;
1012 /* Send SYST request. */
1013 request = ftp_request ("SYST", NULL);
1014 nwritten = fd_write (csock, request, strlen (request), -1);
1022 /* Get appropriate response. */
1023 err = ftp_response (csock, &respline);
1026 if (*respline == '5')
1032 /* Skip the number (215, but 200 (!!!) in case of VMS) */
1033 strtok (respline, " ");
1035 /* Which system type has been reported (we are interested just in the
1036 first word of the server response)? */
1037 request = strtok (NULL, " ");
1039 if (request == NULL)
1040 *server_type = ST_OTHER;
1041 else if (!strcasecmp (request, "VMS"))
1042 *server_type = ST_VMS;
1043 else if (!strcasecmp (request, "UNIX"))
1044 *server_type = ST_UNIX;
1045 else if (!strcasecmp (request, "WINDOWS_NT")
1046 || !strcasecmp (request, "WINDOWS2000"))
1047 *server_type = ST_WINNT;
1048 else if (!strcasecmp (request, "MACOS"))
1049 *server_type = ST_MACOS;
1050 else if (!strcasecmp (request, "OS/400"))
1051 *server_type = ST_OS400;
1053 *server_type = ST_OTHER;
1060 /* Sends the PWD command to the server. */
1062 ftp_pwd (int csock, char **pwd)
1064 char *request, *respline;
1068 /* Send PWD request. */
1069 request = ftp_request ("PWD", NULL);
1070 nwritten = fd_write (csock, request, strlen (request), -1);
1077 /* Get appropriate response. */
1078 err = ftp_response (csock, &respline);
1081 if (*respline == '5')
1088 /* Skip the number (257), leading citation mark, trailing citation mark
1089 and everything following it. */
1090 strtok (respline, "\"");
1091 request = strtok (NULL, "\"");
1093 /* Treat the malformed response as an error, which the caller has
1094 to handle gracefully anyway. */
1097 /* Has the `pwd' been already allocated? Free! */
1100 *pwd = xstrdup (request);
1107 /* Sends the SIZE command to the server, and returns the value in 'size'.
1108 * If an error occurs, size is set to zero. */
1110 ftp_size (int csock, const char *file, wgint *size)
1112 char *request, *respline;
1116 /* Send PWD request. */
1117 request = ftp_request ("SIZE", file);
1118 nwritten = fd_write (csock, request, strlen (request), -1);
1126 /* Get appropriate response. */
1127 err = ftp_response (csock, &respline);
1133 if (*respline == '5')
1136 * Probably means SIZE isn't supported on this server.
1137 * Error is nonfatal since SIZE isn't in RFC 959
1145 *size = str_to_wgint (respline + 4, NULL, 10);
1149 * Couldn't parse the response for some reason. On the (few)
1150 * tests I've done, the response is 213 <SIZE> with nothing else -
1151 * maybe something a bit more resilient is necessary. It's not a
1152 * fatal error, however.
1164 /* If URL's params are of the form "type=X", return character X.
1165 Otherwise, return 'I' (the default type). */
1167 ftp_process_type (const char *params)
1170 && 0 == strncasecmp (params, "type=", 5)
1171 && params[5] != '\0')
1172 return c_toupper (params[5]);