Assignment title: Management
GThis assignment is an extension of the previous one. You may start with your own solution, or start with the A2 key. If you start with your own, you are welcome to swipe any code from the key which you might find useful. The FTP RFC will still be relevant.
Use the Cleansocks library to create a command-line FTP client which will request and print a directory on an FTP server. The program's output will contain the file listing as reported by the server, as well as a log of the interaction with the server. For instance, here's what mine looks like:
[bennet@desktop ftp2]$ ./ftplist gatekeeper.dec.com pub/bausk
>>>> Connected
SVR: 220-
SVR: 220-Welcome to HP Labs FTP Service
SVR: 220-
SVR: 220-Please direct questions or comments to [email protected].
SVR: 220-
SVR: 220-If you are looking for the FTP server for Hewlett Packard Enterprise Labs,
SVR: 220-use ftp.labs.hpe.com instead.
SVR: 220
CLI: USER anonymous
SVR: 331 Please specify the password.
CLI: PASS ******
SVR: 230 Login successful.
>>>> Successfully logged in
CLI: CWD pub/bausk
SVR: 250 Directory successfully changed.
CLI: PASV
SVR: 227 Entering Passive Mode (204,123,3,21,202,224)
>>>> Connecting to 204.123.3.21:51936
CLI: LIST
SVR: 150 Here comes the directory listing.
-rw-rw-r-- 1 ftp ftp 41901 Apr 16 2004 CD_label.jpg
-rw-rw-r-- 1 ftp ftp 12288 Apr 16 2004 VIDEO_TS.BUP
-rw-rw-r-- 1 ftp ftp 12288 Apr 16 2004 VIDEO_TS.IFO
-rw-rw-r-- 1 ftp ftp 36864 Apr 16 2004 VIDEO_TS.VOB
-rw-rw-r-- 1 ftp ftp 16384 Apr 16 2004 VTS_01_0.BUP
-rw-rw-r-- 1 ftp ftp 16384 Apr 16 2004 VTS_01_0.IFO
-rw-rw-r-- 1 ftp ftp 307085312 Apr 16 2004 VTS_01_1.VOB
-rw-rw-r-- 1 ftp ftp 16384 Apr 16 2004 VTS_02_0.BUP
-rw-rw-r-- 1 ftp ftp 16384 Apr 16 2004 VTS_02_0.IFO
-rw-rw-r-- 1 ftp ftp 316180480 Apr 16 2004 VTS_02_1.VOB
SVR: 226 Directory send OK.
CLI: QUIT
SVR: 221 Goodbye.
>>>> Complete
Here, I ran the program with the name of an FTP host and a directory to list on the command line. The program connected to the server, logged in as anonymous, changed to the indicated directory, requested a listing of the directory using passive mode, and printed that listing to the console. It then logged out of the server. As before, it also printed a log of its interaction with the server.
Required behavior
The program should accept the following on its command line:
program [login@]hostname [ directory ]
The hostname is the only required parameter. If the session is to use non-anonymous login, an account is specified before the host name, separated by an at sign. The program will first log in to the server. If a directory name is present, the program will attempt to change to that directory on the server. The program will then request a listing of the current directory, which will be either the original or new one. If a login is specified, the program should request a password from the user before attempting to log in. Should the login fail, the program should request a password again, and re-try the login. The program should keep retrying the login as long as the user is willing to keep typing passwords. If the user enters an empty password (just pushes return after the prompt), the program should stop attempting to log in, disconnect, and exit. If any error is detected along the way, the program should give an error message (unless the error is already obvious from the log), then exit. When exiting, the program should send QUIT to the server, if appropriate, then close any connection(s).
There is no need to issued the HELP command as in the previous assignment
The password request (with possible loop) is the only interaction with the user. If anonymous login is used, there is no interaction.
Creating The Listing
To get the directory listing, first change to the indicated directory (if any) using the PWD command. That is issued over the control connection as others we're used to.
Getting the listing is more complicated, because the server will send the listing data across a separate data connection. There are two ways to establish this connection, and this assignment uses what is called passive mode, where this program will connect to the server (as is usual). Perform the following steps:
1. Send the PASV command to request a passive transfer. This asks the server to listen for a data connection.
2. If the PASV is successful (code 227), the response text will contain the IP address and port to connect to.
3. Make a new socket for data, and connect it to the endpoint described in the 227 response.
4. Issue a LIST command. The server should respond with a 150, indicating that it has started sending the listing on the data connection.
5. Copy bytes from the data connection to the console output. Copy until the server closes (recv returns zero).
6. Close the data connection.
7. You should now receive a 200 response on the control connection indicating that the transfer is complete. Make sure to read this response to verify success.
The PASV Response
The 227 success response from PASV tells you where the server is listening so you can connect, an IP address and port. RFC 959 is generally precise, but it is faulty here. The RFC says that the 227 response should specify the host and port, but it does not specify the format. So we rely on the well-established practice that the information is given as six comma-separated decimal values surrounded by parentheses. The client must search the response string string for this and extract the six values. Examine the 227 response from the example script above:
SVR: 227 Entering Passive Mode (204,123,3,21,202,224)
The first four numbers are just the IP address, more conventionally written as 204.123.3.21. The last two are the high and low bytes of the port number. They can be combined to get the port number by multiplying the first by 256 and adding it to the second. In this case 256×202+224=51936, so we make the data connection to port 51936 on the machine at 204.123.3.21. For the Cleansocks library, you should compute the port number as above and use it to initialize the IPport object. For the IPaddress, you can construct it from the address string like "204.123.3.21", or combine the bytes in a way similar to the port number to get the numerical IP address. Build this endpoint and connect to it to read the listing contents.
It's interesting that the server specifies both host and port for the data connection. It could specify a different host than itself. In fact, the protocol was designed so that the file service might be divided between more than one machine, and the server could direct the client to transfer data from elsewhere. Now days, such a response might be considered fishy, and a client may refuse to make a data connection to an IP different from the server.
Logging In
When using anonymous login, simply attempt one login, and die if it fails. For a real account, you need to ask the user for a password, attempt the log in, and try again if the login fails. When you retry, you must start over by sending the USER command again, even though the user name won't change. The specification calls for repeatedly requesting the password, but always using the user name from the command line. This is just a design judgment that an error is most likely in the password, and typing the user name again is more of a pain than a help. (The user can always exit and start over.)
In the previous assignment, the password was requested once before contacting the server. You may still do that, but if you need to ask again it will have to be after connecting, since you can't find out the password is wrong until you can send it to the server. If you prefer, you may delay the first password request until you are ready to send it to the server. This may be simpler, since you will only have to deal with the password in one place. Either behavior is acceptable. DO NOT, however, respond to a login failure by closing and reopening the connection. Connect once, and make all your login attempts on that original connection.
More Examples
Here are a few more examples.
[bennet@desktop ftp2]$ ./ftplist gatekeeper.dec.com
>>>> Connected
SVR: 220-
SVR: 220-Welcome to HP Labs FTP Service
SVR: 220-
SVR: 220-Please direct questions or comments to [email protected].
SVR: 220-
SVR: 220-If you are looking for the FTP server for Hewlett Packard Enterprise Labs,
SVR: 220-use ftp.labs.hpe.com instead.
SVR: 220
CLI: USER anonymous
SVR: 331 Please specify the password.
CLI: PASS ******
SVR: 230 Login successful.
>>>> Successfully logged in
CLI: PASV
SVR: 227 Entering Passive Mode (204,123,3,21,201,118)
>>>> Connecting to 204.123.3.21:51574
CLI: LIST
SVR: 150 Here comes the directory listing.
-rw-r--r-- 1 ftp ftp 922730 Oct 31 2008 Index-byname
-rw-r--r-- 1 ftp ftp 112552 Oct 31 2008 Index-byname.Z
-rw-r--r-- 1 ftp ftp 922730 Oct 31 2008 Index-bytime
-rw-r--r-- 1 ftp ftp 113230 Oct 31 2008 Index-bytime.Z
drwxr-x--- 2 ftp ftp 4096 Sep 13 00:02 etc
drwxr-xr-x 6 ftp ftp 4096 Sep 12 2008 ftp-archive
drwxr-xr-x 3 ftp ftp 4096 Oct 31 2008 gatekeeper
drwxr-x--t 2 ftp ftp 4096 Sep 13 12:13 incoming
drwxr-x--t 2 ftp ftp 4096 Sep 27 21:43 outgoing
drwxr-x--- 2 ftp ftp 4096 Sep 13 13:21 private
drwxr-xr-x 31 ftp ftp 4096 Sep 29 01:28 pub
-rw-r--r-- 1 ftp ftp 61 Mar 09 2010 robots.txt
drwxr-xr-x 2 ftp ftp 4096 Mar 03 1997 stl
drwxr-xr-x 6 ftp ftp 4096 Dec 02 2014 webconsole
SVR: 226 Directory send OK.
CLI: QUIT
SVR: 221 Goodbye.
>>>> Complete
[bennet@desktop ftp2]$ ./ftplist ftp.sdf.org pub
>>>> Connected
SVR: 220 miku.sdf.org FTP server (NetBSD-ftpd 20110904) ready.
CLI: USER anonymous
SVR: 331 Guest login ok, type your name as password.
CLI: PASS ******
SVR: 230-
SVR:
SVR: Welcome to .. _____ _____
SVR: / _/ /____ ___ ___/ / _/___ _______ _
SVR: / _/ __/ _ \_ (_- _ / _// _ \/ __/ _ `/
SVR: /_/ \__/ .__(_)___/\_,_/_/(_)___/_/ \_, /
SVR: /_/ /___/
SVR:
SVR: -= SDF Public Access UNIX System =-
SVR: Established 1987
SVR:
SVR: Login via SSH as 'new@sdf.org' for a free UNIX shell account
SVR:
SVR: 230 Guest login ok, access restrictions apply.
>>>> Successfully logged in
CLI: CWD pub
SVR: 250 CWD command successful.
CLI: PASV
SVR: 227 Entering Passive Mode (205,166,94,6,212,10)
>>>> Connecting to 205.166.94.6:54282
CLI: LIST
SVR: 150 Opening ASCII mode data connection for '/bin/ls'.
total 160
-rw-r--r-- 1 24670 0 3312 Mar 6 2011 caps.txt
drwxr-xr-x 15 0 0 512 Jul 1 2013 computers
-rw-r--r-- 1 0 0 897 Feb 26 19:21 gophermap
drwxr-xr-x 2 0 0 512 Jul 20 2009 hacking
drwx------ 3 6 0 3072 Mar 2 10:13 incoming
drwxr-xr-x 28 0 0 512 Feb 26 19:21 maps
dr-xr-xr-x 2 0 0 512 Jan 8 2003 norden
drwxr-xr-x 2 0 0 512 Feb 26 19:21 phlogs
drwxr-xr-x 12 0 0 1536 May 12 2016 sdf
drwx---r-x 2603 32767 65535 44544 Mar 3 15:10 users
SVR: 226 Transfer complete.
CLI: QUIT
SVR: 221-
SVR: Data traffic for this session was 0 bytes in 0 files.
SVR: Total traffic for this session was 1541 bytes in 1 transfer.
SVR: 221 Thank you for using the FTP service on miku.sdf.org.
>>>> Complete
[bennet@desktop ftp2]$ ./ftplist [email protected]
>>>> Connected
SVR: 220 bjork.freeshell.org FTP server (NetBSD-ftpd 20110904) ready.
Password:
CLI: USER bogus
SVR: 331 User bogus accepted, provide password for bogus@bjork.
CLI: PASS ******
SVR: 530 Login incorrect.
Password:
CLI: USER bogus
SVR: 331 User bogus accepted, provide password for bogus@bjork.
CLI: PASS ******
SVR: 530 Login incorrect.
Password:
>>>> Login failed
CLI: QUIT
SVR: 221 Thank you for using the FTP service on bjork.freeshell.org.
>>>> Finished
[bennet@desktop ftp2]$ ./ftplist [email protected]
>>>> Connected
SVR: 220-=== Welcome to the Sandbox HTML upload server ===
SVR: 220 This is a private system - No anonymous login
Password:
CLI: USER bennet
SVR: 331 User bennet OK. Password required
CLI: PASS ******
SVR: 530 Login authentication failed
Password:
CLI: USER bennet
SVR: 331 User bennet OK. Password required
CLI: PASS ******
SVR: 230-OK. Current directory is /
SVR: 230-1 files used (0%) - authorized: 200 files
SVR: 230 15 Kbytes used (0%) - authorized: 30720 Kb
>>>> Successfully logged in
CLI: PASV
SVR: 227 Entering Passive Mode (10,27,0,23,176,202)
>>>> Connecting to 10.27.0.23:45258
CLI: LIST
SVR: 150 Accepted data connection
drwxr-xr-x 2 1520 webpost 4096 Jan 17 10:33 .
drwxr-xr-x 2 1520 webpost 4096 Jan 17 10:33 ..
-rw------- 1 1520 webpost 8 Jan 17 10:33 .ftpquota
SVR: 226-Options: -a -l
SVR: 226 3 matches total
CLI: QUIT
SVR: 221-Goodbye. You uploaded 0 and downloaded 0 kbytes.
SVR: 221 Logout.
>>>> Complete
[bennet@desktop ftp2]$ ./ftplist sandbox.mc.edu
>>>> Connected
SVR: 220-=== Welcome to the Sandbox HTML upload server ===
SVR: 220 This is a private system - No anonymous login
CLI: USER anonymous
SVR: 331 User anonymous OK. Password required
CLI: PASS ******
SVR: 530 Login authentication failed
>>>> Anonymous login not allowed
CLI: QUIT
SVR: 221-Goodbye. You uploaded 0 and downloaded 0 kbytes.
SVR: 221 Logout.
>>>> Finished
[bennet@desktop ftp2]$ ./ftplist ftp.cdc.gov pub/14th_Mine_Vent_Sympos_Diesel
>>>> Connected
SVR: 220 Microsoft FTP Service
CLI: USER anonymous
SVR: 331 Anonymous access allowed, send identity (e-mail name) as password.
CLI: PASS ******
SVR: 230 User logged in.
>>>> Successfully logged in
CLI: CWD pub/14th_Mine_Vent_Sympos_Diesel
SVR: 250 CWD command successful.
CLI: PASV
SVR: 227 Entering Passive Mode (198,246,117,106,212,239)
>>>> Connecting to 198.246.117.106:54511
CLI: LIST
SVR: 125 Data connection already open; Transfer starting.
-rwxrwxrwx 1 owner group 833732131 Oct 24 2012 Alex 1.mp4
-rwxrwxrwx 1 owner group 1209167060 Oct 24 2012 Alex 2.mp4
-rwxrwxrwx 1 owner group 1439320149 Oct 24 2012 Alex 3.mp4
-rwxrwxrwx 1 owner group 488926610 Oct 24 2012 Troy Terrillion.mp4
SVR: 226 Transfer complete.
CLI: QUIT
SVR: 221 Goodbye.
>>>> Complete
You may be able to Google up the names of other public FTP servers for additional testing.