Пример #1
0
/*
 Open a file using TRANSACT2_OPEN - async recv
*/
static NTSTATUS smb_raw_nttrans_create_recv(struct smbcli_request *req, 
					    TALLOC_CTX *mem_ctx, 
					    union smb_open *parms)
{
	NTSTATUS status;
	struct smb_nttrans nt;
	uint8_t *params;

	status = smb_raw_nttrans_recv(req, mem_ctx, &nt);
	if (!NT_STATUS_IS_OK(status)) return status;

	if (nt.out.params.length < 69) {
		return NT_STATUS_INVALID_PARAMETER;
	}

	params = nt.out.params.data;

	parms->ntcreatex.out.oplock_level =                 CVAL(params, 0);
	parms->ntcreatex.out.file.fnum =                    SVAL(params, 2);
	parms->ntcreatex.out.create_action =                IVAL(params, 4);
	parms->ntcreatex.out.create_time =   smbcli_pull_nttime(params, 12);
	parms->ntcreatex.out.access_time =   smbcli_pull_nttime(params, 20);
	parms->ntcreatex.out.write_time =    smbcli_pull_nttime(params, 28);
	parms->ntcreatex.out.change_time =   smbcli_pull_nttime(params, 36);
	parms->ntcreatex.out.attrib =                      IVAL(params, 44);
	parms->ntcreatex.out.alloc_size =                  BVAL(params, 48);
	parms->ntcreatex.out.size =                        BVAL(params, 56);
	parms->ntcreatex.out.file_type =                   SVAL(params, 64);
	parms->ntcreatex.out.ipc_state =                   SVAL(params, 66);
	parms->ntcreatex.out.is_directory =                CVAL(params, 68);
	
