1da6c28aaSamw /* 2da6c28aaSamw * CDDL HEADER START 3da6c28aaSamw * 4da6c28aaSamw * The contents of this file are subject to the terms of the 5da6c28aaSamw * Common Development and Distribution License (the "License"). 6da6c28aaSamw * You may not use this file except in compliance with the License. 7da6c28aaSamw * 8da6c28aaSamw * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9da6c28aaSamw * or http://www.opensolaris.org/os/licensing. 10da6c28aaSamw * See the License for the specific language governing permissions 11da6c28aaSamw * and limitations under the License. 12da6c28aaSamw * 13da6c28aaSamw * When distributing Covered Code, include this CDDL HEADER in each 14da6c28aaSamw * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15da6c28aaSamw * If applicable, add the following below this CDDL HEADER, with the 16da6c28aaSamw * fields enclosed by brackets "[]" replaced with your own identifying 17da6c28aaSamw * information: Portions Copyright [yyyy] [name of copyright owner] 18da6c28aaSamw * 19da6c28aaSamw * CDDL HEADER END 20da6c28aaSamw */ 21da6c28aaSamw /* 22148c5f43SAlan Wright * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. 23ccc71be5SGordon Ross * Copyright 2012 Nexenta Systems, Inc. All rights reserved. 24da6c28aaSamw */ 25da6c28aaSamw #include <sys/atomic.h> 26da6c28aaSamw #include <sys/strsubr.h> 27da6c28aaSamw #include <sys/synch.h> 28da6c28aaSamw #include <sys/types.h> 29da6c28aaSamw #include <sys/socketvar.h> 30da6c28aaSamw #include <sys/sdt.h> 31*f9bc6dadSDmitry.Savitsky@nexenta.com #include <sys/random.h> 32da6c28aaSamw #include <smbsrv/netbios.h> 33bbf6f00cSJordan Brown #include <smbsrv/smb_kproto.h> 34bbf6f00cSJordan Brown #include <smbsrv/string.h> 357f667e74Sjose borrego #include <inet/tcp.h> 36da6c28aaSamw 37faa1795aSjb static volatile uint64_t smb_kids; 38da6c28aaSamw 39faa1795aSjb uint32_t smb_keep_alive = SSN_KEEP_ALIVE_TIMEOUT; 40da6c28aaSamw 412c2961f8Sjose borrego static void smb_session_cancel(smb_session_t *); 42da6c28aaSamw static int smb_session_message(smb_session_t *); 43da6c28aaSamw static int smb_session_xprt_puthdr(smb_session_t *, smb_xprt_t *, 44da6c28aaSamw uint8_t *, size_t); 45b89a8333Snatalie li - Sun Microsystems - Irvine United States static smb_user_t *smb_session_lookup_user(smb_session_t *, char *, char *); 469fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States static void smb_session_logoff(smb_session_t *); 47faa1795aSjb static void smb_request_init_command_mbuf(smb_request_t *sr); 487f667e74Sjose borrego void dump_smb_inaddr(smb_inaddr_t *ipaddr); 49*f9bc6dadSDmitry.Savitsky@nexenta.com static void smb_session_genkey(smb_session_t *); 50da6c28aaSamw 51da6c28aaSamw void 524163af6aSjose borrego smb_session_timers(smb_llist_t *ll) 53da6c28aaSamw { 54faa1795aSjb smb_session_t *session; 55da6c28aaSamw 564163af6aSjose borrego smb_llist_enter(ll, RW_READER); 574163af6aSjose borrego session = smb_llist_head(ll); 584163af6aSjose borrego while (session != NULL) { 59da6c28aaSamw /* 60da6c28aaSamw * Walk through the table and decrement each keep_alive 61da6c28aaSamw * timer that has not timed out yet. (keepalive > 0) 62da6c28aaSamw */ 634163af6aSjose borrego SMB_SESSION_VALID(session); 64faa1795aSjb if (session->keep_alive && 65faa1795aSjb (session->keep_alive != (uint32_t)-1)) 66faa1795aSjb session->keep_alive--; 674163af6aSjose borrego session = smb_llist_next(ll, session); 68faa1795aSjb } 694163af6aSjose borrego smb_llist_exit(ll); 70faa1795aSjb } 71da6c28aaSamw 72faa1795aSjb void 734163af6aSjose borrego smb_session_correct_keep_alive_values(smb_llist_t *ll, uint32_t new_keep_alive) 74faa1795aSjb { 75faa1795aSjb smb_session_t *sn; 76faa1795aSjb 77faa1795aSjb if (new_keep_alive == smb_keep_alive) 78faa1795aSjb return; 79faa1795aSjb /* 80faa1795aSjb * keep alive == 0 means do not drop connection if it's idle 81faa1795aSjb */ 82faa1795aSjb smb_keep_alive = (new_keep_alive) ? new_keep_alive : -1; 83faa1795aSjb 84faa1795aSjb /* 85faa1795aSjb * Walk through the table and set each session to the new keep_alive 86faa1795aSjb * value if they have not already timed out. Block clock interrupts. 87faa1795aSjb */ 884163af6aSjose borrego smb_llist_enter(ll, RW_READER); 894163af6aSjose borrego sn = smb_llist_head(ll); 904163af6aSjose borrego while (sn != NULL) { 914163af6aSjose borrego SMB_SESSION_VALID(sn); 924163af6aSjose borrego if (sn->keep_alive != 0) 93faa1795aSjb sn->keep_alive = new_keep_alive; 944163af6aSjose borrego sn = smb_llist_next(ll, sn); 95faa1795aSjb } 964163af6aSjose borrego smb_llist_exit(ll); 97da6c28aaSamw } 98da6c28aaSamw 99da6c28aaSamw /* 100da6c28aaSamw * Send a session message - supports SMB-over-NBT and SMB-over-TCP. 101da6c28aaSamw * 102da6c28aaSamw * The mbuf chain is copied into a contiguous buffer so that the whole 103da6c28aaSamw * message is submitted to smb_sosend as a single request. This should 104da6c28aaSamw * help Ethereal/Wireshark delineate the packets correctly even though 105da6c28aaSamw * TCP_NODELAY has been set on the socket. 106da6c28aaSamw * 107da6c28aaSamw * If an mbuf chain is provided, it will be freed and set to NULL here. 108da6c28aaSamw */ 109da6c28aaSamw int 11021b7895dSjb smb_session_send(smb_session_t *session, uint8_t type, mbuf_chain_t *mbc) 111da6c28aaSamw { 11221b7895dSjb smb_txreq_t *txr; 1135cdbe942Sjb smb_xprt_t hdr; 1145cdbe942Sjb int rc; 115da6c28aaSamw 116da6c28aaSamw switch (session->s_state) { 117da6c28aaSamw case SMB_SESSION_STATE_DISCONNECTED: 118da6c28aaSamw case SMB_SESSION_STATE_TERMINATED: 119da6c28aaSamw if ((mbc != NULL) && (mbc->chain != NULL)) { 120da6c28aaSamw m_freem(mbc->chain); 121da6c28aaSamw mbc->chain = NULL; 122da6c28aaSamw mbc->flags = 0; 123da6c28aaSamw } 124da6c28aaSamw return (ENOTCONN); 125da6c28aaSamw default: 126da6c28aaSamw break; 127da6c28aaSamw } 128da6c28aaSamw 12921b7895dSjb txr = smb_net_txr_alloc(); 130da6c28aaSamw 131da6c28aaSamw if ((mbc != NULL) && (mbc->chain != NULL)) { 13221b7895dSjb rc = mbc_moveout(mbc, (caddr_t)&txr->tr_buf[NETBIOS_HDR_SZ], 13321b7895dSjb sizeof (txr->tr_buf) - NETBIOS_HDR_SZ, &txr->tr_len); 13421b7895dSjb if (rc != 0) { 13521b7895dSjb smb_net_txr_free(txr); 13621b7895dSjb return (rc); 137da6c28aaSamw } 138da6c28aaSamw } 139da6c28aaSamw 140da6c28aaSamw hdr.xh_type = type; 14121b7895dSjb hdr.xh_length = (uint32_t)txr->tr_len; 142da6c28aaSamw 14321b7895dSjb rc = smb_session_xprt_puthdr(session, &hdr, txr->tr_buf, 1445cdbe942Sjb NETBIOS_HDR_SZ); 14521b7895dSjb 14621b7895dSjb if (rc != 0) { 14721b7895dSjb smb_net_txr_free(txr); 14821b7895dSjb return (rc); 149da6c28aaSamw } 15021b7895dSjb txr->tr_len += NETBIOS_HDR_SZ; 151148c5f43SAlan Wright smb_server_add_txb(session->s_server, (int64_t)txr->tr_len); 15221b7895dSjb return (smb_net_txr_send(session->sock, &session->s_txlst, txr)); 153da6c28aaSamw } 154da6c28aaSamw 155da6c28aaSamw /* 156da6c28aaSamw * Read, process and respond to a NetBIOS session request. 157da6c28aaSamw * 158da6c28aaSamw * A NetBIOS session must be established for SMB-over-NetBIOS. Validate 159da6c28aaSamw * the calling and called name format and save the client NetBIOS name, 160da6c28aaSamw * which is used when a NetBIOS session is established to check for and 161da6c28aaSamw * cleanup leftover state from a previous session. 162da6c28aaSamw * 163da6c28aaSamw * Session requests are not valid for SMB-over-TCP, which is unfortunate 164da6c28aaSamw * because without the client name leftover state cannot be cleaned up 165da6c28aaSamw * if the client is behind a NAT server. 166da6c28aaSamw */ 167da6c28aaSamw static int 168da6c28aaSamw smb_session_request(struct smb_session *session) 169da6c28aaSamw { 170da6c28aaSamw int rc; 171da6c28aaSamw char *calling_name; 172da6c28aaSamw char *called_name; 173da6c28aaSamw char client_name[NETBIOS_NAME_SZ]; 174da6c28aaSamw struct mbuf_chain mbc; 175da6c28aaSamw char *names = NULL; 176bbf6f00cSJordan Brown smb_wchar_t *wbuf = NULL; 177da6c28aaSamw smb_xprt_t hdr; 178da6c28aaSamw char *p; 179da6c28aaSamw int rc1, rc2; 180da6c28aaSamw 181da6c28aaSamw session->keep_alive = smb_keep_alive; 182da6c28aaSamw 183faa1795aSjb if ((rc = smb_session_xprt_gethdr(session, &hdr)) != 0) 184faa1795aSjb return (rc); 185da6c28aaSamw 186da6c28aaSamw DTRACE_PROBE2(receive__session__req__xprthdr, struct session *, session, 187da6c28aaSamw smb_xprt_t *, &hdr); 188da6c28aaSamw 189da6c28aaSamw if ((hdr.xh_type != SESSION_REQUEST) || 190da6c28aaSamw (hdr.xh_length != NETBIOS_SESSION_REQUEST_DATA_LENGTH)) { 191da6c28aaSamw DTRACE_PROBE1(receive__session__req__failed, 192da6c28aaSamw struct session *, session); 193da6c28aaSamw return (EINVAL); 194da6c28aaSamw } 195da6c28aaSamw 196da6c28aaSamw names = kmem_alloc(hdr.xh_length, KM_SLEEP); 197da6c28aaSamw 198da6c28aaSamw if ((rc = smb_sorecv(session->sock, names, hdr.xh_length)) != 0) { 199da6c28aaSamw kmem_free(names, hdr.xh_length); 200da6c28aaSamw DTRACE_PROBE1(receive__session__req__failed, 201da6c28aaSamw struct session *, session); 202da6c28aaSamw return (rc); 203da6c28aaSamw } 204da6c28aaSamw 205da6c28aaSamw DTRACE_PROBE3(receive__session__req__data, struct session *, session, 206da6c28aaSamw char *, names, uint32_t, hdr.xh_length); 207da6c28aaSamw 208da6c28aaSamw called_name = &names[0]; 209da6c28aaSamw calling_name = &names[NETBIOS_ENCODED_NAME_SZ + 2]; 210da6c28aaSamw 211da6c28aaSamw rc1 = netbios_name_isvalid(called_name, 0); 212da6c28aaSamw rc2 = netbios_name_isvalid(calling_name, client_name); 213da6c28aaSamw 214da6c28aaSamw if (rc1 == 0 || rc2 == 0) { 215da6c28aaSamw 216da6c28aaSamw DTRACE_PROBE3(receive__invalid__session__req, 217da6c28aaSamw struct session *, session, char *, names, 218da6c28aaSamw uint32_t, hdr.xh_length); 219da6c28aaSamw 220da6c28aaSamw kmem_free(names, hdr.xh_length); 221da6c28aaSamw MBC_INIT(&mbc, MAX_DATAGRAM_LENGTH); 2223db3f65cSamw (void) smb_mbc_encodef(&mbc, "b", 223da6c28aaSamw DATAGRAM_INVALID_SOURCE_NAME_FORMAT); 224da6c28aaSamw (void) smb_session_send(session, NEGATIVE_SESSION_RESPONSE, 225da6c28aaSamw &mbc); 226da6c28aaSamw return (EINVAL); 227da6c28aaSamw } 228da6c28aaSamw 229da6c28aaSamw DTRACE_PROBE3(receive__session__req__calling__decoded, 230da6c28aaSamw struct session *, session, 231da6c28aaSamw char *, calling_name, char *, client_name); 232da6c28aaSamw 233da6c28aaSamw /* 234da6c28aaSamw * The client NetBIOS name is in oem codepage format. 235da6c28aaSamw * We need to convert it to unicode and store it in 236da6c28aaSamw * multi-byte format. We also need to strip off any 237da6c28aaSamw * spaces added as part of the NetBIOS name encoding. 238da6c28aaSamw */ 239bbf6f00cSJordan Brown wbuf = kmem_alloc((SMB_PI_MAX_HOST * sizeof (smb_wchar_t)), KM_SLEEP); 240bbf6f00cSJordan Brown (void) oemtoucs(wbuf, client_name, SMB_PI_MAX_HOST, OEM_CPG_850); 241bbf6f00cSJordan Brown (void) smb_wcstombs(session->workstation, wbuf, SMB_PI_MAX_HOST); 242bbf6f00cSJordan Brown kmem_free(wbuf, (SMB_PI_MAX_HOST * sizeof (smb_wchar_t))); 243da6c28aaSamw 244da6c28aaSamw if ((p = strchr(session->workstation, ' ')) != 0) 245da6c28aaSamw *p = '\0'; 246da6c28aaSamw 247da6c28aaSamw kmem_free(names, hdr.xh_length); 248da6c28aaSamw return (smb_session_send(session, POSITIVE_SESSION_RESPONSE, NULL)); 249da6c28aaSamw } 250da6c28aaSamw 251da6c28aaSamw /* 252da6c28aaSamw * Read 4-byte header from the session socket and build an in-memory 253da6c28aaSamw * session transport header. See smb_xprt_t definition for header 254da6c28aaSamw * format information. 255da6c28aaSamw * 256da6c28aaSamw * Direct hosted NetBIOS-less SMB (SMB-over-TCP) uses port 445. The 257da6c28aaSamw * first byte of the four-byte header must be 0 and the next three 258da6c28aaSamw * bytes contain the length of the remaining data. 259da6c28aaSamw */ 260da6c28aaSamw int 261da6c28aaSamw smb_session_xprt_gethdr(smb_session_t *session, smb_xprt_t *ret_hdr) 262da6c28aaSamw { 263faa1795aSjb int rc; 264faa1795aSjb unsigned char buf[NETBIOS_HDR_SZ]; 265da6c28aaSamw 266faa1795aSjb if ((rc = smb_sorecv(session->sock, buf, NETBIOS_HDR_SZ)) != 0) 267faa1795aSjb return (rc); 268da6c28aaSamw 269da6c28aaSamw switch (session->s_local_port) { 270a0aa776eSAlan Wright case IPPORT_NETBIOS_SSN: 271da6c28aaSamw ret_hdr->xh_type = buf[0]; 272da6c28aaSamw ret_hdr->xh_length = (((uint32_t)buf[1] & 1) << 16) | 273da6c28aaSamw ((uint32_t)buf[2] << 8) | 274da6c28aaSamw ((uint32_t)buf[3]); 275da6c28aaSamw break; 276da6c28aaSamw 277a0aa776eSAlan Wright case IPPORT_SMB: 278da6c28aaSamw ret_hdr->xh_type = buf[0]; 279da6c28aaSamw 280da6c28aaSamw if (ret_hdr->xh_type != 0) { 2817f667e74Sjose borrego cmn_err(CE_WARN, "invalid type (%u)", ret_hdr->xh_type); 2827f667e74Sjose borrego dump_smb_inaddr(&session->ipaddr); 283faa1795aSjb return (EPROTO); 284da6c28aaSamw } 285da6c28aaSamw 286da6c28aaSamw ret_hdr->xh_length = ((uint32_t)buf[1] << 16) | 287da6c28aaSamw ((uint32_t)buf[2] << 8) | 288da6c28aaSamw ((uint32_t)buf[3]); 289da6c28aaSamw break; 290da6c28aaSamw 291da6c28aaSamw default: 2927f667e74Sjose borrego cmn_err(CE_WARN, "invalid port %u", session->s_local_port); 2937f667e74Sjose borrego dump_smb_inaddr(&session->ipaddr); 294faa1795aSjb return (EPROTO); 295da6c28aaSamw } 296da6c28aaSamw 297da6c28aaSamw return (0); 298da6c28aaSamw } 299da6c28aaSamw 300da6c28aaSamw /* 301da6c28aaSamw * Encode a transport session packet header into a 4-byte buffer. 302da6c28aaSamw * See smb_xprt_t definition for header format information. 303da6c28aaSamw */ 304da6c28aaSamw static int 305da6c28aaSamw smb_session_xprt_puthdr(smb_session_t *session, smb_xprt_t *hdr, 306da6c28aaSamw uint8_t *buf, size_t buflen) 307da6c28aaSamw { 308da6c28aaSamw if (session == NULL || hdr == NULL || 309da6c28aaSamw buf == NULL || buflen < NETBIOS_HDR_SZ) { 310da6c28aaSamw return (-1); 311da6c28aaSamw } 312da6c28aaSamw 313da6c28aaSamw switch (session->s_local_port) { 314a0aa776eSAlan Wright case IPPORT_NETBIOS_SSN: 315da6c28aaSamw buf[0] = hdr->xh_type; 316da6c28aaSamw buf[1] = ((hdr->xh_length >> 16) & 1); 317da6c28aaSamw buf[2] = (hdr->xh_length >> 8) & 0xff; 318da6c28aaSamw buf[3] = hdr->xh_length & 0xff; 319da6c28aaSamw break; 320da6c28aaSamw 321a0aa776eSAlan Wright case IPPORT_SMB: 322da6c28aaSamw buf[0] = hdr->xh_type; 323da6c28aaSamw buf[1] = (hdr->xh_length >> 16) & 0xff; 324da6c28aaSamw buf[2] = (hdr->xh_length >> 8) & 0xff; 325da6c28aaSamw buf[3] = hdr->xh_length & 0xff; 326da6c28aaSamw break; 327da6c28aaSamw 328da6c28aaSamw default: 3297f667e74Sjose borrego cmn_err(CE_WARN, "invalid port %u", session->s_local_port); 3307f667e74Sjose borrego dump_smb_inaddr(&session->ipaddr); 331da6c28aaSamw return (-1); 332da6c28aaSamw } 333da6c28aaSamw 334da6c28aaSamw return (0); 335da6c28aaSamw } 336da6c28aaSamw 337faa1795aSjb static void 338da6c28aaSamw smb_request_init_command_mbuf(smb_request_t *sr) 339da6c28aaSamw { 340da6c28aaSamw MGET(sr->command.chain, 0, MT_DATA); 341da6c28aaSamw 342da6c28aaSamw /* 343da6c28aaSamw * Setup mbuf, mimic MCLGET but use the complete packet buffer. 344da6c28aaSamw */ 345da6c28aaSamw sr->command.chain->m_ext.ext_buf = sr->sr_request_buf; 346da6c28aaSamw sr->command.chain->m_data = sr->command.chain->m_ext.ext_buf; 347da6c28aaSamw sr->command.chain->m_len = sr->sr_req_length; 348da6c28aaSamw sr->command.chain->m_flags |= M_EXT; 349da6c28aaSamw sr->command.chain->m_ext.ext_size = sr->sr_req_length; 350da6c28aaSamw sr->command.chain->m_ext.ext_ref = &mclrefnoop; 351da6c28aaSamw 352da6c28aaSamw /* 353da6c28aaSamw * Initialize the rest of the mbuf_chain fields 354da6c28aaSamw */ 355da6c28aaSamw sr->command.flags = 0; 356da6c28aaSamw sr->command.shadow_of = 0; 357da6c28aaSamw sr->command.max_bytes = sr->sr_req_length; 358da6c28aaSamw sr->command.chain_offset = 0; 359da6c28aaSamw } 360da6c28aaSamw 361da6c28aaSamw /* 362da6c28aaSamw * smb_request_cancel 363da6c28aaSamw * 364da6c28aaSamw * Handle a cancel for a request properly depending on the current request 365da6c28aaSamw * state. 366da6c28aaSamw */ 367da6c28aaSamw void 368da6c28aaSamw smb_request_cancel(smb_request_t *sr) 369da6c28aaSamw { 370da6c28aaSamw mutex_enter(&sr->sr_mutex); 371da6c28aaSamw switch (sr->sr_state) { 372da6c28aaSamw 373584e0fceSGordon Ross case SMB_REQ_STATE_INITIALIZING: 374da6c28aaSamw case SMB_REQ_STATE_SUBMITTED: 375da6c28aaSamw case SMB_REQ_STATE_ACTIVE: 376da6c28aaSamw case SMB_REQ_STATE_CLEANED_UP: 377da6c28aaSamw sr->sr_state = SMB_REQ_STATE_CANCELED; 378da6c28aaSamw break; 379da6c28aaSamw 380da6c28aaSamw case SMB_REQ_STATE_WAITING_LOCK: 381da6c28aaSamw /* 382da6c28aaSamw * This request is waiting on a lock. Wakeup everything 383da6c28aaSamw * waiting on the lock so that the relevant thread regains 384da6c28aaSamw * control and notices that is has been canceled. The 385da6c28aaSamw * other lock request threads waiting on this lock will go 386da6c28aaSamw * back to sleep when they discover they are still blocked. 387da6c28aaSamw */ 388da6c28aaSamw sr->sr_state = SMB_REQ_STATE_CANCELED; 389da6c28aaSamw 390da6c28aaSamw ASSERT(sr->sr_awaiting != NULL); 391da6c28aaSamw mutex_enter(&sr->sr_awaiting->l_mutex); 392da6c28aaSamw cv_broadcast(&sr->sr_awaiting->l_cv); 393da6c28aaSamw mutex_exit(&sr->sr_awaiting->l_mutex); 394da6c28aaSamw break; 395da6c28aaSamw 396da6c28aaSamw case SMB_REQ_STATE_WAITING_EVENT: 397da6c28aaSamw /* 398ccc71be5SGordon Ross * This request is waiting in change notify. 399da6c28aaSamw */ 400ccc71be5SGordon Ross sr->sr_state = SMB_REQ_STATE_CANCELED; 401ccc71be5SGordon Ross cv_signal(&sr->sr_ncr.nc_cv); 402da6c28aaSamw break; 403da6c28aaSamw 404ccc71be5SGordon Ross case SMB_REQ_STATE_EVENT_OCCURRED: 405da6c28aaSamw case SMB_REQ_STATE_COMPLETED: 406da6c28aaSamw case SMB_REQ_STATE_CANCELED: 407da6c28aaSamw /* 408da6c28aaSamw * No action required for these states since the request 409da6c28aaSamw * is completing. 410da6c28aaSamw */ 411da6c28aaSamw break; 412584e0fceSGordon Ross 413584e0fceSGordon Ross case SMB_REQ_STATE_FREE: 414da6c28aaSamw default: 4152c2961f8Sjose borrego SMB_PANIC(); 416da6c28aaSamw } 417da6c28aaSamw mutex_exit(&sr->sr_mutex); 418da6c28aaSamw } 419da6c28aaSamw 420da6c28aaSamw /* 4214163af6aSjose borrego * smb_session_receiver 422da6c28aaSamw * 4234163af6aSjose borrego * Receives request from the network and dispatches them to a worker. 424da6c28aaSamw */ 4254163af6aSjose borrego void 4264163af6aSjose borrego smb_session_receiver(smb_session_t *session) 427da6c28aaSamw { 4284163af6aSjose borrego int rc; 429da6c28aaSamw 4304163af6aSjose borrego SMB_SESSION_VALID(session); 4314163af6aSjose borrego 4324163af6aSjose borrego session->s_thread = curthread; 433da6c28aaSamw 434a0aa776eSAlan Wright if (session->s_local_port == IPPORT_NETBIOS_SSN) { 435da6c28aaSamw rc = smb_session_request(session); 4364163af6aSjose borrego if (rc != 0) { 437faa1795aSjb smb_rwx_rwenter(&session->s_lock, RW_WRITER); 438faa1795aSjb session->s_state = SMB_SESSION_STATE_DISCONNECTED; 439faa1795aSjb smb_rwx_rwexit(&session->s_lock); 4404163af6aSjose borrego return; 441faa1795aSjb } 442faa1795aSjb } 443da6c28aaSamw 444da6c28aaSamw smb_rwx_rwenter(&session->s_lock, RW_WRITER); 445faa1795aSjb session->s_state = SMB_SESSION_STATE_ESTABLISHED; 446faa1795aSjb smb_rwx_rwexit(&session->s_lock); 447da6c28aaSamw 4484163af6aSjose borrego (void) smb_session_message(session); 449da6c28aaSamw 450faa1795aSjb smb_rwx_rwenter(&session->s_lock, RW_WRITER); 451da6c28aaSamw session->s_state = SMB_SESSION_STATE_DISCONNECTED; 452da6c28aaSamw smb_rwx_rwexit(&session->s_lock); 453da6c28aaSamw 454faa1795aSjb smb_soshutdown(session->sock); 455faa1795aSjb 456da6c28aaSamw DTRACE_PROBE2(session__drop, struct session *, session, int, rc); 457da6c28aaSamw 458da6c28aaSamw smb_session_cancel(session); 459da6c28aaSamw /* 460da6c28aaSamw * At this point everything related to the session should have been 461da6c28aaSamw * cleaned up and we expect that nothing will attempt to use the 462da6c28aaSamw * socket. 463da6c28aaSamw */ 4644163af6aSjose borrego } 465da6c28aaSamw 4664163af6aSjose borrego /* 4674163af6aSjose borrego * smb_session_disconnect 4684163af6aSjose borrego * 4694163af6aSjose borrego * Disconnects the session passed in. 4704163af6aSjose borrego */ 4714163af6aSjose borrego void 4724163af6aSjose borrego smb_session_disconnect(smb_session_t *session) 4734163af6aSjose borrego { 4744163af6aSjose borrego SMB_SESSION_VALID(session); 4754163af6aSjose borrego 4764163af6aSjose borrego smb_rwx_rwenter(&session->s_lock, RW_WRITER); 4774163af6aSjose borrego switch (session->s_state) { 4784163af6aSjose borrego case SMB_SESSION_STATE_INITIALIZED: 4794163af6aSjose borrego case SMB_SESSION_STATE_CONNECTED: 4804163af6aSjose borrego case SMB_SESSION_STATE_ESTABLISHED: 4814163af6aSjose borrego case SMB_SESSION_STATE_NEGOTIATED: 4824163af6aSjose borrego case SMB_SESSION_STATE_OPLOCK_BREAKING: 4834163af6aSjose borrego case SMB_SESSION_STATE_WRITE_RAW_ACTIVE: 4844163af6aSjose borrego case SMB_SESSION_STATE_READ_RAW_ACTIVE: 4854163af6aSjose borrego smb_soshutdown(session->sock); 4864163af6aSjose borrego session->s_state = SMB_SESSION_STATE_DISCONNECTED; 4874163af6aSjose borrego _NOTE(FALLTHRU) 4884163af6aSjose borrego case SMB_SESSION_STATE_DISCONNECTED: 4894163af6aSjose borrego case SMB_SESSION_STATE_TERMINATED: 4904163af6aSjose borrego break; 4914163af6aSjose borrego } 4924163af6aSjose borrego smb_rwx_rwexit(&session->s_lock); 493da6c28aaSamw } 494da6c28aaSamw 495da6c28aaSamw /* 496da6c28aaSamw * Read and process SMB requests. 497da6c28aaSamw * 498da6c28aaSamw * Returns: 499da6c28aaSamw * 0 Success 500da6c28aaSamw * 1 Unable to read transport header 501da6c28aaSamw * 2 Invalid transport header type 502da6c28aaSamw * 3 Invalid SMB length (too small) 503da6c28aaSamw * 4 Unable to read SMB header 504da6c28aaSamw * 5 Invalid SMB header (bad magic number) 505da6c28aaSamw * 6 Unable to read SMB data 506da6c28aaSamw * 2x Write raw failed 507da6c28aaSamw */ 508da6c28aaSamw static int 509da6c28aaSamw smb_session_message(smb_session_t *session) 510da6c28aaSamw { 511148c5f43SAlan Wright smb_server_t *sv; 512faa1795aSjb smb_request_t *sr = NULL; 513faa1795aSjb smb_xprt_t hdr; 514faa1795aSjb uint8_t *req_buf; 515faa1795aSjb uint32_t resid; 516faa1795aSjb int rc; 517da6c28aaSamw 518148c5f43SAlan Wright sv = session->s_server; 519148c5f43SAlan Wright 520faa1795aSjb for (;;) { 521faa1795aSjb 522faa1795aSjb rc = smb_session_xprt_gethdr(session, &hdr); 523faa1795aSjb if (rc) 524faa1795aSjb return (rc); 525faa1795aSjb 526faa1795aSjb DTRACE_PROBE2(session__receive__xprthdr, session_t *, session, 527faa1795aSjb smb_xprt_t *, &hdr); 528faa1795aSjb 529faa1795aSjb if (hdr.xh_type != SESSION_MESSAGE) { 530faa1795aSjb /* 531faa1795aSjb * Anything other than SESSION_MESSAGE or 532faa1795aSjb * SESSION_KEEP_ALIVE is an error. A SESSION_REQUEST 533faa1795aSjb * may indicate a new session request but we need to 534faa1795aSjb * close this session and we can treat it as an error 535faa1795aSjb * here. 536faa1795aSjb */ 537faa1795aSjb if (hdr.xh_type == SESSION_KEEP_ALIVE) { 538faa1795aSjb session->keep_alive = smb_keep_alive; 539da6c28aaSamw continue; 540da6c28aaSamw } 541faa1795aSjb return (EPROTO); 542da6c28aaSamw } 543da6c28aaSamw 544faa1795aSjb if (hdr.xh_length < SMB_HEADER_LEN) 545faa1795aSjb return (EPROTO); 546da6c28aaSamw 547faa1795aSjb session->keep_alive = smb_keep_alive; 548da6c28aaSamw /* 549faa1795aSjb * Allocate a request context, read the SMB header and validate 550faa1795aSjb * it. The sr includes a buffer large enough to hold the SMB 551faa1795aSjb * request payload. If the header looks valid, read any 552faa1795aSjb * remaining data. 553da6c28aaSamw */ 554faa1795aSjb sr = smb_request_alloc(session, hdr.xh_length); 555da6c28aaSamw 556faa1795aSjb req_buf = (uint8_t *)sr->sr_request_buf; 557faa1795aSjb resid = hdr.xh_length; 558da6c28aaSamw 559faa1795aSjb rc = smb_sorecv(session->sock, req_buf, SMB_HEADER_LEN); 560faa1795aSjb if (rc) { 561faa1795aSjb smb_request_free(sr); 562faa1795aSjb return (rc); 563faa1795aSjb } 564da6c28aaSamw 565faa1795aSjb if (SMB_PROTOCOL_MAGIC_INVALID(sr)) { 566faa1795aSjb smb_request_free(sr); 567faa1795aSjb return (EPROTO); 568faa1795aSjb } 569da6c28aaSamw 570faa1795aSjb if (resid > SMB_HEADER_LEN) { 571faa1795aSjb req_buf += SMB_HEADER_LEN; 572faa1795aSjb resid -= SMB_HEADER_LEN; 573da6c28aaSamw 574faa1795aSjb rc = smb_sorecv(session->sock, req_buf, resid); 575faa1795aSjb if (rc) { 576faa1795aSjb smb_request_free(sr); 577faa1795aSjb return (rc); 578da6c28aaSamw } 579da6c28aaSamw } 580148c5f43SAlan Wright smb_server_add_rxb(sv, 581148c5f43SAlan Wright (int64_t)(hdr.xh_length + NETBIOS_HDR_SZ)); 582faa1795aSjb /* 583faa1795aSjb * Initialize command MBC to represent the received data. 584faa1795aSjb */ 585faa1795aSjb smb_request_init_command_mbuf(sr); 586da6c28aaSamw 587faa1795aSjb DTRACE_PROBE1(session__receive__smb, smb_request_t *, sr); 588da6c28aaSamw 589da6c28aaSamw /* 590faa1795aSjb * If this is a raw write, hand off the request. The handler 591faa1795aSjb * will retrieve the remaining raw data and process the request. 592da6c28aaSamw */ 593faa1795aSjb if (SMB_IS_WRITERAW(sr)) { 594faa1795aSjb rc = smb_handle_write_raw(session, sr); 5959fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States if (rc == 0) 5969fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States continue; 597faa1795aSjb return (rc); 598faa1795aSjb } 599148c5f43SAlan Wright if (sr->session->signing.flags & SMB_SIGNING_ENABLED) { 600148c5f43SAlan Wright if (SMB_IS_NT_CANCEL(sr)) { 601148c5f43SAlan Wright sr->session->signing.seqnum++; 602148c5f43SAlan Wright sr->sr_seqnum = sr->session->signing.seqnum + 1; 603148c5f43SAlan Wright sr->reply_seqnum = 0; 604148c5f43SAlan Wright } else { 605148c5f43SAlan Wright sr->session->signing.seqnum += 2; 606148c5f43SAlan Wright sr->sr_seqnum = sr->session->signing.seqnum; 607148c5f43SAlan Wright sr->reply_seqnum = sr->sr_seqnum + 1; 608148c5f43SAlan Wright } 609148c5f43SAlan Wright } 610148c5f43SAlan Wright sr->sr_time_submitted = gethrtime(); 611faa1795aSjb sr->sr_state = SMB_REQ_STATE_SUBMITTED; 612148c5f43SAlan Wright smb_srqueue_waitq_enter(session->s_srqueue); 6134163af6aSjose borrego (void) taskq_dispatch(session->s_server->sv_worker_pool, 614faa1795aSjb smb_session_worker, sr, TQ_SLEEP); 615da6c28aaSamw } 616da6c28aaSamw } 617da6c28aaSamw 618da6c28aaSamw /* 619a0aa776eSAlan Wright * Port will be IPPORT_NETBIOS_SSN or IPPORT_SMB. 620da6c28aaSamw */ 621da6c28aaSamw smb_session_t * 6227f667e74Sjose borrego smb_session_create(ksocket_t new_so, uint16_t port, smb_server_t *sv, 6237f667e74Sjose borrego int family) 624da6c28aaSamw { 625da6c28aaSamw struct sockaddr_in sin; 6260f1702c5SYu Xiangning socklen_t slen; 6277f667e74Sjose borrego struct sockaddr_in6 sin6; 628da6c28aaSamw smb_session_t *session; 629d3d50737SRafael Vanoni int64_t now; 630da6c28aaSamw 631faa1795aSjb session = kmem_cache_alloc(sv->si_cache_session, KM_SLEEP); 632da6c28aaSamw bzero(session, sizeof (smb_session_t)); 633da6c28aaSamw 634da6c28aaSamw if (smb_idpool_constructor(&session->s_uid_pool)) { 635faa1795aSjb kmem_cache_free(sv->si_cache_session, session); 636da6c28aaSamw return (NULL); 637da6c28aaSamw } 638da6c28aaSamw 639d3d50737SRafael Vanoni now = ddi_get_lbolt64(); 640d3d50737SRafael Vanoni 641da6c28aaSamw session->s_kid = SMB_NEW_KID(); 642faa1795aSjb session->s_state = SMB_SESSION_STATE_INITIALIZED; 643da6c28aaSamw session->native_os = NATIVE_OS_UNKNOWN; 644d3d50737SRafael Vanoni session->opentime = now; 645da6c28aaSamw session->keep_alive = smb_keep_alive; 646d3d50737SRafael Vanoni session->activity_timestamp = now; 647da6c28aaSamw 648*f9bc6dadSDmitry.Savitsky@nexenta.com smb_session_genkey(session); 649*f9bc6dadSDmitry.Savitsky@nexenta.com 650da6c28aaSamw smb_slist_constructor(&session->s_req_list, sizeof (smb_request_t), 651da6c28aaSamw offsetof(smb_request_t, sr_session_lnd)); 652da6c28aaSamw 653da6c28aaSamw smb_llist_constructor(&session->s_user_list, sizeof (smb_user_t), 654da6c28aaSamw offsetof(smb_user_t, u_lnd)); 655da6c28aaSamw 656da6c28aaSamw smb_llist_constructor(&session->s_xa_list, sizeof (smb_xa_t), 657da6c28aaSamw offsetof(smb_xa_t, xa_lnd)); 658da6c28aaSamw 6592c2961f8Sjose borrego list_create(&session->s_oplock_brkreqs, sizeof (mbuf_chain_t), 6602c2961f8Sjose borrego offsetof(mbuf_chain_t, mbc_lnd)); 6612c2961f8Sjose borrego 6625cdbe942Sjb smb_net_txl_constructor(&session->s_txlst); 6635cdbe942Sjb 664da6c28aaSamw smb_rwx_init(&session->s_lock); 665da6c28aaSamw 666148c5f43SAlan Wright if (new_so != NULL) { 6677f667e74Sjose borrego if (family == AF_INET) { 6687f667e74Sjose borrego slen = sizeof (sin); 6697f667e74Sjose borrego (void) ksocket_getsockname(new_so, 6707f667e74Sjose borrego (struct sockaddr *)&sin, &slen, CRED()); 671fc724630SAlan Wright bcopy(&sin.sin_addr, 672fc724630SAlan Wright &session->local_ipaddr.au_addr.au_ipv4, 673fc724630SAlan Wright sizeof (in_addr_t)); 674fc724630SAlan Wright slen = sizeof (sin); 6757f667e74Sjose borrego (void) ksocket_getpeername(new_so, 6767f667e74Sjose borrego (struct sockaddr *)&sin, &slen, CRED()); 677fc724630SAlan Wright bcopy(&sin.sin_addr, 678fc724630SAlan Wright &session->ipaddr.au_addr.au_ipv4, 679fc724630SAlan Wright sizeof (in_addr_t)); 6807f667e74Sjose borrego } else { 6817f667e74Sjose borrego slen = sizeof (sin6); 6827f667e74Sjose borrego (void) ksocket_getsockname(new_so, 6837f667e74Sjose borrego (struct sockaddr *)&sin6, &slen, CRED()); 684fc724630SAlan Wright bcopy(&sin6.sin6_addr, 685fc724630SAlan Wright &session->local_ipaddr.au_addr.au_ipv6, 686fc724630SAlan Wright sizeof (in6_addr_t)); 687fc724630SAlan Wright slen = sizeof (sin6); 6887f667e74Sjose borrego (void) ksocket_getpeername(new_so, 6897f667e74Sjose borrego (struct sockaddr *)&sin6, &slen, CRED()); 690fc724630SAlan Wright bcopy(&sin6.sin6_addr, 691fc724630SAlan Wright &session->ipaddr.au_addr.au_ipv6, 692fc724630SAlan Wright sizeof (in6_addr_t)); 6937f667e74Sjose borrego } 6947f667e74Sjose borrego session->ipaddr.a_family = family; 6957f667e74Sjose borrego session->local_ipaddr.a_family = family; 696faa1795aSjb session->s_local_port = port; 697faa1795aSjb session->sock = new_so; 698148c5f43SAlan Wright if (port == IPPORT_NETBIOS_SSN) 699148c5f43SAlan Wright smb_server_inc_nbt_sess(sv); 700148c5f43SAlan Wright else 701148c5f43SAlan Wright smb_server_inc_tcp_sess(sv); 702faa1795aSjb } 703faa1795aSjb session->s_server = sv; 704faa1795aSjb smb_server_get_cfg(sv, &session->s_cfg); 705148c5f43SAlan Wright session->s_srqueue = &sv->sv_srqueue; 706148c5f43SAlan Wright 707faa1795aSjb session->s_cache_request = sv->si_cache_request; 708faa1795aSjb session->s_cache = sv->si_cache_session; 709da6c28aaSamw session->s_magic = SMB_SESSION_MAGIC; 710da6c28aaSamw return (session); 711da6c28aaSamw } 712da6c28aaSamw 713da6c28aaSamw void 714da6c28aaSamw smb_session_delete(smb_session_t *session) 715da6c28aaSamw { 7162c2961f8Sjose borrego mbuf_chain_t *mbc; 7172c2961f8Sjose borrego 718da6c28aaSamw ASSERT(session->s_magic == SMB_SESSION_MAGIC); 719da6c28aaSamw 7202c2961f8Sjose borrego session->s_magic = 0; 721da6c28aaSamw 722da6c28aaSamw smb_rwx_destroy(&session->s_lock); 7235cdbe942Sjb smb_net_txl_destructor(&session->s_txlst); 7242c2961f8Sjose borrego 7252c2961f8Sjose borrego while ((mbc = list_head(&session->s_oplock_brkreqs)) != NULL) { 7262c2961f8Sjose borrego SMB_MBC_VALID(mbc); 7272c2961f8Sjose borrego list_remove(&session->s_oplock_brkreqs, mbc); 7282c2961f8Sjose borrego smb_mbc_free(mbc); 7292c2961f8Sjose borrego } 7302c2961f8Sjose borrego list_destroy(&session->s_oplock_brkreqs); 7312c2961f8Sjose borrego 732da6c28aaSamw smb_slist_destructor(&session->s_req_list); 733da6c28aaSamw smb_llist_destructor(&session->s_user_list); 734da6c28aaSamw smb_llist_destructor(&session->s_xa_list); 735da6c28aaSamw 736da6c28aaSamw ASSERT(session->s_tree_cnt == 0); 737da6c28aaSamw ASSERT(session->s_file_cnt == 0); 738da6c28aaSamw ASSERT(session->s_dir_cnt == 0); 739da6c28aaSamw 740da6c28aaSamw smb_idpool_destructor(&session->s_uid_pool); 7414163af6aSjose borrego if (session->sock != NULL) { 7424163af6aSjose borrego if (session->s_local_port == IPPORT_NETBIOS_SSN) 7434163af6aSjose borrego smb_server_dec_nbt_sess(session->s_server); 7444163af6aSjose borrego else 7454163af6aSjose borrego smb_server_dec_tcp_sess(session->s_server); 7464163af6aSjose borrego smb_sodestroy(session->sock); 7474163af6aSjose borrego } 748faa1795aSjb kmem_cache_free(session->s_cache, session); 749da6c28aaSamw } 750da6c28aaSamw 7512c2961f8Sjose borrego static void 752da6c28aaSamw smb_session_cancel(smb_session_t *session) 753da6c28aaSamw { 754da6c28aaSamw smb_xa_t *xa, *nextxa; 755da6c28aaSamw 756da6c28aaSamw /* All the request currently being treated must be canceled. */ 757c8ec8eeaSjose borrego smb_session_cancel_requests(session, NULL, NULL); 758da6c28aaSamw 759da6c28aaSamw /* 760da6c28aaSamw * We wait for the completion of all the requests associated with 761da6c28aaSamw * this session. 762da6c28aaSamw */ 763da6c28aaSamw smb_slist_wait_for_empty(&session->s_req_list); 764da6c28aaSamw 765da6c28aaSamw /* 766da6c28aaSamw * At this point the reference count of the users, trees, files, 767da6c28aaSamw * directories should be zero. It should be possible to destroy them 768da6c28aaSamw * without any problem. 769da6c28aaSamw */ 770da6c28aaSamw xa = smb_llist_head(&session->s_xa_list); 771da6c28aaSamw while (xa) { 772da6c28aaSamw nextxa = smb_llist_next(&session->s_xa_list, xa); 773da6c28aaSamw smb_xa_close(xa); 774da6c28aaSamw xa = nextxa; 775da6c28aaSamw } 7769fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 7779fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_session_logoff(session); 778da6c28aaSamw } 779da6c28aaSamw 780c8ec8eeaSjose borrego /* 781c8ec8eeaSjose borrego * Cancel requests. If a non-null tree is specified, only requests specific 782c8ec8eeaSjose borrego * to that tree will be cancelled. If a non-null sr is specified, that sr 783c8ec8eeaSjose borrego * will be not be cancelled - this would typically be the caller's sr. 784c8ec8eeaSjose borrego */ 785da6c28aaSamw void 786da6c28aaSamw smb_session_cancel_requests( 787c8ec8eeaSjose borrego smb_session_t *session, 788c8ec8eeaSjose borrego smb_tree_t *tree, 789c8ec8eeaSjose borrego smb_request_t *exclude_sr) 790da6c28aaSamw { 791da6c28aaSamw smb_request_t *sr; 792da6c28aaSamw 793da6c28aaSamw smb_slist_enter(&session->s_req_list); 794da6c28aaSamw sr = smb_slist_head(&session->s_req_list); 795c8ec8eeaSjose borrego 796da6c28aaSamw while (sr) { 797da6c28aaSamw ASSERT(sr->sr_magic == SMB_REQ_MAGIC); 798c8ec8eeaSjose borrego if ((sr != exclude_sr) && 799c8ec8eeaSjose borrego (tree == NULL || sr->tid_tree == tree)) 800c8ec8eeaSjose borrego smb_request_cancel(sr); 801da6c28aaSamw 802c8ec8eeaSjose borrego sr = smb_slist_next(&session->s_req_list, sr); 803da6c28aaSamw } 804c8ec8eeaSjose borrego 805da6c28aaSamw smb_slist_exit(&session->s_req_list); 806da6c28aaSamw } 807da6c28aaSamw 808da6c28aaSamw void 8092c2961f8Sjose borrego smb_session_worker(void *arg) 810da6c28aaSamw { 811da6c28aaSamw smb_request_t *sr; 812148c5f43SAlan Wright smb_srqueue_t *srq; 813da6c28aaSamw 814da6c28aaSamw sr = (smb_request_t *)arg; 815148c5f43SAlan Wright SMB_REQ_VALID(sr); 816da6c28aaSamw 817148c5f43SAlan Wright srq = sr->session->s_srqueue; 818148c5f43SAlan Wright smb_srqueue_waitq_to_runq(srq); 8192c2961f8Sjose borrego sr->sr_worker = curthread; 820da6c28aaSamw mutex_enter(&sr->sr_mutex); 821148c5f43SAlan Wright sr->sr_time_active = gethrtime(); 822da6c28aaSamw switch (sr->sr_state) { 823da6c28aaSamw case SMB_REQ_STATE_SUBMITTED: 824da6c28aaSamw mutex_exit(&sr->sr_mutex); 82559229f98Sjose borrego if (smb_dispatch_request(sr)) { 82659229f98Sjose borrego mutex_enter(&sr->sr_mutex); 827da6c28aaSamw sr->sr_state = SMB_REQ_STATE_COMPLETED; 828da6c28aaSamw mutex_exit(&sr->sr_mutex); 829da6c28aaSamw smb_request_free(sr); 830da6c28aaSamw } 831da6c28aaSamw break; 832da6c28aaSamw 833da6c28aaSamw default: 834da6c28aaSamw ASSERT(sr->sr_state == SMB_REQ_STATE_CANCELED); 835da6c28aaSamw sr->sr_state = SMB_REQ_STATE_COMPLETED; 836da6c28aaSamw mutex_exit(&sr->sr_mutex); 837da6c28aaSamw smb_request_free(sr); 838da6c28aaSamw break; 839da6c28aaSamw } 840148c5f43SAlan Wright smb_srqueue_runq_exit(srq); 841da6c28aaSamw } 842da6c28aaSamw 843b89a8333Snatalie li - Sun Microsystems - Irvine United States /* 844b89a8333Snatalie li - Sun Microsystems - Irvine United States * smb_session_lookup_user 845b89a8333Snatalie li - Sun Microsystems - Irvine United States */ 846b89a8333Snatalie li - Sun Microsystems - Irvine United States static smb_user_t * 847b89a8333Snatalie li - Sun Microsystems - Irvine United States smb_session_lookup_user(smb_session_t *session, char *domain, char *name) 848b89a8333Snatalie li - Sun Microsystems - Irvine United States { 849b89a8333Snatalie li - Sun Microsystems - Irvine United States smb_user_t *user; 850b89a8333Snatalie li - Sun Microsystems - Irvine United States smb_llist_t *ulist; 851b89a8333Snatalie li - Sun Microsystems - Irvine United States 852b89a8333Snatalie li - Sun Microsystems - Irvine United States ulist = &session->s_user_list; 853b89a8333Snatalie li - Sun Microsystems - Irvine United States smb_llist_enter(ulist, RW_READER); 854b89a8333Snatalie li - Sun Microsystems - Irvine United States user = smb_llist_head(ulist); 855b89a8333Snatalie li - Sun Microsystems - Irvine United States while (user) { 856b89a8333Snatalie li - Sun Microsystems - Irvine United States ASSERT(user->u_magic == SMB_USER_MAGIC); 857bbf6f00cSJordan Brown if (!smb_strcasecmp(user->u_name, name, 0) && 858bbf6f00cSJordan Brown !smb_strcasecmp(user->u_domain, domain, 0)) { 8591fcced4cSJordan Brown if (smb_user_hold(user)) 860b89a8333Snatalie li - Sun Microsystems - Irvine United States break; 861b89a8333Snatalie li - Sun Microsystems - Irvine United States } 862b89a8333Snatalie li - Sun Microsystems - Irvine United States user = smb_llist_next(ulist, user); 863b89a8333Snatalie li - Sun Microsystems - Irvine United States } 864b89a8333Snatalie li - Sun Microsystems - Irvine United States smb_llist_exit(ulist); 865b89a8333Snatalie li - Sun Microsystems - Irvine United States 866b89a8333Snatalie li - Sun Microsystems - Irvine United States return (user); 867b89a8333Snatalie li - Sun Microsystems - Irvine United States } 868b89a8333Snatalie li - Sun Microsystems - Irvine United States 869b89a8333Snatalie li - Sun Microsystems - Irvine United States /* 870b89a8333Snatalie li - Sun Microsystems - Irvine United States * If a user attempts to log in subsequently from the specified session, 871b89a8333Snatalie li - Sun Microsystems - Irvine United States * duplicates the existing SMB user instance such that all SMB user 872b89a8333Snatalie li - Sun Microsystems - Irvine United States * instances that corresponds to the same user on the given session 873b89a8333Snatalie li - Sun Microsystems - Irvine United States * reference the same user's cred. 874b89a8333Snatalie li - Sun Microsystems - Irvine United States * 875b89a8333Snatalie li - Sun Microsystems - Irvine United States * Returns NULL if the given user hasn't yet logged in from this 876b89a8333Snatalie li - Sun Microsystems - Irvine United States * specified session. Otherwise, returns a user instance that corresponds 877b89a8333Snatalie li - Sun Microsystems - Irvine United States * to this subsequent login. 878b89a8333Snatalie li - Sun Microsystems - Irvine United States */ 879b89a8333Snatalie li - Sun Microsystems - Irvine United States smb_user_t * 880b89a8333Snatalie li - Sun Microsystems - Irvine United States smb_session_dup_user(smb_session_t *session, char *domain, char *account_name) 881b89a8333Snatalie li - Sun Microsystems - Irvine United States { 882b89a8333Snatalie li - Sun Microsystems - Irvine United States smb_user_t *orig_user = NULL; 883b89a8333Snatalie li - Sun Microsystems - Irvine United States smb_user_t *user = NULL; 884b89a8333Snatalie li - Sun Microsystems - Irvine United States 885b89a8333Snatalie li - Sun Microsystems - Irvine United States orig_user = smb_session_lookup_user(session, domain, 886b89a8333Snatalie li - Sun Microsystems - Irvine United States account_name); 887b89a8333Snatalie li - Sun Microsystems - Irvine United States 888b89a8333Snatalie li - Sun Microsystems - Irvine United States if (orig_user) { 889b89a8333Snatalie li - Sun Microsystems - Irvine United States user = smb_user_dup(orig_user); 890b89a8333Snatalie li - Sun Microsystems - Irvine United States smb_user_release(orig_user); 891b89a8333Snatalie li - Sun Microsystems - Irvine United States } 892b89a8333Snatalie li - Sun Microsystems - Irvine United States 893b89a8333Snatalie li - Sun Microsystems - Irvine United States return (user); 894b89a8333Snatalie li - Sun Microsystems - Irvine United States } 895b89a8333Snatalie li - Sun Microsystems - Irvine United States 8969fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States /* 8979fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States * Find a user on the specified session by SMB UID. 8989fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States */ 8999fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_user_t * 9009fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_session_lookup_uid(smb_session_t *session, uint16_t uid) 9019fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States { 9029fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_user_t *user; 9039fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_llist_t *user_list; 9049fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 9059fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States SMB_SESSION_VALID(session); 9069fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 9079fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States user_list = &session->s_user_list; 9089fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_llist_enter(user_list, RW_READER); 9099fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 9109fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States user = smb_llist_head(user_list); 9119fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States while (user) { 9129fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States SMB_USER_VALID(user); 9139fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States ASSERT(user->u_session == session); 9149fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 9159fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States if (user->u_uid == uid) { 9169fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States if (!smb_user_hold(user)) 9179fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States break; 9189fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 9199fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_llist_exit(user_list); 9209fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States return (user); 9219fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States } 9229fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 9239fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States user = smb_llist_next(user_list, user); 9249fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States } 9259fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 9269fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_llist_exit(user_list); 9279fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States return (NULL); 9289fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States } 9299fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 9309fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States void 9319fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_session_post_user(smb_session_t *session, smb_user_t *user) 9329fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States { 9339fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States SMB_USER_VALID(user); 9349fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States ASSERT(user->u_refcnt == 0); 9359fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States ASSERT(user->u_state == SMB_USER_STATE_LOGGED_OFF); 9369fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States ASSERT(user->u_session == session); 9379fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 9389fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_llist_post(&session->s_user_list, user, smb_user_delete); 9399fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States } 9409fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 9419fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States /* 9429fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States * Logoff all users associated with the specified session. 9439fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States */ 9449fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States static void 9459fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_session_logoff(smb_session_t *session) 9469fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States { 9479fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_user_t *user; 9489fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 9499fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States SMB_SESSION_VALID(session); 9509fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 9519fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_llist_enter(&session->s_user_list, RW_READER); 9529fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 9539fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States user = smb_llist_head(&session->s_user_list); 9549fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States while (user) { 9559fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States SMB_USER_VALID(user); 9569fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States ASSERT(user->u_session == session); 9579fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 9589fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States if (smb_user_hold(user)) { 9599fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_user_logoff(user); 9609fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_user_release(user); 9619fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States } 9629fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 9639fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States user = smb_llist_next(&session->s_user_list, user); 9649fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States } 9659fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 9669fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_llist_exit(&session->s_user_list); 9679fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States } 9689fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 9699fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States /* 9709fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States * Disconnect any trees associated with the specified share. 9719fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States * Iterate through the users on this session and tell each user 9729fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States * to disconnect from the share. 9739fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States */ 9749fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States void 9759fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_session_disconnect_share(smb_session_t *session, const char *sharename) 9769fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States { 9779fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_user_t *user; 9789fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 9799fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States SMB_SESSION_VALID(session); 9809fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 9819fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_llist_enter(&session->s_user_list, RW_READER); 9829fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 9839fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States user = smb_llist_head(&session->s_user_list); 9849fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States while (user) { 9859fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States SMB_USER_VALID(user); 9869fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States ASSERT(user->u_session == session); 9879fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 9889fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States if (smb_user_hold(user)) { 9899fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_user_disconnect_share(user, sharename); 9909fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_user_release(user); 9919fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States } 9929fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 9939fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States user = smb_llist_next(&session->s_user_list, user); 9949fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States } 9959fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 9969fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_llist_exit(&session->s_user_list); 9979fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States } 9989fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 9991fcced4cSJordan Brown /* 10001fcced4cSJordan Brown * Copy the session workstation/client name to buf. If the workstation 10011fcced4cSJordan Brown * is an empty string (which it will be on TCP connections), use the 10021fcced4cSJordan Brown * client IP address. 10031fcced4cSJordan Brown */ 10041fcced4cSJordan Brown void 10051fcced4cSJordan Brown smb_session_getclient(smb_session_t *sn, char *buf, size_t buflen) 10061fcced4cSJordan Brown { 10071fcced4cSJordan Brown char ipbuf[INET6_ADDRSTRLEN]; 10081fcced4cSJordan Brown smb_inaddr_t *ipaddr; 10091fcced4cSJordan Brown 10101fcced4cSJordan Brown ASSERT(sn); 10111fcced4cSJordan Brown ASSERT(buf); 10121fcced4cSJordan Brown ASSERT(buflen); 10131fcced4cSJordan Brown 10141fcced4cSJordan Brown *buf = '\0'; 10151fcced4cSJordan Brown 10161fcced4cSJordan Brown if (sn->workstation[0] != '\0') { 10171fcced4cSJordan Brown (void) strlcpy(buf, sn->workstation, buflen); 10181fcced4cSJordan Brown return; 10191fcced4cSJordan Brown } 10201fcced4cSJordan Brown 10211fcced4cSJordan Brown ipaddr = &sn->ipaddr; 10221fcced4cSJordan Brown if (smb_inet_ntop(ipaddr, ipbuf, SMB_IPSTRLEN(ipaddr->a_family))) 10231fcced4cSJordan Brown (void) strlcpy(buf, ipbuf, buflen); 10241fcced4cSJordan Brown } 10251fcced4cSJordan Brown 10261fcced4cSJordan Brown /* 10271fcced4cSJordan Brown * Check whether or not the specified client name is the client of this 10281fcced4cSJordan Brown * session. The name may be in UNC format (\\CLIENT). 10291fcced4cSJordan Brown * 10301fcced4cSJordan Brown * A workstation/client name is setup on NBT connections as part of the 10311fcced4cSJordan Brown * NetBIOS session request but that isn't available on TCP connections. 10321fcced4cSJordan Brown * If the session doesn't have a client name we typically return the 10331fcced4cSJordan Brown * client IP address as the workstation name on MSRPC requests. So we 10341fcced4cSJordan Brown * check for the IP address here in addition to the workstation name. 10351fcced4cSJordan Brown */ 10361fcced4cSJordan Brown boolean_t 10371fcced4cSJordan Brown smb_session_isclient(smb_session_t *sn, const char *client) 10381fcced4cSJordan Brown { 10391fcced4cSJordan Brown char buf[INET6_ADDRSTRLEN]; 10401fcced4cSJordan Brown smb_inaddr_t *ipaddr; 10411fcced4cSJordan Brown 10421fcced4cSJordan Brown client += strspn(client, "\\"); 10431fcced4cSJordan Brown 1044bbf6f00cSJordan Brown if (smb_strcasecmp(client, sn->workstation, 0) == 0) 10451fcced4cSJordan Brown return (B_TRUE); 10461fcced4cSJordan Brown 10471fcced4cSJordan Brown ipaddr = &sn->ipaddr; 10481fcced4cSJordan Brown if (smb_inet_ntop(ipaddr, buf, SMB_IPSTRLEN(ipaddr->a_family)) == NULL) 10491fcced4cSJordan Brown return (B_FALSE); 10501fcced4cSJordan Brown 1051bbf6f00cSJordan Brown if (smb_strcasecmp(client, buf, 0) == 0) 10521fcced4cSJordan Brown return (B_TRUE); 10531fcced4cSJordan Brown 10541fcced4cSJordan Brown return (B_FALSE); 10551fcced4cSJordan Brown } 10561fcced4cSJordan Brown 1057faa1795aSjb /* 1058faa1795aSjb * smb_request_alloc 1059faa1795aSjb * 1060faa1795aSjb * Allocate an smb_request_t structure from the kmem_cache. Partially 1061faa1795aSjb * initialize the found/new request. 1062faa1795aSjb * 1063faa1795aSjb * Returns pointer to a request 1064faa1795aSjb */ 1065faa1795aSjb smb_request_t * 1066faa1795aSjb smb_request_alloc(smb_session_t *session, int req_length) 1067faa1795aSjb { 1068faa1795aSjb smb_request_t *sr; 1069faa1795aSjb 1070faa1795aSjb ASSERT(session->s_magic == SMB_SESSION_MAGIC); 1071faa1795aSjb 1072faa1795aSjb sr = kmem_cache_alloc(session->s_cache_request, KM_SLEEP); 1073faa1795aSjb 1074faa1795aSjb /* 1075faa1795aSjb * Future: Use constructor to pre-initialize some fields. For now 1076faa1795aSjb * there are so many fields that it is easiest just to zero the 1077faa1795aSjb * whole thing and start over. 1078faa1795aSjb */ 1079faa1795aSjb bzero(sr, sizeof (smb_request_t)); 1080faa1795aSjb 1081faa1795aSjb mutex_init(&sr->sr_mutex, NULL, MUTEX_DEFAULT, NULL); 1082ccc71be5SGordon Ross cv_init(&sr->sr_ncr.nc_cv, NULL, CV_DEFAULT, NULL); 1083bbf6f00cSJordan Brown smb_srm_init(sr); 1084faa1795aSjb sr->session = session; 1085faa1795aSjb sr->sr_server = session->s_server; 1086faa1795aSjb sr->sr_gmtoff = session->s_server->si_gmtoff; 1087faa1795aSjb sr->sr_cache = session->s_server->si_cache_request; 1088faa1795aSjb sr->sr_cfg = &session->s_cfg; 1089faa1795aSjb sr->command.max_bytes = req_length; 1090faa1795aSjb sr->reply.max_bytes = smb_maxbufsize; 1091faa1795aSjb sr->sr_req_length = req_length; 1092faa1795aSjb if (req_length) 1093faa1795aSjb sr->sr_request_buf = kmem_alloc(req_length, KM_SLEEP); 1094faa1795aSjb sr->sr_magic = SMB_REQ_MAGIC; 1095faa1795aSjb sr->sr_state = SMB_REQ_STATE_INITIALIZING; 1096faa1795aSjb smb_slist_insert_tail(&session->s_req_list, sr); 1097faa1795aSjb return (sr); 1098faa1795aSjb } 1099faa1795aSjb 1100faa1795aSjb /* 1101faa1795aSjb * smb_request_free 1102faa1795aSjb * 1103faa1795aSjb * release the memories which have been allocated for a smb request. 1104faa1795aSjb */ 1105faa1795aSjb void 1106faa1795aSjb smb_request_free(smb_request_t *sr) 1107faa1795aSjb { 1108faa1795aSjb ASSERT(sr->sr_magic == SMB_REQ_MAGIC); 1109faa1795aSjb ASSERT(sr->session); 1110faa1795aSjb ASSERT(sr->r_xa == NULL); 1111ccc71be5SGordon Ross ASSERT(sr->sr_ncr.nc_fname == NULL); 1112faa1795aSjb 1113cb174861Sjoyce mcintosh if (sr->fid_ofile != NULL) { 1114cb174861Sjoyce mcintosh smb_ofile_request_complete(sr->fid_ofile); 11152c2961f8Sjose borrego smb_ofile_release(sr->fid_ofile); 1116cb174861Sjoyce mcintosh } 11172c2961f8Sjose borrego 11182c2961f8Sjose borrego if (sr->tid_tree != NULL) 1119faa1795aSjb smb_tree_release(sr->tid_tree); 1120faa1795aSjb 11212c2961f8Sjose borrego if (sr->uid_user != NULL) 1122faa1795aSjb smb_user_release(sr->uid_user); 1123faa1795aSjb 1124faa1795aSjb smb_slist_remove(&sr->session->s_req_list, sr); 1125faa1795aSjb 1126faa1795aSjb sr->session = NULL; 1127faa1795aSjb 1128bbf6f00cSJordan Brown smb_srm_fini(sr); 1129faa1795aSjb 1130faa1795aSjb if (sr->sr_request_buf) 1131faa1795aSjb kmem_free(sr->sr_request_buf, sr->sr_req_length); 1132faa1795aSjb if (sr->command.chain) 1133faa1795aSjb m_freem(sr->command.chain); 1134faa1795aSjb if (sr->reply.chain) 1135faa1795aSjb m_freem(sr->reply.chain); 1136faa1795aSjb if (sr->raw_data.chain) 1137faa1795aSjb m_freem(sr->raw_data.chain); 1138faa1795aSjb 1139faa1795aSjb sr->sr_magic = 0; 1140ccc71be5SGordon Ross cv_destroy(&sr->sr_ncr.nc_cv); 1141faa1795aSjb mutex_destroy(&sr->sr_mutex); 1142faa1795aSjb kmem_cache_free(sr->sr_cache, sr); 1143da6c28aaSamw } 11447f667e74Sjose borrego 11457f667e74Sjose borrego void 11467f667e74Sjose borrego dump_smb_inaddr(smb_inaddr_t *ipaddr) 11477f667e74Sjose borrego { 11481fcced4cSJordan Brown char ipstr[INET6_ADDRSTRLEN]; 11497f667e74Sjose borrego 11507f667e74Sjose borrego if (smb_inet_ntop(ipaddr, ipstr, SMB_IPSTRLEN(ipaddr->a_family))) 11517f667e74Sjose borrego cmn_err(CE_WARN, "error ipstr=%s", ipstr); 11527f667e74Sjose borrego else 11537f667e74Sjose borrego cmn_err(CE_WARN, "error converting ip address"); 11547f667e74Sjose borrego } 11552c2961f8Sjose borrego 11562c2961f8Sjose borrego boolean_t 11572c2961f8Sjose borrego smb_session_oplocks_enable(smb_session_t *session) 11582c2961f8Sjose borrego { 11592c2961f8Sjose borrego SMB_SESSION_VALID(session); 11602c2961f8Sjose borrego if (session->s_cfg.skc_oplock_enable == 0) 11612c2961f8Sjose borrego return (B_FALSE); 11622c2961f8Sjose borrego else 11632c2961f8Sjose borrego return (B_TRUE); 11642c2961f8Sjose borrego } 11652c2961f8Sjose borrego 1166cb174861Sjoyce mcintosh boolean_t 1167cb174861Sjoyce mcintosh smb_session_levelII_oplocks(smb_session_t *session) 1168cb174861Sjoyce mcintosh { 1169cb174861Sjoyce mcintosh SMB_SESSION_VALID(session); 1170cb174861Sjoyce mcintosh return (session->capabilities & CAP_LEVEL_II_OPLOCKS); 1171cb174861Sjoyce mcintosh } 1172cb174861Sjoyce mcintosh 11732c2961f8Sjose borrego /* 1174cb174861Sjoyce mcintosh * smb_session_oplock_break 11752c2961f8Sjose borrego * 1176cb174861Sjoyce mcintosh * The session lock must NOT be held by the caller of this thread; 1177cb174861Sjoyce mcintosh * as this would cause a deadlock. 11782c2961f8Sjose borrego */ 11792c2961f8Sjose borrego void 1180cb174861Sjoyce mcintosh smb_session_oplock_break(smb_session_t *session, 1181cb174861Sjoyce mcintosh uint16_t tid, uint16_t fid, uint8_t brk) 11822c2961f8Sjose borrego { 11832c2961f8Sjose borrego mbuf_chain_t *mbc; 11842c2961f8Sjose borrego 11852c2961f8Sjose borrego SMB_SESSION_VALID(session); 11862c2961f8Sjose borrego 11872c2961f8Sjose borrego mbc = smb_mbc_alloc(MLEN); 11882c2961f8Sjose borrego 1189cb174861Sjoyce mcintosh (void) smb_mbc_encodef(mbc, "Mb19.wwwwbb3.wbb10.", 11902c2961f8Sjose borrego SMB_COM_LOCKING_ANDX, 1191cb174861Sjoyce mcintosh tid, 11922c2961f8Sjose borrego 0xFFFF, 0, 0xFFFF, 8, 0xFF, 1193cb174861Sjoyce mcintosh fid, 1194cb174861Sjoyce mcintosh LOCKING_ANDX_OPLOCK_RELEASE, 1195cb174861Sjoyce mcintosh (brk == SMB_OPLOCK_BREAK_TO_LEVEL_II) ? 1 : 0); 11962c2961f8Sjose borrego 11972c2961f8Sjose borrego smb_rwx_rwenter(&session->s_lock, RW_WRITER); 11982c2961f8Sjose borrego switch (session->s_state) { 11992c2961f8Sjose borrego case SMB_SESSION_STATE_NEGOTIATED: 12002c2961f8Sjose borrego case SMB_SESSION_STATE_OPLOCK_BREAKING: 1201cb174861Sjoyce mcintosh case SMB_SESSION_STATE_WRITE_RAW_ACTIVE: 12022c2961f8Sjose borrego session->s_state = SMB_SESSION_STATE_OPLOCK_BREAKING; 12032c2961f8Sjose borrego (void) smb_session_send(session, 0, mbc); 12042c2961f8Sjose borrego smb_mbc_free(mbc); 12052c2961f8Sjose borrego break; 12062c2961f8Sjose borrego 12072c2961f8Sjose borrego case SMB_SESSION_STATE_READ_RAW_ACTIVE: 12082c2961f8Sjose borrego list_insert_tail(&session->s_oplock_brkreqs, mbc); 12092c2961f8Sjose borrego break; 12102c2961f8Sjose borrego 12112c2961f8Sjose borrego case SMB_SESSION_STATE_DISCONNECTED: 12122c2961f8Sjose borrego case SMB_SESSION_STATE_TERMINATED: 12132c2961f8Sjose borrego smb_mbc_free(mbc); 12142c2961f8Sjose borrego break; 12152c2961f8Sjose borrego 12162c2961f8Sjose borrego default: 12172c2961f8Sjose borrego SMB_PANIC(); 12182c2961f8Sjose borrego } 12192c2961f8Sjose borrego smb_rwx_rwexit(&session->s_lock); 12202c2961f8Sjose borrego } 1221*f9bc6dadSDmitry.Savitsky@nexenta.com 1222*f9bc6dadSDmitry.Savitsky@nexenta.com static void 1223*f9bc6dadSDmitry.Savitsky@nexenta.com smb_session_genkey(smb_session_t *session) 1224*f9bc6dadSDmitry.Savitsky@nexenta.com { 1225*f9bc6dadSDmitry.Savitsky@nexenta.com uint8_t tmp_key[SMB_CHALLENGE_SZ]; 1226*f9bc6dadSDmitry.Savitsky@nexenta.com 1227*f9bc6dadSDmitry.Savitsky@nexenta.com (void) random_get_pseudo_bytes(tmp_key, SMB_CHALLENGE_SZ); 1228*f9bc6dadSDmitry.Savitsky@nexenta.com bcopy(tmp_key, &session->challenge_key, SMB_CHALLENGE_SZ); 1229*f9bc6dadSDmitry.Savitsky@nexenta.com session->challenge_len = SMB_CHALLENGE_SZ; 1230*f9bc6dadSDmitry.Savitsky@nexenta.com 1231*f9bc6dadSDmitry.Savitsky@nexenta.com (void) random_get_pseudo_bytes(tmp_key, 4); 1232*f9bc6dadSDmitry.Savitsky@nexenta.com session->sesskey = tmp_key[0] | tmp_key[1] << 8 | 1233*f9bc6dadSDmitry.Savitsky@nexenta.com tmp_key[2] << 16 | tmp_key[3] << 24; 1234*f9bc6dadSDmitry.Savitsky@nexenta.com } 1235