Example #1
0
/*
 * smb_transfer_write_raw_data
 *
 * Handles the second transfer phase of SMB_COM_WRITE_RAW.  smb_com_write_raw()
 * will process the parameters and data from the SMB and send the initial
 * SMB response.  This function reads the remaining data from the socket
 * as it arrives from the client.
 *
 * Clients may send KEEP_ALIVE messages (when using NBT) between the first
 * and second parts of write raw requests.  The only session transport
 * types accepted here are SESSION_MESSAGE or SESSION_KEEP_ALIVE.
 *
 * Returns 0 for success, non-zero for failure
 */
int
smb_transfer_write_raw_data(smb_request_t *sr, smb_rw_param_t *param)
{
	smb_session_t *session = sr->session;
	smb_xprt_t hdr;
	void *pbuf;

	do {
		if (smb_session_xprt_gethdr(session, &hdr) != 0)
			return (-1);

		if ((hdr.xh_type == SESSION_MESSAGE) ||
		    (hdr.xh_type == SESSION_KEEP_ALIVE)) {
			session->keep_alive = smb_keep_alive;
		} else {
			return (-1);
		}
	} while (hdr.xh_type == SESSION_KEEP_ALIVE);

	if (hdr.xh_length < param->rw_vdb.vdb_uio.uio_resid)
		return (-1); /* Less data than we were expecting. */

	pbuf = smb_srm_alloc(sr, hdr.xh_length);
	if (smb_sorecv(session->sock, pbuf, hdr.xh_length) != 0)
		return (-1);

	param->rw_vdb.vdb_iovec[0].iov_base = pbuf;
	param->rw_vdb.vdb_uio.uio_iovcnt = 1;
	param->rw_vdb.vdb_uio.uio_segflg = UIO_SYSSPACE;
	param->rw_vdb.vdb_uio.uio_extflg = UIO_COPY_DEFAULT;
	return (0);
}
Example #2
0
/*
 * Read, process and respond to a NetBIOS session request.
 *
 * A NetBIOS session must be established for SMB-over-NetBIOS.  Validate
 * the calling and called name format and save the client NetBIOS name,
 * which is used when a NetBIOS session is established to check for and
 * cleanup leftover state from a previous session.
 *
 * Session requests are not valid for SMB-over-TCP, which is unfortunate
 * because without the client name leftover state cannot be cleaned up
 * if the client is behind a NAT server.
 */
static int
smb_netbios_session_request(struct smb_session *session)
{
	int			rc;
	char			*calling_name;
	char			*called_name;
	char 			client_name[NETBIOS_NAME_SZ];
	struct mbuf_chain 	mbc;
	char 			*names = NULL;
	smb_wchar_t		*wbuf = NULL;
	smb_xprt_t		hdr;
	char *p;
	int rc1, rc2;

	session->keep_alive = smb_keep_alive;

	if ((rc = smb_session_xprt_gethdr(session, &hdr)) != 0)
		return (rc);

	DTRACE_PROBE2(receive__session__req__xprthdr, struct session *, session,
	    smb_xprt_t *, &hdr);

	if ((hdr.xh_type != SESSION_REQUEST) ||
	    (hdr.xh_length != NETBIOS_SESSION_REQUEST_DATA_LENGTH)) {
		DTRACE_PROBE1(receive__session__req__failed,
		    struct session *, session);
		return (EINVAL);
	}

	names = kmem_alloc(hdr.xh_length, KM_SLEEP);

	if ((rc = smb_sorecv(session->sock, names, hdr.xh_length)) != 0) {
		kmem_free(names, hdr.xh_length);
		DTRACE_PROBE1(receive__session__req__failed,
		    struct session *, session);
		return (rc);
	}

	DTRACE_PROBE3(receive__session__req__data, struct session *, session,
	    char *, names, uint32_t, hdr.xh_length);

	called_name = &names[0];
	calling_name = &names[NETBIOS_ENCODED_NAME_SZ + 2];

	rc1 = netbios_name_isvalid(called_name, 0);
	rc2 = netbios_name_isvalid(calling_name, client_name);

	if (rc1 == 0 || rc2 == 0) {

		DTRACE_PROBE3(receive__invalid__session__req,
		    struct session *, session, char *, names,
		    uint32_t, hdr.xh_length);

		kmem_free(names, hdr.xh_length);
		MBC_INIT(&mbc, MAX_DATAGRAM_LENGTH);
		(void) smb_mbc_encodef(&mbc, "b",
		    DATAGRAM_INVALID_SOURCE_NAME_FORMAT);
		(void) smb_session_send(session, NEGATIVE_SESSION_RESPONSE,
		    &mbc);
		return (EINVAL);
	}