	return NT_STATUS_OK;
}
Пример #2
0
/*
  recv a create reply
*/
NTSTATUS smb2_create_recv(struct smb2_request *req, TALLOC_CTX *mem_ctx, struct smb2_create *io)
{
	NTSTATUS status;

	if (!smb2_request_receive(req) || 
	    !smb2_request_is_ok(req)) {
		return smb2_request_destroy(req);
	}

	SMB2_CHECK_PACKET_RECV(req, 0x58, True);

	io->out.oplock_flags   = SVAL(req->in.body, 0x02);
	io->out.create_action  = IVAL(req->in.body, 0x04);
	io->out.create_time    = smbcli_pull_nttime(req->in.body, 0x08);
	io->out.access_time    = smbcli_pull_nttime(req->in.body, 0x10);
	io->out.write_time     = smbcli_pull_nttime(req->in.body, 0x18);
	io->out.change_time    = smbcli_pull_nttime(req->in.body, 0x20);
	io->out.alloc_size     = BVAL(req->in.body, 0x28);
	io->out.size           = BVAL(req->in.body, 0x30);
	io->out.file_attr      = IVAL(req->in.body, 0x38);
	io->out._pad           = IVAL(req->in.body, 0x3C);
	smb2_pull_handle(req->in.body+0x40, &io->out.file.handle);
	status = smb2_pull_o32s32_blob(&req->in, mem_ctx, req->in.body+0x50, &io->out.blob);
	if (!NT_STATUS_IS_OK(status)) {
		smb2_request_destroy(req);
		return status;
	}

	return smb2_request_destroy(req);
}
Пример #3
0
void smb2srv_negprot_recv(struct smb2srv_request *req)
{
	struct smb2_negprot *io;
	int i;

	if (req->in.body_size < 0x26) {
		smbsrv_terminate_connection(req->smb_conn, "Bad body size in SMB2 negprot");
		return;
	}

	io = talloc(req, struct smb2_negprot);
	if (!io) {
		smbsrv_terminate_connection(req->smb_conn, nt_errstr(NT_STATUS_NO_MEMORY));
		talloc_free(req);
		return;
	}

	io->in.dialect_count = SVAL(req->in.body, 0x02);
	io->in.security_mode = SVAL(req->in.body, 0x04);
	io->in.reserved      = SVAL(req->in.body, 0x06);
	io->in.capabilities  = IVAL(req->in.body, 0x08);
	req->status = smbcli_pull_guid(req->in.body, 0xC, &io->in.client_guid);
	if (!NT_STATUS_IS_OK(req->status)) {
		smbsrv_terminate_connection(req->smb_conn, "Bad GUID in SMB2 negprot");
		talloc_free(req);
		return;
	}
	io->in.start_time = smbcli_pull_nttime(req->in.body, 0x1C);

	io->in.dialects = talloc_array(req, uint16_t, io->in.dialect_count);
	if (io->in.dialects == NULL) {
		smbsrv_terminate_connection(req->smb_conn, nt_errstr(NT_STATUS_NO_MEMORY));
		talloc_free(req);
		return;
	}
	for (i=0;i<io->in.dialect_count;i++) {
		io->in.dialects[i] = SVAL(req->in.body, 0x24+i*2);
	}

	req->status = smb2srv_negprot_backend(req, io);

	if (req->control_flags & SMB2SRV_REQ_CTRL_FLAG_NOT_REPLY) {
		talloc_free(req);
		return;
	}
	smb2srv_negprot_send(req, io);
}
Пример #4
0
/*
 Send a negprot command.
*/
NTSTATUS smb_raw_negotiate_recv(struct smbcli_request *req)
{
	struct smbcli_transport *transport = req->transport;
	int protocol;

	if (!smbcli_request_receive(req) ||
	    smbcli_request_is_error(req)) {
		return smbcli_request_destroy(req);
	}

	SMBCLI_CHECK_MIN_WCT(req, 1);

	protocol = SVALS(req->in.vwv, VWV(0));

	if (protocol >= ARRAY_SIZE(prots) || protocol < 0) {
		req->status = NT_STATUS_UNSUCCESSFUL;
		return smbcli_request_destroy(req);
	}

	transport->negotiate.protocol = prots[protocol].prot;

	if (transport->negotiate.protocol >= PROTOCOL_NT1) {
		NTTIME ntt;

		/* NT protocol */
		SMBCLI_CHECK_WCT(req, 17);
		transport->negotiate.sec_mode = CVAL(req->in.vwv,VWV(1));
		transport->negotiate.max_mux  = SVAL(req->in.vwv,VWV(1)+1);
		transport->negotiate.max_xmit = IVAL(req->in.vwv,VWV(3)+1);
		transport->negotiate.sesskey  = IVAL(req->in.vwv,VWV(7)+1);
		transport->negotiate.capabilities = IVAL(req->in.vwv,VWV(9)+1);

		/* this time arrives in real GMT */
		ntt = smbcli_pull_nttime(req->in.vwv, VWV(11)+1);
		transport->negotiate.server_time = nt_time_to_unix(ntt);		
		transport->negotiate.server_zone = SVALS(req->in.vwv,VWV(15)+1) * 60;
		transport->negotiate.key_len = CVAL(req->in.vwv,VWV(16)+1);

		if (transport->negotiate.capabilities & CAP_EXTENDED_SECURITY) {
			if (req->in.data_size < 16) {
				goto failed;
			}
			transport->negotiate.server_guid = smbcli_req_pull_blob(&req->in.bufinfo, transport, req->in.data, 16);
			transport->negotiate.secblob = smbcli_req_pull_blob(&req->in.bufinfo, transport, req->in.data + 16, req->in.data_size - 16);
		} else {
			if (req->in.data_size < (transport->negotiate.key_len)) {
				goto failed;
			}
			transport->negotiate.secblob = smbcli_req_pull_blob(&req->in.bufinfo, transport, req->in.data, transport->negotiate.key_len);
			smbcli_req_pull_string(&req->in.bufinfo, transport, &transport->negotiate.server_domain,
					    req->in.data+transport->negotiate.key_len,
					    req->in.data_size-transport->negotiate.key_len, STR_UNICODE|STR_NOALIGN);
			/* here comes the server name */
		}

		if (transport->negotiate.capabilities & CAP_RAW_MODE) {
			transport->negotiate.readbraw_supported = true;
			transport->negotiate.writebraw_supported = true;
		}

		if (transport->negotiate.capabilities & CAP_LOCK_AND_READ)
			transport->negotiate.lockread_supported = true;
	} else if (transport->negotiate.protocol >= PROTOCOL_LANMAN1) {
		SMBCLI_CHECK_WCT(req, 13);
		transport->negotiate.sec_mode = SVAL(req->in.vwv,VWV(1));
		transport->negotiate.max_xmit = SVAL(req->in.vwv,VWV(2));
		transport->negotiate.sesskey =  IVAL(req->in.vwv,VWV(6));
		transport->negotiate.server_zone = SVALS(req->in.vwv,VWV(10)) * 60;
		
		/* this time is converted to GMT by raw_pull_dos_date */
		transport->negotiate.server_time = raw_pull_dos_date(transport,
								     req->in.vwv+VWV(8));
		if ((SVAL(req->in.vwv,VWV(5)) & 0x1)) {
			transport->negotiate.readbraw_supported = 1;
		}
		if ((SVAL(req->in.vwv,VWV(5)) & 0x2)) {
			transport->negotiate.writebraw_supported = 1;
		}
		transport->negotiate.secblob = smbcli_req_pull_blob(&req->in.bufinfo, transport, 
								 req->in.data, req->in.data_size);
	} else {
		/* the old core protocol */
		transport->negotiate.sec_mode = 0;
		transport->negotiate.server_time = time(NULL);
		transport->negotiate.max_xmit = transport->options.max_xmit;
		transport->negotiate.server_zone = get_time_zone(transport->negotiate.server_time);
	}

	/* a way to force ascii SMB */
	if (!transport->options.unicode) {
		transport->negotiate.capabilities &= ~CAP_UNICODE;
	}

	if (!transport->options.ntstatus_support) {
		transport->negotiate.capabilities &= ~CAP_STATUS32;
	}

	if (!transport->options.use_level2_oplocks) {
		transport->negotiate.capabilities &= ~CAP_LEVEL_II_OPLOCKS;
	}

failed:
	return smbcli_request_destroy(req);
}
Пример #5
0
/****************************************************************************
 Open a file - async recv
****************************************************************************/
_PUBLIC_ NTSTATUS smb_raw_open_recv(struct smbcli_request *req, TALLOC_CTX *mem_ctx, union smb_open *parms)
{
	NTSTATUS status;

	if (!smbcli_request_receive(req) ||
	    smbcli_request_is_error(req)) {
		goto failed;
	}

	switch (parms->openold.level) {
	case RAW_OPEN_T2OPEN:
		return smb_raw_t2open_recv(req, mem_ctx, parms);

	case RAW_OPEN_OPEN:
		SMBCLI_CHECK_WCT(req, 7);
		parms->openold.out.file.fnum = SVAL(req->in.vwv, VWV(0));
		parms->openold.out.attrib = SVAL(req->in.vwv, VWV(1));
		parms->openold.out.write_time = raw_pull_dos_date3(req->transport,
								req->in.vwv + VWV(2));
		parms->openold.out.size = IVAL(req->in.vwv, VWV(4));
		parms->openold.out.rmode = SVAL(req->in.vwv, VWV(6));
		break;

	case RAW_OPEN_OPENX:
		SMBCLI_CHECK_MIN_WCT(req, 15);
		parms->openx.out.file.fnum = SVAL(req->in.vwv, VWV(2));
		parms->openx.out.attrib = SVAL(req->in.vwv, VWV(3));
		parms->openx.out.write_time = raw_pull_dos_date3(req->transport,
								 req->in.vwv + VWV(4));
		parms->openx.out.size = IVAL(req->in.vwv, VWV(6));
		parms->openx.out.access = SVAL(req->in.vwv, VWV(8));
		parms->openx.out.ftype = SVAL(req->in.vwv, VWV(9));
		parms->openx.out.devstate = SVAL(req->in.vwv, VWV(10));
		parms->openx.out.action = SVAL(req->in.vwv, VWV(11));
		parms->openx.out.unique_fid = IVAL(req->in.vwv, VWV(12));
		if (req->in.wct >= 19) {
			parms->openx.out.access_mask = IVAL(req->in.vwv, VWV(15));
			parms->openx.out.unknown =     IVAL(req->in.vwv, VWV(17));
		} else {
			parms->openx.out.access_mask = 0;
			parms->openx.out.unknown = 0;
		}
		break;

	case RAW_OPEN_MKNEW:
		SMBCLI_CHECK_WCT(req, 1);
		parms->mknew.out.file.fnum = SVAL(req->in.vwv, VWV(0));
		break;

	case RAW_OPEN_CREATE:
		SMBCLI_CHECK_WCT(req, 1);
		parms->create.out.file.fnum = SVAL(req->in.vwv, VWV(0));
		break;

	case RAW_OPEN_CTEMP:
		SMBCLI_CHECK_WCT(req, 1);
		parms->ctemp.out.file.fnum = SVAL(req->in.vwv, VWV(0));
		smbcli_req_pull_string(&req->in.bufinfo, mem_ctx, &parms->ctemp.out.name, req->in.data, -1, STR_TERMINATE | STR_ASCII);
		break;

	case RAW_OPEN_SPLOPEN:
		SMBCLI_CHECK_WCT(req, 1);
		parms->splopen.out.file.fnum = SVAL(req->in.vwv, VWV(0));
		break;

	case RAW_OPEN_NTCREATEX:
		SMBCLI_CHECK_MIN_WCT(req, 34);
		parms->ntcreatex.out.oplock_level =              CVAL(req->in.vwv, 4);
		parms->ntcreatex.out.file.fnum =                 SVAL(req->in.vwv, 5);
		parms->ntcreatex.out.create_action =             IVAL(req->in.vwv, 7);
		parms->ntcreatex.out.create_time =   smbcli_pull_nttime(req->in.vwv, 11);
		parms->ntcreatex.out.access_time =   smbcli_pull_nttime(req->in.vwv, 19);
		parms->ntcreatex.out.write_time =    smbcli_pull_nttime(req->in.vwv, 27);
		parms->ntcreatex.out.change_time =   smbcli_pull_nttime(req->in.vwv, 35);
		parms->ntcreatex.out.attrib =                   IVAL(req->in.vwv, 43);
		parms->ntcreatex.out.alloc_size =               BVAL(req->in.vwv, 47);
		parms->ntcreatex.out.size =                     BVAL(req->in.vwv, 55);
		parms->ntcreatex.out.file_type =                SVAL(req->in.vwv, 63);
		parms->ntcreatex.out.ipc_state =                SVAL(req->in.vwv, 65);
		parms->ntcreatex.out.is_directory =             CVAL(req->in.vwv, 67);
		break;

	case RAW_OPEN_NTTRANS_CREATE:
		return smb_raw_nttrans_create_recv(req, mem_ctx, parms);

	case RAW_OPEN_OPENX_READX:
		SMBCLI_CHECK_MIN_WCT(req, 15);
		parms->openxreadx.out.file.fnum = SVAL(req->in.vwv, VWV(2));
		parms->openxreadx.out.attrib = SVAL(req->in.vwv, VWV(3));
		parms->openxreadx.out.write_time = raw_pull_dos_date3(req->transport,
								 req->in.vwv + VWV(4));
		parms->openxreadx.out.size = IVAL(req->in.vwv, VWV(6));
		parms->openxreadx.out.access = SVAL(req->in.vwv, VWV(8));
		parms->openxreadx.out.ftype = SVAL(req->in.vwv, VWV(9));
		parms->openxreadx.out.devstate = SVAL(req->in.vwv, VWV(10));
		parms->openxreadx.out.action = SVAL(req->in.vwv, VWV(11));
		parms->openxreadx.out.unique_fid = IVAL(req->in.vwv, VWV(12));
		if (req->in.wct >= 19) {
			parms->openxreadx.out.access_mask = IVAL(req->in.vwv, VWV(15));
			parms->openxreadx.out.unknown =     IVAL(req->in.vwv, VWV(17));
		} else {
			parms->openxreadx.out.access_mask = 0;
			parms->openxreadx.out.unknown = 0;
		}

		status = smbcli_chained_advance(req);
		if (!NT_STATUS_IS_OK(status)) {
			return status;
		}

		SMBCLI_CHECK_WCT(req, 12);
		parms->openxreadx.out.remaining       = SVAL(req->in.vwv, VWV(2));
		parms->openxreadx.out.compaction_mode = SVAL(req->in.vwv, VWV(3));
		parms->openxreadx.out.nread = SVAL(req->in.vwv, VWV(5));
		if (parms->openxreadx.out.nread > 
		    MAX(parms->openxreadx.in.mincnt, parms->openxreadx.in.maxcnt) ||
		    !smbcli_raw_pull_data(&req->in.bufinfo, req->in.hdr + SVAL(req->in.vwv, VWV(6)), 
					  parms->openxreadx.out.nread, 
					  parms->openxreadx.out.data)) {
			req->status = NT_STATUS_BUFFER_TOO_SMALL;
		}
		break;

	case RAW_OPEN_NTCREATEX_READX:
		SMBCLI_CHECK_MIN_WCT(req, 34);
		parms->ntcreatexreadx.out.oplock_level =              CVAL(req->in.vwv, 4);
		parms->ntcreatexreadx.out.file.fnum =                 SVAL(req->in.vwv, 5);
		parms->ntcreatexreadx.out.create_action =             IVAL(req->in.vwv, 7);
		parms->ntcreatexreadx.out.create_time =   smbcli_pull_nttime(req->in.vwv, 11);
		parms->ntcreatexreadx.out.access_time =   smbcli_pull_nttime(req->in.vwv, 19);
		parms->ntcreatexreadx.out.write_time =    smbcli_pull_nttime(req->in.vwv, 27);
		parms->ntcreatexreadx.out.change_time =   smbcli_pull_nttime(req->in.vwv, 35);
		parms->ntcreatexreadx.out.attrib =                   IVAL(req->in.vwv, 43);
		parms->ntcreatexreadx.out.alloc_size =               BVAL(req->in.vwv, 47);
		parms->ntcreatexreadx.out.size =                     BVAL(req->in.vwv, 55);
		parms->ntcreatexreadx.out.file_type =                SVAL(req->in.vwv, 63);
		parms->ntcreatexreadx.out.ipc_state =                SVAL(req->in.vwv, 65);
		parms->ntcreatexreadx.out.is_directory =             CVAL(req->in.vwv, 67);

		status = smbcli_chained_advance(req);
		if (!NT_STATUS_IS_OK(status)) {
			return status;
		}

		SMBCLI_CHECK_WCT(req, 12);
		parms->ntcreatexreadx.out.remaining       = SVAL(req->in.vwv, VWV(2));
		parms->ntcreatexreadx.out.compaction_mode = SVAL(req->in.vwv, VWV(3));
		parms->ntcreatexreadx.out.nread = SVAL(req->in.vwv, VWV(5));
		if (parms->ntcreatexreadx.out.nread >
		    MAX(parms->ntcreatexreadx.in.mincnt, parms->ntcreatexreadx.in.maxcnt) ||
		    !smbcli_raw_pull_data(&req->in.bufinfo, req->in.hdr + SVAL(req->in.vwv, VWV(6)),
			                  parms->ntcreatexreadx.out.nread,
			                  parms->ntcreatexreadx.out.data)) {
			req->status = NT_STATUS_BUFFER_TOO_SMALL;
		}
		break;

	case RAW_OPEN_SMB2:
		req->status = NT_STATUS_INTERNAL_ERROR;
		break;
	}

failed:
	return smbcli_request_destroy(req);
}
Пример #6
0
/*
  parse a trans2 search response. 
  Return the number of bytes consumed
  return 0 for success with end of list
  return -1 for a parse error
*/
static int parse_trans2_search(struct smbcli_tree *tree,
			       TALLOC_CTX *mem_ctx, 
			       enum smb_search_data_level level,
			       uint16_t flags,
			       DATA_BLOB *blob,
			       union smb_search_data *data)
{
	unsigned int len, ofs;
	uint32_t ea_size;
	DATA_BLOB eablob;
	NTSTATUS status;

