Giter VIP home page Giter VIP logo

ptftpd's People

Contributors

bias-keenly avatar cabalist avatar fifteenhex avatar lalten avatar maximeh avatar mpetazzoni avatar oxyduck-g avatar uspike avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

ptftpd's Issues

RecursionError in TFTPServer.send_response

I tried to send a 150MiB file but got a RecursionError in TFTPServer.send_response.

I noticed that you already fixed this in 61f0d9f. This commit, however, is not part of the latest ptftpd-1.3 release.

I hope that this is just an oversight. Just to let you know.

Thanks for your work on ptftpd.

Feature: MAC Based Leases / DHCP Accept Previous Clients

Hello again

I have a use case where I am installing an OS via the PXE server and I need the DHCP server to respond to a previously known PXE client.

The workflow is as follows currently:

  • system requests IP as PXE client (accepted)
  • select OS install from PXE menu
  • OS installer needs DHCP address to communicate but is rejected because it is not a PXE client any more (rejected)

Proposed change:

  1. move to MAC based leases, if a specific MAC makes multiple DHCP requests it will always receive the same
    • right now only IP and timeout are captured. Proposal is to add MAC as primary key and keep both IP and timeout as children of the MAC key.
  2. add flag to accept previous PXE clients so that my use case will be satisfied

I have PRs ready but want to confirm this flow is proper before I submit.

Thanks

cannot stat /proc/sys/net/inet/udp/maxdgram

Linux 5.10.20-1-lts

INFO(tftpd): Serving file tp_recovery.bin to host 192.168.0.2...
sysctl: cannot stat /proc/sys/net/inet/udp/maxdgram: Нет такого файла или каталога
INFO(tftpd): Serving file tp_recovery.bin to host 192.168.0.2...
sysctl: cannot stat /proc/sys/net/inet/udp/maxdgram: Нет такого файла или каталога

Allow the usage of IOStrings and do not close file objects

It would be nice that the tftpclient could be used to download a file into memory (IOStrings). I did a quick and dirty method for TFTPClient:

    def getAsIOString(self, filepath):
        """ zieht das file in einen String """
        self.PTFTP_STATE = state.TFTPState(self.peer, proto.OP_RRQ,
                '', filepath, self.transfer_mode, not self.rfc1350)

        self.PTFTP_STATE.file = StringIO.StringIO()
        self.PTFTP_STATE.packetnum = 1
        self.PTFTP_STATE.state = state.STATE_RECV

        opts = dict(self.opts)

        # When not running in RFC1350 compliance mode, append tsize: 0
        # to the list of options in the request to get the requested
        # file size back in the OACK.
        if not self.rfc1350:
            opts[proto.TFTP_OPTION_TSIZE] = 0

        packet = proto.TFTPHelper.createRRQ(filepath, self.transfer_mode, opts)

        self.sock.sendto(packet, self.peer)
        self.handle()

        if self.error:
            error, errmsg = self.error
            raise IOError('Downloading failed (%r, %r)' % (error, errmsg))
        return self.PTFTP_STATE.file

But that only works if I remove the close() functions in state.py. But as I'm not that deep into that code I don't know what that breaks.

Broken on Linux

tftpserver.py seems to be using this to work out how big the UDP packets it sends can be:

def get_max_udp_datagram_size():
    """Retrieve the maximum UDP datagram size allowed by the system."""
    val = subprocess.check_output(['sysctl', '-n', 'net.inet.udp.maxdgram'])
    return int(val)

This fails on linux because that property doesn't exist. I guess it's a BSD/OSX thing.
Maybe this should be changed to check the exit value of sysctl and use the safe maximum of 508 bytes if sysctl returns an error or doesn't run at all because the user isn't root.

get_ip_config_for_iface() python3 error

In dhcpserver.get_ip_config_for_iface():

Iface is a string, and on python3:

    ifname = struct.pack('256s', iface[:15])
E   struct.error: argument for 's' must be a bytes object

Suggested fix:

ifname = struct.pack('256s', iface[:15].encode())

Feature: Optional HTTP Server

I have a use case where, as part of this solution, I would like to export some files over HTTP to be consumed by my PXE client (OS install files). If the concept is approved I will submit a PR to create the following flags.

  • -h / --http-server (flag)
    • start HTTP server (by default will export tftp root on the default port (8080))
  • -p / --http-port (optional)
    • HTTP port to use
    • default is 8080
  • -r / --http-root (optional)
    • HTTP root export path
    • default is tftp root

