Пример #1
0
/*
  pull a string from a blob in a trans2 request
*/
size_t smbsrv_blob_pull_string(struct smbsrv_request *req, 
			       const DATA_BLOB *blob,
			       uint16_t offset,
			       const char **str,
			       int flags)
{
	*str = NULL;
	/* we use STR_NO_RANGE_CHECK because the params are allocated
	   separately in a DATA_BLOB, so we need to do our own range
	   checking */
	if (offset >= blob->length) {
		return 0;
	}
	
	return req_pull_string(req, str, 
			       blob->data + offset, 
			       blob->length - offset,
			       STR_NO_RANGE_CHECK | flags);
}
Пример #2
0
/**
  pull a ASCII4 string buffer from a request packet, returning a talloced string
  
  an ASCII4 buffer is a null terminated string that has a prefix
  of the character 0x4. It tends to be used in older parts of the protocol.

  on failure *dest is set to the zero length string. This seems to
  match win2000 behaviour
*/
size_t req_pull_ascii4(struct request_bufinfo *bufinfo, const char **dest, const uint8_t *src, unsigned int flags)
{
	ssize_t ret;

	if (PTR_DIFF(src, bufinfo->data) + 1 > bufinfo->data_size) {
		/* win2000 treats this as the empty string! */
		(*dest) = talloc_strdup(bufinfo->mem_ctx, "");
		return 0;
	}

	/* this consumes the 0x4 byte. We don't check whether the byte
	   is actually 0x4 or not. This matches win2000 server
	   behaviour */
	src++;

	ret = req_pull_string(bufinfo, dest, src, -1, flags);
	if (ret == -1) {
		(*dest) = talloc_strdup(bufinfo->mem_ctx, "");
		return 1;
	}
	
	return ret + 1;
}
Пример #3
0
/*
  Reply to an SMBtrans or SMBtrans2 request
*/
static void reply_trans_generic(struct smbsrv_request *req, uint8_t command)
{
	struct smb_trans2 *trans;
	int i;
	uint16_t param_ofs, data_ofs;
	uint16_t param_count, data_count;
	uint16_t param_total, data_total;

	/* parse request */
	if (req->in.wct < 14) {
		smbsrv_send_error(req, NT_STATUS_INVALID_PARAMETER);
		return;
	}

	trans = talloc(req, struct smb_trans2);
	if (trans == NULL) {
		smbsrv_send_error(req, NT_STATUS_NO_MEMORY);
		return;
	}

	param_total           = SVAL(req->in.vwv, VWV(0));
	data_total            = SVAL(req->in.vwv, VWV(1));
	trans->in.max_param   = SVAL(req->in.vwv, VWV(2));
	trans->in.max_data    = SVAL(req->in.vwv, VWV(3));
	trans->in.max_setup   = CVAL(req->in.vwv, VWV(4));
	trans->in.flags       = SVAL(req->in.vwv, VWV(5));
	trans->in.timeout     = IVAL(req->in.vwv, VWV(6));
	param_count           = SVAL(req->in.vwv, VWV(9));
	param_ofs             = SVAL(req->in.vwv, VWV(10));
	data_count            = SVAL(req->in.vwv, VWV(11));
	data_ofs              = SVAL(req->in.vwv, VWV(12));
	trans->in.setup_count = CVAL(req->in.vwv, VWV(13));

	if (req->in.wct != 14 + trans->in.setup_count) {
		smbsrv_send_error(req, NT_STATUS_DOS(ERRSRV, ERRerror));
		return;
	}

	/* parse out the setup words */
	trans->in.setup = talloc_array(trans, uint16_t, trans->in.setup_count);
	if (trans->in.setup_count && !trans->in.setup) {
		smbsrv_send_error(req, NT_STATUS_NO_MEMORY);
		return;
	}
	for (i=0;i<trans->in.setup_count;i++) {
		trans->in.setup[i] = SVAL(req->in.vwv, VWV(14+i));
	}

	if (command == SMBtrans) {
		req_pull_string(&req->in.bufinfo, &trans->in.trans_name, req->in.data, -1, STR_TERMINATE);
	}

	if (!req_pull_blob(&req->in.bufinfo, req->in.hdr + param_ofs, param_count, &trans->in.params) ||
	    !req_pull_blob(&req->in.bufinfo, req->in.hdr + data_ofs, data_count, &trans->in.data)) {
		smbsrv_send_error(req, NT_STATUS_FOOBAR);
		return;
	}

	/* is it a partial request? if so, then send a 'send more' message */
	if (param_total > param_count || data_total > data_count) {
		reply_trans_continue(req, command, trans);
		return;
	}

	reply_trans_complete(req, command, trans);
}
Пример #4
0
/* 
   parse NTTRANS_CREATE request
 */