	switch (level) {
	case RAW_SEARCH_DATA_GENERIC:
	case RAW_SEARCH_DATA_SEARCH:
		/* handled elsewhere */
		return -1;

	case RAW_SEARCH_DATA_STANDARD:
		if (flags & FLAG_TRANS2_FIND_REQUIRE_RESUME) {
			if (blob->length < 4) return -1;
			data->standard.resume_key = IVAL(blob->data, 0);
			blob->data += 4;
			blob->length -= 4;
		}
		if (blob->length < 24) return -1;
		data->standard.create_time = raw_pull_dos_date2(tree->session->transport,
								blob->data + 0);
		data->standard.access_time = raw_pull_dos_date2(tree->session->transport,
								blob->data + 4);
		data->standard.write_time  = raw_pull_dos_date2(tree->session->transport,
								blob->data + 8);
		data->standard.size        = IVAL(blob->data, 12);
		data->standard.alloc_size  = IVAL(blob->data, 16);
		data->standard.attrib      = SVAL(blob->data, 20);
		len = smbcli_blob_pull_string(tree->session, mem_ctx, blob,
					   &data->standard.name,
					   22, 23, STR_LEN8BIT | STR_TERMINATE | STR_LEN_NOTERM);
		return len + 23;

	case RAW_SEARCH_DATA_EA_SIZE:
		if (flags & FLAG_TRANS2_FIND_REQUIRE_RESUME) {
			if (blob->length < 4) return -1;
			data->ea_size.resume_key = IVAL(blob->data, 0);
			blob->data += 4;
			blob->length -= 4;
		}
		if (blob->length < 28) return -1;
		data->ea_size.create_time = raw_pull_dos_date2(tree->session->transport,
							       blob->data + 0);
		data->ea_size.access_time = raw_pull_dos_date2(tree->session->transport,
							       blob->data + 4);
		data->ea_size.write_time  = raw_pull_dos_date2(tree->session->transport,
							       blob->data + 8);
		data->ea_size.size        = IVAL(blob->data, 12);
		data->ea_size.alloc_size  = IVAL(blob->data, 16);
		data->ea_size.attrib      = SVAL(blob->data, 20);
		data->ea_size.ea_size     = IVAL(blob->data, 22);
		len = smbcli_blob_pull_string(tree->session, mem_ctx, blob,
					   &data->ea_size.name,
					   26, 27, STR_LEN8BIT | STR_TERMINATE | STR_NOALIGN);
		return len + 27 + 1;

	case RAW_SEARCH_DATA_EA_LIST:
		if (flags & FLAG_TRANS2_FIND_REQUIRE_RESUME) {
			if (blob->length < 4) return -1;
			data->ea_list.resume_key = IVAL(blob->data, 0);
			blob->data += 4;
			blob->length -= 4;
		}
		if (blob->length < 28) return -1;
		data->ea_list.create_time = raw_pull_dos_date2(tree->session->transport,
							       blob->data + 0);
		data->ea_list.access_time = raw_pull_dos_date2(tree->session->transport,
							       blob->data + 4);
		data->ea_list.write_time  = raw_pull_dos_date2(tree->session->transport,
							       blob->data + 8);
		data->ea_list.size        = IVAL(blob->data, 12);
		data->ea_list.alloc_size  = IVAL(blob->data, 16);
		data->ea_list.attrib      = SVAL(blob->data, 20);
		ea_size                   = IVAL(blob->data, 22);
		if (ea_size > 0xFFFF) {
			return -1;
		}
		eablob.data = blob->data + 22;
		eablob.length = ea_size;
		if (eablob.length > blob->length - 24) {
			return -1;
		}
		status = ea_pull_list(&eablob, mem_ctx, 
				      &data->ea_list.eas.num_eas,
				      &data->ea_list.eas.eas);
		if (!NT_STATUS_IS_OK(status)) {
			return -1;
		}
		len = smbcli_blob_pull_string(tree->session, mem_ctx, blob,
					      &data->ea_list.name,
					      22+ea_size, 23+ea_size, 
					      STR_LEN8BIT | STR_NOALIGN);
		return len + ea_size + 23 + 1;

	case RAW_SEARCH_DATA_UNIX_INFO:
		if (blob->length < 109) return -1;
		ofs                                  = IVAL(blob->data,             0);
		data->unix_info.file_index           = IVAL(blob->data,             4);
		data->unix_info.size                 = BVAL(blob->data,             8);
		data->unix_info.alloc_size           = BVAL(blob->data,            16);
		data->unix_info.status_change_time   = smbcli_pull_nttime(blob->data, 24);
		data->unix_info.access_time          = smbcli_pull_nttime(blob->data, 32);
		data->unix_info.change_time          = smbcli_pull_nttime(blob->data, 40);
		data->unix_info.uid                  = IVAL(blob->data,            48);
		data->unix_info.gid                  = IVAL(blob->data,            56);
		data->unix_info.file_type            = IVAL(blob->data,            64);
		data->unix_info.dev_major            = BVAL(blob->data,            68);
		data->unix_info.dev_minor            = BVAL(blob->data,            76);
		data->unix_info.unique_id            = BVAL(blob->data,            84);
		data->unix_info.permissions          = IVAL(blob->data,            92);
		data->unix_info.nlink                = IVAL(blob->data,           100);
		/* There is no length field for this name but we know it's null terminated. */
		len = smbcli_blob_pull_unix_string(tree->session, mem_ctx, blob,
					   &data->unix_info.name, 108, 0);
		if (ofs != 0 && ofs < 108+len) {
			return -1;
		}
		return ofs;

	case RAW_SEARCH_DATA_UNIX_INFO2:
		/*   8 - size of ofs + file_index
		 * 116 - size of unix_info2
		 *   4 - size of name length
		 *   2 - "." is the shortest name
		 */
		if (blob->length < (116 + 8 + 4 + 2)) {
			return -1;
		}

		ofs                                 = IVAL(blob->data,   0);
		data->unix_info2.file_index         = IVAL(blob->data,   4);
		data->unix_info2.end_of_file        = BVAL(blob->data,   8);
		data->unix_info2.num_bytes          = BVAL(blob->data,  16);
		data->unix_info2.status_change_time = smbcli_pull_nttime(blob->data, 24);
		data->unix_info2.access_time        = smbcli_pull_nttime(blob->data, 32);
		data->unix_info2.change_time        = smbcli_pull_nttime(blob->data, 40);
		data->unix_info2.uid                = IVAL(blob->data,  48);
		data->unix_info2.gid                = IVAL(blob->data,  56);
		data->unix_info2.file_type          = IVAL(blob->data,  64);
		data->unix_info2.dev_major          = BVAL(blob->data,  68);
		data->unix_info2.dev_minor          = BVAL(blob->data,  76);
		data->unix_info2.unique_id          = BVAL(blob->data,  84);
		data->unix_info2.permissions        = IVAL(blob->data,  92);
		data->unix_info2.nlink              = IVAL(blob->data, 100);
		data->unix_info2.create_time	    = smbcli_pull_nttime(blob->data, 108);
		data->unix_info2.file_flags	    = IVAL(blob->data, 116);
		data->unix_info2.flags_mask	    = IVAL(blob->data, 120);

		/* There is a 4 byte length field for this name. The length
		 * does not include the NULL terminator.
		 */
		len = smbcli_blob_pull_string(tree->session, mem_ctx, blob,
				       &data->unix_info2.name,
				       8 + 116, /* offset to length */
				       8 + 116 + 4, /* offset to string */
				       0);

		if (ofs != 0 && ofs < (8 + 116 + 4 + len)) {
			return -1;
		}

		return ofs;

		case RAW_SEARCH_DATA_DIRECTORY_INFO:
		case RAW_SEARCH_DATA_FULL_DIRECTORY_INFO:
		case RAW_SEARCH_DATA_NAME_INFO:
		case RAW_SEARCH_DATA_BOTH_DIRECTORY_INFO:
		case RAW_SEARCH_DATA_ID_FULL_DIRECTORY_INFO:
		case RAW_SEARCH_DATA_ID_BOTH_DIRECTORY_INFO: {
			unsigned int str_flags = STR_UNICODE;
			if (!(tree->session->transport->negotiate.capabilities & CAP_UNICODE)) {
				str_flags = STR_ASCII;
			}
			
		status = smb_raw_search_common(mem_ctx, level, blob, data, &ofs, str_flags);
		if (!NT_STATUS_IS_OK(status)) {
			return -1;
		}
		return ofs;
	}
	}

