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. */
45 #include <sys/types.h>
54 char ftp_last_respline[128];
57 /* Get the response of FTP server and allocate enough room to handle
58 it. <CR> and <LF> characters are stripped from the line, and the
59 line is 0-terminated. All the response lines but the last one are
60 skipped. The last line is determined as described in RFC959. */
63 ftp_response (int fd, char **ret_line)
68 char *line = fd_read_line (fd);
72 /* Strip trailing CRLF before printing the line, so that
73 escnonprint doesn't include bogus \012 and \015. */
74 p = strchr (line, '\0');
75 if (p > line && p[-1] == '\n')
77 if (p > line && p[-1] == '\r')
80 if (opt.server_response)
81 logprintf (LOG_NOTQUIET, "%s\n", escnonprint (line));
83 DEBUGP (("%s\n", escnonprint (line)));
85 /* The last line of output is the one that begins with "ddd ". */
86 if (ISDIGIT (line[0]) && ISDIGIT (line[1]) && ISDIGIT (line[2])
89 strncpy (ftp_last_respline, line, sizeof (ftp_last_respline));
90 ftp_last_respline[sizeof (ftp_last_respline) - 1] = '\0';
98 /* Returns the malloc-ed FTP request, ending with <CR><LF>, printing
99 it if printing is required. If VALUE is NULL, just use
102 ftp_request (const char *command, const char *value)
106 res = concat_strings (command, " ", value, "\r\n", (char *) 0);
108 res = concat_strings (command, "\r\n", (char *) 0);
109 if (opt.server_response)
111 /* Hack: don't print out password. */
112 if (strncmp (res, "PASS", 4) != 0)
113 logprintf (LOG_ALWAYS, "--> %s\n", res);
115 logputs (LOG_ALWAYS, "--> PASS Turtle Power!\n\n");
118 DEBUGP (("\n--> %s\n", res));
122 /* Sends the USER and PASS commands to the server, to control
123 connection socket csock. */
125 ftp_login (int csock, const char *acc, const char *pass)
128 char *request, *respline;
132 err = ftp_response (csock, &respline);
135 if (*respline != '2')
141 /* Send USER username. */
142 request = ftp_request ("USER", acc);
143 nwritten = fd_write (csock, request, strlen (request), -1.0);
150 /* Get appropriate response. */
151 err = ftp_response (csock, &respline);
157 /* An unprobable possibility of logging without a password. */
158 if (*respline == '2')
163 /* Else, only response 3 is appropriate. */
164 if (*respline != '3')
167 return FTPLOGREFUSED;
171 static const char *skey_head[] = {
176 const char *seed = NULL;
178 for (i = 0; i < countof (skey_head); i++)
180 int l = strlen (skey_head[i]);
181 if (0 == strncasecmp (skey_head[i], respline, l))
189 int skey_sequence = 0;
191 /* Extract the sequence from SEED. */
192 for (; ISDIGIT (*seed); seed++)
193 skey_sequence = 10 * skey_sequence + *seed - '0';
199 return FTPLOGREFUSED;
201 /* Replace the password with the SKEY response to the
203 pass = skey_response (skey_sequence, seed, pass);
206 #endif /* ENABLE_OPIE */
208 /* Send PASS password. */
209 request = ftp_request ("PASS", pass);
210 nwritten = fd_write (csock, request, strlen (request), -1.0);
217 /* Get appropriate response. */
218 err = ftp_response (csock, &respline);
224 if (*respline != '2')
235 ip_address_to_port_repr (const ip_address *addr, int port, char *buf,
240 assert (addr != NULL);
241 assert (addr->type == IPV4_ADDRESS);
242 assert (buf != NULL);
243 /* buf must contain the argument of PORT (of the form a,b,c,d,e,f). */
244 assert (buflen >= 6 * 4);
246 ptr = ADDRESS_IPV4_DATA (addr);
247 snprintf (buf, buflen, "%d,%d,%d,%d,%d,%d", ptr[0], ptr[1],
248 ptr[2], ptr[3], (port & 0xff00) >> 8, port & 0xff);
249 buf[buflen - 1] = '\0';
252 /* Bind a port and send the appropriate PORT command to the FTP
253 server. Use acceptport after RETR, to get the socket of data
256 ftp_port (int csock, int *local_sock)
259 char *request, *respline;
263 /* Must contain the argument of PORT (of the form a,b,c,d,e,f). */
264 char bytes[6 * 4 + 1];
266 /* Get the address of this side of the connection. */
267 if (!socket_ip_address (csock, &addr, ENDPOINT_LOCAL))
270 assert (addr.type == IPV4_ADDRESS);
272 /* Setting port to 0 lets the system choose a free port. */
276 *local_sock = bind_local (&addr, &port);
280 /* Construct the argument of PORT (of the form a,b,c,d,e,f). */
281 ip_address_to_port_repr (&addr, port, bytes, sizeof (bytes));
283 /* Send PORT request. */
284 request = ftp_request ("PORT", bytes);
285 nwritten = fd_write (csock, request, strlen (request), -1.0);
289 fd_close (*local_sock);
294 /* Get appropriate response. */
295 err = ftp_response (csock, &respline);
299 fd_close (*local_sock);
302 if (*respline != '2')
305 fd_close (*local_sock);
314 ip_address_to_lprt_repr (const ip_address *addr, int port, char *buf,
319 assert (addr != NULL);
320 assert (addr->type == IPV4_ADDRESS || addr->type == IPV6_ADDRESS);
321 assert (buf != NULL);
322 /* buf must contain the argument of LPRT (of the form af,n,h1,h2,...,hn,p1,p2). */
323 assert (buflen >= 21 * 4);
325 /* Construct the argument of LPRT (of the form af,n,h1,h2,...,hn,p1,p2). */
329 ptr = ADDRESS_IPV4_DATA (addr);
330 snprintf (buf, buflen, "%d,%d,%d,%d,%d,%d,%d,%d,%d", 4, 4,
331 ptr[0], ptr[1], ptr[2], ptr[3], 2,
332 (port & 0xff00) >> 8, port & 0xff);
333 buf[buflen - 1] = '\0';
336 ptr = ADDRESS_IPV6_DATA (addr);
337 snprintf (buf, buflen, "%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d",
338 6, 16, ptr[0], ptr[1], ptr[2], ptr[3], ptr[4], ptr[5], ptr[6], ptr[7],
339 ptr[8], ptr[9], ptr[10], ptr[11], ptr[12], ptr[13], ptr[14], ptr[15], 2,
340 (port & 0xff00) >> 8, port & 0xff);
341 buf[buflen - 1] = '\0';
346 /* Bind a port and send the appropriate PORT command to the FTP
347 server. Use acceptport after RETR, to get the socket of data
350 ftp_lprt (int csock, int *local_sock)
353 char *request, *respline;
357 /* Must contain the argument of LPRT (of the form af,n,h1,h2,...,hn,p1,p2). */
358 char bytes[21 * 4 + 1];
360 /* Get the address of this side of the connection. */
361 if (!socket_ip_address (csock, &addr, ENDPOINT_LOCAL))
364 assert (addr.type == IPV4_ADDRESS || addr.type == IPV6_ADDRESS);
366 /* Setting port to 0 lets the system choose a free port. */
370 *local_sock = bind_local (&addr, &port);
374 /* Construct the argument of LPRT (of the form af,n,h1,h2,...,hn,p1,p2). */
375 ip_address_to_lprt_repr (&addr, port, bytes, sizeof (bytes));
377 /* Send PORT request. */
378 request = ftp_request ("LPRT", bytes);
379 nwritten = fd_write (csock, request, strlen (request), -1.0);
383 fd_close (*local_sock);
387 /* Get appropriate response. */
388 err = ftp_response (csock, &respline);
392 fd_close (*local_sock);
395 if (*respline != '2')
398 fd_close (*local_sock);
406 ip_address_to_eprt_repr (const ip_address *addr, int port, char *buf,
411 assert (addr != NULL);
412 assert (addr->type == IPV4_ADDRESS || addr->type == IPV6_ADDRESS);
413 assert (buf != NULL);
414 /* buf must contain the argument of EPRT (of the form |af|addr|port|).
415 * 4 chars for the | separators, INET6_ADDRSTRLEN chars for addr
416 * 1 char for af (1-2) and 5 chars for port (0-65535) */
417 assert (buflen >= 4 + INET6_ADDRSTRLEN + 1 + 5);
419 /* Construct the argument of EPRT (of the form |af|addr|port|). */
420 afnum = (addr->type == IPV4_ADDRESS ? 1 : 2);
421 snprintf (buf, buflen, "|%d|%s|%d|", afnum, pretty_print_address (addr), port);
422 buf[buflen - 1] = '\0';
425 /* Bind a port and send the appropriate PORT command to the FTP
426 server. Use acceptport after RETR, to get the socket of data
429 ftp_eprt (int csock, int *local_sock)
432 char *request, *respline;
436 /* Must contain the argument of EPRT (of the form |af|addr|port|).
437 * 4 chars for the | separators, ENABLE_IPV6_ADDRSTRLEN chars for addr
438 * 1 char for af (1-2) and 5 chars for port (0-65535) */
439 char bytes[4 + INET6_ADDRSTRLEN + 1 + 5 + 1];
441 /* Get the address of this side of the connection. */
442 if (!socket_ip_address (csock, &addr, ENDPOINT_LOCAL))
445 assert (addr.type == IPV4_ADDRESS || addr.type == IPV6_ADDRESS);
447 /* Setting port to 0 lets the system choose a free port. */
451 *local_sock = bind_local (&addr, &port);
455 /* Construct the argument of LPRT (of the form af,n,h1,h2,...,hn,p1,p2). */
456 ip_address_to_eprt_repr (&addr, port, bytes, sizeof (bytes));
458 /* Send PORT request. */
459 request = ftp_request ("EPRT", bytes);
460 nwritten = fd_write (csock, request, strlen (request), -1.0);
464 fd_close (*local_sock);
468 /* Get appropriate response. */
469 err = ftp_response (csock, &respline);
473 fd_close (*local_sock);
476 if (*respline != '2')
479 fd_close (*local_sock);
487 /* Similar to ftp_port, but uses `PASV' to initiate the passive FTP
488 transfer. Reads the response from server and parses it. Reads the
489 host and port addresses and returns them. */
491 ftp_pasv (int csock, ip_address *addr, int *port)
493 char *request, *respline, *s;
496 unsigned char tmp[6];
498 assert (addr != NULL);
499 assert (port != NULL);
503 /* Form the request. */
504 request = ftp_request ("PASV", NULL);
506 nwritten = fd_write (csock, request, strlen (request), -1.0);
513 /* Get the server response. */
514 err = ftp_response (csock, &respline);
520 if (*respline != '2')
525 /* Parse the request. */
527 for (s += 4; *s && !ISDIGIT (*s); s++);
530 for (i = 0; i < 6; i++)
533 for (; ISDIGIT (*s); s++)
534 tmp[i] = (*s - '0') + 10 * tmp[i];
539 /* When on the last number, anything can be a terminator. */
546 addr->type = IPV4_ADDRESS;
547 memcpy (ADDRESS_IPV4_DATA (addr), tmp, 4);
548 *port = ((tmp[4] << 8) & 0xff00) + tmp[5];
554 /* Similar to ftp_lprt, but uses `LPSV' to initiate the passive FTP
555 transfer. Reads the response from server and parses it. Reads the
556 host and port addresses and returns them. */
558 ftp_lpsv (int csock, ip_address *addr, int *port)
560 char *request, *respline, *s;
561 int nwritten, i, af, addrlen, portlen;
563 unsigned char tmp[16];
564 unsigned char tmpprt[2];
566 assert (addr != NULL);
567 assert (port != NULL);
571 /* Form the request. */
572 request = ftp_request ("LPSV", NULL);
575 nwritten = fd_write (csock, request, strlen (request), -1.0);
583 /* Get the server response. */
584 err = ftp_response (csock, &respline);
590 if (*respline != '2')
596 /* Parse the response. */
598 for (s += 4; *s && !ISDIGIT (*s); s++);
602 /* First, get the address family */
604 for (; ISDIGIT (*s); s++)
605 af = (*s - '0') + 10 * af;
607 if (af != 4 && af != 6)
613 if (!*s || *s++ != ',')
619 /* Then, get the address length */
621 for (; ISDIGIT (*s); s++)
622 addrlen = (*s - '0') + 10 * addrlen;
624 if (!*s || *s++ != ',')
636 if ((af == 4 && addrlen != 4)
637 || (af == 6 && addrlen != 16))
643 /* Now, we get the actual address */
644 for (i = 0; i < addrlen; i++)
647 for (; ISDIGIT (*s); s++)
648 tmp[i] = (*s - '0') + 10 * tmp[i];
658 /* Now, get the port length */
660 for (; ISDIGIT (*s); s++)
661 portlen = (*s - '0') + 10 * portlen;
663 if (!*s || *s++ != ',')
675 /* Finally, we get the port number */
677 for (; ISDIGIT (*s); s++)
678 tmpprt[0] = (*s - '0') + 10 * tmpprt[0];
680 if (!*s || *s++ != ',')
687 for (; ISDIGIT (*s); s++)
688 tmpprt[1] = (*s - '0') + 10 * tmpprt[1];
694 addr->type = IPV4_ADDRESS;
695 memcpy (ADDRESS_IPV4_DATA (addr), tmp, 4);
696 *port = ((tmpprt[0] << 8) & 0xff00) + tmpprt[1];
697 DEBUGP (("lpsv addr is: %s\n", pretty_print_address(addr)));
698 DEBUGP (("tmpprt[0] is: %d\n", tmpprt[0]));
699 DEBUGP (("tmpprt[1] is: %d\n", tmpprt[1]));
700 DEBUGP (("*port is: %d\n", *port));
705 addr->type = IPV6_ADDRESS;
706 memcpy (ADDRESS_IPV6_DATA (addr), tmp, 16);
707 *port = ((tmpprt[0] << 8) & 0xff00) + tmpprt[1];
708 DEBUGP (("lpsv addr is: %s\n", pretty_print_address(addr)));
709 DEBUGP (("tmpprt[0] is: %d\n", tmpprt[0]));
710 DEBUGP (("tmpprt[1] is: %d\n", tmpprt[1]));
711 DEBUGP (("*port is: %d\n", *port));
718 /* Similar to ftp_eprt, but uses `EPSV' to initiate the passive FTP
719 transfer. Reads the response from server and parses it. Reads the
720 host and port addresses and returns them. */
722 ftp_epsv (int csock, ip_address *ip, int *port)
724 char *request, *respline, *start, delim, *s;
730 assert (port != NULL);
732 /* IP already contains the IP address of the control connection's
733 peer, so we don't need to call socket_ip_address here. */
735 /* Form the request. */
736 /* EPSV 1 means that we ask for IPv4 and EPSV 2 means that we ask for IPv6. */
737 request = ftp_request ("EPSV", (ip->type == IPV4_ADDRESS ? "1" : "2"));
740 nwritten = fd_write (csock, request, strlen (request), -1.0);
748 /* Get the server response. */
749 err = ftp_response (csock, &respline);
755 if (*respline != '2')
761 assert (respline != NULL);
763 DEBUGP(("respline is %s\n", respline));
765 /* Parse the response. */
768 /* Skip the useless stuff and get what's inside the parentheses */
769 start = strchr (respline, '(');
776 /* Skip the first two void fields */
779 if (delim < 33 || delim > 126)
785 for (i = 0; i < 2; i++)
794 /* Finally, get the port number */
796 for (i = 1; ISDIGIT (*s); s++)
803 tport = (*s - '0') + 10 * tport;
806 /* Make sure that the response terminates correcty */
826 /* Sends the TYPE request to the server. */
828 ftp_type (int csock, int type)
830 char *request, *respline;
835 /* Construct argument. */
838 /* Send TYPE request. */
839 request = ftp_request ("TYPE", stype);
840 nwritten = fd_write (csock, request, strlen (request), -1.0);
847 /* Get appropriate response. */
848 err = ftp_response (csock, &respline);
854 if (*respline != '2')
857 return FTPUNKNOWNTYPE;
864 /* Changes the working directory by issuing a CWD command to the
867 ftp_cwd (int csock, const char *dir)
869 char *request, *respline;
873 /* Send CWD request. */
874 request = ftp_request ("CWD", dir);
875 nwritten = fd_write (csock, request, strlen (request), -1.0);
882 /* Get appropriate response. */
883 err = ftp_response (csock, &respline);
889 if (*respline == '5')
894 if (*respline != '2')
904 /* Sends REST command to the FTP server. */
906 ftp_rest (int csock, wgint offset)
908 char *request, *respline;
912 request = ftp_request ("REST", number_to_static_string (offset));
913 nwritten = fd_write (csock, request, strlen (request), -1.0);
920 /* Get appropriate response. */
921 err = ftp_response (csock, &respline);
927 if (*respline != '3')
937 /* Sends RETR command to the FTP server. */
939 ftp_retr (int csock, const char *file)
941 char *request, *respline;
945 /* Send RETR request. */
946 request = ftp_request ("RETR", file);
947 nwritten = fd_write (csock, request, strlen (request), -1.0);
954 /* Get appropriate response. */
955 err = ftp_response (csock, &respline);
961 if (*respline == '5')
966 if (*respline != '1')
976 /* Sends the LIST command to the server. If FILE is NULL, send just
977 `LIST' (no space). */
979 ftp_list (int csock, const char *file)
981 char *request, *respline;
985 /* Send LIST request. */
986 request = ftp_request ("LIST", file);
987 nwritten = fd_write (csock, request, strlen (request), -1.0);
994 /* Get appropriate respone. */
995 err = ftp_response (csock, &respline);
1001 if (*respline == '5')
1006 if (*respline != '1')
1016 /* Sends the SYST command to the server. */
1018 ftp_syst (int csock, enum stype *server_type)
1020 char *request, *respline;
1024 /* Send SYST request. */
1025 request = ftp_request ("SYST", NULL);
1026 nwritten = fd_write (csock, request, strlen (request), -1.0);
1034 /* Get appropriate response. */
1035 err = ftp_response (csock, &respline);
1041 if (*respline == '5')
1047 /* Skip the number (215, but 200 (!!!) in case of VMS) */
1048 strtok (respline, " ");
1050 /* Which system type has been reported (we are interested just in the
1051 first word of the server response)? */
1052 request = strtok (NULL, " ");
1054 if (!strcasecmp (request, "VMS"))
1055 *server_type = ST_VMS;
1056 else if (!strcasecmp (request, "UNIX"))
1057 *server_type = ST_UNIX;
1058 else if (!strcasecmp (request, "WINDOWS_NT")
1059 || !strcasecmp (request, "WINDOWS2000"))
1060 *server_type = ST_WINNT;
1061 else if (!strcasecmp (request, "MACOS"))
1062 *server_type = ST_MACOS;
1063 else if (!strcasecmp (request, "OS/400"))
1064 *server_type = ST_OS400;
1066 *server_type = ST_OTHER;
1073 /* Sends the PWD command to the server. */
1075 ftp_pwd (int csock, char **pwd)
1077 char *request, *respline;
1081 /* Send PWD request. */
1082 request = ftp_request ("PWD", NULL);
1083 nwritten = fd_write (csock, request, strlen (request), -1.0);
1090 /* Get appropriate response. */
1091 err = ftp_response (csock, &respline);
1097 if (*respline == '5')
1103 /* Skip the number (257), leading citation mark, trailing citation mark
1104 and everything following it. */
1105 strtok (respline, "\"");
1106 request = strtok (NULL, "\"");
1108 /* Has the `pwd' been already allocated? Free! */
1111 *pwd = xstrdup (request);
1118 /* Sends the SIZE command to the server, and returns the value in 'size'.
1119 * If an error occurs, size is set to zero. */
1121 ftp_size (int csock, const char *file, wgint *size)
1123 char *request, *respline;
1127 /* Send PWD request. */
1128 request = ftp_request ("SIZE", file);
1129 nwritten = fd_write (csock, request, strlen (request), -1.0);
1137 /* Get appropriate response. */
1138 err = ftp_response (csock, &respline);
1145 if (*respline == '5')
1148 * Probably means SIZE isn't supported on this server.
1149 * Error is nonfatal since SIZE isn't in RFC 959
1157 *size = str_to_wgint (respline + 4, NULL, 10);
1161 * Couldn't parse the response for some reason. On the (few)
1162 * tests I've done, the response is 213 <SIZE> with nothing else -
1163 * maybe something a bit more resilient is necessary. It's not a
1164 * fatal error, however.
1176 /* If URL's params are of the form "type=X", return character X.
1177 Otherwise, return 'I' (the default type). */
1179 ftp_process_type (const char *params)
1182 && 0 == strncasecmp (params, "type=", 5)
1183 && params[5] != '\0')
1184 return TOUPPER (params[5]);