Cisco IOS uploads to ptftpd fail with "File already exists error"

FYI, I tried to use ptftpd under python 2.6.6, running as root to receive a configuration file from Cisco IOS. When the switch sent the first UDP packet to port 69, ptftpd started opening the new file to receive the config, but never sent a tftp response packet.

When Cisco IOS retried four seconds later, ptftpd responded that the file already exists, and that killed the tftp session.

Is there anything else I can do to help fix this issue?

DHCP Server Offering IPs to All Clients

First, I want to say I think this is a terrific project and concept. Thank you for making it.

I have been testing the PXE / DHCP server functionality for a project I am working on. The documentation states that the DHCP server is only supposed to respond to PXE requests. Only responding to PXE requests is the desired behavior for my use case as well. I have found that the DHCP server is responding to all clients, including phones, watches, etc. and offering the IP addresses.

The current code checks for the existence of DHCP option 55 to determine if the request is PXE related or not. From my research, DHCP option 55 is the parameter request list, and is included in most or all DHCP requests. All requests I have received when running this include option 55, PXE or not. Please see the following Cisco support article for a wireshark look at option 55. https://www.cisco.com/c/en/us/support/docs/security/identity-services-engine/116235-configure-ise-00.html

One solution that I have found is to check if option 60 (vendor class identifier) begins with PXEClient. I have seen articles and open source PXE systems that suggest using the option 60 to determine PXE clients and only send these clients the next server and bootfile options. This is also how you determine if the PXE request is EUFI or BIOS. https://wiki.fogproject.org/wiki/index.php/BIOS_and_UEFI_Co-Existence

I will submit a PR shortly with this proposed change.

tftpserver.py - Directory traversal attack

Your code

 if not peer_state.filepath.startswith(self.server.root):
....
peer_state.file = open(peer_state.filepath)

Allows a directory traversal attack. Why? I'll show you in bash:

$ sudo mkdir /tftpboot
$ cat /tftpboot/../etc/passwd
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
sys:x:3:3:sys:/dev:/usr/sbin/nologin
sync:x:4:65534:sync:/bin:/bin/sync

run the process as root and you get the /etc/shadow as attacker.

Data block number starting on 0 makes server incompatible with RFC 1350

I had to implement a TFTP Client with RFC 1350 specifications for class and I think I found a bug where, when sending a file from client, the server expects first DATA block number to be 0 when it should be 1.

Here is what the documentation says: "The block numbers on data packets begin with one and increase by one for each new block of data."

Got into the code and printed the number the server receives and the one it expects. They are different so it stops the transfer.
image

Is this a bug or is it intentional and I'm missing something?

Protocol gets out of sequence if the client misses packets.

I'm fixing up ethernet on a little embedded thing and I noticed this:

The server sends block 10. The client doesn't see it so it sends an ack for block 9 again expecting get block 10 resent
but gets 11 instead.

Packet dumps:

