Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
def handle(self, pkt, raddress, rport):
"""Handle an initial RRQ packet as a server."""
logger.debug("In TftpStateServerRecvRRQ.handle")
sendoack = self.serverInitial(pkt, raddress, rport)
path = self.full_path
logger.info("Opening file %s for reading" % path)
if self.context.vfs.norm_path(path):
self.context.fileobj = self.context.vfs.open(
path.replace(self.context.root + "/", ""), "rb"
)
else:
logger.info("File not found: %s", path.replace(self.context.root + "/", ""))
self.sendError(TftpErrors.FileNotFound)
raise TftpException("File not found: {}".format(path))
# Options negotiation.
if sendoack and "tsize" in self.context.options:
# getting the file size for the tsize option. As we handle
# file-like objects and not only real files, we use this seeking
# method instead of asking the OS
self.context.fileobj.seek(0, os.SEEK_END)
tsize = str(self.context.fileobj.tell())
self.context.fileobj.seek(0, 0)
self.context.options["tsize"] = tsize
if sendoack:
# Note, next_block is 0 here since that's the proper
# acknowledgement to an OACK.
# FIXME: perhaps we do need a TftpStateExpectOACK class...
if self.state.state == 'rrq':
logger.debug("Received RRQ. Composing response.")
self.filename = self.root + os.sep + recvpkt.filename
logger.debug("The path to the desired file is %s" %
self.filename)
self.filename = os.path.abspath(self.filename)
logger.debug("The absolute path is %s" % self.filename)
# Security check. Make sure it's prefixed by the tftproot.
if re.match(r'%s' % self.root, self.filename):
logger.debug("The path appears to be safe: %s" %
self.filename)
else:
logger.error("Insecure path: %s" % self.filename)
self.errors += 1
self.senderror(self.sock,
TftpErrors.AccessViolation,
raddress,
rport)
raise TftpException, "Insecure path: %s" % self.filename
# Does the file exist?
if os.path.exists(self.filename):
logger.debug("File %s exists." % self.filename)
# Check options. Currently we only support the blksize
# option.
if recvpkt.options.has_key('blksize'):
logger.debug("RRQ includes a blksize option")
blksize = int(recvpkt.options['blksize'])
if blksize >= MIN_BLKSIZE and blksize <= MAX_BLKSIZE:
logger.debug("Client requested blksize = %d"
% blksize)
def handle(self, pkt, raddress, rport):
"""Handle a packet we just received."""
logger.debug("Using TFTPStateServerStart.handle")
if isinstance(pkt, TftpPacketRRQ):
logger.debug("Handling an RRQ packet")
return TFTPStateServerRecvRRQ(self.context).handle(pkt, raddress, rport)
elif isinstance(pkt, TftpPacketWRQ):
logger.debug("Handling a WRQ packet")
return TFTPStateServerRecvWRQ(self.context).handle(pkt, raddress, rport)
else:
self.sendError(tftpy.TftpErrors.IllegalTftpOp)
raise TftpException("Invalid packet to begin upload/download: %s" % pkt)
logger.debug("Setting default options, blksize")
self.context.options = {"blksize": tftpy.DEF_BLKSIZE}
if options:
logger.debug("Options requested: %s", options)
supported_options = self.returnSupportedOptions(options)
self.context.options.update(supported_options)
sendoack = True
# FIXME - only octet mode is supported at this time.
if pkt.mode != "octet":
logger.info("Received non-octet mode request. Replying with binary data.")
# test host/port of client end
if self.context.host != raddress or self.context.port != rport:
self.sendError(TftpErrors.UnknownTID)
logger.error(
"Expected traffic from %s:%s but received it from %s:%s instead."
% (self.context.host, self.context.port, raddress, rport)
)
# Return same state, we're still waiting for valid traffic.
return self
logger.debug("Requested filename is %s", pkt.filename)
if pkt.filename.startswith(self.context.root):
full_path = pkt.filename
else:
full_path = os.path.join(self.context.root, pkt.filename.lstrip("/"))
try:
logger.info("Full path of file to be uploaded is {}".format(full_path))
self.full_path = full_path
except fs.errors.FSError:
logger.warning("requested file is not within the server root - bad")
self.senderror(self.sock,
TftpErrors.FailedNegotiation,
self.host,
self.port)
raise TftpException, "Failed option negotiation"
else:
logger.debug("Client %s requested no options."
% self.key)
self.start_download()
else:
logger.error("Requested file %s does not exist." %
self.filename)
self.senderror(self.sock,
TftpErrors.FileNotFound,
raddress,
rport)
raise TftpException, "Requested file not found: %s" % self.filename
else:
# We're receiving an RRQ when we're not expecting one.
logger.error("Received an RRQ in handler %s "
"but we're in state %s" % (self.key, self.state))
self.errors += 1
# Next packet type
elif isinstance(recvpkt, TftpPacketACK):
logger.debug("Received an ACK from the client.")
if recvpkt.blocknumber == 0 and self.state.state == 'oack':
logger.debug("Received ACK with 0 blocknumber, starting download")
self.start_download()
self.options['blksize'] = blksize
else:
logger.warning("Client %s requested invalid "
"blocksize %d, responding with default"
% (self.key, blksize))
self.options['blksize'] = DEF_BLKSIZE
logger.debug("Composing and sending OACK packet")
self.send_oack()
elif len(recvpkt.options.keys()) > 0:
logger.warning("Client %s requested unsupported options: %s"
% (self.key, recvpkt.options))
logger.warning("Responding with negotiation error")
self.senderror(self.sock,
TftpErrors.FailedNegotiation,
self.host,
self.port)
raise TftpException, "Failed option negotiation"
else:
logger.debug("Client %s requested no options."
% self.key)
self.start_download()
else:
logger.error("Requested file %s does not exist." %
self.filename)
self.senderror(self.sock,
TftpErrors.FileNotFound,
raddress,
rport)
"Expected traffic from %s:%s but received it from %s:%s instead."
% (self.context.host, self.context.port, raddress, rport)
)
# Return same state, we're still waiting for valid traffic.
return self
logger.debug("Requested filename is %s", pkt.filename)
if pkt.filename.startswith(self.context.root):
full_path = pkt.filename
else:
full_path = os.path.join(self.context.root, pkt.filename.lstrip("/"))
try:
logger.info("Full path of file to be uploaded is {}".format(full_path))
self.full_path = full_path
except fs.errors.FSError:
logger.warning("requested file is not within the server root - bad")
self.sendError(TftpErrors.IllegalTftpOp)
raise TftpException("Bad file path")
self.context.file_to_transfer = pkt.filename
return sendoack
logger.info(" %s = %s" % (key, self.options[key]))
logger.debug("sending ACK to OACK")
ackpkt = TftpPacketACK()
ackpkt.blocknumber = 0
self.sock.sendto(ackpkt.encode().buffer, (self.host, self.port))
self.state.state = 'ack'
else:
logger.error("failed to negotiate options")
self.senderror(self.sock, TftpErrors.FailedNegotiation, self.host, self.port)
self.state.state = 'err'
raise TftpException, "Failed to negotiate options"
elif isinstance(recvpkt, TftpPacketACK):
# Umm, we ACK, the server doesn't.
self.state.state = 'err'
self.senderror(self.sock, TftpErrors.IllegalTftpOp, self.host, self.port)
tftpassert(False, "Received ACK from server while in download")
elif isinstance(recvpkt, TftpPacketERR):
self.state.state = 'err'
self.senderror(self.sock, TftpErrors.IllegalTftpOp, self.host, self.port)
tftpassert(False, "Received ERR from server: " + str(recvpkt))
elif isinstance(recvpkt, TftpPacketWRQ):
self.state.state = 'err'
self.senderror(self.sock, TftpErrors.IllegalTftpOp, self.host, self.port)
tftpassert(False, "Received WRQ from server: " + str(recvpkt))
else:
self.state.state = 'err'
self.senderror(self.sock, TftpErrors.IllegalTftpOp, self.host, self.port)
tftpassert(False, "Received unknown packet type from server: "