Ejemplo n.º 1
0
 def test_exception_needs_newer(self):
     with pytest.raises(SMBUnsupportedFeature) as exc:
         raise SMBUnsupportedFeature(Dialects.SMB_3_0_0, Dialects.SMB_3_1_1,
                                     "feature", True)
     assert str(exc.value) == "feature is not available on the " \
                              "negotiated dialect (768) SMB_3_0_0, " \
                              "requires dialect (785) SMB_3_1_1 or newer"
Ejemplo n.º 2
0
    def read(self,
             offset,
             length,
             min_length=0,
             unbuffered=False,
             wait=True,
             send=True):
        """
        Reads from an opened file or pipe

        Supports out of band send function, call this function with send=False
        to return a tuple of (SMB2ReadRequest, receive_func) instead of
        sending the the request and waiting for the response. The receive_func
        can be used to get the response from the server by passing in the
        Request that was used to sent it out of band.

        :param offset: The offset to start the read of the file.
        :param length: The number of bytes to read from the offset.
        :param min_length: The minimum number of bytes to be read for a
            successful operation.
        :param unbuffered: Whether to the server should cache the read data at
            intermediate layers, only value for SMB 3.0.2 or newer
        :param wait: If send=True, whether to wait for a response if
            STATUS_PENDING was received from the server or fail.
        :param send: Whether to send the request in the same call or return the
            message to the caller and the unpack function
        :return: A byte string of the bytes read
        """
        if length > self.connection.max_read_size:
            raise SMBException("The requested read length %d is greater than "
                               "the maximum negotiated read size %d" %
                               (length, self.connection.max_read_size))

        read = SMB2ReadRequest()
        read['length'] = length
        read['offset'] = offset
        read['minimum_count'] = min_length
        read['file_id'] = self.file_id
        read['padding'] = b"\x50"

        if unbuffered:
            if self.connection.dialect < Dialects.SMB_3_0_2:
                raise SMBUnsupportedFeature(self.connection.dialect,
                                            Dialects.SMB_3_0_2,
                                            "SMB2_READFLAG_READ_UNBUFFERED",
                                            True)
            read['flags'].set_flag(ReadFlags.SMB2_READFLAG_READ_UNBUFFERED)

        if not send:
            return read, self._read_response

        log.info("Session: %s, Tree Connect ID: %s - sending SMB2 Read "
                 "Request for file %s" %
                 (self.tree_connect.session.username,
                  self.tree_connect.share_name, self.file_name))
        log.debug(str(read))
        request = self.connection.send(read,
                                       self.tree_connect.session.session_id,
                                       self.tree_connect.tree_connect_id)
        return self._read_response(request, wait)
Ejemplo n.º 3
0
    def write(self, data, offset=0, write_through=False, unbuffered=False,
              wait=True, send=True):
        """
        Writes data to an opened file.

        Supports out of band send function, call this function with send=False
        to return a tuple of (SMBWriteRequest, receive_func) instead of
        sending the the request and waiting for the response. The receive_func
        can be used to get the response from the server by passing in the
        Request that was used to sent it out of band.

        :param data: The bytes data to write.
        :param offset: The offset in the file to write the bytes at
        :param write_through: Whether written data is persisted to the
            underlying storage, not valid for SMB 2.0.2.
        :param unbuffered: Whether to the server should cache the write data at
            intermediate layers, only value for SMB 3.0.2 or newer
        :param wait: If send=True, whether to wait for a response if
            STATUS_PENDING was received from the server or fail.
        :param send: Whether to send the request in the same call or return the
            message to the caller and the unpack function
        :return: The number of bytes written
        """
        data_len = len(data)
        if data_len > self.connection.max_write_size:
            raise SMBException("The requested write length %d is greater than "
                               "the maximum negotiated write size %d"
                               % (data_len, self.connection.max_write_size))

        write = SMB2WriteRequest()
        write['length'] = len(data)
        write['offset'] = offset
        write['file_id'] = self.file_id
        write['buffer'] = data

        if write_through:
            if self.connection.dialect < Dialects.SMB_2_1_0:
                raise SMBUnsupportedFeature(self.connection.dialect,
                                            Dialects.SMB_2_1_0,
                                            "SMB2_WRITEFLAG_WRITE_THROUGH",
                                            True)
            write['flags'].set_flag(WriteFlags.SMB2_WRITEFLAG_WRITE_THROUGH)

        if unbuffered:
            if self.connection.dialect < Dialects.SMB_3_0_2:
                raise SMBUnsupportedFeature(self.connection.dialect,
                                            Dialects.SMB_3_0_2,
                                            "SMB2_WRITEFLAG_WRITE_UNBUFFERED",
                                            True)
            write['flags'].set_flag(WriteFlags.SMB2_WRITEFLAG_WRITE_UNBUFFERED)

        if not send:
            return write, self._write_response

        log.info("Session: %s, Tree Connect: %s - sending SMB2 Write Request "
                 "for file %s" % (self.tree_connect.session.username,
                                  self.tree_connect.share_name,
                                  self.file_name))
        log.debug(str(write))
        request = self.connection.send(write,
                                       self.tree_connect.session.session_id,
                                       self.tree_connect.tree_connect_id)
        return self._write_response(request, wait)