static NTSTATUS nttrans_create(struct smbsrv_request *req, 
			       struct nttrans_op *op)
{
	struct smb_nttrans *trans = op->trans;
	union smb_open *io;
	uint16_t fname_len;
	uint32_t sd_length, ea_length;
	NTSTATUS status;
	uint8_t *params;
	enum ndr_err_code ndr_err;

	if (trans->in.params.length < 54) {
		return NT_STATUS_INVALID_PARAMETER;
	}

	/* parse the request */
	io = talloc(op, union smb_open);
	NT_STATUS_HAVE_NO_MEMORY(io);

	io->ntcreatex.level = RAW_OPEN_NTTRANS_CREATE;

	params = trans->in.params.data;

	io->ntcreatex.in.flags            = IVAL(params,  0);
	io->ntcreatex.in.root_fid.ntvfs   = smbsrv_pull_fnum(req, params, 4);
	io->ntcreatex.in.access_mask      = IVAL(params,  8);
	io->ntcreatex.in.alloc_size       = BVAL(params, 12);
	io->ntcreatex.in.file_attr        = IVAL(params, 20);
	io->ntcreatex.in.share_access     = IVAL(params, 24);
	io->ntcreatex.in.open_disposition = IVAL(params, 28);
	io->ntcreatex.in.create_options   = IVAL(params, 32);
	sd_length                         = IVAL(params, 36);
	ea_length                         = IVAL(params, 40);
	fname_len                         = IVAL(params, 44);
	io->ntcreatex.in.impersonation    = IVAL(params, 48);
	io->ntcreatex.in.security_flags   = CVAL(params, 52);
	io->ntcreatex.in.sec_desc         = NULL;
	io->ntcreatex.in.ea_list          = NULL;
	io->ntcreatex.in.query_maximal_access = false;
	io->ntcreatex.in.query_on_disk_id = false;
	io->ntcreatex.in.private_flags    = 0;

	req_pull_string(&req->in.bufinfo, &io->ntcreatex.in.fname, 
			params + 53, 
			MIN(fname_len+1, trans->in.params.length - 53),
			STR_NO_RANGE_CHECK | STR_TERMINATE);
	if (!io->ntcreatex.in.fname) {
		return NT_STATUS_INVALID_PARAMETER;
	}

	if (sd_length > trans->in.data.length ||
	    ea_length > trans->in.data.length ||
	    (sd_length+ea_length) > trans->in.data.length) {
		return NT_STATUS_INVALID_PARAMETER;
	}

	/* this call has an optional security descriptor */
	if (sd_length != 0) {
		DATA_BLOB blob;
		blob.data = trans->in.data.data;
		blob.length = sd_length;
		io->ntcreatex.in.sec_desc = talloc(io, struct security_descriptor);
		if (io->ntcreatex.in.sec_desc == NULL) {
			return NT_STATUS_NO_MEMORY;
		}
		ndr_err = ndr_pull_struct_blob(&blob, io, 
					       io->ntcreatex.in.sec_desc,
					       (ndr_pull_flags_fn_t)ndr_pull_security_descriptor);
		if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
			return ndr_map_error2ntstatus(ndr_err);
		}
	}