19:10:13.194542 70:85:c2:8e:66:d7 (oui Unknown) > be:e8:98:09:13:90 (oui Unknown), ethertype IPv4 (0x0800), length 558: (tos 0x0, ttl 64, id 1798, offset 0, flags [DF], proto UDP (17), length 544)
    192.168.3.235.tftp > 192.168.3.245.1028:  516 DATA block 10
        0x0000:  bee8 9809 1390 7085 c28e 66d7 0800 4500  ......p...f...E.
        0x0010:  0220 0706 4000 4011 a896 c0a8 03eb c0a8  ....@.@.........
        0x0020:  03f5 0045 0404 020c 8b4e 0003 000a 0020  ...E.....N......
        0x0030:  521a c9f8 3820 d9f8 3820 120c 1204 c9f8  R...8...8.......
        0x0040:  3820 d9f8 3820 c9f8 c820 7047 fff7 e7bf  8...8.....pG....
        0x0050:  7047 d9f8 c830 41ea 0051 41f4 4061 43f8  pG...0A..QA.@aC.
        0x0060:  2010 7047 08b5 d9f8 0020 d9f8 0430 db07  ..pG.........0..
        0x0070:  0ad5 02eb c002 906c 000d d36c 916c 1b0d  .......l...l.l..
        0x0080:  03eb 1153 8342 00d8 08bd 1e21 fff7 e1ff  ...S.B.....!....
        0x0090:  0130 f2e7 11ee 103f 43f4 8053 01ee 103f  .0.....?C..S...?
        0x00a0:  bff3 6f8f 7047 11ee 103f 11ee 103f 23f4  ..o.pG...?...?#.
        0x00b0:  8053 01ee 103f bff3 6f8f 7047 11ee 100f  .S...?..o.pG....
        0x00c0:  c0f3 0030 7047 10b5 11ee 104f 14f0 0104  ...0pG.....O....
        0x00d0:  27d1 fff7 f3f9 2046 1221 0134 fff7 b9ff  '......F.!.4....
        0x00e0:  b4f5 805f f7d1 0020 fff7 bcff 0023 02ee  ..._.........#..
        0x00f0:  503f d9f8 c830 23f4 7f53 23f0 3f03 43f0  P?...0#..S#.?.C.
        0x0100:  5903 02ee 103f 4ff0 ff33 03ee 103f fff7  Y....?O..3...?..
        0x0110:  9fff 11ee 103f 43f0 0103 01ee 103f bff3  .....?C......?..
        0x0120:  6f8f 11ee 103f 43f0 0403 01ee 103f bff3  o....?C......?..
        0x0130:  6f8f 10bd 10b5 11ee 103f 5b07 09d5 11ee  o........?[.....
        0x0140:  104f fff7 acf9 24f0 0504 01ee 104f bff3  .O....$......O..
        0x0150:  6f8f 10bd 11ee 100f c0f3 8000 7047 0020  o...........pG..
        0x0160:  7047 4ff0 8062 0020 c9f8 3c20 7047 ff22  pGO..b....<.pG."
        0x0170:  024b 1a80 7922 1a80 fee7 b81c 001f 08b5  .K..y"..........
        0x0180:  fff7 88ff bde8 0840 fff7 9dbf 11ee 300f  [email protected].
        0x0190:  40f0 4000 01ee 300f 7047 bff3 5f8f 0022  @[email protected].._.."
        0x01a0:  074b 1a80 bff3 5f8f 0122 1a80 054a 1388  .K...._.."...J..
        0x01b0:  9bb2 bff3 5f8f db04 f9d5 7047 00bf 1444  ...._.....pG...D
        0x01c0:  201f 4044 201f fff7 e8bf fff7 e6bf 0d4b  [email protected]
        0x01d0:  1b78 d92b 13d0 05d8 ae2b 12d0 c22b 06d0  .x.+.....+...+..
        0x01e0:  0020 7047 ee2b 14bf 0020 0520 7047 064b  ..pG.+......pG.K
        0x01f0:  9b8a b3f5 886f 0cbf 0320 0220 7047 0420  .....o......pG..
        0x0200:  7047 0120 7047 003c 001f 0040 001f 08b5  pG..pG.<...@....
        0x0210:  0ef0 8ffe 4ff4 f072 024b 0020 1a60 08bd  ....O..r.K...`..
        0x0220:  00bf 0020 0016 08b5 0246 fff7 d0ff       .........F....
19:10:18.194645 be:e8:98:09:13:90 (oui Unknown) > 70:85:c2:8e:66:d7 (oui Unknown), ethertype IPv4 (0x0800), length 60: (tos 0x0, ttl 255, id 47, offset 0, flags [DF], proto UDP (17), length 32)
    192.168.3.245.1028 > 192.168.3.235.tftp:  4 ACK block 9
        0x0000:  7085 c28e 66d7 bee8 9809 1390 0800 4500  p...f.........E.
        0x0010:  0020 002f 4000 ff11 f26c c0a8 03f5 c0a8  .../@....l......
        0x0020:  03eb 0404 0045 000c 0000 0004 0009 0000  .....E..........
        0x0030:  0000 0000 0000 0000 0000 0000            ............
19:10:18.194816 70:85:c2:8e:66:d7 (oui Unknown) > be:e8:98:09:13:90 (oui Unknown), ethertype IPv4 (0x0800), length 558: (tos 0x0, ttl 64, id 2225, offset 0, flags [DF], proto UDP (17), length 544)
    192.168.3.235.tftp > 192.168.3.245.1028:  516 DATA block 11
        0x0000:  bee8 9809 1390 7085 c28e 66d7 0800 4500  ......p...f...E.
        0x0010:  0220 08b1 4000 4011 a6eb c0a8 03eb c0a8  ....@.@.........
        0x0020:  03f5 0045 0404 020c 8b4e 0003 000b 0138  ...E.....N.....8
        0x0030:  0528 13d8 dfe8 00f0 030c 0c10 100e 0849  .(.............I
        0x0040:  1046 20f0 85f9 0038 18bf 0120 4042 08bd  .F.....8....@B..
        0x0050:  0549 f5e7 0549 f3e7 0549 f1e7 4ff0 ff30  .I...I...I..O..0
        0x0060:  f5e7 4574 0220 4f74 0220 5974 0220 6374  ..Et..Ot..Yt..ct
        0x0070:  0220 08b5 1ef0 93fb 0020 08bd 0000 2de9  ..............-.
        0x0080:  f04d 2b4b 8ab0 1b78 0622 8df8 1030 294b  .M+K...x."...0)K

Server output:

ERROR(tftpd): Got ACK with incoherent data packet number. Aborting transfer.

Feature: DHCP scope (PR #23)

The current behavior of ptftplib is to use the entire network that the chosen interface is on as the DHCP scope. This is fine if ptftp is the only author of IP addresses on that network. In my case, however, I have systems with static IPs on that network. As such, I would need the option to specify a DHCP scope to the DHCP server.

Please see #23

Python 3 support

I think it would be great if this supported Python3. Take a look here: #9

Converting the libraries over to handling bytes should be totally doable but some tests are needed.

tftp Not working on Windows with Python 3.7

I have a problem using ptftpd on Windows 10 64-Bit with python 3.7.7.
I installed ptftpd v1.3 with pip
I'm serving my root directory by using "ptftpd -v {78112962-C189-455B-95E8-CF41298AAD8E} H:\Python"
In "H:\Python\blubb\bla" is a file "blubb.txt"
If I try to get the file from a client "get blubb/bla/blubb.txt" I get the error
INFO(tftpd): Serving file blubb/bla/test.TXT to host 192.168.56.10...
ERROR(tftpd): Got ACK with incoherent data packet number. Aborting transfer.

I already tried to change the "" to "/", serving diffrent files and also put it directly in the root directory. But nothing worked.

I also tried to execute the cmd as admin but still the same.

Any ideas?

python3 experimental

I need this package for python3 so download it using:
pip install git+https://github.com/mpetazzoni/ptftpd@master

While downloading the file using the get method here it throws following error:
lib/python3.5/site-packages/ptftplib/proto.py", line 139, in createRRQ
struct.error: argument for 's' must be a bytes object

Is this package is ready for python3 or not ?

Medium-ish size transfer fails

Trying to transfer a ~100 MB ubi image to an embedded device running uboot.

I first had to apply the patch from #20 to allow the server to run at all on Linux.

The file transfers, apparently nearly all of the file, but it fails at a consistent point with the following traceback:

Exception happened during processing of request from ('192.168.5.1', 3675)
Traceback (most recent call last):
  File "/usr/lib64/python2.7/SocketServer.py", line 295, in _handle_request_noblock
    self.process_request(request, client_address)
  File "/usr/lib64/python2.7/SocketServer.py", line 321, in process_request
    self.finish_request(request, client_address)
  File "/usr/lib64/python2.7/SocketServer.py", line 334, in finish_request
    self.RequestHandlerClass(request, client_address, self)
  File "/usr/lib64/python2.7/SocketServer.py", line 651, in __init__
    self.finish()
  File "/usr/lib64/python2.7/SocketServer.py", line 731, in finish
    self.socket.sendto(self.wfile.getvalue(), self.client_address)
error: [Errno 90] Message too long

On the client, it aborts with: TFTP error: 'Unknown transfer ID.' (5)

I'm running python 2.7 on Centos 7

Client isn't swapping ports after first block 1 data packet from (any) server

Just testing this library out, looks nice however I'm failing to make a valid TFTP get transfer.

What I see happening (with Wireshark):

  1. RRQ to port 69 from ptftpd client to any server
  2. Server replies with data block 1 from port X
  3. Client replies with ACK to port 69 (Wrong!)

Step 3 should be:
3. Client replies with ACK to port X
...since the client should now be using port X instead (forever) of 69

Am I missing something here? Otherwise lib looks very nice - much cleaner than TFTPy!

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.