	/* invalid level */
	return -1;
}
Пример #7
0
/*
  parse the wire search formats that are in common between SMB and
  SMB2
*/
NTSTATUS smb_raw_search_common(TALLOC_CTX *mem_ctx, 
			       enum smb_search_data_level level,
			       const DATA_BLOB *blob,
			       union smb_search_data *data,
			       unsigned int *next_ofs,
			       unsigned int str_flags)
{
	unsigned int len, blen;

	if (blob->length < 4) {
		return NT_STATUS_INFO_LENGTH_MISMATCH;
	}

	*next_ofs = IVAL(blob->data, 0);
	if (*next_ofs != 0) {
		blen = *next_ofs;
	} else {
		blen = blob->length;
	}

	switch (level) {
	case RAW_SEARCH_DATA_DIRECTORY_INFO:
		if (blen < 65) return NT_STATUS_INFO_LENGTH_MISMATCH;
		data->directory_info.file_index  = IVAL(blob->data,             4);
		data->directory_info.create_time = smbcli_pull_nttime(blob->data,  8);
		data->directory_info.access_time = smbcli_pull_nttime(blob->data, 16);
		data->directory_info.write_time  = smbcli_pull_nttime(blob->data, 24);
		data->directory_info.change_time = smbcli_pull_nttime(blob->data, 32);
		data->directory_info.size        = BVAL(blob->data,            40);
		data->directory_info.alloc_size  = BVAL(blob->data,            48);
		data->directory_info.attrib      = IVAL(blob->data,            56);
		len = smbcli_blob_pull_string(NULL, mem_ctx, blob,
					      &data->directory_info.name,
					      60, 64, str_flags);
		if (*next_ofs != 0 && *next_ofs < 64+len) {
			return NT_STATUS_INFO_LENGTH_MISMATCH;
		}
		return NT_STATUS_OK;

	case RAW_SEARCH_DATA_FULL_DIRECTORY_INFO:
		if (blen < 69) return NT_STATUS_INFO_LENGTH_MISMATCH;
		data->full_directory_info.file_index  = IVAL(blob->data,                4);
		data->full_directory_info.create_time = smbcli_pull_nttime(blob->data,  8);
		data->full_directory_info.access_time = smbcli_pull_nttime(blob->data, 16);
		data->full_directory_info.write_time  = smbcli_pull_nttime(blob->data, 24);
		data->full_directory_info.change_time = smbcli_pull_nttime(blob->data, 32);
		data->full_directory_info.size        = BVAL(blob->data,               40);
		data->full_directory_info.alloc_size  = BVAL(blob->data,               48);
		data->full_directory_info.attrib      = IVAL(blob->data,               56);
		data->full_directory_info.ea_size     = IVAL(blob->data,               64);
		len = smbcli_blob_pull_string(NULL, mem_ctx, blob,
					      &data->full_directory_info.name,
					      60, 68, str_flags);
		if (*next_ofs != 0 && *next_ofs < 68+len) {
			return NT_STATUS_INFO_LENGTH_MISMATCH;
		}
		return NT_STATUS_OK;

	case RAW_SEARCH_DATA_NAME_INFO:
		if (blen < 13) return NT_STATUS_INFO_LENGTH_MISMATCH;
		data->name_info.file_index  = IVAL(blob->data, 4);
		len = smbcli_blob_pull_string(NULL, mem_ctx, blob,
					      &data->name_info.name,
					      8, 12, str_flags);
		if (*next_ofs != 0 && *next_ofs < 12+len) {
			return NT_STATUS_INFO_LENGTH_MISMATCH;
		}
		return NT_STATUS_OK;


	case RAW_SEARCH_DATA_BOTH_DIRECTORY_INFO:
		if (blen < 95) return NT_STATUS_INFO_LENGTH_MISMATCH;
		data->both_directory_info.file_index  = IVAL(blob->data,                4);
		data->both_directory_info.create_time = smbcli_pull_nttime(blob->data,  8);
		data->both_directory_info.access_time = smbcli_pull_nttime(blob->data, 16);
		data->both_directory_info.write_time  = smbcli_pull_nttime(blob->data, 24);
		data->both_directory_info.change_time = smbcli_pull_nttime(blob->data, 32);
		data->both_directory_info.size        = BVAL(blob->data,               40);
		data->both_directory_info.alloc_size  = BVAL(blob->data,               48);
		data->both_directory_info.attrib      = IVAL(blob->data,               56);
		data->both_directory_info.ea_size     = IVAL(blob->data,               64);
		smbcli_blob_pull_string(NULL, mem_ctx, blob,
					&data->both_directory_info.short_name,
					68, 70, STR_LEN8BIT | STR_UNICODE);
		len = smbcli_blob_pull_string(NULL, mem_ctx, blob,
					      &data->both_directory_info.name,
					      60, 94, str_flags);
		if (*next_ofs != 0 && *next_ofs < 94+len) {
			return NT_STATUS_INFO_LENGTH_MISMATCH;
		}
		return NT_STATUS_OK;


	case RAW_SEARCH_DATA_ID_FULL_DIRECTORY_INFO:
		if (blen < 81) return NT_STATUS_INFO_LENGTH_MISMATCH;
		data->id_full_directory_info.file_index  = IVAL(blob->data,             4);
		data->id_full_directory_info.create_time = smbcli_pull_nttime(blob->data,  8);
		data->id_full_directory_info.access_time = smbcli_pull_nttime(blob->data, 16);
		data->id_full_directory_info.write_time  = smbcli_pull_nttime(blob->data, 24);
		data->id_full_directory_info.change_time = smbcli_pull_nttime(blob->data, 32);
		data->id_full_directory_info.size        = BVAL(blob->data,            40);
		data->id_full_directory_info.alloc_size  = BVAL(blob->data,            48);
		data->id_full_directory_info.attrib      = IVAL(blob->data,            56);
		data->id_full_directory_info.ea_size     = IVAL(blob->data,            64);
		data->id_full_directory_info.file_id     = BVAL(blob->data,            72);
		len = smbcli_blob_pull_string(NULL, mem_ctx, blob,
					      &data->id_full_directory_info.name,
					      60, 80, str_flags);
		if (*next_ofs != 0 && *next_ofs < 80+len) {
			return NT_STATUS_INFO_LENGTH_MISMATCH;
		}
		return NT_STATUS_OK;

	case RAW_SEARCH_DATA_ID_BOTH_DIRECTORY_INFO:
		if (blen < 105) return NT_STATUS_INFO_LENGTH_MISMATCH;
		data->id_both_directory_info.file_index  = IVAL(blob->data,             4);
		data->id_both_directory_info.create_time = smbcli_pull_nttime(blob->data,  8);
		data->id_both_directory_info.access_time = smbcli_pull_nttime(blob->data, 16);
		data->id_both_directory_info.write_time  = smbcli_pull_nttime(blob->data, 24);
		data->id_both_directory_info.change_time = smbcli_pull_nttime(blob->data, 32);
		data->id_both_directory_info.size        = BVAL(blob->data,            40);
		data->id_both_directory_info.alloc_size  = BVAL(blob->data,            48);
		data->id_both_directory_info.attrib      = SVAL(blob->data,            56);
		data->id_both_directory_info.ea_size     = IVAL(blob->data,            64);
		smbcli_blob_pull_string(NULL, mem_ctx, blob,
				     &data->id_both_directory_info.short_name,
				     68, 70, STR_LEN8BIT | STR_UNICODE);
		memcpy(data->id_both_directory_info.short_name_buf, blob->data + 70, 24);
		data->id_both_directory_info.file_id     = BVAL(blob->data,            96);
		len = smbcli_blob_pull_string(NULL, mem_ctx, blob,
					      &data->id_both_directory_info.name,
					      60, 104, str_flags);
		if (*next_ofs != 0 && *next_ofs < 104+len) {
			return NT_STATUS_INFO_LENGTH_MISMATCH;
		}
		return NT_STATUS_OK;
	
	default:
		break;
	}

	/* invalid level */
	return NT_STATUS_INVALID_INFO_CLASS;
}
Пример #8
0
/*
  parse the fsinfo 'passthru' level replies
*/
NTSTATUS smb_raw_fsinfo_passthru_parse(DATA_BLOB blob, TALLOC_CTX *mem_ctx, 
				       enum smb_fsinfo_level level,
				       union smb_fsinfo *fsinfo)
{
	NTSTATUS status = NT_STATUS_OK;
	int i;

