Beispiel #1
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;
}
Beispiel #2
0
/*
 Open a file using NTTRANS CREATE - async send 
*/
static struct smbcli_request *smb_raw_nttrans_create_send(struct smbcli_tree *tree, 
							  union smb_open *parms)
{
	struct smb_nttrans nt;
	uint8_t *params;
	TALLOC_CTX *mem_ctx = talloc_new(tree);
	uint16_t fname_len;
	DATA_BLOB sd_blob, ea_blob;
	struct smbcli_request *req;

	nt.in.max_setup = 0;
	nt.in.max_param = 101;
	nt.in.max_data  = 0;
	nt.in.setup_count = 0;
	nt.in.function = NT_TRANSACT_CREATE;
	nt.in.setup = NULL;

	sd_blob = data_blob(NULL, 0);
	ea_blob = data_blob(NULL, 0);

	if (parms->ntcreatex.in.sec_desc) {
		enum ndr_err_code ndr_err;
		ndr_err = ndr_push_struct_blob(&sd_blob, mem_ctx, 
					       parms->ntcreatex.in.sec_desc,
					       (ndr_push_flags_fn_t)ndr_push_security_descriptor);
		if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
			talloc_free(mem_ctx);
			return NULL;
		}
	}

	if (parms->ntcreatex.in.ea_list) {
		uint32_t ea_size = ea_list_size_chained(parms->ntcreatex.in.ea_list->num_eas,
							parms->ntcreatex.in.ea_list->eas, 4);
		ea_blob = data_blob_talloc(mem_ctx, NULL, ea_size);
		if (ea_blob.data == NULL) {
			return NULL;
		}
		ea_put_list_chained(ea_blob.data, 
				    parms->ntcreatex.in.ea_list->num_eas,
				    parms->ntcreatex.in.ea_list->eas, 4);
	}

	nt.in.params = data_blob_talloc(mem_ctx, NULL, 53);
	if (nt.in.params.data == NULL) {
		talloc_free(mem_ctx);
		return NULL;
	}

	/* build the parameter section */
	params = nt.in.params.data;

	SIVAL(params,  0, parms->ntcreatex.in.flags);
	SIVAL(params,  4, parms->ntcreatex.in.root_fid.fnum);
	SIVAL(params,  8, parms->ntcreatex.in.access_mask);
	SBVAL(params, 12, parms->ntcreatex.in.alloc_size);
	SIVAL(params, 20, parms->ntcreatex.in.file_attr);
	SIVAL(params, 24, parms->ntcreatex.in.share_access);
	SIVAL(params, 28, parms->ntcreatex.in.open_disposition);
	SIVAL(params, 32, parms->ntcreatex.in.create_options);
	SIVAL(params, 36, sd_blob.length);
	SIVAL(params, 40, ea_blob.length);
	SIVAL(params, 48, parms->ntcreatex.in.impersonation);
	SCVAL(params, 52, parms->ntcreatex.in.security_flags);

	/* the empty string first forces the correct alignment */
	smbcli_blob_append_string(tree->session, mem_ctx, &nt.in.params,"", 0);
	fname_len = smbcli_blob_append_string(tree->session, mem_ctx, &nt.in.params,
					      parms->ntcreatex.in.fname, STR_TERMINATE);

	SIVAL(nt.in.params.data, 44, fname_len);

	/* build the data section */
	nt.in.data = data_blob_talloc(mem_ctx, NULL, sd_blob.length + ea_blob.length);
	memcpy(nt.in.data.data, sd_blob.data, sd_blob.length);
	memcpy(nt.in.data.data+sd_blob.length, ea_blob.data, ea_blob.length);

	/* send the request on its way */
	req = smb_raw_nttrans_send(tree, &nt);

	talloc_free(mem_ctx);
	
	return req;
}
Beispiel #3
0
NTSTATUS smbsrv_push_passthru_fileinfo(TALLOC_CTX *mem_ctx,
				       DATA_BLOB *blob,
				       enum smb_fileinfo_level level,
				       union smb_fileinfo *st,
				       int default_str_flags)
{
	uint_t i;
	size_t list_size;

	switch (level) {
	case RAW_FILEINFO_BASIC_INFORMATION:
		BLOB_CHECK(smbsrv_blob_grow_data(mem_ctx, blob, 40));

		push_nttime(blob->data,  0, st->basic_info.out.create_time);
		push_nttime(blob->data,  8, st->basic_info.out.access_time);
		push_nttime(blob->data, 16, st->basic_info.out.write_time);
		push_nttime(blob->data, 24, st->basic_info.out.change_time);
		SIVAL(blob->data,       32, st->basic_info.out.attrib);
		SIVAL(blob->data,       36, 0); /* padding */
		return NT_STATUS_OK;

	case RAW_FILEINFO_NETWORK_OPEN_INFORMATION:
		BLOB_CHECK(smbsrv_blob_grow_data(mem_ctx, blob, 56));

		push_nttime(blob->data,  0, st->network_open_information.out.create_time);
		push_nttime(blob->data,  8, st->network_open_information.out.access_time);
		push_nttime(blob->data, 16, st->network_open_information.out.write_time);
		push_nttime(blob->data, 24, st->network_open_information.out.change_time);
		SBVAL(blob->data,       32, st->network_open_information.out.alloc_size);
		SBVAL(blob->data,       40, st->network_open_information.out.size);
		SIVAL(blob->data,       48, st->network_open_information.out.attrib);
		SIVAL(blob->data,       52, 0); /* padding */
		return NT_STATUS_OK;

	case RAW_FILEINFO_STANDARD_INFORMATION:
		BLOB_CHECK(smbsrv_blob_grow_data(mem_ctx, blob, 24));

		SBVAL(blob->data,  0, st->standard_info.out.alloc_size);
		SBVAL(blob->data,  8, st->standard_info.out.size);
		SIVAL(blob->data, 16, st->standard_info.out.nlink);
		SCVAL(blob->data, 20, st->standard_info.out.delete_pending);
		SCVAL(blob->data, 21, st->standard_info.out.directory);
		SSVAL(blob->data, 22, 0); /* padding */
		return NT_STATUS_OK;

	case RAW_FILEINFO_ATTRIBUTE_TAG_INFORMATION:
		BLOB_CHECK(smbsrv_blob_grow_data(mem_ctx, blob, 8));

		SIVAL(blob->data,  0, st->attribute_tag_information.out.attrib);
		SIVAL(blob->data,  4, st->attribute_tag_information.out.reparse_tag);
		return NT_STATUS_OK;

	case RAW_FILEINFO_EA_INFORMATION:
		BLOB_CHECK(smbsrv_blob_grow_data(mem_ctx, blob, 4));

		SIVAL(blob->data,  0, st->ea_info.out.ea_size);
		return NT_STATUS_OK;

	case RAW_FILEINFO_MODE_INFORMATION:
		BLOB_CHECK(smbsrv_blob_grow_data(mem_ctx, blob, 4));

		SIVAL(blob->data,  0, st->mode_information.out.mode);
		return NT_STATUS_OK;

	case RAW_FILEINFO_ALIGNMENT_INFORMATION:
		BLOB_CHECK(smbsrv_blob_grow_data(mem_ctx, blob, 4));

		SIVAL(blob->data,  0, 
		      st->alignment_information.out.alignment_requirement);
		return NT_STATUS_OK;

	case RAW_FILEINFO_ACCESS_INFORMATION:
		BLOB_CHECK(smbsrv_blob_grow_data(mem_ctx, blob, 4));

		SIVAL(blob->data,  0, st->access_information.out.access_flags);
		return NT_STATUS_OK;

	case RAW_FILEINFO_POSITION_INFORMATION:
		BLOB_CHECK(smbsrv_blob_grow_data(mem_ctx, blob, 8));

		SBVAL(blob->data,  0, st->position_information.out.position);
		return NT_STATUS_OK;

	case RAW_FILEINFO_COMPRESSION_INFORMATION:
		BLOB_CHECK(smbsrv_blob_grow_data(mem_ctx, blob, 16));

		SBVAL(blob->data,  0, st->compression_info.out.compressed_size);
		SSVAL(blob->data,  8, st->compression_info.out.format);
		SCVAL(blob->data, 10, st->compression_info.out.unit_shift);
		SCVAL(blob->data, 11, st->compression_info.out.chunk_shift);
		SCVAL(blob->data, 12, st->compression_info.out.cluster_shift);
		SSVAL(blob->data, 13, 0); /* 3 bytes padding */
		SCVAL(blob->data, 15, 0);
		return NT_STATUS_OK;

	case RAW_FILEINFO_INTERNAL_INFORMATION:
		BLOB_CHECK(smbsrv_blob_grow_data(mem_ctx, blob, 8));

		SBVAL(blob->data,  0, st->internal_information.out.file_id);
		return NT_STATUS_OK;

	case RAW_FILEINFO_ALL_INFORMATION:
		BLOB_CHECK(smbsrv_blob_grow_data(mem_ctx, blob, 72));

		push_nttime(blob->data,  0, st->all_info.out.create_time);
		push_nttime(blob->data,  8, st->all_info.out.access_time);
		push_nttime(blob->data, 16, st->all_info.out.write_time);
		push_nttime(blob->data, 24, st->all_info.out.change_time);
		SIVAL(blob->data,       32, st->all_info.out.attrib);
		SIVAL(blob->data,       36, 0); /* padding */
		SBVAL(blob->data,       40, st->all_info.out.alloc_size);
		SBVAL(blob->data,       48, st->all_info.out.size);
		SIVAL(blob->data,       56, st->all_info.out.nlink);
		SCVAL(blob->data,       60, st->all_info.out.delete_pending);
		SCVAL(blob->data,       61, st->all_info.out.directory);
		SSVAL(blob->data,       62, 0); /* padding */
		SIVAL(blob->data,       64, st->all_info.out.ea_size);
		BLOB_CHECK(smbsrv_blob_append_string(mem_ctx, blob,
						     st->all_info.out.fname.s,
						     68, default_str_flags,
						     STR_UNICODE));
		return NT_STATUS_OK;

	case RAW_FILEINFO_NAME_INFORMATION:
		BLOB_CHECK(smbsrv_blob_grow_data(mem_ctx, blob, 4));

		BLOB_CHECK(smbsrv_blob_append_string(mem_ctx, blob,
						     st->name_info.out.fname.s,
						     0, default_str_flags,
						     STR_UNICODE));
		return NT_STATUS_OK;

	case RAW_FILEINFO_ALT_NAME_INFORMATION:
		BLOB_CHECK(smbsrv_blob_grow_data(mem_ctx, blob, 4));

		BLOB_CHECK(smbsrv_blob_append_string(mem_ctx, blob, 
						     st->alt_name_info.out.fname.s,
						     0, default_str_flags,
						     STR_UNICODE));
		return NT_STATUS_OK;

	case RAW_FILEINFO_STREAM_INFORMATION:
		for (i=0;i<st->stream_info.out.num_streams;i++) {
			uint32_t data_size = blob->length;
			uint8_t *data;

			BLOB_CHECK(smbsrv_blob_grow_data(mem_ctx, blob, data_size + 24));
			data = blob->data + data_size;
			SBVAL(data,  8, st->stream_info.out.streams[i].size);
			SBVAL(data, 16, st->stream_info.out.streams[i].alloc_size);
			BLOB_CHECK(smbsrv_blob_append_string(mem_ctx, blob,
							     st->stream_info.out.streams[i].stream_name.s,
							     data_size + 4, default_str_flags,
							     STR_UNICODE));
			if (i == st->stream_info.out.num_streams - 1) {
				SIVAL(blob->data, data_size, 0);
			} else {
				BLOB_CHECK(smbsrv_blob_fill_data(mem_ctx, blob, (blob->length+7)&~7));
				SIVAL(blob->data, data_size, 
				      blob->length - data_size);
			}
		}
		return NT_STATUS_OK;

	case RAW_FILEINFO_SMB2_ALL_EAS:
		/* if no eas are returned the backend should
		 * have returned NO_EAS_ON_FILE or NO_MORE_EAS
		 *
		 * so it's a programmer error if num_eas == 0
		 */
		if (st->all_eas.out.num_eas == 0) {
			smb_panic("0 eas for SMB2_ALL_EAS - programmer error in ntvfs backend");
		}

		list_size = ea_list_size_chained(st->all_eas.out.num_eas,
						 st->all_eas.out.eas);
		BLOB_CHECK(smbsrv_blob_grow_data(mem_ctx, blob, list_size));

		ea_put_list_chained(blob->data,
				    st->all_eas.out.num_eas,
				    st->all_eas.out.eas);
		return NT_STATUS_OK;

	case RAW_FILEINFO_SMB2_ALL_INFORMATION:
		BLOB_CHECK(smbsrv_blob_grow_data(mem_ctx, blob, 0x64));

		push_nttime(blob->data, 0x00, st->all_info2.out.create_time);
		push_nttime(blob->data, 0x08, st->all_info2.out.access_time);
		push_nttime(blob->data, 0x10, st->all_info2.out.write_time);
		push_nttime(blob->data, 0x18, st->all_info2.out.change_time);
		SIVAL(blob->data,       0x20, st->all_info2.out.attrib);
		SIVAL(blob->data,       0x24, st->all_info2.out.unknown1);
		SBVAL(blob->data,       0x28, st->all_info2.out.alloc_size);
		SBVAL(blob->data,       0x30, st->all_info2.out.size);
		SIVAL(blob->data,       0x38, st->all_info2.out.nlink);
		SCVAL(blob->data,       0x3C, st->all_info2.out.delete_pending);
		SCVAL(blob->data,       0x3D, st->all_info2.out.directory);
		SSVAL(blob->data,       0x3E, 0); /* padding */
		SBVAL(blob->data,	0x40, st->all_info2.out.file_id);
		SIVAL(blob->data,       0x48, st->all_info2.out.ea_size);
		SIVAL(blob->data,	0x4C, st->all_info2.out.access_mask);
		SBVAL(blob->data,	0x50, st->all_info2.out.position);
		SBVAL(blob->data,	0x58, st->all_info2.out.mode);
		BLOB_CHECK(smbsrv_blob_append_string(mem_ctx, blob,
						     st->all_info2.out.fname.s,
						     0x60, default_str_flags,
						     STR_UNICODE));
		return NT_STATUS_OK;

	default:
		return NT_STATUS_INVALID_LEVEL;
	}

	return NT_STATUS_INVALID_LEVEL;
}
Beispiel #4
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;
}