2 Copyright (C) 1995, 1996, 1997, 1998, 2000 Free Software Foundation, Inc.
4 This file is part of GNU Wget.
6 GNU Wget is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 GNU Wget is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with Wget; if not, write to the Free Software
18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
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. */
49 char ftp_last_respline[128];
52 /* Get the response of FTP server and allocate enough room to handle
53 it. <CR> and <LF> characters are stripped from the line, and the
54 line is 0-terminated. All the response lines but the last one are
55 skipped. The last line is determined as described in RFC959.
57 If the line is successfully read, FTPOK is returned, and *ret_line
58 is assigned a freshly allocated line. Otherwise, FTPRERR is
59 returned, and the value of *ret_line should be ignored. */
62 ftp_response (int fd, char **ret_line)
67 char *line = fd_read_line (fd);
71 /* Strip trailing CRLF before printing the line, so that
72 escnonprint doesn't include bogus \012 and \015. */
73 p = strchr (line, '\0');
74 if (p > line && p[-1] == '\n')
76 if (p > line && p[-1] == '\r')
79 if (opt.server_response)
80 logprintf (LOG_NOTQUIET, "%s\n", escnonprint (line));
82 DEBUGP (("%s\n", escnonprint (line)));
84 /* The last line of output is the one that begins with "ddd ". */
85 if (ISDIGIT (line[0]) && ISDIGIT (line[1]) && ISDIGIT (line[2])
88 strncpy (ftp_last_respline, line, sizeof (ftp_last_respline));
89 ftp_last_respline[sizeof (ftp_last_respline) - 1] = '\0';
97 /* Returns the malloc-ed FTP request, ending with <CR><LF>, printing
98 it if printing is required. If VALUE is NULL, just use
101 ftp_request (const char *command, const char *value)
106 /* Check for newlines in VALUE (possibly injected by the %0A URL
107 escape) making the callers inadvertently send multiple FTP
108 commands at once. Without this check an attacker could
109 intentionally redirect to ftp://server/fakedir%0Acommand.../
110 and execute arbitrary FTP command on a remote FTP server. */
111 if (strpbrk (value, "\r\n"))
113 /* Copy VALUE to the stack and modify CR/LF to space. */
115 STRDUP_ALLOCA (defanged, value);
116 for (p = defanged; *p; p++)
117 if (*p == '\r' || *p == '\n')
119 DEBUGP (("\nDetected newlines in %s \"%s\"; changing to %s \"%s\"\n",
120 command, escnonprint (value), command, escnonprint (defanged)));
121 /* Make VALUE point to the defanged copy of the string. */
124 res = concat_strings (command, " ", value, "\r\n", (char *) 0);
127 res = concat_strings (command, "\r\n", (char *) 0);
128 if (opt.server_response)
130 /* Hack: don't print out password. */
131 if (strncmp (res, "PASS", 4) != 0)
132 logprintf (LOG_ALWAYS, "--> %s\n", res);
134 logputs (LOG_ALWAYS, "--> PASS Turtle Power!\n\n");
137 DEBUGP (("\n--> %s\n", res));
141 /* Sends the USER and PASS commands to the server, to control
142 connection socket csock. */
144 ftp_login (int csock, const char *acc, const char *pass)
147 char *request, *respline;
151 err = ftp_response (csock, &respline);
154 if (*respline != '2')
160 /* Send USER username. */
161 request = ftp_request ("USER", acc);
162 nwritten = fd_write (csock, request, strlen (request), -1);
169 /* Get appropriate response. */
170 err = ftp_response (csock, &respline);
173 /* An unprobable possibility of logging without a password. */
174 if (*respline == '2')
179 /* Else, only response 3 is appropriate. */
180 if (*respline != '3')
183 return FTPLOGREFUSED;
187 static const char *skey_head[] = {
192 const char *seed = NULL;
194 for (i = 0; i < countof (skey_head); i++)
196 int l = strlen (skey_head[i]);
197 if (0 == strncasecmp (skey_head[i], respline, l))
205 int skey_sequence = 0;
207 /* Extract the sequence from SEED. */
208 for (; ISDIGIT (*seed); seed++)
209 skey_sequence = 10 * skey_sequence + *seed - '0';
215 return FTPLOGREFUSED;
217 /* Replace the password with the SKEY response to the
219 pass = skey_response (skey_sequence, seed, pass);
222 #endif /* ENABLE_OPIE */
224 /* Send PASS password. */
225 request = ftp_request ("PASS", pass);
226 nwritten = fd_write (csock, request, strlen (request), -1);
233 /* Get appropriate response. */
234 err = ftp_response (csock, &respline);
237 if (*respline != '2')
248 ip_address_to_port_repr (const ip_address *addr, int port, char *buf,
253 assert (addr != NULL);
254 assert (addr->type == IPV4_ADDRESS);
255 assert (buf != NULL);
256 /* buf must contain the argument of PORT (of the form a,b,c,d,e,f). */
257 assert (buflen >= 6 * 4);
259 ptr = ADDRESS_IPV4_DATA (addr);
260 snprintf (buf, buflen, "%d,%d,%d,%d,%d,%d", ptr[0], ptr[1],
261 ptr[2], ptr[3], (port & 0xff00) >> 8, port & 0xff);
262 buf[buflen - 1] = '\0';
265 /* Bind a port and send the appropriate PORT command to the FTP
266 server. Use acceptport after RETR, to get the socket of data
269 ftp_port (int csock, int *local_sock)
272 char *request, *respline;
276 /* Must contain the argument of PORT (of the form a,b,c,d,e,f). */
277 char bytes[6 * 4 + 1];
279 /* Get the address of this side of the connection. */
280 if (!socket_ip_address (csock, &addr, ENDPOINT_LOCAL))
283 assert (addr.type == IPV4_ADDRESS);
285 /* Setting port to 0 lets the system choose a free port. */
289 *local_sock = bind_local (&addr, &port);
293 /* Construct the argument of PORT (of the form a,b,c,d,e,f). */
294 ip_address_to_port_repr (&addr, port, bytes, sizeof (bytes));
296 /* Send PORT request. */
297 request = ftp_request ("PORT", bytes);
298 nwritten = fd_write (csock, request, strlen (request), -1);
302 fd_close (*local_sock);
307 /* Get appropriate response. */
308 err = ftp_response (csock, &respline);
311 fd_close (*local_sock);
314 if (*respline != '2')
317 fd_close (*local_sock);
326 ip_address_to_lprt_repr (const ip_address *addr, int port, char *buf,
331 assert (addr != NULL);
332 assert (addr->type == IPV4_ADDRESS || addr->type == IPV6_ADDRESS);
333 assert (buf != NULL);
334 /* buf must contain the argument of LPRT (of the form af,n,h1,h2,...,hn,p1,p2). */
335 assert (buflen >= 21 * 4);
337 /* Construct the argument of LPRT (of the form af,n,h1,h2,...,hn,p1,p2). */
341 ptr = ADDRESS_IPV4_DATA (addr);
342 snprintf (buf, buflen, "%d,%d,%d,%d,%d,%d,%d,%d,%d", 4, 4,
343 ptr[0], ptr[1], ptr[2], ptr[3], 2,
344 (port & 0xff00) >> 8, port & 0xff);
345 buf[buflen - 1] = '\0';
348 ptr = ADDRESS_IPV6_DATA (addr);
349 snprintf (buf, buflen, "%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d",
350 6, 16, ptr[0], ptr[1], ptr[2], ptr[3], ptr[4], ptr[5], ptr[6], ptr[7],
351 ptr[8], ptr[9], ptr[10], ptr[11], ptr[12], ptr[13], ptr[14], ptr[15], 2,
352 (port & 0xff00) >> 8, port & 0xff);
353 buf[buflen - 1] = '\0';
358 /* Bind a port and send the appropriate PORT command to the FTP
359 server. Use acceptport after RETR, to get the socket of data
362 ftp_lprt (int csock, int *local_sock)
365 char *request, *respline;
369 /* Must contain the argument of LPRT (of the form af,n,h1,h2,...,hn,p1,p2). */
370 char bytes[21 * 4 + 1];
372 /* Get the address of this side of the connection. */
373 if (!socket_ip_address (csock, &addr, ENDPOINT_LOCAL))
376 assert (addr.type == IPV4_ADDRESS || addr.type == IPV6_ADDRESS);
378 /* Setting port to 0 lets the system choose a free port. */
382 *local_sock = bind_local (&addr, &port);
386 /* Construct the argument of LPRT (of the form af,n,h1,h2,...,hn,p1,p2). */
387 ip_address_to_lprt_repr (&addr, port, bytes, sizeof (bytes));
389 /* Send PORT request. */
390 request = ftp_request ("LPRT", bytes);
391 nwritten = fd_write (csock, request, strlen (request), -1);
395 fd_close (*local_sock);
399 /* Get appropriate response. */
400 err = ftp_response (csock, &respline);
403 fd_close (*local_sock);
406 if (*respline != '2')
409 fd_close (*local_sock);
417 ip_address_to_eprt_repr (const ip_address *addr, int port, char *buf,
422 assert (addr != NULL);
423 assert (addr->type == IPV4_ADDRESS || addr->type == IPV6_ADDRESS);
424 assert (buf != NULL);
425 /* buf must contain the argument of EPRT (of the form |af|addr|port|).
426 * 4 chars for the | separators, INET6_ADDRSTRLEN chars for addr
427 * 1 char for af (1-2) and 5 chars for port (0-65535) */
428 assert (buflen >= 4 + INET6_ADDRSTRLEN + 1 + 5);
430 /* Construct the argument of EPRT (of the form |af|addr|port|). */
431 afnum = (addr->type == IPV4_ADDRESS ? 1 : 2);
432 snprintf (buf, buflen, "|%d|%s|%d|", afnum, pretty_print_address (addr), port);
433 buf[buflen - 1] = '\0';
436 /* Bind a port and send the appropriate PORT command to the FTP
437 server. Use acceptport after RETR, to get the socket of data
440 ftp_eprt (int csock, int *local_sock)
443 char *request, *respline;
447 /* Must contain the argument of EPRT (of the form |af|addr|port|).
448 * 4 chars for the | separators, INET6_ADDRSTRLEN chars for addr
449 * 1 char for af (1-2) and 5 chars for port (0-65535) */
450 char bytes[4 + INET6_ADDRSTRLEN + 1 + 5 + 1];
452 /* Get the address of this side of the connection. */
453 if (!socket_ip_address (csock, &addr, ENDPOINT_LOCAL))
456 assert (addr.type == IPV4_ADDRESS || addr.type == IPV6_ADDRESS);
458 /* Setting port to 0 lets the system choose a free port. */
462 *local_sock = bind_local (&addr, &port);
466 /* Construct the argument of EPRT (of the form |af|addr|port|). */
467 ip_address_to_eprt_repr (&addr, port, bytes, sizeof (bytes));
469 /* Send PORT request. */
470 request = ftp_request ("EPRT", bytes);
471 nwritten = fd_write (csock, request, strlen (request), -1);
475 fd_close (*local_sock);
479 /* Get appropriate response. */
480 err = ftp_response (csock, &respline);
483 fd_close (*local_sock);
486 if (*respline != '2')
489 fd_close (*local_sock);
497 /* Similar to ftp_port, but uses `PASV' to initiate the passive FTP
498 transfer. Reads the response from server and parses it. Reads the
499 host and port addresses and returns them. */
501 ftp_pasv (int csock, ip_address *addr, int *port)
503 char *request, *respline, *s;
506 unsigned char tmp[6];
508 assert (addr != NULL);
509 assert (port != NULL);
513 /* Form the request. */
514 request = ftp_request ("PASV", NULL);
516 nwritten = fd_write (csock, request, strlen (request), -1);
523 /* Get the server response. */
524 err = ftp_response (csock, &respline);
527 if (*respline != '2')
532 /* Parse the request. */
534 for (s += 4; *s && !ISDIGIT (*s); s++);
537 for (i = 0; i < 6; i++)
540 for (; ISDIGIT (*s); s++)
541 tmp[i] = (*s - '0') + 10 * tmp[i];
546 /* When on the last number, anything can be a terminator. */
553 addr->type = IPV4_ADDRESS;
554 memcpy (ADDRESS_IPV4_DATA (addr), tmp, 4);
555 *port = ((tmp[4] << 8) & 0xff00) + tmp[5];
561 /* Similar to ftp_lprt, but uses `LPSV' to initiate the passive FTP
562 transfer. Reads the response from server and parses it. Reads the
563 host and port addresses and returns them. */
565 ftp_lpsv (int csock, ip_address *addr, int *port)
567 char *request, *respline, *s;
568 int nwritten, i, af, addrlen, portlen;
570 unsigned char tmp[16];
571 unsigned char tmpprt[2];
573 assert (addr != NULL);
574 assert (port != NULL);
578 /* Form the request. */
579 request = ftp_request ("LPSV", NULL);
582 nwritten = fd_write (csock, request, strlen (request), -1);
590 /* Get the server response. */
591 err = ftp_response (csock, &respline);
594 if (*respline != '2')
600 /* Parse the response. */
602 for (s += 4; *s && !ISDIGIT (*s); s++);
606 /* First, get the address family */
608 for (; ISDIGIT (*s); s++)
609 af = (*s - '0') + 10 * af;
611 if (af != 4 && af != 6)
617 if (!*s || *s++ != ',')
623 /* Then, get the address length */
625 for (; ISDIGIT (*s); s++)
626 addrlen = (*s - '0') + 10 * addrlen;
628 if (!*s || *s++ != ',')
640 if ((af == 4 && addrlen != 4)
641 || (af == 6 && addrlen != 16))
647 /* Now, we get the actual address */
648 for (i = 0; i < addrlen; i++)
651 for (; ISDIGIT (*s); s++)
652 tmp[i] = (*s - '0') + 10 * tmp[i];
662 /* Now, get the port length */
664 for (; ISDIGIT (*s); s++)
665 portlen = (*s - '0') + 10 * portlen;
667 if (!*s || *s++ != ',')
679 /* Finally, we get the port number */
681 for (; ISDIGIT (*s); s++)
682 tmpprt[0] = (*s - '0') + 10 * tmpprt[0];
684 if (!*s || *s++ != ',')
691 for (; ISDIGIT (*s); s++)
692 tmpprt[1] = (*s - '0') + 10 * tmpprt[1];
698 addr->type = IPV4_ADDRESS;
699 memcpy (ADDRESS_IPV4_DATA (addr), tmp, 4);
700 *port = ((tmpprt[0] << 8) & 0xff00) + tmpprt[1];
701 DEBUGP (("lpsv addr is: %s\n", pretty_print_address(addr)));
702 DEBUGP (("tmpprt[0] is: %d\n", tmpprt[0]));
703 DEBUGP (("tmpprt[1] is: %d\n", tmpprt[1]));
704 DEBUGP (("*port is: %d\n", *port));
709 addr->type = IPV6_ADDRESS;
710 memcpy (ADDRESS_IPV6_DATA (addr), tmp, 16);
711 *port = ((tmpprt[0] << 8) & 0xff00) + tmpprt[1];
712 DEBUGP (("lpsv addr is: %s\n", pretty_print_address(addr)));
713 DEBUGP (("tmpprt[0] is: %d\n", tmpprt[0]));
714 DEBUGP (("tmpprt[1] is: %d\n", tmpprt[1]));
715 DEBUGP (("*port is: %d\n", *port));
722 /* Similar to ftp_eprt, but uses `EPSV' to initiate the passive FTP
723 transfer. Reads the response from server and parses it. Reads the
724 host and port addresses and returns them. */
726 ftp_epsv (int csock, ip_address *ip, int *port)
728 char *request, *respline, *start, delim, *s;
734 assert (port != NULL);
736 /* IP already contains the IP address of the control connection's
737 peer, so we don't need to call socket_ip_address here. */
739 /* Form the request. */
740 /* EPSV 1 means that we ask for IPv4 and EPSV 2 means that we ask for IPv6. */
741 request = ftp_request ("EPSV", (ip->type == IPV4_ADDRESS ? "1" : "2"));
744 nwritten = fd_write (csock, request, strlen (request), -1);
752 /* Get the server response. */
753 err = ftp_response (csock, &respline);
756 if (*respline != '2')
762 assert (respline != NULL);
764 DEBUGP(("respline is %s\n", respline));
766 /* Parse the response. */
769 /* Skip the useless stuff and get what's inside the parentheses */
770 start = strchr (respline, '(');
777 /* Skip the first two void fields */
780 if (delim < 33 || delim > 126)
786 for (i = 0; i < 2; i++)
795 /* Finally, get the port number */
797 for (i = 1; ISDIGIT (*s); s++)
804 tport = (*s - '0') + 10 * tport;
807 /* Make sure that the response terminates correcty */
827 /* Sends the TYPE request to the server. */
829 ftp_type (int csock, int type)
831 char *request, *respline;
836 /* Construct argument. */
839 /* Send TYPE request. */
840 request = ftp_request ("TYPE", stype);
841 nwritten = fd_write (csock, request, strlen (request), -1);
848 /* Get appropriate response. */
849 err = ftp_response (csock, &respline);
852 if (*respline != '2')
855 return FTPUNKNOWNTYPE;
862 /* Changes the working directory by issuing a CWD command to the
865 ftp_cwd (int csock, const char *dir)
867 char *request, *respline;
871 /* Send CWD request. */
872 request = ftp_request ("CWD", dir);
873 nwritten = fd_write (csock, request, strlen (request), -1);
880 /* Get appropriate response. */
881 err = ftp_response (csock, &respline);
884 if (*respline == '5')
889 if (*respline != '2')
899 /* Sends REST command to the FTP server. */
901 ftp_rest (int csock, wgint offset)
903 char *request, *respline;
907 request = ftp_request ("REST", number_to_static_string (offset));
908 nwritten = fd_write (csock, request, strlen (request), -1);
915 /* Get appropriate response. */
916 err = ftp_response (csock, &respline);
919 if (*respline != '3')
929 /* Sends RETR command to the FTP server. */
931 ftp_retr (int csock, const char *file)
933 char *request, *respline;
937 /* Send RETR request. */
938 request = ftp_request ("RETR", file);
939 nwritten = fd_write (csock, request, strlen (request), -1);
946 /* Get appropriate response. */
947 err = ftp_response (csock, &respline);
950 if (*respline == '5')
955 if (*respline != '1')
965 /* Sends the LIST command to the server. If FILE is NULL, send just
966 `LIST' (no space). */
968 ftp_list (int csock, const char *file)
970 char *request, *respline;
974 /* Send LIST request. */
975 request = ftp_request ("LIST", file);
976 nwritten = fd_write (csock, request, strlen (request), -1);
983 /* Get appropriate respone. */
984 err = ftp_response (csock, &respline);
987 if (*respline == '5')
992 if (*respline != '1')
1002 /* Sends the SYST command to the server. */
1004 ftp_syst (int csock, enum stype *server_type)
1006 char *request, *respline;
1010 /* Send SYST request. */
1011 request = ftp_request ("SYST", NULL);
1012 nwritten = fd_write (csock, request, strlen (request), -1);
1020 /* Get appropriate response. */
1021 err = ftp_response (csock, &respline);
1024 if (*respline == '5')
1030 /* Skip the number (215, but 200 (!!!) in case of VMS) */
1031 strtok (respline, " ");
1033 /* Which system type has been reported (we are interested just in the
1034 first word of the server response)? */
1035 request = strtok (NULL, " ");
1037 if (!strcasecmp (request, "VMS"))
1038 *server_type = ST_VMS;
1039 else if (!strcasecmp (request, "UNIX"))
1040 *server_type = ST_UNIX;
1041 else if (!strcasecmp (request, "WINDOWS_NT")
1042 || !strcasecmp (request, "WINDOWS2000"))
1043 *server_type = ST_WINNT;
1044 else if (!strcasecmp (request, "MACOS"))
1045 *server_type = ST_MACOS;
1046 else if (!strcasecmp (request, "OS/400"))
1047 *server_type = ST_OS400;
1049 *server_type = ST_OTHER;
1056 /* Sends the PWD command to the server. */
1058 ftp_pwd (int csock, char **pwd)
1060 char *request, *respline;
1064 /* Send PWD request. */
1065 request = ftp_request ("PWD", NULL);
1066 nwritten = fd_write (csock, request, strlen (request), -1);
1073 /* Get appropriate response. */
1074 err = ftp_response (csock, &respline);
1077 if (*respline == '5')
1084 /* Skip the number (257), leading citation mark, trailing citation mark
1085 and everything following it. */
1086 strtok (respline, "\"");
1087 request = strtok (NULL, "\"");
1089 /* Treat the malformed response as an error, which the caller has
1090 to handle gracefully anyway. */
1093 /* Has the `pwd' been already allocated? Free! */
1096 *pwd = xstrdup (request);
1103 /* Sends the SIZE command to the server, and returns the value in 'size'.
1104 * If an error occurs, size is set to zero. */
1106 ftp_size (int csock, const char *file, wgint *size)
1108 char *request, *respline;
1112 /* Send PWD request. */
1113 request = ftp_request ("SIZE", file);
1114 nwritten = fd_write (csock, request, strlen (request), -1);
1122 /* Get appropriate response. */
1123 err = ftp_response (csock, &respline);
1129 if (*respline == '5')
1132 * Probably means SIZE isn't supported on this server.
1133 * Error is nonfatal since SIZE isn't in RFC 959
1141 *size = str_to_wgint (respline + 4, NULL, 10);
1145 * Couldn't parse the response for some reason. On the (few)
1146 * tests I've done, the response is 213 <SIZE> with nothing else -
1147 * maybe something a bit more resilient is necessary. It's not a
1148 * fatal error, however.
1160 /* If URL's params are of the form "type=X", return character X.
1161 Otherwise, return 'I' (the default type). */
1163 ftp_process_type (const char *params)
1166 && 0 == strncasecmp (params, "type=", 5)
1167 && params[5] != '\0')
1168 return TOUPPER (params[5]);