	/* parse the results */
	switch (level) {
	case RAW_QFS_VOLUME_INFORMATION:
		QFS_CHECK_MIN_SIZE(18);
		fsinfo->volume_info.out.create_time   = smbcli_pull_nttime(blob.data, 0);
		fsinfo->volume_info.out.serial_number = IVAL(blob.data, 8);
		smbcli_blob_pull_string(NULL, mem_ctx, &blob, 
					&fsinfo->volume_info.out.volume_name,
					12, 18, STR_UNICODE);
		break;		

	case RAW_QFS_SIZE_INFORMATION:
		QFS_CHECK_SIZE(24);
		fsinfo->size_info.out.total_alloc_units = BVAL(blob.data,  0);
		fsinfo->size_info.out.avail_alloc_units = BVAL(blob.data,  8);
		fsinfo->size_info.out.sectors_per_unit =  IVAL(blob.data, 16);
		fsinfo->size_info.out.bytes_per_sector =  IVAL(blob.data, 20); 
		break;		

	case RAW_QFS_DEVICE_INFORMATION:
		QFS_CHECK_SIZE(8);
		fsinfo->device_info.out.device_type     = IVAL(blob.data,  0);
		fsinfo->device_info.out.characteristics = IVAL(blob.data,  4);
		break;		

	case RAW_QFS_ATTRIBUTE_INFORMATION:
		QFS_CHECK_MIN_SIZE(12);
		fsinfo->attribute_info.out.fs_attr   =                 IVAL(blob.data, 0);
		fsinfo->attribute_info.out.max_file_component_length = IVAL(blob.data, 4);
		smbcli_blob_pull_string(NULL, mem_ctx, &blob, 
					&fsinfo->attribute_info.out.fs_type,
					8, 12, STR_UNICODE);
		break;		

	case RAW_QFS_QUOTA_INFORMATION:
		QFS_CHECK_SIZE(48);
		fsinfo->quota_information.out.unknown[0] =  BVAL(blob.data,  0);
		fsinfo->quota_information.out.unknown[1] =  BVAL(blob.data,  8);
		fsinfo->quota_information.out.unknown[2] =  BVAL(blob.data, 16);
		fsinfo->quota_information.out.quota_soft =  BVAL(blob.data, 24);
		fsinfo->quota_information.out.quota_hard =  BVAL(blob.data, 32);
		fsinfo->quota_information.out.quota_flags = BVAL(blob.data, 40);
		break;		

	case RAW_QFS_FULL_SIZE_INFORMATION:
		QFS_CHECK_SIZE(32);
		fsinfo->full_size_information.out.total_alloc_units =        BVAL(blob.data,  0);
		fsinfo->full_size_information.out.call_avail_alloc_units =   BVAL(blob.data,  8);
		fsinfo->full_size_information.out.actual_avail_alloc_units = BVAL(blob.data, 16);
		fsinfo->full_size_information.out.sectors_per_unit =         IVAL(blob.data, 24);
		fsinfo->full_size_information.out.bytes_per_sector =         IVAL(blob.data, 28);
		break;		

	case RAW_QFS_OBJECTID_INFORMATION:
		QFS_CHECK_SIZE(64);
		status = ndr_pull_struct_blob(&blob, mem_ctx, &fsinfo->objectid_information.out.guid,
					      (ndr_pull_flags_fn_t)ndr_pull_GUID);
		for (i=0;i<6;i++) {
			fsinfo->objectid_information.out.unknown[i] = BVAL(blob.data, 16 + i*8);
		}
		break;
		
	default:
		status = NT_STATUS_INVALID_INFO_CLASS;
	}

failed:
	return status;
}
Пример #9
0
/*
  recv a create reply
*/
NTSTATUS smb2_create_recv(struct smb2_request *req, TALLOC_CTX *mem_ctx, struct smb2_create *io)
{
	NTSTATUS status;
	DATA_BLOB blob;
	int i;

	if (!smb2_request_receive(req) || 
	    !smb2_request_is_ok(req)) {
		return smb2_request_destroy(req);
	}

	SMB2_CHECK_PACKET_RECV(req, 0x58, true);
	ZERO_STRUCT(io->out);
	io->out.oplock_level   = CVAL(req->in.body, 0x02);
	io->out.reserved       = CVAL(req->in.body, 0x03);
	io->out.create_action  = IVAL(req->in.body, 0x04);
	io->out.create_time    = smbcli_pull_nttime(req->in.body, 0x08);
	io->out.access_time    = smbcli_pull_nttime(req->in.body, 0x10);
	io->out.write_time     = smbcli_pull_nttime(req->in.body, 0x18);
	io->out.change_time    = smbcli_pull_nttime(req->in.body, 0x20);
	io->out.alloc_size     = BVAL(req->in.body, 0x28);
	io->out.size           = BVAL(req->in.body, 0x30);
	io->out.file_attr      = IVAL(req->in.body, 0x38);
	io->out.reserved2      = IVAL(req->in.body, 0x3C);
	smb2_pull_handle(req->in.body+0x40, &io->out.file.handle);
	status = smb2_pull_o32s32_blob(&req->in, mem_ctx, req->in.body+0x50, &blob);
	if (!NT_STATUS_IS_OK(status)) {
		smb2_request_destroy(req);
		return status;
	}

	status = smb2_create_blob_parse(mem_ctx, blob, &io->out.blobs);
	if (!NT_STATUS_IS_OK(status)) {
		smb2_request_destroy(req);
		return status;
	}

	/* pull out the parsed blobs */
	for (i=0;i<io->out.blobs.num_blobs;i++) {
		if (strcmp(io->out.blobs.blobs[i].tag, SMB2_CREATE_TAG_MXAC) == 0) {
			/* TODO: this also contains a status field in
			   first 4 bytes */
			if (io->out.blobs.blobs[i].data.length != 8) {
				smb2_request_destroy(req);
				return NT_STATUS_INVALID_NETWORK_RESPONSE;
			}
			io->out.maximal_access = IVAL(io->out.blobs.blobs[i].data.data, 4);
		}
		if (strcmp(io->out.blobs.blobs[i].tag, SMB2_CREATE_TAG_QFID) == 0) {
			if (io->out.blobs.blobs[i].data.length != 32) {
				smb2_request_destroy(req);
				return NT_STATUS_INVALID_NETWORK_RESPONSE;
			}
			memcpy(io->out.on_disk_id, io->out.blobs.blobs[i].data.data, 32);
		}
		if (strcmp(io->out.blobs.blobs[i].tag, SMB2_CREATE_TAG_RQLS) == 0) {
			uint8_t *data;
			if (io->out.blobs.blobs[i].data.length != 32) {
				smb2_request_destroy(req);
				return NT_STATUS_INVALID_NETWORK_RESPONSE;
			}

			data = io->out.blobs.blobs[i].data.data;
			memcpy(&io->out.lease_response.lease_key, data, 16);
			io->out.lease_response.lease_state = IVAL(data, 16);
			io->out.lease_response.lease_flags = IVAL(data, 20);
			io->out.lease_response.lease_duration = BVAL(data, 24);
		}
	}

	data_blob_free(&blob);

	return smb2_request_destroy(req);
}