Commit 4db481b0ab81dda2b5b6aba890513c44feb17866

  • avatar
  • Giovanni Misitano <gialmisi @stu…nt.jyu.fi> (Committer)
  • Sat Jan 19 02:21:45 EET 2019
  • avatar
  • Giovanni Misitano <gialmisi @stu…nt.jyu.fi> (Author)
  • Sat Jan 19 02:21:45 EET 2019
TFTP almost functional.
file/tftpclient.py
(66 / 217)
  
77 ftpclient ip_address port
88"""
99
10import argparse
11import socket
12import re
13import threading
14import getpass
10import socket
11import random
1512
13# ip = "0.0.0.0"
14# TID = random.randint(2000, 20000)
1615
17def control_connection(ip, port, bsize):
18 control = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
16# s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
17# s.bind((ip, TID))
1918
20 try:
21 control.connect((ip, port))
22 except:
23 print("Could not connect to the ftp-server on {}:{}".format(ip, port))
24 return "Connection refused on {}:{}".format(ip, port)
19# message = bytearray()
20# message.append(0)
21# message.append(1)
22# filename = bytearray('message.txt'.encode('utf-8'))
23# message += filename
24# message.append(0)
25# mode = bytearray('netascii'.encode('utf-8'))
26# message += mode
27# message.append(0)
2528
26 states = ["AUTHORIZATION_1", "AUTHORIZATION_2", "LOGGED_IN"]
29# s.sendto(message, (ip, 69))
2730
28 # Check initial connection to be ok
29 response = get_response_array(control, bsize)
30 if response is not None and len(response) > 1 and response[0] == "220":
31 print("Connection successful!")
32 else:
33 print("Could not connect to the ftp-server on {}:{}".format(ip, port))
34 return "FTP service not available!"
31# data, addr = s.recvfrom(512)
3532
36 state = "AUTHORIZATION_1"
33# print(data)
34# print(addr)
3735
38 # Main loop
39 while True:
40 if state == "AUTHORIZATION_1":
41 username = input("Username:")
4236
43 send_to_socket(control, "USER {}\r\n".format(username))
44 response = get_response_array(control, bsize)
37def RRQ(ip, port, filename):
38 s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
39 s.bind(('0.0.0.0', 0))
4540
46 if response and len(response) > 1 and response[0] == "331":
47 print("Username ok. Give password.")
48 state = "AUTHORIZATION_2"
49 else:
50 print("Username {} not valid.".format(username))
41 message = rw_pckg(1, filename, 'netascii')
5142
52 elif state == "AUTHORIZATION_2":
53 password = getpass.getpass()
43 s.sendto(message, (ip, port))
5444
55 send_to_socket(control, "PASS {}\r\n".format(password))
56 response = get_response_array(control, bsize)
45 data, addr = s.recvfrom(512)
5746
58 if response and len(response) > 1 and response[0] == "230":
59 print("Login successful.")
60 print_help()
61 state = "LOGGED_IN"
62 else:
63 print("Login incorrect!")
64 state = "AUTHORIZATION_1"
47 # get port for transactions
48 port = addr[1]
6549
66 elif state == "LOGGED_IN":
67 query = parse_query(input(">"))
50 blknum = int.from_bytes(data[2:4], byteorder="big")
51 message = ack_pckg(blknum)
52 s.sendto(message, (ip, port))
53 data, addr = s.recvfrom(512)
6854
69 if not query:
70 print("Bad command.")
55 return data
7156
72 elif query[0] in ['q', 'quit']:
73 print("Quitting...")
74 break
57
7558
76 elif query[0] in ['h', 'help']:
77 print_help()
59def rw_pckg(rw, filename, mode):
60 message = bytearray()
61 message.append(0)
62 message.append(rw)
63 filename = bytearray(filename.encode('utf-8'))
64 message += filename
65 message.append(0)
66 mode = bytearray(mode.encode('utf-8'))
67 message += mode
68 message.append(0)
7869
79 elif query[0] in ['l', 'list']:
80 arg = None
81 if len(query) > 1:
82 arg = query[1]
70 return message
8371
84 send_to_socket(control, "PASV\r\n")
85 response = get_response_array(control, bsize)
72def data_pckg(blknum, data):
73 message = bytearray()
74 message.append(0)
75 message.append(3)
76 message.append(blknum)
77 message += bytearray(data.encode('utf8'))
8678
87 if response and response[0] == '227':
88 # PASSIVE MODE
89 # foramt of response '(ip,ip,ip,ip,port,port)'
90 ip_and_port = eval(response[-1])
91 dataport = bit_decimals_to_port(ip_and_port[-2], ip_and_port[-1])
79 return message
9280
93 data = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
9481
95 try:
96 data.connect((ip, dataport))
97 except:
98 print("Could not connect to the ftp-server on {}:{}".format(ip, port))
99 data = None
82def ack_pckg(blknum):
83 message = bytearray()
84 message.append(0)
85 message.append(4)
86 message += blknum.to_bytes(2, "big")
10087
101 if data:
102 if not arg:
103 send_to_socket(control, "LIST\r\n")
104 else:
105 send_to_socket(control, "LIST {}\r\n".format(arg))
88 return message
10689
107 response = get_response_array(control, bsize)
10890
109 files = []
110 if response[0] == "150":
111 while True:
112 file = data.recv(bsize)
113 if not file:
114 break
91def error_pckg(code, msg):
92 message = bytearray()
93 message.append(0)
94 message.append(5)
95 message += bytearray(msg.encode('utf-8'))
96 message.append(0)
11597
116 files.append(str(file, 'utf-8'))
98 return message
11799
118 for file in files:
119 print(file)
120100
121 response = get_response_array(control, bsize)
122 if response[0] != "226":
123 print("Problem in transfering the list, error code: {}".format(response[0]))
124
125 else:
126 print("Could not fetch file.")
127
128 else:
129 print("Could not estabilish data connection.")
130
131 elif query[0] in ['r', 'retr']:
132 if len(query) < 2:
133 print("Must specify which file to transfer.")
134
135 else:
136 arg = query[1]
137
138 send_to_socket(control, "PASV\r\n")
139 response = get_response_array(control, bsize)
140
141 if response and response[0] == '227':
142 # PASSIVE MODE
143 # foramt of response '(ip,ip,ip,ip,port,port)'
144 ip_and_port = eval(response[-1])
145 dataport = bit_decimals_to_port(ip_and_port[-2], ip_and_port[-1])
146
147 data = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
148
149 try:
150 data.connect((ip, dataport))
151 except:
152 print("Could not connect to the ftp-server on {}:{}".format(ip, port))
153 data = None
154
155 if data:
156 send_to_socket(control, "RETR {}\r\n".format(arg))
157
158 response = get_response_array(control, bsize)
159
160 files = []
161 if response[0] == "150":
162 while True:
163 file = data.recv(bsize)
164 if not file:
165 break
166
167 files.append(str(file, 'utf-8'))
168
169 file_name = "{}".format(arg)
170 with open(file_name, 'a') as fhandle:
171 for file in files:
172 fhandle.write(file)
173
174 response = get_response_array(control, bsize)
175 if response[0] != "226":
176 print("Problem in transfering the list, error code: {}".format(response[0]))
177 else:
178 print("File '{}' transfered successfully!".format(file_name))
179
180 else:
181 print("Could not fetch file.")
182
183 else:
184 print("Could not estabilish data connection.")
185
186 control.close()
187 return "All fine"
188
189
190def port_to_bit_decimals(port):
191 whole = '{0:016b}'.format(port)
192 upper = int(whole[0:8], 2)
193 lower = int(whole[8:], 2)
194
195 return upper, lower
196
197
198def bit_decimals_to_port(upper, lower):
199 whole = '{0:08b}'.format(upper) + '{0:08b}'.format(lower)
200 whole = int(whole, 2)
201
202 return whole
203
204
205def get_response_array(sock, bsize):
206 """Splits a response into a string array."""
207 data = sock.recv(bsize)
208
209 if data == b'':
210 return None
211
212 data_s = (str(data.strip(), 'utf-8'))
213 data_s = data_s.split()
214
215 return data_s
216
217
218def send_to_socket(sock, string):
219 sock.send(bytes(string, 'utf-8'))
220 return
221
222def parse_query(query):
223 if not query:
224 return None
225
226 query = query.split()
227 query[0] = query[0].lower()
228
229 return query
230
231def print_help():
232 print("Supported commands:")
233 print("\tl, list \t\t Request directory listing or file info.")
234 print("\tr, retr \t\t Retrieve a specified file.")
235 print("\th, help \t\t Print this help message.")
236 print("\tq, quit \t\t Close the connection to the server and quit.")
237
238def main(ip, port):
239 bsize = 1024
240 print(bit_decimals_to_port(125, 99))
241 print("{}:{}".format(ip, port, bsize))
242
243 control_connection(ip, port, bsize)
244 return
245
246
247101if __name__ == "__main__":
248 parser = argparse.ArgumentParser(description='Simple FTP client')
102 result = RRQ("0.0.0.0", 69, "message.txt")
249103
250 parser.add_argument('-a', action="store", dest="address", default="127.0.0.1")
251 parser.add_argument('-p', action="store", dest="port", default=1050, type=int)
252
253 results = parser.parse_args()
254
255 main(results.address, results.port)
104 print(result)