xref: /illumos-gate/usr/src/uts/common/fs/smbsrv/smb_session.c (revision dd72704bd9e794056c558153663c739e2012d721)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 /*
22  * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
23  * Copyright 2020 Tintri by DDN, Inc.  All rights reserved.
24  * Copyright 2022 RackTop Systems, Inc.
25  */
26 
27 #include <sys/atomic.h>
28 #include <sys/synch.h>
29 #include <sys/types.h>
30 #include <sys/sdt.h>
31 #include <sys/random.h>
32 #include <smbsrv/netbios.h>
33 #include <smbsrv/smb2_kproto.h>
34 #include <smbsrv/string.h>
35 #include <netinet/tcp.h>
36 
37 /* How many iovec we'll handle as a local array (no allocation) */
38 #define	SMB_LOCAL_IOV_MAX	16
39 
40 #define	SMB_NEW_KID()	atomic_inc_64_nv(&smb_kids)
41 
42 static volatile uint64_t smb_kids;
43 
44 /*
45  * We track the keepalive in minutes, but this constant
46  * specifies it in seconds, so convert to minutes.
47  */
48 uint32_t smb_keep_alive = SMB_PI_KEEP_ALIVE_MIN / 60;
49 
50 /*
51  * This is the maximum time we'll allow a "session" to exist with no
52  * authenticated smb_user_t objects on it.  This allows a client to
53  * logoff their "one and only" user session and then logon as some
54  * different user.  (There are some tests that do that.)  The same
55  * timeout mechanism also reduces the impact of clients that might
56  * open TCP connections but never authenticate.
57  */
58 int smb_session_auth_tmo = 30; /* sec. */
59 
60 /*
61  * There are many smbtorture test cases that send
62  * racing requests, and where the tests fail if we
63  * don't execute them in exactly the order sent.
64  * These are test bugs.  The protocol makes no
65  * guarantees about execution order of requests
66  * that are concurrently active.
67  *
68  * Nonetheless, smbtorture has many useful tests,
69  * so we have this work-around we can enable to
70  * basically force sequential execution.  When
71  * enabled, insert a delay after each request is
72  * issued a taskq job.  Enable this with mdb by
73  * setting smb_reader_delay to 10.  Don't make it
74  * more than 500 or so or the server will appear
75  * to be so slow that tests may time out.
76  */
77 int smb_reader_delay = 0;  /* mSec. */
78 
79 static int  smbsr_newrq_initial(smb_request_t *);
80 
81 static void smb_session_cancel(smb_session_t *);
82 static int smb_session_reader(smb_session_t *);
83 static int smb_session_xprt_puthdr(smb_session_t *,
84     uint8_t msg_type, uint32_t msg_len,
85     uint8_t *dst, size_t dstlen);
86 static void smb_session_disconnect_trees(smb_session_t	*);
87 static void smb_request_init_command_mbuf(smb_request_t *sr);
88 static void smb_session_genkey(smb_session_t *);
89 
90 /*
91  * This (legacy) code is in support of an "idle timeout" feature,
92  * which is apparently incomplete.  To complete it, we should:
93  * when the keep_alive timer expires, check whether the client
94  * has any open files, and if not then kill their session.
95  * Right now the timers are there, but nothing happens when
96  * a timer expires.
97  *
98  * Todo: complete logic to kill idle sessions.
99  *
100  * Only called when sv_cfg.skc_keepalive != 0
101  */
102 void
103 smb_session_timers(smb_server_t *sv)
104 {
105 	smb_session_t	*session;
106 	smb_llist_t	*ll;
107 
108 	ll = &sv->sv_session_list;
109 	smb_llist_enter(ll, RW_READER);
110 	session = smb_llist_head(ll);
111 	while (session != NULL) {
112 		/*
113 		 * Walk through the table and decrement each keep_alive
114 		 * timer that has not timed out yet. (keepalive > 0)
115 		 */
116 		SMB_SESSION_VALID(session);
117 		if (session->keep_alive &&
118 		    (session->keep_alive != (uint32_t)-1))
119 			session->keep_alive--;
120 
121 		session = smb_llist_next(ll, session);
122 	}
123 	smb_llist_exit(ll);
124 }
125 
126 /*
127  * Send a session message - supports SMB-over-NBT and SMB-over-TCP.
128  * If an mbuf chain is provided (optional), it will be freed and
129  * set to NULL -- unconditionally!  (error or not)
130  *
131  * Builds a I/O vector (uio/iov) to do the send from mbufs, plus one
132  * segment for the 4-byte NBT header.
133  */
134 int
135 smb_session_send(smb_session_t *session, uint8_t nbt_type, mbuf_chain_t *mbc)
136 {
137 	uio_t		uio;
138 	iovec_t		local_iov[SMB_LOCAL_IOV_MAX];
139 	iovec_t		*alloc_iov = NULL;
140 	int		alloc_sz = 0;
141 	mbuf_t		*m;
142 	uint8_t		nbt_hdr[NETBIOS_HDR_SZ];
143 	uint32_t	nbt_len;
144 	int		i, nseg;
145 	int		rc;
146 
147 	switch (session->s_state) {
148 	case SMB_SESSION_STATE_DISCONNECTED:
149 	case SMB_SESSION_STATE_TERMINATED:
150 		rc = ENOTCONN;
151 		goto out;
152 	default:
153 		break;
154 	}
155 
156 	/*
157 	 * Setup the IOV.  First, count the number of IOV segments
158 	 * (plus one for the NBT header) and decide whether we
159 	 * need to allocate an iovec or can use local_iov;
160 	 */
161 	bzero(&uio, sizeof (uio));
162 	nseg = 1;
163 	m = (mbc != NULL) ? mbc->chain : NULL;
164 	while (m != NULL) {
165 		nseg++;
166 		m = m->m_next;
167 	}
168 	if (nseg <= SMB_LOCAL_IOV_MAX) {
169 		uio.uio_iov = local_iov;
170 	} else {
171 		alloc_sz = nseg * sizeof (iovec_t);
172 		alloc_iov = kmem_alloc(alloc_sz, KM_SLEEP);
173 		uio.uio_iov = alloc_iov;
174 	}
175 	uio.uio_iovcnt = nseg;
176 	uio.uio_segflg = UIO_SYSSPACE;
177 	uio.uio_extflg = UIO_COPY_DEFAULT;
178 
179 	/*
180 	 * Build the iov list, meanwhile computing the length of
181 	 * the SMB payload (to put in the NBT header).
182 	 */
183 	uio.uio_iov[0].iov_base = (void *)nbt_hdr;
184 	uio.uio_iov[0].iov_len = sizeof (nbt_hdr);
185 	i = 1;
186 	nbt_len = 0;
187 	m = (mbc != NULL) ? mbc->chain : NULL;
188 	while (m != NULL) {
189 		uio.uio_iov[i].iov_base = m->m_data;
190 		uio.uio_iov[i++].iov_len = m->m_len;
191 		nbt_len += m->m_len;
192 		m = m->m_next;
193 	}
194 	ASSERT3S(i, ==, nseg);
195 
196 	/*
197 	 * Set the NBT header, set uio_resid
198 	 */
199 	uio.uio_resid = nbt_len + NETBIOS_HDR_SZ;
200 	rc = smb_session_xprt_puthdr(session, nbt_type, nbt_len,
201 	    nbt_hdr, NETBIOS_HDR_SZ);
202 	if (rc != 0)
203 		goto out;
204 
205 	smb_server_add_txb(session->s_server, (int64_t)uio.uio_resid);
206 	rc = smb_net_send_uio(session, &uio);
207 
208 out:
209 	if (alloc_iov != NULL)
210 		kmem_free(alloc_iov, alloc_sz);
211 	if ((mbc != NULL) && (mbc->chain != NULL)) {
212 		m_freem(mbc->chain);
213 		mbc->chain = NULL;
214 		mbc->flags = 0;
215 	}
216 	return (rc);
217 }
218 
219 /*
220  * Read, process and respond to a NetBIOS session request.
221  *
222  * A NetBIOS session must be established for SMB-over-NetBIOS.  Validate
223  * the calling and called name format and save the client NetBIOS name,
224  * which is used when a NetBIOS session is established to check for and
225  * cleanup leftover state from a previous session.
226  *
227  * Session requests are not valid for SMB-over-TCP, which is unfortunate
228  * because without the client name leftover state cannot be cleaned up
229  * if the client is behind a NAT server.
230  */
231 static int
232 smb_netbios_session_request(struct smb_session *session)
233 {
234 	int			rc;
235 	char			*calling_name;
236 	char			*called_name;
237 	char			client_name[NETBIOS_NAME_SZ];
238 	struct mbuf_chain	mbc;
239 	char			*names = NULL;
240 	smb_wchar_t		*wbuf = NULL;
241 	smb_xprt_t		hdr;
242 	char *p;
243 	int rc1, rc2;
244 
245 	session->keep_alive = smb_keep_alive;
246 
247 	if ((rc = smb_session_xprt_gethdr(session, &hdr)) != 0)
248 		return (rc);
249 
250 	DTRACE_PROBE2(receive__session__req__xprthdr, struct session *, session,
251 	    smb_xprt_t *, &hdr);
252 
253 	if ((hdr.xh_type != SESSION_REQUEST) ||
254 	    (hdr.xh_length != NETBIOS_SESSION_REQUEST_DATA_LENGTH)) {
255 		DTRACE_PROBE1(receive__session__req__failed,
256 		    struct session *, session);
257 		return (EINVAL);
258 	}
259 
260 	names = kmem_alloc(hdr.xh_length, KM_SLEEP);
261 
262 	if ((rc = smb_sorecv(session->sock, names, hdr.xh_length)) != 0) {
263 		kmem_free(names, hdr.xh_length);
264 		DTRACE_PROBE1(receive__session__req__failed,
265 		    struct session *, session);
266 		return (rc);
267 	}
268 
269 	DTRACE_PROBE3(receive__session__req__data, struct session *, session,
270 	    char *, names, uint32_t, hdr.xh_length);
271 
272 	called_name = &names[0];
273 	calling_name = &names[NETBIOS_ENCODED_NAME_SZ + 2];
274 
275 	rc1 = netbios_name_isvalid(called_name, 0);
276 	rc2 = netbios_name_isvalid(calling_name, client_name);
277 
278 	if (rc1 == 0 || rc2 == 0) {
279 
280 		DTRACE_PROBE3(receive__invalid__session__req,
281 		    struct session *, session, char *, names,
282 		    uint32_t, hdr.xh_length);
283 
284 		kmem_free(names, hdr.xh_length);
285 		MBC_INIT(&mbc, MAX_DATAGRAM_LENGTH);
286 		(void) smb_mbc_encodef(&mbc, "b",
287 		    DATAGRAM_INVALID_SOURCE_NAME_FORMAT);
288 		(void) smb_session_send(session, NEGATIVE_SESSION_RESPONSE,
289 		    &mbc);
290 		return (EINVAL);
291 	}
292 
293 	DTRACE_PROBE3(receive__session__req__calling__decoded,
294 	    struct session *, session,
295 	    char *, calling_name, char *, client_name);
296 
297 	/*
298 	 * The client NetBIOS name is in oem codepage format.
299 	 * We need to convert it to unicode and store it in
300 	 * multi-byte format.  We also need to strip off any
301 	 * spaces added as part of the NetBIOS name encoding.
302 	 */
303 	wbuf = kmem_alloc((SMB_PI_MAX_HOST * sizeof (smb_wchar_t)), KM_SLEEP);
304 	(void) oemtoucs(wbuf, client_name, SMB_PI_MAX_HOST, OEM_CPG_850);
305 	(void) smb_wcstombs(session->workstation, wbuf, SMB_PI_MAX_HOST);
306 	kmem_free(wbuf, (SMB_PI_MAX_HOST * sizeof (smb_wchar_t)));
307 
308 	if ((p = strchr(session->workstation, ' ')) != 0)
309 		*p = '\0';
310 
311 	kmem_free(names, hdr.xh_length);
312 	return (smb_session_send(session, POSITIVE_SESSION_RESPONSE, NULL));
313 }
314 
315 /*
316  * Read 4-byte header from the session socket and build an in-memory
317  * session transport header.  See smb_xprt_t definition for header
318  * format information.
319  *
320  * Direct hosted NetBIOS-less SMB (SMB-over-TCP) uses port 445.  The
321  * first byte of the four-byte header must be 0 and the next three
322  * bytes contain the length of the remaining data.
323  */
324 int
325 smb_session_xprt_gethdr(smb_session_t *session, smb_xprt_t *ret_hdr)
326 {
327 	int		rc;
328 	unsigned char	buf[NETBIOS_HDR_SZ];
329 
330 	if ((rc = smb_sorecv(session->sock, buf, NETBIOS_HDR_SZ)) != 0)
331 		return (rc);
332 
333 	switch (session->s_local_port) {
334 	case IPPORT_NETBIOS_SSN:
335 		ret_hdr->xh_type = buf[0];
336 		ret_hdr->xh_length = (((uint32_t)buf[1] & 1) << 16) |
337 		    ((uint32_t)buf[2] << 8) |
338 		    ((uint32_t)buf[3]);
339 		break;
340 
341 	case IPPORT_SMB:
342 		ret_hdr->xh_type = buf[0];
343 
344 		if (ret_hdr->xh_type != 0) {
345 			cmn_err(CE_WARN, "invalid NBT type (%u) from %s",
346 			    ret_hdr->xh_type, session->ip_addr_str);
347 			return (EPROTO);
348 		}
349 
350 		ret_hdr->xh_length = ((uint32_t)buf[1] << 16) |
351 		    ((uint32_t)buf[2] << 8) |
352 		    ((uint32_t)buf[3]);
353 		break;
354 
355 	default:
356 		cmn_err(CE_WARN, "invalid port %u", session->s_local_port);
357 		return (EPROTO);
358 	}
359 
360 	return (0);
361 }
362 
363 /*
364  * Encode a transport session packet header into a 4-byte buffer.
365  */
366 static int
367 smb_session_xprt_puthdr(smb_session_t *session,
368     uint8_t msg_type, uint32_t msg_length,
369     uint8_t *buf, size_t buflen)
370 {
371 	if (buf == NULL || buflen < NETBIOS_HDR_SZ) {
372 		return (-1);
373 	}
374 
375 	switch (session->s_local_port) {
376 	case IPPORT_NETBIOS_SSN:
377 		/* Per RFC 1001, 1002: msg. len < 128KB */
378 		if (msg_length >= (1 << 17))
379 			return (-1);
380 		buf[0] = msg_type;
381 		buf[1] = ((msg_length >> 16) & 1);
382 		buf[2] = (msg_length >> 8) & 0xff;
383 		buf[3] = msg_length & 0xff;
384 		break;
385 
386 	case IPPORT_SMB:
387 		/*
388 		 * SMB over TCP is like NetBIOS but the one byte
389 		 * message type is always zero, and the length
390 		 * part is three bytes.  It could actually use
391 		 * longer messages, but this is conservative.
392 		 */
393 		if (msg_length >= (1 << 24))
394 			return (-1);
395 		buf[0] = msg_type;
396 		buf[1] = (msg_length >> 16) & 0xff;
397 		buf[2] = (msg_length >> 8) & 0xff;
398 		buf[3] = msg_length & 0xff;
399 		break;
400 
401 	default:
402 		cmn_err(CE_WARN, "invalid port %u", session->s_local_port);
403 		return (-1);
404 	}
405 
406 	return (0);
407 }
408 
409 static void
410 smb_request_init_command_mbuf(smb_request_t *sr)
411 {
412 
413 	/*
414 	 * Setup mbuf using the buffer we allocated.
415 	 */
416 	MBC_ATTACH_BUF(&sr->command, sr->sr_request_buf, sr->sr_req_length);
417 
418 	sr->command.flags = 0;
419 	sr->command.shadow_of = NULL;
420 }
421 
422 /*
423  * smb_request_cancel
424  *
425  * Handle a cancel for a request properly depending on the current request
426  * state.
427  */
428 void
429 smb_request_cancel(smb_request_t *sr)
430 {
431 	void (*cancel_method)(smb_request_t *) = NULL;
432 
433 	mutex_enter(&sr->sr_mutex);
434 	switch (sr->sr_state) {
435 
436 	case SMB_REQ_STATE_INITIALIZING:
437 	case SMB_REQ_STATE_SUBMITTED:
438 	case SMB_REQ_STATE_ACTIVE:
439 	case SMB_REQ_STATE_CLEANED_UP:
440 		sr->sr_state = SMB_REQ_STATE_CANCELLED;
441 		break;
442 
443 	case SMB_REQ_STATE_WAITING_AUTH:
444 	case SMB_REQ_STATE_WAITING_FCN1:
445 	case SMB_REQ_STATE_WAITING_LOCK:
446 	case SMB_REQ_STATE_WAITING_PIPE:
447 	case SMB_REQ_STATE_WAITING_OLBRK:
448 		/*
449 		 * These are states that have a cancel_method.
450 		 * Make the state change now, to ensure that
451 		 * we call cancel_method exactly once.  Do the
452 		 * method call below, after we drop sr_mutex.
453 		 * When the cancelled request thread resumes,
454 		 * it should re-take sr_mutex and set sr_state
455 		 * to CANCELLED, then return STATUS_CANCELLED.
456 		 */
457 		sr->sr_state = SMB_REQ_STATE_CANCEL_PENDING;
458 		cancel_method = sr->cancel_method;
459 		VERIFY(cancel_method != NULL);
460 		break;
461 
462 	case SMB_REQ_STATE_WAITING_FCN2:
463 	case SMB_REQ_STATE_COMPLETED:
464 	case SMB_REQ_STATE_CANCEL_PENDING:
465 	case SMB_REQ_STATE_CANCELLED:
466 		/*
467 		 * No action required for these states since the request
468 		 * is completing.
469 		 */
470 		break;
471 
472 	case SMB_REQ_STATE_FREE:
473 	default:
474 		SMB_PANIC();
475 	}
476 	mutex_exit(&sr->sr_mutex);
477 
478 	if (cancel_method != NULL) {
479 		cancel_method(sr);
480 	}
481 }
482 
483 /*
484  * smb_session_receiver
485  *
486  * Receives request from the network and dispatches them to a worker.
487  *
488  * When we receive a disconnect here, it _could_ be due to the server
489  * having initiated disconnect, in which case the session state will be
490  * SMB_SESSION_STATE_TERMINATED and we want to keep that state so later
491  * tear-down logic will know which side initiated.
492  */
493 void
494 smb_session_receiver(smb_session_t *session)
495 {
496 	int	rc = 0;
497 	timeout_id_t tmo = NULL;
498 
499 	SMB_SESSION_VALID(session);
500 
501 	session->s_thread = curthread;
502 
503 	if (session->s_local_port == IPPORT_NETBIOS_SSN) {
504 		rc = smb_netbios_session_request(session);
505 		if (rc != 0) {
506 			smb_rwx_rwenter(&session->s_lock, RW_WRITER);
507 			if (session->s_state != SMB_SESSION_STATE_TERMINATED)
508 				session->s_state =
509 				    SMB_SESSION_STATE_DISCONNECTED;
510 			smb_rwx_rwexit(&session->s_lock);
511 			return;
512 		}
513 	}
514 
515 	smb_rwx_rwenter(&session->s_lock, RW_WRITER);
516 	session->s_state = SMB_SESSION_STATE_ESTABLISHED;
517 	session->s_auth_tmo = timeout((tmo_func_t)smb_session_disconnect,
518 	    session, SEC_TO_TICK(smb_session_auth_tmo));
519 	smb_rwx_rwexit(&session->s_lock);
520 
521 	(void) smb_session_reader(session);
522 
523 	smb_rwx_rwenter(&session->s_lock, RW_WRITER);
524 	if (session->s_state != SMB_SESSION_STATE_TERMINATED)
525 		session->s_state = SMB_SESSION_STATE_DISCONNECTED;
526 	tmo = session->s_auth_tmo;
527 	session->s_auth_tmo = NULL;
528 	smb_rwx_rwexit(&session->s_lock);
529 
530 	/* Timeout callback takes s_lock. See untimeout(9f) */
531 	if (tmo != NULL)
532 		(void) untimeout(tmo);
533 
534 	smb_soshutdown(session->sock);
535 
536 	DTRACE_PROBE2(session__drop, struct session *, session, int, rc);
537 
538 	smb_session_cancel(session);
539 	/*
540 	 * At this point everything related to the session should have been
541 	 * cleaned up and we expect that nothing will attempt to use the
542 	 * socket.
543 	 */
544 }
545 
546 /*
547  * smb_session_disconnect
548  *
549  * Server-initiated disconnect (i.e. server shutdown)
550  */
551 void
552 smb_session_disconnect(smb_session_t *session)
553 {
554 	SMB_SESSION_VALID(session);
555 
556 	smb_rwx_rwenter(&session->s_lock, RW_WRITER);
557 	switch (session->s_state) {
558 	case SMB_SESSION_STATE_INITIALIZED:
559 	case SMB_SESSION_STATE_CONNECTED:
560 	case SMB_SESSION_STATE_ESTABLISHED:
561 	case SMB_SESSION_STATE_NEGOTIATED:
562 		smb_soshutdown(session->sock);
563 		session->s_state = SMB_SESSION_STATE_TERMINATED;
564 		break;
565 	case SMB_SESSION_STATE_DISCONNECTED:
566 	case SMB_SESSION_STATE_TERMINATED:
567 		break;
568 	}
569 	smb_rwx_rwexit(&session->s_lock);
570 }
571 
572 /*
573  * Read and process SMB requests.
574  *
575  * Returns:
576  *	0	Success
577  *	1	Unable to read transport header
578  *	2	Invalid transport header type
579  *	3	Invalid SMB length (too small)
580  *	4	Unable to read SMB header
581  *	5	Invalid SMB header (bad magic number)
582  *	6	Unable to read SMB data
583  */
584 static int
585 smb_session_reader(smb_session_t *session)
586 {
587 	smb_server_t	*sv;
588 	smb_request_t	*sr = NULL;
589 	smb_xprt_t	hdr;
590 	uint8_t		*req_buf;
591 	uint32_t	resid;
592 	int		rc;
593 
594 	sv = session->s_server;
595 
596 	for (;;) {
597 
598 		rc = smb_session_xprt_gethdr(session, &hdr);
599 		if (rc)
600 			return (rc);
601 
602 		DTRACE_PROBE2(session__receive__xprthdr, session_t *, session,
603 		    smb_xprt_t *, &hdr);
604 
605 		if (hdr.xh_type != SESSION_MESSAGE) {
606 			/*
607 			 * Anything other than SESSION_MESSAGE or
608 			 * SESSION_KEEP_ALIVE is an error.  A SESSION_REQUEST
609 			 * may indicate a new session request but we need to
610 			 * close this session and we can treat it as an error
611 			 * here.
612 			 */
613 			if (hdr.xh_type == SESSION_KEEP_ALIVE) {
614 				session->keep_alive = smb_keep_alive;
615 				continue;
616 			}
617 			return (EPROTO);
618 		}
619 
620 		if (hdr.xh_length == 0) {
621 			/* zero length is another form of keep alive */
622 			session->keep_alive = smb_keep_alive;
623 			continue;
624 		}
625 
626 		if (hdr.xh_length < SMB_HEADER_LEN)
627 			return (EPROTO);
628 		if (hdr.xh_length > session->cmd_max_bytes)
629 			return (EPROTO);
630 
631 		session->keep_alive = smb_keep_alive;
632 
633 		/*
634 		 * Allocate a request context, read the whole message.
635 		 * If the request alloc fails, we've disconnected
636 		 * and won't be able to send the reply anyway, so bail now.
637 		 */
638 		if ((sr = smb_request_alloc(session, hdr.xh_length)) == NULL)
639 			break;
640 
641 		req_buf = (uint8_t *)sr->sr_request_buf;
642 		resid = hdr.xh_length;
643 
644 		rc = smb_sorecv(session->sock, req_buf, resid);
645 		if (rc) {
646 			smb_request_free(sr);
647 			break;
648 		}
649 
650 		/* accounting: received bytes */
651 		smb_server_add_rxb(sv,
652 		    (int64_t)(hdr.xh_length + NETBIOS_HDR_SZ));
653 
654 		/*
655 		 * Initialize command MBC to represent the received data.
656 		 */
657 		smb_request_init_command_mbuf(sr);
658 
659 		DTRACE_PROBE1(session__receive__smb, smb_request_t *, sr);
660 
661 		rc = session->newrq_func(sr);
662 		sr = NULL;	/* enqueued or freed */
663 		if (rc != 0)
664 			break;
665 
666 		/* See notes where this is defined (above). */
667 		if (smb_reader_delay) {
668 			delay(MSEC_TO_TICK(smb_reader_delay));
669 		}
670 	}
671 	return (rc);
672 }
673 
674 /*
675  * This is the initial handler for new smb requests, called from
676  * from smb_session_reader when we have not yet seen any requests.
677  * The first SMB request must be "negotiate", which determines
678  * which protocol and dialect we'll be using.  That's the ONLY
679  * request type handled here, because with all later requests,
680  * we know the protocol and handle those with either the SMB1 or
681  * SMB2 handlers:  smb1sr_post() or smb2sr_post().
682  * Those do NOT allow SMB negotiate, because that's only allowed
683  * as the first request on new session.
684  *
685  * This and other "post a request" handlers must either enqueue
686  * the new request for the session taskq, or smb_request_free it
687  * (in case we've decided to drop this connection).  In this
688  * (special) new request handler, we always free the request.
689  *
690  * Return value is 0 for success, and anything else will
691  * terminate the reader thread (drop the connection).
692  */
693 static int
694 smbsr_newrq_initial(smb_request_t *sr)
695 {
696 	uint32_t magic;
697 	int rc = EPROTO;
698 
699 	mutex_enter(&sr->sr_mutex);
700 	sr->sr_state = SMB_REQ_STATE_ACTIVE;
701 	mutex_exit(&sr->sr_mutex);
702 
703 	magic = SMB_READ_PROTOCOL(sr->sr_request_buf);
704 	if (magic == SMB_PROTOCOL_MAGIC)
705 		rc = smb1_newrq_negotiate(sr);
706 	if (magic == SMB2_PROTOCOL_MAGIC)
707 		rc = smb2_newrq_negotiate(sr);
708 
709 	mutex_enter(&sr->sr_mutex);
710 	sr->sr_state = SMB_REQ_STATE_COMPLETED;
711 	mutex_exit(&sr->sr_mutex);
712 
713 	smb_request_free(sr);
714 	return (rc);
715 }
716 
717 /*
718  * Port will be IPPORT_NETBIOS_SSN or IPPORT_SMB.
719  */
720 smb_session_t *
721 smb_session_create(ksocket_t new_so, uint16_t port, smb_server_t *sv,
722     int family)
723 {
724 	struct sockaddr_in	sin;
725 	socklen_t		slen;
726 	struct sockaddr_in6	sin6;
727 	smb_session_t		*session;
728 	int64_t			now;
729 	uint16_t		rport;
730 
731 	session = kmem_cache_alloc(smb_cache_session, KM_SLEEP);
732 	bzero(session, sizeof (smb_session_t));
733 
734 	if (smb_idpool_constructor(&session->s_uid_pool)) {
735 		kmem_cache_free(smb_cache_session, session);
736 		return (NULL);
737 	}
738 	if (smb_idpool_constructor(&session->s_tid_pool)) {
739 		smb_idpool_destructor(&session->s_uid_pool);
740 		kmem_cache_free(smb_cache_session, session);
741 		return (NULL);
742 	}
743 
744 	now = ddi_get_lbolt64();
745 
746 	session->s_server = sv;
747 	session->s_kid = SMB_NEW_KID();
748 	session->s_state = SMB_SESSION_STATE_INITIALIZED;
749 	session->native_os = NATIVE_OS_UNKNOWN;
750 	session->opentime = now;
751 	session->keep_alive = smb_keep_alive;
752 	session->activity_timestamp = now;
753 	smb_session_genkey(session);
754 
755 	mutex_init(&session->s_credits_mutex, NULL, MUTEX_DEFAULT, NULL);
756 
757 	smb_slist_constructor(&session->s_req_list, sizeof (smb_request_t),
758 	    offsetof(smb_request_t, sr_session_lnd));
759 
760 	smb_llist_constructor(&session->s_user_list, sizeof (smb_user_t),
761 	    offsetof(smb_user_t, u_lnd));
762 
763 	smb_llist_constructor(&session->s_tree_list, sizeof (smb_tree_t),
764 	    offsetof(smb_tree_t, t_lnd));
765 
766 	smb_llist_constructor(&session->s_xa_list, sizeof (smb_xa_t),
767 	    offsetof(smb_xa_t, xa_lnd));
768 
769 	smb_net_txl_constructor(&session->s_txlst);
770 
771 	smb_rwx_init(&session->s_lock);
772 
773 	session->s_srqueue = &sv->sv_srqueue;
774 	smb_server_get_cfg(sv, &session->s_cfg);
775 
776 	if (new_so == NULL) {
777 		/*
778 		 * This call is creating the special "server" session,
779 		 * used for kshare export, oplock breaks, CA import.
780 		 * CA import creates temporary trees on this session
781 		 * and those should never get map/unmap up-calls, so
782 		 * force the map/unmap flags zero on this session.
783 		 * Set a "modern" dialect for CA import too, so
784 		 * pathname parse doesn't do OS/2 stuff, etc.
785 		 */
786 		session->s_cfg.skc_execflags = 0;
787 		session->dialect = session->s_cfg.skc_max_protocol;
788 	} else {
789 		if (family == AF_INET) {
790 			slen = sizeof (sin);
791 			(void) ksocket_getsockname(new_so,
792 			    (struct sockaddr *)&sin, &slen, CRED());
793 			bcopy(&sin.sin_addr,
794 			    &session->local_ipaddr.au_addr.au_ipv4,
795 			    sizeof (in_addr_t));
796 			slen = sizeof (sin);
797 			(void) ksocket_getpeername(new_so,
798 			    (struct sockaddr *)&sin, &slen, CRED());
799 			bcopy(&sin.sin_addr,
800 			    &session->ipaddr.au_addr.au_ipv4,
801 			    sizeof (in_addr_t));
802 			rport = sin.sin_port;
803 		} else {
804 			slen = sizeof (sin6);
805 			(void) ksocket_getsockname(new_so,
806 			    (struct sockaddr *)&sin6, &slen, CRED());
807 			bcopy(&sin6.sin6_addr,
808 			    &session->local_ipaddr.au_addr.au_ipv6,
809 			    sizeof (in6_addr_t));
810 			slen = sizeof (sin6);
811 			(void) ksocket_getpeername(new_so,
812 			    (struct sockaddr *)&sin6, &slen, CRED());
813 			bcopy(&sin6.sin6_addr,
814 			    &session->ipaddr.au_addr.au_ipv6,
815 			    sizeof (in6_addr_t));
816 			rport = sin6.sin6_port;
817 		}
818 		session->ipaddr.a_family = family;
819 		session->local_ipaddr.a_family = family;
820 		session->s_local_port = port;
821 		session->s_remote_port = ntohs(rport);
822 		session->sock = new_so;
823 		(void) smb_inet_ntop(&session->ipaddr,
824 		    session->ip_addr_str, INET6_ADDRSTRLEN);
825 		if (port == IPPORT_NETBIOS_SSN)
826 			smb_server_inc_nbt_sess(sv);
827 		else
828 			smb_server_inc_tcp_sess(sv);
829 	}
830 
831 	/*
832 	 * The initial new request handler is special,
833 	 * and only accepts negotiation requests.
834 	 */
835 	session->newrq_func = smbsr_newrq_initial;
836 
837 	/* These may increase in SMB2 negotiate. */
838 	session->cmd_max_bytes = SMB_REQ_MAX_SIZE;
839 	session->reply_max_bytes = SMB_REQ_MAX_SIZE;
840 
841 	session->s_magic = SMB_SESSION_MAGIC;
842 	return (session);
843 }
844 
845 void
846 smb_session_delete(smb_session_t *session)
847 {
848 
849 	ASSERT(session->s_magic == SMB_SESSION_MAGIC);
850 
851 	if (session->enc_mech != NULL)
852 		smb3_encrypt_fini(session);
853 
854 	if (session->sign_fini != NULL)
855 		session->sign_fini(session);
856 
857 	if (session->signing.mackey != NULL) {
858 		kmem_free(session->signing.mackey,
859 		    session->signing.mackey_len);
860 	}
861 
862 	if (session->preauth_mech != NULL)
863 		smb31_preauth_fini(session);
864 
865 	session->s_magic = 0;
866 
867 	smb_rwx_destroy(&session->s_lock);
868 	smb_net_txl_destructor(&session->s_txlst);
869 
870 	mutex_destroy(&session->s_credits_mutex);
871 
872 	smb_slist_destructor(&session->s_req_list);
873 	smb_llist_destructor(&session->s_tree_list);
874 	smb_llist_destructor(&session->s_user_list);
875 	smb_llist_destructor(&session->s_xa_list);
876 
877 	ASSERT(session->s_tree_cnt == 0);
878 	ASSERT(session->s_file_cnt == 0);
879 	ASSERT(session->s_dir_cnt == 0);
880 
881 	smb_idpool_destructor(&session->s_tid_pool);
882 	smb_idpool_destructor(&session->s_uid_pool);
883 	if (session->sock != NULL) {
884 		if (session->s_local_port == IPPORT_NETBIOS_SSN)
885 			smb_server_dec_nbt_sess(session->s_server);
886 		else
887 			smb_server_dec_tcp_sess(session->s_server);
888 		smb_sodestroy(session->sock);
889 	}
890 	kmem_cache_free(smb_cache_session, session);
891 }
892 
893 static void
894 smb_session_cancel(smb_session_t *session)
895 {
896 	smb_xa_t	*xa, *nextxa;
897 
898 	/* All the request currently being treated must be canceled. */
899 	smb_session_cancel_requests(session, NULL, NULL);
900 
901 	/*
902 	 * We wait for the completion of all the requests associated with
903 	 * this session.
904 	 */
905 	smb_slist_wait_for_empty(&session->s_req_list);
906 
907 	/*
908 	 * Cleanup transact state objects
909 	 */
910 	xa = smb_llist_head(&session->s_xa_list);
911 	while (xa) {
912 		nextxa = smb_llist_next(&session->s_xa_list, xa);
913 		smb_xa_close(xa);
914 		xa = nextxa;
915 	}
916 
917 	/*
918 	 * At this point the reference count of the files and directories
919 	 * should be zero. It should be possible to destroy them without
920 	 * any problem, which should trigger the destruction of other objects.
921 	 */
922 	smb_session_logoff(session);
923 }
924 
925 /*
926  * Cancel requests.  If a non-null tree is specified, only requests specific
927  * to that tree will be cancelled.  If a non-null sr is specified, that sr
928  * will be not be cancelled - this would typically be the caller's sr.
929  */
930 void
931 smb_session_cancel_requests(
932     smb_session_t	*session,
933     smb_tree_t		*tree,
934     smb_request_t	*exclude_sr)
935 {
936 	smb_request_t	*sr;
937 
938 	smb_slist_enter(&session->s_req_list);
939 	sr = smb_slist_head(&session->s_req_list);
940 
941 	while (sr) {
942 		ASSERT(sr->sr_magic == SMB_REQ_MAGIC);
943 		if ((sr != exclude_sr) &&
944 		    (tree == NULL || sr->tid_tree == tree))
945 			smb_request_cancel(sr);
946 
947 		sr = smb_slist_next(&session->s_req_list, sr);
948 	}
949 
950 	smb_slist_exit(&session->s_req_list);
951 }
952 
953 /*
954  * Find a user on the specified session by SMB UID.
955  */
956 smb_user_t *
957 smb_session_lookup_uid(smb_session_t *session, uint16_t uid)
958 {
959 	return (smb_session_lookup_uid_st(session, 0, uid,
960 	    SMB_USER_STATE_LOGGED_ON));
961 }
962 
963 /*
964  * Find a user on the specified session by SMB2 SSNID.
965  */
966 smb_user_t *
967 smb_session_lookup_ssnid(smb_session_t *session, uint64_t ssnid)
968 {
969 	return (smb_session_lookup_uid_st(session, ssnid, 0,
970 	    SMB_USER_STATE_LOGGED_ON));
971 }
972 
973 smb_user_t *
974 smb_session_lookup_uid_st(smb_session_t *session, uint64_t ssnid,
975     uint16_t uid, smb_user_state_t st)
976 {
977 	smb_user_t	*user;
978 	smb_llist_t	*user_list;
979 
980 	SMB_SESSION_VALID(session);
981 
982 	user_list = &session->s_user_list;
983 	smb_llist_enter(user_list, RW_READER);
984 
985 	for (user = smb_llist_head(user_list);
986 	    user != NULL;
987 	    user = smb_llist_next(user_list, user)) {
988 
989 		SMB_USER_VALID(user);
990 		ASSERT(user->u_session == session);
991 
992 		if (user->u_ssnid != ssnid && user->u_uid != uid)
993 			continue;
994 
995 		mutex_enter(&user->u_mutex);
996 		if (user->u_state == st) {
997 			// smb_user_hold_internal(user);
998 			user->u_refcnt++;
999 			mutex_exit(&user->u_mutex);
1000 			break;
1001 		}
1002 		mutex_exit(&user->u_mutex);
1003 	}
1004 
1005 	smb_llist_exit(user_list);
1006 	return (user);
1007 }
1008 
1009 /*
1010  * Find a tree by tree-id.
1011  */
1012 smb_tree_t *
1013 smb_session_lookup_tree(
1014     smb_session_t	*session,
1015     uint16_t		tid)
1016 {
1017 	smb_tree_t	*tree;
1018 
1019 	SMB_SESSION_VALID(session);
1020 
1021 	smb_llist_enter(&session->s_tree_list, RW_READER);
1022 	tree = smb_llist_head(&session->s_tree_list);
1023 
1024 	while (tree) {
1025 		ASSERT3U(tree->t_magic, ==, SMB_TREE_MAGIC);
1026 		ASSERT(tree->t_session == session);
1027 
1028 		if (tree->t_tid == tid) {
1029 			if (smb_tree_hold(tree)) {
1030 				smb_llist_exit(&session->s_tree_list);
1031 				return (tree);
1032 			} else {
1033 				smb_llist_exit(&session->s_tree_list);
1034 				return (NULL);
1035 			}
1036 		}
1037 
1038 		tree = smb_llist_next(&session->s_tree_list, tree);
1039 	}
1040 
1041 	smb_llist_exit(&session->s_tree_list);
1042 	return (NULL);
1043 }
1044 
1045 /*
1046  * Disconnect all trees that match the specified client process-id.
1047  * Used by the SMB1 "process exit" request.
1048  */
1049 void
1050 smb_session_close_pid(
1051     smb_session_t	*session,
1052     uint32_t		pid)
1053 {
1054 	smb_llist_t	*tree_list = &session->s_tree_list;
1055 	smb_tree_t	*tree;
1056 
1057 	smb_llist_enter(tree_list, RW_READER);
1058 
1059 	tree = smb_llist_head(tree_list);
1060 	while (tree) {
1061 		if (smb_tree_hold(tree)) {
1062 			smb_tree_close_pid(tree, pid);
1063 			smb_tree_release(tree);
1064 		}
1065 		tree = smb_llist_next(tree_list, tree);
1066 	}
1067 
1068 	smb_llist_exit(tree_list);
1069 }
1070 
1071 static void
1072 smb_session_tree_dtor(void *arg)
1073 {
1074 	smb_tree_t	*tree = arg;
1075 
1076 	smb_tree_disconnect(tree, B_TRUE);
1077 	/* release the ref acquired during the traversal loop */
1078 	smb_tree_release(tree);
1079 }
1080 
1081 
1082 /*
1083  * Disconnect all trees that this user has connected.
1084  */
1085 void
1086 smb_session_disconnect_owned_trees(
1087     smb_session_t	*session,
1088     smb_user_t		*owner)
1089 {
1090 	smb_tree_t	*tree;
1091 	smb_llist_t	*tree_list = &session->s_tree_list;
1092 
1093 	SMB_SESSION_VALID(session);
1094 	SMB_USER_VALID(owner);
1095 
1096 	smb_llist_enter(tree_list, RW_READER);
1097 
1098 	tree = smb_llist_head(tree_list);
1099 	while (tree) {
1100 		if ((tree->t_owner == owner) &&
1101 		    smb_tree_hold(tree)) {
1102 			/*
1103 			 * smb_tree_hold() succeeded, hence we are in state
1104 			 * SMB_TREE_STATE_CONNECTED; schedule this tree
1105 			 * for disconnect after smb_llist_exit because
1106 			 * the "unmap exec" up-call can block, and we'd
1107 			 * rather not block with the tree list locked.
1108 			 */
1109 			smb_llist_post(tree_list, tree, smb_session_tree_dtor);
1110 		}
1111 		tree = smb_llist_next(tree_list, tree);
1112 	}
1113 
1114 	/* drop the lock and flush the dtor queue */
1115 	smb_llist_exit(tree_list);
1116 }
1117 
1118 /*
1119  * Disconnect all trees that this user has connected.
1120  */
1121 static void
1122 smb_session_disconnect_trees(
1123     smb_session_t	*session)
1124 {
1125 	smb_llist_t	*tree_list = &session->s_tree_list;
1126 	smb_tree_t	*tree;
1127 
1128 	smb_llist_enter(tree_list, RW_READER);
1129 
1130 	tree = smb_llist_head(tree_list);
1131 	while (tree) {
1132 		if (smb_tree_hold(tree)) {
1133 			smb_llist_post(tree_list, tree,
1134 			    smb_session_tree_dtor);
1135 		}
1136 		tree = smb_llist_next(tree_list, tree);
1137 	}
1138 
1139 	/* drop the lock and flush the dtor queue */
1140 	smb_llist_exit(tree_list);
1141 }
1142 
1143 /*
1144  * Variant of smb_session_tree_dtor that also
1145  * cancels requests using this tree.
1146  */
1147 static void
1148 smb_session_tree_kill(void *arg)
1149 {
1150 	smb_tree_t	*tree = arg;
1151 
1152 	SMB_TREE_VALID(tree);
1153 
1154 	smb_tree_disconnect(tree, B_TRUE);
1155 	smb_session_cancel_requests(tree->t_session, tree, NULL);
1156 
1157 	/* release the ref acquired during the traversal loop */
1158 	smb_tree_release(tree);
1159 }
1160 
1161 /*
1162  * Disconnect all trees that match the specified share name,
1163  * and kill requests using those trees.
1164  */
1165 void
1166 smb_session_disconnect_share(
1167     smb_session_t	*session,
1168     const char		*sharename)
1169 {
1170 	smb_llist_t	*ll;
1171 	smb_tree_t	*tree;
1172 
1173 	SMB_SESSION_VALID(session);
1174 
1175 	ll = &session->s_tree_list;
1176 	smb_llist_enter(ll, RW_READER);
1177 
1178 	for (tree = smb_llist_head(ll);
1179 	    tree != NULL;
1180 	    tree = smb_llist_next(ll, tree)) {
1181 
1182 		SMB_TREE_VALID(tree);
1183 		ASSERT(tree->t_session == session);
1184 
1185 		if (smb_strcasecmp(tree->t_sharename, sharename, 0) != 0)
1186 			continue;
1187 
1188 		if (smb_tree_hold(tree)) {
1189 			smb_llist_post(ll, tree,
1190 			    smb_session_tree_kill);
1191 		}
1192 	}
1193 
1194 	smb_llist_exit(ll);
1195 }
1196 
1197 int smb_session_logoff_maxwait = 2 * MILLISEC;	/* 2 sec. */
1198 
1199 /*
1200  * Logoff all users associated with the specified session.
1201  *
1202  * This is called for both server-initiated disconnect
1203  * (SMB_SESSION_STATE_TERMINATED) and client-initiated
1204  * disconnect (SMB_SESSION_STATE_DISCONNECTED).
1205  * If client-initiated, save durable handles.
1206  */
1207 void
1208 smb_session_logoff(smb_session_t *session)
1209 {
1210 	smb_llist_t	*ulist;
1211 	smb_user_t	*user;
1212 	int		count;
1213 	int		timeleft = smb_session_logoff_maxwait;
1214 
1215 	SMB_SESSION_VALID(session);
1216 
1217 top:
1218 	ulist = &session->s_user_list;
1219 	smb_llist_enter(ulist, RW_READER);
1220 
1221 	user = smb_llist_head(ulist);
1222 	while (user) {
1223 		SMB_USER_VALID(user);
1224 		ASSERT(user->u_session == session);
1225 
1226 		mutex_enter(&user->u_mutex);
1227 		switch (user->u_state) {
1228 		case SMB_USER_STATE_LOGGING_ON:
1229 		case SMB_USER_STATE_LOGGED_ON:
1230 			// smb_user_hold_internal(user);
1231 			user->u_refcnt++;
1232 			mutex_exit(&user->u_mutex);
1233 			smb_user_logoff(user);
1234 			smb_user_release(user);
1235 			break;
1236 
1237 		case SMB_USER_STATE_LOGGED_OFF:
1238 		case SMB_USER_STATE_LOGGING_OFF:
1239 			mutex_exit(&user->u_mutex);
1240 			break;
1241 
1242 		default:
1243 			mutex_exit(&user->u_mutex);
1244 			ASSERT(0);
1245 			break;
1246 		}
1247 
1248 		user = smb_llist_next(ulist, user);
1249 	}
1250 
1251 	count = smb_llist_get_count(ulist);
1252 
1253 	/* drop the lock and flush the dtor queue */
1254 	smb_llist_exit(ulist);
1255 
1256 	/*
1257 	 * Wait (briefly) for user objects to go away.
1258 	 * They might linger, eg. if some ofile ref has been
1259 	 * forgotten, which holds, a tree and a user.
1260 	 * See smb_session_destroy.
1261 	 */
1262 	if (count == 0) {
1263 		/* User list is empty. */
1264 		smb_rwx_rwenter(&session->s_lock, RW_WRITER);
1265 		session->s_state = SMB_SESSION_STATE_SHUTDOWN;
1266 		smb_rwx_rwexit(&session->s_lock);
1267 	} else {
1268 		smb_rwx_rwenter(&session->s_lock, RW_READER);
1269 		if (session->s_state != SMB_SESSION_STATE_SHUTDOWN &&
1270 		    timeleft > 0) {
1271 			/* May be signaled in smb_user_delete */
1272 			(void) smb_rwx_cvwait(&session->s_lock,
1273 			    MSEC_TO_TICK(200));
1274 			timeleft -= 200;
1275 			smb_rwx_rwexit(&session->s_lock);
1276 			goto top;
1277 		}
1278 		smb_rwx_rwexit(&session->s_lock);
1279 	}
1280 
1281 	/*
1282 	 * User list should be empty now.
1283 	 * (Checked in smb_session_destroy)
1284 	 */
1285 
1286 	/*
1287 	 * User logoff happens first so we'll set preserve_opens
1288 	 * for client-initiated disconnect.  When that's done
1289 	 * there should be no trees left, but check anyway.
1290 	 */
1291 	smb_session_disconnect_trees(session);
1292 }
1293 
1294 /*
1295  * Copy the session workstation/client name to buf.  If the workstation
1296  * is an empty string (which it will be on TCP connections), use the
1297  * client IP address.
1298  */
1299 void
1300 smb_session_getclient(smb_session_t *sn, char *buf, size_t buflen)
1301 {
1302 
1303 	*buf = '\0';
1304 
1305 	if (sn->workstation[0] != '\0') {
1306 		(void) strlcpy(buf, sn->workstation, buflen);
1307 		return;
1308 	}
1309 
1310 	(void) strlcpy(buf, sn->ip_addr_str, buflen);
1311 }
1312 
1313 /*
1314  * Check whether or not the specified client name is the client of this
1315  * session.  The name may be in UNC format (\\CLIENT).
1316  *
1317  * A workstation/client name is setup on NBT connections as part of the
1318  * NetBIOS session request but that isn't available on TCP connections.
1319  * If the session doesn't have a client name we typically return the
1320  * client IP address as the workstation name on MSRPC requests.  So we
1321  * check for the IP address here in addition to the workstation name.
1322  */
1323 boolean_t
1324 smb_session_isclient(smb_session_t *sn, const char *client)
1325 {
1326 
1327 	client += strspn(client, "\\");
1328 
1329 	if (smb_strcasecmp(client, sn->workstation, 0) == 0)
1330 		return (B_TRUE);
1331 
1332 	if (smb_strcasecmp(client, sn->ip_addr_str, 0) == 0)
1333 		return (B_TRUE);
1334 
1335 	return (B_FALSE);
1336 }
1337 
1338 /*
1339  * smb_request_alloc
1340  *
1341  * Allocate an smb_request_t structure from the kmem_cache.  Partially
1342  * initialize the found/new request.
1343  *
1344  * Returns pointer to a request, or NULL if the session state is
1345  * one in which new requests are no longer allowed.
1346  */
1347 smb_request_t *
1348 smb_request_alloc(smb_session_t *session, int req_length)
1349 {
1350 	smb_request_t	*sr;
1351 
1352 	ASSERT(session->s_magic == SMB_SESSION_MAGIC);
1353 	ASSERT(req_length <= session->cmd_max_bytes);
1354 
1355 	sr = kmem_cache_alloc(smb_cache_request, KM_SLEEP);
1356 
1357 	/*
1358 	 * Future:  Use constructor to pre-initialize some fields.  For now
1359 	 * there are so many fields that it is easiest just to zero the
1360 	 * whole thing and start over.
1361 	 */
1362 	bzero(sr, sizeof (smb_request_t));
1363 
1364 	mutex_init(&sr->sr_mutex, NULL, MUTEX_DEFAULT, NULL);
1365 	smb_srm_init(sr);
1366 	sr->session = session;
1367 	sr->sr_server = session->s_server;
1368 	sr->sr_gmtoff = session->s_server->si_gmtoff;
1369 	sr->sr_cfg = &session->s_cfg;
1370 	sr->command.max_bytes = req_length;
1371 	sr->reply.max_bytes = session->reply_max_bytes;
1372 	sr->sr_req_length = req_length;
1373 	if (req_length)
1374 		sr->sr_request_buf = kmem_alloc(req_length, KM_SLEEP);
1375 	sr->sr_magic = SMB_REQ_MAGIC;
1376 	sr->sr_state = SMB_REQ_STATE_INITIALIZING;
1377 
1378 	/*
1379 	 * Only allow new SMB requests in some states.
1380 	 */
1381 	smb_rwx_rwenter(&session->s_lock, RW_WRITER);
1382 	switch (session->s_state) {
1383 	case SMB_SESSION_STATE_CONNECTED:
1384 	case SMB_SESSION_STATE_INITIALIZED:
1385 	case SMB_SESSION_STATE_ESTABLISHED:
1386 	case SMB_SESSION_STATE_NEGOTIATED:
1387 		smb_slist_insert_tail(&session->s_req_list, sr);
1388 		break;
1389 
1390 	default:
1391 		ASSERT(0);
1392 		/* FALLTHROUGH */
1393 	case SMB_SESSION_STATE_DISCONNECTED:
1394 	case SMB_SESSION_STATE_SHUTDOWN:
1395 	case SMB_SESSION_STATE_TERMINATED:
1396 		/* Disallow new requests in these states. */
1397 		if (sr->sr_request_buf)
1398 			kmem_free(sr->sr_request_buf, sr->sr_req_length);
1399 		sr->session = NULL;
1400 		sr->sr_magic = 0;
1401 		mutex_destroy(&sr->sr_mutex);
1402 		kmem_cache_free(smb_cache_request, sr);
1403 		sr = NULL;
1404 		break;
1405 	}
1406 	smb_rwx_rwexit(&session->s_lock);
1407 
1408 	return (sr);
1409 }
1410 
1411 /*
1412  * smb_request_free
1413  *
1414  * release the memories which have been allocated for a smb request.
1415  */
1416 void
1417 smb_request_free(smb_request_t *sr)
1418 {
1419 	ASSERT(sr->sr_magic == SMB_REQ_MAGIC);
1420 	ASSERT(sr->session);
1421 	ASSERT(sr->r_xa == NULL);
1422 
1423 	if (sr->fid_ofile != NULL) {
1424 		smb_ofile_release(sr->fid_ofile);
1425 	}
1426 
1427 	if (sr->tid_tree != NULL)
1428 		smb_tree_release(sr->tid_tree);
1429 
1430 	if (sr->uid_user != NULL)
1431 		smb_user_release(sr->uid_user);
1432 
1433 	if (sr->tform_ssn != NULL)
1434 		smb_user_release(sr->tform_ssn);
1435 
1436 	/*
1437 	 * The above may have left work on the delete queues
1438 	 */
1439 	smb_llist_flush(&sr->session->s_tree_list);
1440 	smb_llist_flush(&sr->session->s_user_list);
1441 
1442 	smb_slist_remove(&sr->session->s_req_list, sr);
1443 
1444 	sr->session = NULL;
1445 
1446 	smb_srm_fini(sr);
1447 
1448 	if (sr->sr_request_buf)
1449 		kmem_free(sr->sr_request_buf, sr->sr_req_length);
1450 	if (sr->command.chain)
1451 		m_freem(sr->command.chain);
1452 	if (sr->reply.chain)
1453 		m_freem(sr->reply.chain);
1454 	if (sr->raw_data.chain)
1455 		m_freem(sr->raw_data.chain);
1456 
1457 	sr->sr_magic = 0;
1458 	mutex_destroy(&sr->sr_mutex);
1459 	kmem_cache_free(smb_cache_request, sr);
1460 }
1461 
1462 boolean_t
1463 smb_session_oplocks_enable(smb_session_t *session)
1464 {
1465 	SMB_SESSION_VALID(session);
1466 	if (session->s_cfg.skc_oplock_enable == 0)
1467 		return (B_FALSE);
1468 	else
1469 		return (B_TRUE);
1470 }
1471 
1472 boolean_t
1473 smb_session_levelII_oplocks(smb_session_t *session)
1474 {
1475 	SMB_SESSION_VALID(session);
1476 
1477 	/* Older clients only do Level II oplocks if negotiated. */
1478 	if ((session->capabilities & CAP_LEVEL_II_OPLOCKS) != 0)
1479 		return (B_TRUE);
1480 
1481 	return (B_FALSE);
1482 }
1483 
1484 static void
1485 smb_session_genkey(smb_session_t *session)
1486 {
1487 	uint8_t		tmp_key[SMB_CHALLENGE_SZ];
1488 
1489 	(void) random_get_pseudo_bytes(tmp_key, SMB_CHALLENGE_SZ);
1490 	bcopy(tmp_key, &session->challenge_key, SMB_CHALLENGE_SZ);
1491 	session->challenge_len = SMB_CHALLENGE_SZ;
1492 
1493 	(void) random_get_pseudo_bytes(tmp_key, 4);
1494 	session->sesskey = tmp_key[0] | tmp_key[1] << 8 |
1495 	    tmp_key[2] << 16 | tmp_key[3] << 24;
1496 }
1497