Example #1
0
/*
  send a find request
*/
struct smb2_request *smb2_find_send(struct smb2_tree *tree, struct smb2_find *io)
{
    struct smb2_request *req;
    NTSTATUS status;

    req = smb2_request_init_tree(tree, SMB2_OP_QUERY_DIRECTORY, 0x20, true, 0);
    if (req == NULL) return NULL;

    SCVAL(req->out.body, 0x02, io->in.level);
    SCVAL(req->out.body, 0x03, io->in.continue_flags);
    SIVAL(req->out.body, 0x04, io->in.file_index);
    smb2_push_handle(req->out.body+0x08, &io->in.file.handle);

    status = smb2_push_o16s16_string(&req->out, 0x18, io->in.pattern);
    if (!NT_STATUS_IS_OK(status)) {
        talloc_free(req);
        return NULL;
    }

    SIVAL(req->out.body, 0x1C, io->in.max_response_size);

    smb2_transport_send(req);

    return req;
}
Example #2
0
/*
  send a create request
*/
struct smb2_request *smb2_create_send(struct smb2_tree *tree, struct smb2_create *io)
{
	struct smb2_request *req;
	NTSTATUS status;
	DATA_BLOB blob = data_blob(NULL, 0);

	req = smb2_request_init_tree(tree, SMB2_OP_CREATE, 0x38, True, 0);
	if (req == NULL) return NULL;

	SSVAL(req->out.body, 0x02, io->in.oplock_flags);
	SIVAL(req->out.body, 0x04, io->in.impersonation);
	SIVAL(req->out.body, 0x08, io->in.unknown3[0]);
	SIVAL(req->out.body, 0x0C, io->in.unknown3[1]);
	SIVAL(req->out.body, 0x10, io->in.unknown3[2]);
	SIVAL(req->out.body, 0x14, io->in.unknown3[3]);
	SIVAL(req->out.body, 0x18, io->in.access_mask);
	SIVAL(req->out.body, 0x1C, io->in.file_attr);
	SIVAL(req->out.body, 0x20, io->in.share_access);
	SIVAL(req->out.body, 0x24, io->in.open_disposition);
	SIVAL(req->out.body, 0x28, io->in.create_options);

	status = smb2_push_o16s16_string(&req->out, 0x2C, io->in.fname);
	if (!NT_STATUS_IS_OK(status)) {
		talloc_free(req);
		return NULL;
	}

	if (io->in.eas.num_eas != 0) {
		DATA_BLOB b = data_blob_talloc(req, NULL, 
					       ea_list_size_chained(io->in.eas.num_eas, io->in.eas.eas));
		ea_put_list_chained(b.data, io->in.eas.num_eas, io->in.eas.eas);
		status = smb2_create_blob_add(req, &blob, CREATE_TAG_EXTA, b, False);
		if (!NT_STATUS_IS_OK(status)) {
			talloc_free(req);
			return NULL;
		}
		data_blob_free(&b);
	}

	/* an empty MxAc tag seems to be used to ask the server to
	   return the maximum access mask allowed on the file */
	status = smb2_create_blob_add(req, &blob, CREATE_TAG_MXAC, data_blob(NULL, 0), True);

	if (!NT_STATUS_IS_OK(status)) {
		talloc_free(req);
		return NULL;
	}
	status = smb2_push_o32s32_blob(&req->out, 0x30, blob);
	if (!NT_STATUS_IS_OK(status)) {
		talloc_free(req);
		return NULL;
	}

	smb2_transport_send(req);

	return req;
}
Example #3
0
/*
  Send a Lease Break Acknowledgement
*/
struct smb2_request *smb2_lease_break_ack_send(struct smb2_tree *tree,
                                               struct smb2_lease_break_ack *io)
{
	struct smb2_request *req;

	req = smb2_request_init_tree(tree, SMB2_OP_BREAK, 0x24, false, 0);
	if (req == NULL) return NULL;

	SIVAL(req->out.body, 0x02, io->in.reserved);
	SIVAL(req->out.body, 0x04, io->in.lease.lease_flags);
	memcpy(req->out.body+0x8, &io->in.lease.lease_key,
	    sizeof(struct smb2_lease_key));
	SIVAL(req->out.body, 0x18, io->in.lease.lease_state);
	SBVAL(req->out.body, 0x1C, io->in.lease.lease_duration);

