/* * 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); }
/* * 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); }