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 2019 Nexenta Systems, Inc.  All rights reserved.
24  * Copyright 2020 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
smb_session_timers(smb_server_t * sv)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
smb_session_send(smb_session_t * session,uint8_t nbt_type,mbuf_chain_t * mbc)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
smb_netbios_session_request(struct smb_session * session)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
smb_session_xprt_gethdr(smb_session_t * session,smb_xprt_t * ret_hdr)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
smb_session_xprt_puthdr(smb_session_t * session,uint8_t msg_type,uint32_t msg_length,uint8_t * buf,size_t buflen)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
smb_request_init_command_mbuf(smb_request_t * sr)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
smb_request_cancel(smb_request_t * sr)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 		/*
448 		 * These are states that have a cancel_method.
449 		 * Make the state change now, to ensure that
450 		 * we call cancel_method exactly once.  Do the
451 		 * method call below, after we drop sr_mutex.
452 		 * When the cancelled request thread resumes,
453 		 * it should re-take sr_mutex and set sr_state
454 		 * to CANCELLED, then return STATUS_CANCELLED.
455 		 */
456 		sr->sr_state = SMB_REQ_STATE_CANCEL_PENDING;
457 		cancel_method = sr->cancel_method;
458 		VERIFY(cancel_method != NULL);
459 		break;
460 
461 	case SMB_REQ_STATE_WAITING_FCN2:
462 	case SMB_REQ_STATE_COMPLETED:
463 	case SMB_REQ_STATE_CANCEL_PENDING:
464 	case SMB_REQ_STATE_CANCELLED:
465 		/*
466 		 * No action required for these states since the request
467 		 * is completing.
468 		 */
469 		break;
470 
471 	case SMB_REQ_STATE_FREE:
472 	default:
473 		SMB_PANIC();
474 	}
475 	mutex_exit(&sr->sr_mutex);
476 
477 	if (cancel_method != NULL) {
478 		cancel_method(sr);
479 	}
480 }
481 
482 /*
483  * smb_session_receiver
484  *
485  * Receives request from the network and dispatches them to a worker.
486  *
487  * When we receive a disconnect here, it _could_ be due to the server
488  * having initiated disconnect, in which case the session state will be
489  * SMB_SESSION_STATE_TERMINATED and we want to keep that state so later
490  * tear-down logic will know which side initiated.
491  */
492 void
smb_session_receiver(smb_session_t * session)493 smb_session_receiver(smb_session_t *session)
494 {
495 	int	rc = 0;
496 	timeout_id_t tmo = NULL;
497 
498 	SMB_SESSION_VALID(session);
499 
500 	session->s_thread = curthread;
501 
502 	if (session->s_local_port == IPPORT_NETBIOS_SSN) {
503 		rc = smb_netbios_session_request(session);
504 		if (rc != 0) {
505 			smb_rwx_rwenter(&session->s_lock, RW_WRITER);
506 			if (session->s_state != SMB_SESSION_STATE_TERMINATED)
507 				session->s_state =
508 				    SMB_SESSION_STATE_DISCONNECTED;
509 			smb_rwx_rwexit(&session->s_lock);
510 			return;
511 		}
512 	}
513 
514 	smb_rwx_rwenter(&session->s_lock, RW_WRITER);
515 	session->s_state = SMB_SESSION_STATE_ESTABLISHED;
516 	session->s_auth_tmo = timeout((tmo_func_t)smb_session_disconnect,
517 	    session, SEC_TO_TICK(smb_session_auth_tmo));
518 	smb_rwx_rwexit(&session->s_lock);
519 
520 	(void) smb_session_reader(session);
521 
522 	smb_rwx_rwenter(&session->s_lock, RW_WRITER);
523 	if (session->s_state != SMB_SESSION_STATE_TERMINATED)
524 		session->s_state = SMB_SESSION_STATE_DISCONNECTED;
525 	tmo = session->s_auth_tmo;
526 	session->s_auth_tmo = NULL;
527 	smb_rwx_rwexit(&session->s_lock);
528 
529 	/* Timeout callback takes s_lock. See untimeout(9f) */
530 	if (tmo != NULL)
531 		(void) untimeout(tmo);
532 
533 	smb_soshutdown(session->sock);
534 
535 	DTRACE_PROBE2(session__drop, struct session *, session, int, rc);
536 
537 	smb_session_cancel(session);
538 	/*
539 	 * At this point everything related to the session should have been
540 	 * cleaned up and we expect that nothing will attempt to use the
541 	 * socket.
542 	 */
543 }
544 
545 /*
546  * smb_session_disconnect
547  *
548  * Server-initiated disconnect (i.e. server shutdown)
549  */
550 void
smb_session_disconnect(smb_session_t * session)551 smb_session_disconnect(smb_session_t *session)
552 {
553 	SMB_SESSION_VALID(session);
554 
555 	smb_rwx_rwenter(&session->s_lock, RW_WRITER);
556 	switch (session->s_state) {
557 	case SMB_SESSION_STATE_INITIALIZED:
558 	case SMB_SESSION_STATE_CONNECTED:
559 	case SMB_SESSION_STATE_ESTABLISHED:
560 	case SMB_SESSION_STATE_NEGOTIATED:
561 		smb_soshutdown(session->sock);
562 		session->s_state = SMB_SESSION_STATE_TERMINATED;
563 		break;
564 	case SMB_SESSION_STATE_DISCONNECTED:
565 	case SMB_SESSION_STATE_TERMINATED:
566 		break;
567 	}
568 	smb_rwx_rwexit(&session->s_lock);
569 }
570 
571 /*
572  * Read and process SMB requests.
573  *
574  * Returns:
575  *	0	Success
576  *	1	Unable to read transport header
577  *	2	Invalid transport header type
578  *	3	Invalid SMB length (too small)
579  *	4	Unable to read SMB header
580  *	5	Invalid SMB header (bad magic number)
581  *	6	Unable to read SMB data
582  */
583 static int
smb_session_reader(smb_session_t * session)584 smb_session_reader(smb_session_t *session)
585 {
586 	smb_server_t	*sv;
587 	smb_request_t	*sr = NULL;
588 	smb_xprt_t	hdr;
589 	uint8_t		*req_buf;
590 	uint32_t	resid;
591 	int		rc;
592 
593 	sv = session->s_server;
594 
595 	for (;;) {
596 
597 		rc = smb_session_xprt_gethdr(session, &hdr);
598 		if (rc)
599 			return (rc);
600 
601 		DTRACE_PROBE2(session__receive__xprthdr, session_t *, session,
602 		    smb_xprt_t *, &hdr);
603 
604 		if (hdr.xh_type != SESSION_MESSAGE) {
605 			/*
606 			 * Anything other than SESSION_MESSAGE or
607 			 * SESSION_KEEP_ALIVE is an error.  A SESSION_REQUEST
608 			 * may indicate a new session request but we need to
609 			 * close this session and we can treat it as an error
610 			 * here.
611 			 */
612 			if (hdr.xh_type == SESSION_KEEP_ALIVE) {
613 				session->keep_alive = smb_keep_alive;
614 				continue;
615 			}
616 			return (EPROTO);
617 		}
618 
619 		if (hdr.xh_length == 0) {
620 			/* zero length is another form of keep alive */
621 			session->keep_alive = smb_keep_alive;
622 			continue;
623 		}
624 
625 		if (hdr.xh_length < SMB_HEADER_LEN)
626 			return (EPROTO);
627 		if (hdr.xh_length > session->cmd_max_bytes)
628 			return (EPROTO);
629 
630 		session->keep_alive = smb_keep_alive;
631 
632 		/*
633 		 * Allocate a request context, read the whole message.
634 		 * If the request alloc fails, we've disconnected
635 		 * and won't be able to send the reply anyway, so bail now.
636 		 */
637 		if ((sr = smb_request_alloc(session, hdr.xh_length)) == NULL)
638 			break;
639 
640 		req_buf = (uint8_t *)sr->sr_request_buf;
641 		resid = hdr.xh_length;
642 
643 		rc = smb_sorecv(session->sock, req_buf, resid);
644 		if (rc) {
645 			smb_request_free(sr);
646 			break;
647 		}
648 
649 		/* accounting: received bytes */
650 		smb_server_add_rxb(sv,
651 		    (int64_t)(hdr.xh_length + NETBIOS_HDR_SZ));
652 
653 		/*
654 		 * Initialize command MBC to represent the received data.
655 		 */
656 		smb_request_init_command_mbuf(sr);
657 
658 		DTRACE_PROBE1(session__receive__smb, smb_request_t *, sr);
659 
660 		rc = session->newrq_func(sr);
661 		sr = NULL;	/* enqueued or freed */
662 		if (rc != 0)
663 			break;
664 
665 		/* See notes where this is defined (above). */
666 		if (smb_reader_delay) {
667 			delay(MSEC_TO_TICK(smb_reader_delay));
668 		}
669 	}
670 	return (rc);
671 }
672 
673 /*
674  * This is the initial handler for new smb requests, called from
675  * from smb_session_reader when we have not yet seen any requests.
676  * The first SMB request must be "negotiate", which determines
677  * which protocol and dialect we'll be using.  That's the ONLY
678  * request type handled here, because with all later requests,
679  * we know the protocol and handle those with either the SMB1 or
680  * SMB2 handlers:  smb1sr_post() or smb2sr_post().
681  * Those do NOT allow SMB negotiate, because that's only allowed
682  * as the first request on new session.
683  *
684  * This and other "post a request" handlers must either enqueue
685  * the new request for the session taskq, or smb_request_free it
686  * (in case we've decided to drop this connection).  In this
687  * (special) new request handler, we always free the request.
688  *
689  * Return value is 0 for success, and anything else will
690  * terminate the reader thread (drop the connection).
691  */
692 static int
smbsr_newrq_initial(smb_request_t * sr)693 smbsr_newrq_initial(smb_request_t *sr)
694 {
695 	uint32_t magic;
696 	int rc = EPROTO;
697 
698 	mutex_enter(&sr->sr_mutex);
699 	sr->sr_state = SMB_REQ_STATE_ACTIVE;
700 	mutex_exit(&sr->sr_mutex);
701 
702 	magic = SMB_READ_PROTOCOL(sr->sr_request_buf);
703 	if (magic == SMB_PROTOCOL_MAGIC)
704 		rc = smb1_newrq_negotiate(sr);
705 	if (magic == SMB2_PROTOCOL_MAGIC)
706 		rc = smb2_newrq_negotiate(sr);
707 
708 	mutex_enter(&sr->sr_mutex);
709 	sr->sr_state = SMB_REQ_STATE_COMPLETED;
710 	mutex_exit(&sr->sr_mutex);
711 
712 	smb_request_free(sr);
713 	return (rc);
714 }
715 
716 /*
717  * Port will be IPPORT_NETBIOS_SSN or IPPORT_SMB.
718  */
719 smb_session_t *
smb_session_create(ksocket_t new_so,uint16_t port,smb_server_t * sv,int family)720 smb_session_create(ksocket_t new_so, uint16_t port, smb_server_t *sv,
721     int family)
722 {
723 	struct sockaddr_in	sin;
724 	socklen_t		slen;
725 	struct sockaddr_in6	sin6;
726 	smb_session_t		*session;
727 	int64_t			now;
728 	uint16_t		rport;
729 
730 	session = kmem_cache_alloc(smb_cache_session, KM_SLEEP);
731 	bzero(session, sizeof (smb_session_t));
732 
733 	if (smb_idpool_constructor(&session->s_uid_pool)) {
734 		kmem_cache_free(smb_cache_session, session);
735 		return (NULL);
736 	}
737 	if (smb_idpool_constructor(&session->s_tid_pool)) {
738 		smb_idpool_destructor(&session->s_uid_pool);
739 		kmem_cache_free(smb_cache_session, session);
740 		return (NULL);
741 	}
742 
743 	now = ddi_get_lbolt64();
744 
745 	session->s_server = sv;
746 	session->s_kid = SMB_NEW_KID();
747 	session->s_state = SMB_SESSION_STATE_INITIALIZED;
748 	session->native_os = NATIVE_OS_UNKNOWN;
749 	session->opentime = now;
750 	session->keep_alive = smb_keep_alive;
751 	session->activity_timestamp = now;
752 	smb_session_genkey(session);
753 
754 	mutex_init(&session->s_credits_mutex, NULL, MUTEX_DEFAULT, NULL);
755 
756 	smb_slist_constructor(&session->s_req_list, sizeof (smb_request_t),
757 	    offsetof(smb_request_t, sr_session_lnd));
758 
759 	smb_llist_constructor(&session->s_user_list, sizeof (smb_user_t),
760 	    offsetof(smb_user_t, u_lnd));
761 
762 	smb_llist_constructor(&session->s_tree_list, sizeof (smb_tree_t),
763 	    offsetof(smb_tree_t, t_lnd));
764 
765 	smb_llist_constructor(&session->s_xa_list, sizeof (smb_xa_t),
766 	    offsetof(smb_xa_t, xa_lnd));
767 
768 	smb_net_txl_constructor(&session->s_txlst);
769 
770 	smb_rwx_init(&session->s_lock);
771 
772 	session->s_srqueue = &sv->sv_srqueue;
773 	smb_server_get_cfg(sv, &session->s_cfg);
774 
775 	if (new_so == NULL) {
776 		/*
777 		 * This call is creating the special "server" session,
778 		 * used for kshare export, oplock breaks, CA import.
779 		 * CA import creates temporary trees on this session
780 		 * and those should never get map/unmap up-calls, so
781 		 * force the map/unmap flags zero on this session.
782 		 * Set a "modern" dialect for CA import too, so
783 		 * pathname parse doesn't do OS/2 stuff, etc.
784 		 */
785 		session->s_cfg.skc_execflags = 0;
786 		session->dialect = session->s_cfg.skc_max_protocol;
787 	} else {
788 		if (family == AF_INET) {
789 			slen = sizeof (sin);
790 			(void) ksocket_getsockname(new_so,
791 			    (struct sockaddr *)&sin, &slen, CRED());
792 			bcopy(&sin.sin_addr,
793 			    &session->local_ipaddr.au_addr.au_ipv4,
794 			    sizeof (in_addr_t));
795 			slen = sizeof (sin);
796 			(void) ksocket_getpeername(new_so,
797 			    (struct sockaddr *)&sin, &slen, CRED());
798 			bcopy(&sin.sin_addr,
799 			    &session->ipaddr.au_addr.au_ipv4,
800 			    sizeof (in_addr_t));
801 			rport = sin.sin_port;
802 		} else {
803 			slen = sizeof (sin6);
804 			(void) ksocket_getsockname(new_so,
805 			    (struct sockaddr *)&sin6, &slen, CRED());
806 			bcopy(&sin6.sin6_addr,
807 			    &session->local_ipaddr.au_addr.au_ipv6,
808 			    sizeof (in6_addr_t));
809 			slen = sizeof (sin6);
810 			(void) ksocket_getpeername(new_so,
811 			    (struct sockaddr *)&sin6, &slen, CRED());
812 			bcopy(&sin6.sin6_addr,
813 			    &session->ipaddr.au_addr.au_ipv6,
814 			    sizeof (in6_addr_t));
815 			rport = sin6.sin6_port;
816 		}
817 		session->ipaddr.a_family = family;
818 		session->local_ipaddr.a_family = family;
819 		session->s_local_port = port;
820 		session->s_remote_port = ntohs(rport);
821 		session->sock = new_so;
822 		(void) smb_inet_ntop(&session->ipaddr,
823 		    session->ip_addr_str, INET6_ADDRSTRLEN);
824 		if (port == IPPORT_NETBIOS_SSN)
825 			smb_server_inc_nbt_sess(sv);
826 		else
827 			smb_server_inc_tcp_sess(sv);
828 	}
829 
830 	/*
831 	 * The initial new request handler is special,
832 	 * and only accepts negotiation requests.
833 	 */
834 	session->newrq_func = smbsr_newrq_initial;
835 
836 	/* These may increase in SMB2 negotiate. */
837 	session->cmd_max_bytes = SMB_REQ_MAX_SIZE;
838 	session->reply_max_bytes = SMB_REQ_MAX_SIZE;
839 
840 	session->s_magic = SMB_SESSION_MAGIC;
841 	return (session);
842 }
843 
844 void
smb_session_delete(smb_session_t * session)845 smb_session_delete(smb_session_t *session)
846 {
847 
848 	ASSERT(session->s_magic == SMB_SESSION_MAGIC);
849 
850 	if (session->enc_mech != NULL)
851 		smb3_encrypt_fini(session);
852 
853 	if (session->sign_fini != NULL)
854 		session->sign_fini(session);
855 
856 	if (session->signing.mackey != NULL) {
857 		kmem_free(session->signing.mackey,
858 		    session->signing.mackey_len);
859 	}
860 
861 	if (session->preauth_mech != NULL)
862 		smb31_preauth_fini(session);
863 
864 	session->s_magic = 0;
865 
866 	smb_rwx_destroy(&session->s_lock);
867 	smb_net_txl_destructor(&session->s_txlst);
868 
869 	mutex_destroy(&session->s_credits_mutex);
870 
871 	smb_slist_destructor(&session->s_req_list);
872 	smb_llist_destructor(&session->s_tree_list);
873 	smb_llist_destructor(&session->s_user_list);
874 	smb_llist_destructor(&session->s_xa_list);
875 
876 	ASSERT(session->s_tree_cnt == 0);
877 	ASSERT(session->s_file_cnt == 0);
878 	ASSERT(session->s_dir_cnt == 0);
879 
880 	smb_idpool_destructor(&session->s_tid_pool);
881 	smb_idpool_destructor(&session->s_uid_pool);
882 	if (session->sock != NULL) {
883 		if (session->s_local_port == IPPORT_NETBIOS_SSN)
884 			smb_server_dec_nbt_sess(session->s_server);
885 		else
886 			smb_server_dec_tcp_sess(session->s_server);
887 		smb_sodestroy(session->sock);
888 	}
889 	kmem_cache_free(smb_cache_session, session);
890 }
891 
892 static void
smb_session_cancel(smb_session_t * session)893 smb_session_cancel(smb_session_t *session)
894 {
895 	smb_xa_t	*xa, *nextxa;
896 
897 	/* All the request currently being treated must be canceled. */
898 	smb_session_cancel_requests(session, NULL, NULL);
899 
900 	/*
901 	 * We wait for the completion of all the requests associated with
902 	 * this session.
903 	 */
904 	smb_slist_wait_for_empty(&session->s_req_list);
905 
906 	/*
907 	 * Cleanup transact state objects
908 	 */
909 	xa = smb_llist_head(&session->s_xa_list);
910 	while (xa) {
911 		nextxa = smb_llist_next(&session->s_xa_list, xa);
912 		smb_xa_close(xa);
913 		xa = nextxa;
914 	}
915 
916 	/*
917 	 * At this point the reference count of the files and directories
918 	 * should be zero. It should be possible to destroy them without
919 	 * any problem, which should trigger the destruction of other objects.
920 	 */
921 	smb_session_logoff(session);
922 }
923 
924 /*
925  * Cancel requests.  If a non-null tree is specified, only requests specific
926  * to that tree will be cancelled.  If a non-null sr is specified, that sr
927  * will be not be cancelled - this would typically be the caller's sr.
928  */
929 void
smb_session_cancel_requests(smb_session_t * session,smb_tree_t * tree,smb_request_t * exclude_sr)930 smb_session_cancel_requests(
931     smb_session_t	*session,
932     smb_tree_t		*tree,
933     smb_request_t	*exclude_sr)
934 {
935 	smb_request_t	*sr;
936 
937 	smb_slist_enter(&session->s_req_list);
938 	sr = smb_slist_head(&session->s_req_list);
939 
940 	while (sr) {
941 		ASSERT(sr->sr_magic == SMB_REQ_MAGIC);
942 		if ((sr != exclude_sr) &&
943 		    (tree == NULL || sr->tid_tree == tree))
944 			smb_request_cancel(sr);
945 
946 		sr = smb_slist_next(&session->s_req_list, sr);
947 	}
948 
949 	smb_slist_exit(&session->s_req_list);
950 }
951 
952 /*
953  * Find a user on the specified session by SMB UID.
954  */
955 smb_user_t *
smb_session_lookup_uid(smb_session_t * session,uint16_t uid)956 smb_session_lookup_uid(smb_session_t *session, uint16_t uid)
957 {
958 	return (smb_session_lookup_uid_st(session, 0, uid,
959 	    SMB_USER_STATE_LOGGED_ON));
960 }
961 
962 /*
963  * Find a user on the specified session by SMB2 SSNID.
964  */
965 smb_user_t *
smb_session_lookup_ssnid(smb_session_t * session,uint64_t ssnid)966 smb_session_lookup_ssnid(smb_session_t *session, uint64_t ssnid)
967 {
968 	return (smb_session_lookup_uid_st(session, ssnid, 0,
969 	    SMB_USER_STATE_LOGGED_ON));
970 }
971 
972 smb_user_t *
smb_session_lookup_uid_st(smb_session_t * session,uint64_t ssnid,uint16_t uid,smb_user_state_t st)973 smb_session_lookup_uid_st(smb_session_t *session, uint64_t ssnid,
974     uint16_t uid, smb_user_state_t st)
975 {
976 	smb_user_t	*user;
977 	smb_llist_t	*user_list;
978 
979 	SMB_SESSION_VALID(session);
980 
981 	user_list = &session->s_user_list;
982 	smb_llist_enter(user_list, RW_READER);
983 
984 	for (user = smb_llist_head(user_list);
985 	    user != NULL;
986 	    user = smb_llist_next(user_list, user)) {
987 
988 		SMB_USER_VALID(user);
989 		ASSERT(user->u_session == session);
990 
991 		if (user->u_ssnid != ssnid && user->u_uid != uid)
992 			continue;
993 
994 		mutex_enter(&user->u_mutex);
995 		if (user->u_state == st) {
996 			// smb_user_hold_internal(user);
997 			user->u_refcnt++;
998 			mutex_exit(&user->u_mutex);
999 			break;
1000 		}
1001 		mutex_exit(&user->u_mutex);
1002 	}
1003 
1004 	smb_llist_exit(user_list);
1005 	return (user);
1006 }
1007 
1008 /*
1009  * Find a tree by tree-id.
1010  */
1011 smb_tree_t *
smb_session_lookup_tree(smb_session_t * session,uint16_t tid)1012 smb_session_lookup_tree(
1013     smb_session_t	*session,
1014     uint16_t		tid)
1015 {
1016 	smb_tree_t	*tree;
1017 
1018 	SMB_SESSION_VALID(session);
1019 
1020 	smb_llist_enter(&session->s_tree_list, RW_READER);
1021 	tree = smb_llist_head(&session->s_tree_list);
1022 
1023 	while (tree) {
1024 		ASSERT3U(tree->t_magic, ==, SMB_TREE_MAGIC);
1025 		ASSERT(tree->t_session == session);
1026 
1027 		if (tree->t_tid == tid) {
1028 			if (smb_tree_hold(tree)) {
1029 				smb_llist_exit(&session->s_tree_list);
1030 				return (tree);
1031 			} else {
1032 				smb_llist_exit(&session->s_tree_list);
1033 				return (NULL);
1034 			}
1035 		}
1036 
1037 		tree = smb_llist_next(&session->s_tree_list, tree);
1038 	}
1039 
1040 	smb_llist_exit(&session->s_tree_list);
1041 	return (NULL);
1042 }
1043 
1044 /*
1045  * Disconnect all trees that match the specified client process-id.
1046  * Used by the SMB1 "process exit" request.
1047  */
1048 void
smb_session_close_pid(smb_session_t * session,uint32_t pid)1049 smb_session_close_pid(
1050     smb_session_t	*session,
1051     uint32_t		pid)
1052 {
1053 	smb_llist_t	*tree_list = &session->s_tree_list;
1054 	smb_tree_t	*tree;
1055 
1056 	smb_llist_enter(tree_list, RW_READER);
1057 
1058 	tree = smb_llist_head(tree_list);
1059 	while (tree) {
1060 		if (smb_tree_hold(tree)) {
1061 			smb_tree_close_pid(tree, pid);
1062 			smb_tree_release(tree);
1063 		}
1064 		tree = smb_llist_next(tree_list, tree);
1065 	}
1066 
1067 	smb_llist_exit(tree_list);
1068 }
1069 
1070 static void
smb_session_tree_dtor(void * arg)1071 smb_session_tree_dtor(void *arg)
1072 {
1073 	smb_tree_t	*tree = arg;
1074 
1075 	smb_tree_disconnect(tree, B_TRUE);
1076 	/* release the ref acquired during the traversal loop */
1077 	smb_tree_release(tree);
1078 }
1079 
1080 
1081 /*
1082  * Disconnect all trees that this user has connected.
1083  */
1084 void
smb_session_disconnect_owned_trees(smb_session_t * session,smb_user_t * owner)1085 smb_session_disconnect_owned_trees(
1086     smb_session_t	*session,
1087     smb_user_t		*owner)
1088 {
1089 	smb_tree_t	*tree;
1090 	smb_llist_t	*tree_list = &session->s_tree_list;
1091 
1092 	SMB_SESSION_VALID(session);
1093 	SMB_USER_VALID(owner);
1094 
1095 	smb_llist_enter(tree_list, RW_READER);
1096 
1097 	tree = smb_llist_head(tree_list);
1098 	while (tree) {
1099 		if ((tree->t_owner == owner) &&
1100 		    smb_tree_hold(tree)) {
1101 			/*
1102 			 * smb_tree_hold() succeeded, hence we are in state
1103 			 * SMB_TREE_STATE_CONNECTED; schedule this tree
1104 			 * for disconnect after smb_llist_exit because
1105 			 * the "unmap exec" up-call can block, and we'd
1106 			 * rather not block with the tree list locked.
1107 			 */
1108 			smb_llist_post(tree_list, tree, smb_session_tree_dtor);
1109 		}
1110 		tree = smb_llist_next(tree_list, tree);
1111 	}
1112 
1113 	/* drop the lock and flush the dtor queue */
1114 	smb_llist_exit(tree_list);
1115 }
1116 
1117 /*
1118  * Disconnect all trees that this user has connected.
1119  */
1120 static void
smb_session_disconnect_trees(smb_session_t * session)1121 smb_session_disconnect_trees(
1122     smb_session_t	*session)
1123 {
1124 	smb_llist_t	*tree_list = &session->s_tree_list;
1125 	smb_tree_t	*tree;
1126 
1127 	smb_llist_enter(tree_list, RW_READER);
1128 
1129 	tree = smb_llist_head(tree_list);
1130 	while (tree) {
1131 		if (smb_tree_hold(tree)) {
1132 			smb_llist_post(tree_list, tree,
1133 			    smb_session_tree_dtor);
1134 		}
1135 		tree = smb_llist_next(tree_list, tree);
1136 	}
1137 
1138 	/* drop the lock and flush the dtor queue */
1139 	smb_llist_exit(tree_list);
1140 }
1141 
1142 /*
1143  * Variant of smb_session_tree_dtor that also
1144  * cancels requests using this tree.
1145  */
1146 static void
smb_session_tree_kill(void * arg)1147 smb_session_tree_kill(void *arg)
1148 {
1149 	smb_tree_t	*tree = arg;
1150 
1151 	SMB_TREE_VALID(tree);
1152 
1153 	smb_tree_disconnect(tree, B_TRUE);
1154 	smb_session_cancel_requests(tree->t_session, tree, NULL);
1155 
1156 	/* release the ref acquired during the traversal loop */
1157 	smb_tree_release(tree);
1158 }
1159 
1160 /*
1161  * Disconnect all trees that match the specified share name,
1162  * and kill requests using those trees.
1163  */
1164 void
smb_session_disconnect_share(smb_session_t * session,const char * sharename)1165 smb_session_disconnect_share(
1166     smb_session_t	*session,
1167     const char		*sharename)
1168 {
1169 	smb_llist_t	*ll;
1170 	smb_tree_t	*tree;
1171 
1172 	SMB_SESSION_VALID(session);
1173 
1174 	ll = &session->s_tree_list;
1175 	smb_llist_enter(ll, RW_READER);
1176 
1177 	for (tree = smb_llist_head(ll);
1178 	    tree != NULL;
1179 	    tree = smb_llist_next(ll, tree)) {
1180 
1181 		SMB_TREE_VALID(tree);
1182 		ASSERT(tree->t_session == session);
1183 
1184 		if (smb_strcasecmp(tree->t_sharename, sharename, 0) != 0)
1185 			continue;
1186 
1187 		if (smb_tree_hold(tree)) {
1188 			smb_llist_post(ll, tree,
1189 			    smb_session_tree_kill);
1190 		}
1191 	}
1192 
1193 	smb_llist_exit(ll);
1194 }
1195 
1196 /*
1197  * Logoff all users associated with the specified session.
1198  *
1199  * This is called for both server-initiated disconnect
1200  * (SMB_SESSION_STATE_TERMINATED) and client-initiated
1201  * disconnect (SMB_SESSION_STATE_DISCONNECTED).
1202  * If client-initiated, save durable handles.
1203  */
1204 void
smb_session_logoff(smb_session_t * session)1205 smb_session_logoff(smb_session_t *session)
1206 {
1207 	smb_llist_t	*ulist;
1208 	smb_user_t	*user;
1209 
1210 	SMB_SESSION_VALID(session);
1211 
1212 top:
1213 	ulist = &session->s_user_list;
1214 	smb_llist_enter(ulist, RW_READER);
1215 
1216 	user = smb_llist_head(ulist);
1217 	while (user) {
1218 		SMB_USER_VALID(user);
1219 		ASSERT(user->u_session == session);
1220 
1221 		mutex_enter(&user->u_mutex);
1222 		switch (user->u_state) {
1223 		case SMB_USER_STATE_LOGGING_ON:
1224 		case SMB_USER_STATE_LOGGED_ON:
1225 			// smb_user_hold_internal(user);
1226 			user->u_refcnt++;
1227 			mutex_exit(&user->u_mutex);
1228 			smb_user_logoff(user);
1229 			smb_user_release(user);
1230 			break;
1231 
1232 		case SMB_USER_STATE_LOGGED_OFF:
1233 		case SMB_USER_STATE_LOGGING_OFF:
1234 			mutex_exit(&user->u_mutex);
1235 			break;
1236 
1237 		default:
1238 			mutex_exit(&user->u_mutex);
1239 			ASSERT(0);
1240 			break;
1241 		}
1242 
1243 		user = smb_llist_next(ulist, user);
1244 	}
1245 
1246 	/* Needed below (Was the list empty?) */
1247 	user = smb_llist_head(ulist);
1248 
1249 	smb_llist_exit(ulist);
1250 
1251 	/*
1252 	 * It's possible for user objects to remain due to references
1253 	 * obtained via smb_server_lookup_ssnid(), when an SMB2
1254 	 * session setup is destroying a previous session.
1255 	 *
1256 	 * Wait for user objects to clear out (last refs. go away,
1257 	 * then smb_user_delete takes them out of the list).  When
1258 	 * the last user object is removed, the session state is
1259 	 * set to SHUTDOWN and s_lock is signaled.
1260 	 *
1261 	 * Not all places that call smb_user_release necessarily
1262 	 * flush the delete queue, so after we wait for the list
1263 	 * to empty out, go back to the top and recheck the list
1264 	 * delete queue to make sure smb_user_delete happens.
1265 	 */
1266 	if (user == NULL) {
1267 		/* User list is empty. */
1268 		smb_rwx_rwenter(&session->s_lock, RW_WRITER);
1269 		session->s_state = SMB_SESSION_STATE_SHUTDOWN;
1270 		smb_rwx_rwexit(&session->s_lock);
1271 	} else {
1272 		smb_rwx_rwenter(&session->s_lock, RW_READER);
1273 		if (session->s_state != SMB_SESSION_STATE_SHUTDOWN) {
1274 			(void) smb_rwx_cvwait(&session->s_lock,
1275 			    MSEC_TO_TICK(200));
1276 			smb_rwx_rwexit(&session->s_lock);
1277 			goto top;
1278 		}
1279 		smb_rwx_rwexit(&session->s_lock);
1280 	}
1281 	ASSERT(session->s_state == SMB_SESSION_STATE_SHUTDOWN);
1282 
1283 	/*
1284 	 * User list should be empty now.
1285 	 */
1286 #ifdef	DEBUG
1287 	if (ulist->ll_count != 0) {
1288 		cmn_err(CE_WARN, "user list not empty?");
1289 		debug_enter("s_user_list");
1290 	}
1291 #endif
1292 
1293 	/*
1294 	 * User logoff happens first so we'll set preserve_opens
1295 	 * for client-initiated disconnect.  When that's done
1296 	 * there should be no trees left, but check anyway.
1297 	 */
1298 	smb_session_disconnect_trees(session);
1299 }
1300 
1301 /*
1302  * Copy the session workstation/client name to buf.  If the workstation
1303  * is an empty string (which it will be on TCP connections), use the
1304  * client IP address.
1305  */
1306 void
smb_session_getclient(smb_session_t * sn,char * buf,size_t buflen)1307 smb_session_getclient(smb_session_t *sn, char *buf, size_t buflen)
1308 {
1309 
1310 	*buf = '\0';
1311 
1312 	if (sn->workstation[0] != '\0') {
1313 		(void) strlcpy(buf, sn->workstation, buflen);
1314 		return;
1315 	}
1316 
1317 	(void) strlcpy(buf, sn->ip_addr_str, buflen);
1318 }
1319 
1320 /*
1321  * Check whether or not the specified client name is the client of this
1322  * session.  The name may be in UNC format (\\CLIENT).
1323  *
1324  * A workstation/client name is setup on NBT connections as part of the
1325  * NetBIOS session request but that isn't available on TCP connections.
1326  * If the session doesn't have a client name we typically return the
1327  * client IP address as the workstation name on MSRPC requests.  So we
1328  * check for the IP address here in addition to the workstation name.
1329  */
1330 boolean_t
smb_session_isclient(smb_session_t * sn,const char * client)1331 smb_session_isclient(smb_session_t *sn, const char *client)
1332 {
1333 
1334 	client += strspn(client, "\\");
1335 
1336 	if (smb_strcasecmp(client, sn->workstation, 0) == 0)
1337 		return (B_TRUE);
1338 
1339 	if (smb_strcasecmp(client, sn->ip_addr_str, 0) == 0)
1340 		return (B_TRUE);
1341 
1342 	return (B_FALSE);
1343 }
1344 
1345 /*
1346  * smb_request_alloc
1347  *
1348  * Allocate an smb_request_t structure from the kmem_cache.  Partially
1349  * initialize the found/new request.
1350  *
1351  * Returns pointer to a request, or NULL if the session state is
1352  * one in which new requests are no longer allowed.
1353  */
1354 smb_request_t *
smb_request_alloc(smb_session_t * session,int req_length)1355 smb_request_alloc(smb_session_t *session, int req_length)
1356 {
1357 	smb_request_t	*sr;
1358 
1359 	ASSERT(session->s_magic == SMB_SESSION_MAGIC);
1360 	ASSERT(req_length <= session->cmd_max_bytes);
1361 
1362 	sr = kmem_cache_alloc(smb_cache_request, KM_SLEEP);
1363 
1364 	/*
1365 	 * Future:  Use constructor to pre-initialize some fields.  For now
1366 	 * there are so many fields that it is easiest just to zero the
1367 	 * whole thing and start over.
1368 	 */
1369 	bzero(sr, sizeof (smb_request_t));
1370 
1371 	mutex_init(&sr->sr_mutex, NULL, MUTEX_DEFAULT, NULL);
1372 	smb_srm_init(sr);
1373 	sr->session = session;
1374 	sr->sr_server = session->s_server;
1375 	sr->sr_gmtoff = session->s_server->si_gmtoff;
1376 	sr->sr_cfg = &session->s_cfg;
1377 	sr->command.max_bytes = req_length;
1378 	sr->reply.max_bytes = session->reply_max_bytes;
1379 	sr->sr_req_length = req_length;
1380 	if (req_length)
1381 		sr->sr_request_buf = kmem_alloc(req_length, KM_SLEEP);
1382 	sr->sr_magic = SMB_REQ_MAGIC;
1383 	sr->sr_state = SMB_REQ_STATE_INITIALIZING;
1384 
1385 	/*
1386 	 * Only allow new SMB requests in some states.
1387 	 */
1388 	smb_rwx_rwenter(&session->s_lock, RW_WRITER);
1389 	switch (session->s_state) {
1390 	case SMB_SESSION_STATE_CONNECTED:
1391 	case SMB_SESSION_STATE_INITIALIZED:
1392 	case SMB_SESSION_STATE_ESTABLISHED:
1393 	case SMB_SESSION_STATE_NEGOTIATED:
1394 		smb_slist_insert_tail(&session->s_req_list, sr);
1395 		break;
1396 
1397 	default:
1398 		ASSERT(0);
1399 		/* FALLTHROUGH */
1400 	case SMB_SESSION_STATE_DISCONNECTED:
1401 	case SMB_SESSION_STATE_SHUTDOWN:
1402 	case SMB_SESSION_STATE_TERMINATED:
1403 		/* Disallow new requests in these states. */
1404 		if (sr->sr_request_buf)
1405 			kmem_free(sr->sr_request_buf, sr->sr_req_length);
1406 		sr->session = NULL;
1407 		sr->sr_magic = 0;
1408 		mutex_destroy(&sr->sr_mutex);
1409 		kmem_cache_free(smb_cache_request, sr);
1410 		sr = NULL;
1411 		break;
1412 	}
1413 	smb_rwx_rwexit(&session->s_lock);
1414 
1415 	return (sr);
1416 }
1417 
1418 /*
1419  * smb_request_free
1420  *
1421  * release the memories which have been allocated for a smb request.
1422  */
1423 void
smb_request_free(smb_request_t * sr)1424 smb_request_free(smb_request_t *sr)
1425 {
1426 	ASSERT(sr->sr_magic == SMB_REQ_MAGIC);
1427 	ASSERT(sr->session);
1428 	ASSERT(sr->r_xa == NULL);
1429 
1430 	if (sr->fid_ofile != NULL) {
1431 		smb_ofile_release(sr->fid_ofile);
1432 	}
1433 
1434 	if (sr->tid_tree != NULL)
1435 		smb_tree_release(sr->tid_tree);
1436 
1437 	if (sr->uid_user != NULL)
1438 		smb_user_release(sr->uid_user);
1439 
1440 	if (sr->tform_ssn != NULL)
1441 		smb_user_release(sr->tform_ssn);
1442 
1443 	/*
1444 	 * The above may have left work on the delete queues
1445 	 */
1446 	smb_llist_flush(&sr->session->s_tree_list);
1447 	smb_llist_flush(&sr->session->s_user_list);
1448 
1449 	smb_slist_remove(&sr->session->s_req_list, sr);
1450 
1451 	sr->session = NULL;
1452 
1453 	smb_srm_fini(sr);
1454 
1455 	if (sr->sr_request_buf)
1456 		kmem_free(sr->sr_request_buf, sr->sr_req_length);
1457 	if (sr->command.chain)
1458 		m_freem(sr->command.chain);
1459 	if (sr->reply.chain)
1460 		m_freem(sr->reply.chain);
1461 	if (sr->raw_data.chain)
1462 		m_freem(sr->raw_data.chain);
1463 
1464 	sr->sr_magic = 0;
1465 	mutex_destroy(&sr->sr_mutex);
1466 	kmem_cache_free(smb_cache_request, sr);
1467 }
1468 
1469 boolean_t
smb_session_oplocks_enable(smb_session_t * session)1470 smb_session_oplocks_enable(smb_session_t *session)
1471 {
1472 	SMB_SESSION_VALID(session);
1473 	if (session->s_cfg.skc_oplock_enable == 0)
1474 		return (B_FALSE);
1475 	else
1476 		return (B_TRUE);
1477 }
1478 
1479 boolean_t
smb_session_levelII_oplocks(smb_session_t * session)1480 smb_session_levelII_oplocks(smb_session_t *session)
1481 {
1482 	SMB_SESSION_VALID(session);
1483 
1484 	/* Older clients only do Level II oplocks if negotiated. */
1485 	if ((session->capabilities & CAP_LEVEL_II_OPLOCKS) != 0)
1486 		return (B_TRUE);
1487 
1488 	return (B_FALSE);
1489 }
1490 
1491 static void
smb_session_genkey(smb_session_t * session)1492 smb_session_genkey(smb_session_t *session)
1493 {
1494 	uint8_t		tmp_key[SMB_CHALLENGE_SZ];
1495 
1496 	(void) random_get_pseudo_bytes(tmp_key, SMB_CHALLENGE_SZ);
1497 	bcopy(tmp_key, &session->challenge_key, SMB_CHALLENGE_SZ);
1498 	session->challenge_len = SMB_CHALLENGE_SZ;
1499 
1500 	(void) random_get_pseudo_bytes(tmp_key, 4);
1501 	session->sesskey = tmp_key[0] | tmp_key[1] << 8 |
1502 	    tmp_key[2] << 16 | tmp_key[3] << 24;
1503 }
1504