	smb2_transport_send(req);

	return req;
}
Example #4
0
/*
  send a read request
*/
struct smb2_request *smb2_read_send(struct smb2_tree *tree, struct smb2_read *io)
{
	struct smb2_request *req;

	req = smb2_request_init_tree(tree, SMB2_OP_READ, 0x30, true, 0);
	if (req == NULL) return NULL;

	SCVAL(req->out.body, 0x02, 0); /* pad */
	SCVAL(req->out.body, 0x03, 0); /* reserved */
	SIVAL(req->out.body, 0x04, io->in.length);
	SBVAL(req->out.body, 0x08, io->in.offset);
	smb2_push_handle(req->out.body+0x10, &io->in.file.handle);
	SIVAL(req->out.body, 0x20, io->in.min_count);
	SIVAL(req->out.body, 0x24, io->in.channel);
	SIVAL(req->out.body, 0x28, io->in.remaining);
	SSVAL(req->out.body, 0x2C, io->in.channel_offset);
	SSVAL(req->out.body, 0x2E, io->in.channel_length);

	req->credit_charge = (MAX(io->in.length, 1) - 1)/ 65536 + 1;

	smb2_transport_send(req);

	return req;
}
Example #5
0
/*
  send a write request
*/
struct smb2_request *smb2_write_send(struct smb2_tree *tree, struct smb2_write *io)
{
	NTSTATUS status;
	struct smb2_request *req;

	req = smb2_request_init_tree(tree, SMB2_OP_WRITE, 0x30, true, io->in.data.length);
	if (req == NULL) return NULL;

	status = smb2_push_o16s32_blob(&req->out, 0x02, io->in.data);
	if (!NT_STATUS_IS_OK(status)) {
		talloc_free(req);
		return NULL;
	}

	SBVAL(req->out.body, 0x08, io->in.offset);
	smb2_push_handle(req->out.body+0x10, &io->in.file.handle);

	SBVAL(req->out.body, 0x20, io->in.unknown1);
	SBVAL(req->out.body, 0x28, io->in.unknown2);

	smb2_transport_send(req);

	return req;
}
Example #6
0
/*
  send a create request
*/
struct smb2_request *smb2_create_send(struct smb2_tree *tree, struct smb2_create *io)
{
	struct smb2_request *req;
	NTSTATUS status;
	DATA_BLOB blob;
	struct smb2_create_blobs blobs;
	int i;

	ZERO_STRUCT(blobs);

	req = smb2_request_init_tree(tree, SMB2_OP_CREATE, 0x38, true, 0);
	if (req == NULL) return NULL;

	SCVAL(req->out.body, 0x02, io->in.security_flags);
	SCVAL(req->out.body, 0x03, io->in.oplock_level);
	SIVAL(req->out.body, 0x04, io->in.impersonation_level);
	SBVAL(req->out.body, 0x08, io->in.create_flags);
	SBVAL(req->out.body, 0x10, io->in.reserved);
	SIVAL(req->out.body, 0x18, io->in.desired_access);
	SIVAL(req->out.body, 0x1C, io->in.file_attributes);
	SIVAL(req->out.body, 0x20, io->in.share_access);
	SIVAL(req->out.body, 0x24, io->in.create_disposition);
	SIVAL(req->out.body, 0x28, io->in.create_options);

	status = smb2_push_o16s16_string(&req->out, 0x2C, io->in.fname);
	if (!NT_STATUS_IS_OK(status)) {
		talloc_free(req);
		return NULL;
	}

	/* now add all the optional blobs */
	if (io->in.eas.num_eas != 0) {
		DATA_BLOB b = data_blob_talloc(req, NULL, 
					       ea_list_size_chained(io->in.eas.num_eas, io->in.eas.eas, 4));
		ea_put_list_chained(b.data, io->in.eas.num_eas, io->in.eas.eas, 4);
		status = smb2_create_blob_add(req, &blobs,
					      SMB2_CREATE_TAG_EXTA, b);
		if (!NT_STATUS_IS_OK(status)) {
			talloc_free(req);
			return NULL;
		}
		data_blob_free(&b);
	}

	/* an empty MxAc tag seems to be used to ask the server to
	   return the maximum access mask allowed on the file */
	if (io->in.query_maximal_access) {
		/* TODO: MS-SMB2 2.2.13.2.5 says this can contain a timestamp? What to do
		   with that if it doesn't match? */
		status = smb2_create_blob_add(req, &blobs,
					      SMB2_CREATE_TAG_MXAC, data_blob(NULL, 0));
		if (!NT_STATUS_IS_OK(status)) {
			talloc_free(req);
			return NULL;
		}
	}

	if (io->in.alloc_size != 0) {
		uint8_t data[8];
		SBVAL(data, 0, io->in.alloc_size);
		status = smb2_create_blob_add(req, &blobs,
					      SMB2_CREATE_TAG_ALSI, data_blob_const(data, 8));
		if (!NT_STATUS_IS_OK(status)) {
			talloc_free(req);
			return NULL;
		}
	}

	if (io->in.durable_open) {
		status = smb2_create_blob_add(req, &blobs,
					      SMB2_CREATE_TAG_DHNQ, data_blob_talloc_zero(req, 16));
		if (!NT_STATUS_IS_OK(status)) {
			talloc_free(req);
			return NULL;
		}
	}

	if (io->in.durable_handle) {
		uint8_t data[16];
		smb2_push_handle(data, io->in.durable_handle);
		status = smb2_create_blob_add(req, &blobs,
					      SMB2_CREATE_TAG_DHNC, data_blob_const(data, 16));
		if (!NT_STATUS_IS_OK(status)) {
			talloc_free(req);
			return NULL;
		}
	}

	if (io->in.timewarp) {
		uint8_t data[8];
		SBVAL(data, 0, io->in.timewarp);		
		status = smb2_create_blob_add(req, &blobs,
					      SMB2_CREATE_TAG_TWRP, data_blob_const(data, 8));
		if (!NT_STATUS_IS_OK(status)) {
			talloc_free(req);
			return NULL;
		}
	}

	if (io->in.sec_desc) {
		enum ndr_err_code ndr_err;
		DATA_BLOB sd_blob;
		ndr_err = ndr_push_struct_blob(&sd_blob, req, io->in.sec_desc,
					       (ndr_push_flags_fn_t)ndr_push_security_descriptor);
		if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
			talloc_free(req);
			return NULL;
		}
		status = smb2_create_blob_add(req, &blobs,
					      SMB2_CREATE_TAG_SECD, sd_blob);
		if (!NT_STATUS_IS_OK(status)) {
			talloc_free(req);
			return NULL;
		}
	}

	if (io->in.query_on_disk_id) {
		status = smb2_create_blob_add(req, &blobs,
					      SMB2_CREATE_TAG_QFID, data_blob(NULL, 0));
		if (!NT_STATUS_IS_OK(status)) {
			talloc_free(req);
			return NULL;
		}
	}

	if (io->in.lease_request) {
		uint8_t data[32];

		memcpy(&data[0], &io->in.lease_request->lease_key, 16);
		SIVAL(data, 16, io->in.lease_request->lease_state);
		SIVAL(data, 20, io->in.lease_request->lease_flags);
		SBVAL(data, 24, io->in.lease_request->lease_duration);

		status = smb2_create_blob_add(req, &blobs,
					      SMB2_CREATE_TAG_RQLS,
					      data_blob_const(data, 32));
		if (!NT_STATUS_IS_OK(status)) {
			talloc_free(req);
			return NULL;
		}
	}

	/* and any custom blobs */
	for (i=0;i<io->in.blobs.num_blobs;i++) {
		status = smb2_create_blob_add(req, &blobs,
					      io->in.blobs.blobs[i].tag, 
					      io->in.blobs.blobs[i].data);
		if (!NT_STATUS_IS_OK(status)) {
			talloc_free(req);
			return NULL;
		}
	}


	status = smb2_create_blob_push(req, &blob, blobs);
	if (!NT_STATUS_IS_OK(status)) {
		talloc_free(req);
		return NULL;
	}

	status = smb2_push_o32s32_blob(&req->out, 0x30, blob);
	if (!NT_STATUS_IS_OK(status)) {
		talloc_free(req);
		return NULL;
	}

	data_blob_free(&blob);

	smb2_transport_send(req);

	return req;
}