xref: /titanic_51/usr/src/uts/common/fs/smbsrv/smb_session.c (revision ac823a0f31ed9c8cbe505cee2def262ac92ea6cd)
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  */
24 #include <sys/atomic.h>
25 #include <sys/strsubr.h>
26 #include <sys/synch.h>
27 #include <sys/types.h>
28 #include <sys/socketvar.h>
29 #include <sys/sdt.h>
30 #include <smbsrv/netbios.h>
31 #include <smbsrv/smb_kproto.h>
32 #include <smbsrv/string.h>
33 #include <inet/tcp.h>
34 
35 static volatile uint64_t smb_kids;
36 
37 uint32_t smb_keep_alive = SSN_KEEP_ALIVE_TIMEOUT;
38 
39 static void smb_session_cancel(smb_session_t *);
40 static int smb_session_message(smb_session_t *);
41 static int smb_session_xprt_puthdr(smb_session_t *, smb_xprt_t *,
42     uint8_t *, size_t);
43 static smb_user_t *smb_session_lookup_user(smb_session_t *, char *, char *);
44 static void smb_session_logoff(smb_session_t *);
45 static void smb_request_init_command_mbuf(smb_request_t *sr);
46 void dump_smb_inaddr(smb_inaddr_t *ipaddr);
47 
48 void
49 smb_session_timers(smb_llist_t *ll)
50 {
51 	smb_session_t	*session;
52 
53 	smb_llist_enter(ll, RW_READER);
54 	session = smb_llist_head(ll);
55 	while (session != NULL) {
56 		/*
57 		 * Walk through the table and decrement each keep_alive
58 		 * timer that has not timed out yet. (keepalive > 0)
59 		 */
60 		SMB_SESSION_VALID(session);
61 		if (session->keep_alive &&
62 		    (session->keep_alive != (uint32_t)-1))
63 			session->keep_alive--;
64 		session = smb_llist_next(ll, session);
65 	}
66 	smb_llist_exit(ll);
67 }
68 
69 void
70 smb_session_correct_keep_alive_values(smb_llist_t *ll, uint32_t new_keep_alive)
71 {
72 	smb_session_t		*sn;
73 
74 	if (new_keep_alive == smb_keep_alive)
75 		return;
76 	/*
77 	 * keep alive == 0 means do not drop connection if it's idle
78 	 */
79 	smb_keep_alive = (new_keep_alive) ? new_keep_alive : -1;
80 
81 	/*
82 	 * Walk through the table and set each session to the new keep_alive
83 	 * value if they have not already timed out.  Block clock interrupts.
84 	 */
85 	smb_llist_enter(ll, RW_READER);
86 	sn = smb_llist_head(ll);
87 	while (sn != NULL) {
88 		SMB_SESSION_VALID(sn);
89 		if (sn->keep_alive != 0)
90 			sn->keep_alive = new_keep_alive;
91 		sn = smb_llist_next(ll, sn);
92 	}
93 	smb_llist_exit(ll);
94 }
95 
96 /*
97  * smb_reconnection_check
98  *
99  * This function is called when a client indicates its current connection
100  * should be the only one it has with the server, as indicated by VC=0 in
101  * a SessionSetupX request. We go through the session list and destroy any
102  * stale connections for that client.
103  *
104  * Clients don't associate IP addresses and servers. So a client may make
105  * independent connections (i.e. with VC=0) to a server with multiple
106  * IP addresses. So, when checking for a reconnection, we need to include
107  * the local IP address, to which the client is connecting, when checking
108  * for stale sessions.
109  *
110  * Also check the server's NetBIOS name to support simultaneous access by
111  * multiple clients behind a NAT server.  This will only work for SMB over
112  * NetBIOS on TCP port 139, it will not work SMB over TCP port 445 because
113  * there is no NetBIOS name.  See also Knowledge Base article Q301673.
114  */
115 void
116 smb_session_reconnection_check(smb_llist_t *ll, smb_session_t *sess)
117 {
118 	smb_session_t	*sn;
119 
120 	smb_llist_enter(ll, RW_READER);
121 	sn = smb_llist_head(ll);
122 	while (sn != NULL) {
123 		SMB_SESSION_VALID(sn);
124 		if ((sn != sess) &&
125 		    smb_inet_equal(&sn->ipaddr, &sess->ipaddr) &&
126 		    smb_inet_equal(&sn->local_ipaddr, &sess->local_ipaddr) &&
127 		    (strcasecmp(sn->workstation, sess->workstation) == 0) &&
128 		    (sn->opentime <= sess->opentime) &&
129 		    (sn->s_kid < sess->s_kid)) {
130 			smb_session_disconnect(sn);
131 		}
132 		sn = smb_llist_next(ll, sn);
133 	}
134 	smb_llist_exit(ll);
135 }
136 
137 /*
138  * Send a session message - supports SMB-over-NBT and SMB-over-TCP.
139  *
140  * The mbuf chain is copied into a contiguous buffer so that the whole
141  * message is submitted to smb_sosend as a single request.  This should
142  * help Ethereal/Wireshark delineate the packets correctly even though
143  * TCP_NODELAY has been set on the socket.
144  *
145  * If an mbuf chain is provided, it will be freed and set to NULL here.
146  */
147 int
148 smb_session_send(smb_session_t *session, uint8_t type, mbuf_chain_t *mbc)
149 {
150 	smb_txreq_t	*txr;
151 	smb_xprt_t	hdr;
152 	int		rc;
153 
154 	switch (session->s_state) {
155 	case SMB_SESSION_STATE_DISCONNECTED:
156 	case SMB_SESSION_STATE_TERMINATED:
157 		if ((mbc != NULL) && (mbc->chain != NULL)) {
158 			m_freem(mbc->chain);
159 			mbc->chain = NULL;
160 			mbc->flags = 0;
161 		}
162 		return (ENOTCONN);
163 	default:
164 		break;
165 	}
166 
167 	txr = smb_net_txr_alloc();
168 
169 	if ((mbc != NULL) && (mbc->chain != NULL)) {
170 		rc = mbc_moveout(mbc, (caddr_t)&txr->tr_buf[NETBIOS_HDR_SZ],
171 		    sizeof (txr->tr_buf) - NETBIOS_HDR_SZ, &txr->tr_len);
172 		if (rc != 0) {
173 			smb_net_txr_free(txr);
174 			return (rc);
175 		}
176 	}
177 
178 	hdr.xh_type = type;
179 	hdr.xh_length = (uint32_t)txr->tr_len;
180 
181 	rc = smb_session_xprt_puthdr(session, &hdr, txr->tr_buf,
182 	    NETBIOS_HDR_SZ);
183 
184 	if (rc != 0) {
185 		smb_net_txr_free(txr);
186 		return (rc);
187 	}
188 	txr->tr_len += NETBIOS_HDR_SZ;
189 	smb_server_add_txb(session->s_server, (int64_t)txr->tr_len);
190 	return (smb_net_txr_send(session->sock, &session->s_txlst, txr));
191 }
192 
193 /*
194  * Read, process and respond to a NetBIOS session request.
195  *
196  * A NetBIOS session must be established for SMB-over-NetBIOS.  Validate
197  * the calling and called name format and save the client NetBIOS name,
198  * which is used when a NetBIOS session is established to check for and
199  * cleanup leftover state from a previous session.
200  *
201  * Session requests are not valid for SMB-over-TCP, which is unfortunate
202  * because without the client name leftover state cannot be cleaned up
203  * if the client is behind a NAT server.
204  */
205 static int
206 smb_session_request(struct smb_session *session)
207 {
208 	int			rc;
209 	char			*calling_name;
210 	char			*called_name;
211 	char 			client_name[NETBIOS_NAME_SZ];
212 	struct mbuf_chain 	mbc;
213 	char 			*names = NULL;
214 	smb_wchar_t		*wbuf = NULL;
215 	smb_xprt_t		hdr;
216 	char *p;
217 	int rc1, rc2;
218 
219 	session->keep_alive = smb_keep_alive;
220 
221 	if ((rc = smb_session_xprt_gethdr(session, &hdr)) != 0)
222 		return (rc);
223 
224 	DTRACE_PROBE2(receive__session__req__xprthdr, struct session *, session,
225 	    smb_xprt_t *, &hdr);
226 
227 	if ((hdr.xh_type != SESSION_REQUEST) ||
228 	    (hdr.xh_length != NETBIOS_SESSION_REQUEST_DATA_LENGTH)) {
229 		DTRACE_PROBE1(receive__session__req__failed,
230 		    struct session *, session);
231 		return (EINVAL);
232 	}
233 
234 	names = kmem_alloc(hdr.xh_length, KM_SLEEP);
235 
236 	if ((rc = smb_sorecv(session->sock, names, hdr.xh_length)) != 0) {
237 		kmem_free(names, hdr.xh_length);
238 		DTRACE_PROBE1(receive__session__req__failed,
239 		    struct session *, session);
240 		return (rc);
241 	}
242 
243 	DTRACE_PROBE3(receive__session__req__data, struct session *, session,
244 	    char *, names, uint32_t, hdr.xh_length);
245 
246 	called_name = &names[0];
247 	calling_name = &names[NETBIOS_ENCODED_NAME_SZ + 2];
248 
249 	rc1 = netbios_name_isvalid(called_name, 0);
250 	rc2 = netbios_name_isvalid(calling_name, client_name);
251 
252 	if (rc1 == 0 || rc2 == 0) {
253 
254 		DTRACE_PROBE3(receive__invalid__session__req,
255 		    struct session *, session, char *, names,
256 		    uint32_t, hdr.xh_length);
257 
258 		kmem_free(names, hdr.xh_length);
259 		MBC_INIT(&mbc, MAX_DATAGRAM_LENGTH);
260 		(void) smb_mbc_encodef(&mbc, "b",
261 		    DATAGRAM_INVALID_SOURCE_NAME_FORMAT);
262 		(void) smb_session_send(session, NEGATIVE_SESSION_RESPONSE,
263 		    &mbc);
264 		return (EINVAL);
265 	}
266 
267 	DTRACE_PROBE3(receive__session__req__calling__decoded,
268 	    struct session *, session,
269 	    char *, calling_name, char *, client_name);
270 
271 	/*
272 	 * The client NetBIOS name is in oem codepage format.
273 	 * We need to convert it to unicode and store it in
274 	 * multi-byte format.  We also need to strip off any
275 	 * spaces added as part of the NetBIOS name encoding.
276 	 */
277 	wbuf = kmem_alloc((SMB_PI_MAX_HOST * sizeof (smb_wchar_t)), KM_SLEEP);
278 	(void) oemtoucs(wbuf, client_name, SMB_PI_MAX_HOST, OEM_CPG_850);
279 	(void) smb_wcstombs(session->workstation, wbuf, SMB_PI_MAX_HOST);
280 	kmem_free(wbuf, (SMB_PI_MAX_HOST * sizeof (smb_wchar_t)));
281 
282 	if ((p = strchr(session->workstation, ' ')) != 0)
283 		*p = '\0';
284 
285 	kmem_free(names, hdr.xh_length);
286 	return (smb_session_send(session, POSITIVE_SESSION_RESPONSE, NULL));
287 }
288 
289 /*
290  * Read 4-byte header from the session socket and build an in-memory
291  * session transport header.  See smb_xprt_t definition for header
292  * format information.
293  *
294  * Direct hosted NetBIOS-less SMB (SMB-over-TCP) uses port 445.  The
295  * first byte of the four-byte header must be 0 and the next three
296  * bytes contain the length of the remaining data.
297  */
298 int
299 smb_session_xprt_gethdr(smb_session_t *session, smb_xprt_t *ret_hdr)
300 {
301 	int		rc;
302 	unsigned char	buf[NETBIOS_HDR_SZ];
303 
304 	if ((rc = smb_sorecv(session->sock, buf, NETBIOS_HDR_SZ)) != 0)
305 		return (rc);
306 
307 	switch (session->s_local_port) {
308 	case IPPORT_NETBIOS_SSN:
309 		ret_hdr->xh_type = buf[0];
310 		ret_hdr->xh_length = (((uint32_t)buf[1] & 1) << 16) |
311 		    ((uint32_t)buf[2] << 8) |
312 		    ((uint32_t)buf[3]);
313 		break;
314 
315 	case IPPORT_SMB:
316 		ret_hdr->xh_type = buf[0];
317 
318 		if (ret_hdr->xh_type != 0) {
319 			cmn_err(CE_WARN, "invalid type (%u)", ret_hdr->xh_type);
320 			dump_smb_inaddr(&session->ipaddr);
321 			return (EPROTO);
322 		}
323 
324 		ret_hdr->xh_length = ((uint32_t)buf[1] << 16) |
325 		    ((uint32_t)buf[2] << 8) |
326 		    ((uint32_t)buf[3]);
327 		break;
328 
329 	default:
330 		cmn_err(CE_WARN, "invalid port %u", session->s_local_port);
331 		dump_smb_inaddr(&session->ipaddr);
332 		return (EPROTO);
333 	}
334 
335 	return (0);
336 }
337 
338 /*
339  * Encode a transport session packet header into a 4-byte buffer.
340  * See smb_xprt_t definition for header format information.
341  */
342 static int
343 smb_session_xprt_puthdr(smb_session_t *session, smb_xprt_t *hdr,
344     uint8_t *buf, size_t buflen)
345 {
346 	if (session == NULL || hdr == NULL ||
347 	    buf == NULL || buflen < NETBIOS_HDR_SZ) {
348 		return (-1);
349 	}
350 
351 	switch (session->s_local_port) {
352 	case IPPORT_NETBIOS_SSN:
353 		buf[0] = hdr->xh_type;
354 		buf[1] = ((hdr->xh_length >> 16) & 1);
355 		buf[2] = (hdr->xh_length >> 8) & 0xff;
356 		buf[3] = hdr->xh_length & 0xff;
357 		break;
358 
359 	case IPPORT_SMB:
360 		buf[0] = hdr->xh_type;
361 		buf[1] = (hdr->xh_length >> 16) & 0xff;
362 		buf[2] = (hdr->xh_length >> 8) & 0xff;
363 		buf[3] = hdr->xh_length & 0xff;
364 		break;
365 
366 	default:
367 		cmn_err(CE_WARN, "invalid port %u", session->s_local_port);
368 		dump_smb_inaddr(&session->ipaddr);
369 		return (-1);
370 	}
371 
372 	return (0);
373 }
374 
375 static void
376 smb_request_init_command_mbuf(smb_request_t *sr)
377 {
378 	MGET(sr->command.chain, 0, MT_DATA);
379 
380 	/*
381 	 * Setup mbuf, mimic MCLGET but use the complete packet buffer.
382 	 */
383 	sr->command.chain->m_ext.ext_buf = sr->sr_request_buf;
384 	sr->command.chain->m_data = sr->command.chain->m_ext.ext_buf;
385 	sr->command.chain->m_len = sr->sr_req_length;
386 	sr->command.chain->m_flags |= M_EXT;
387 	sr->command.chain->m_ext.ext_size = sr->sr_req_length;
388 	sr->command.chain->m_ext.ext_ref = &mclrefnoop;
389 
390 	/*
391 	 * Initialize the rest of the mbuf_chain fields
392 	 */
393 	sr->command.flags = 0;
394 	sr->command.shadow_of = 0;
395 	sr->command.max_bytes = sr->sr_req_length;
396 	sr->command.chain_offset = 0;
397 }
398 
399 /*
400  * smb_request_cancel
401  *
402  * Handle a cancel for a request properly depending on the current request
403  * state.
404  */
405 void
406 smb_request_cancel(smb_request_t *sr)
407 {
408 	mutex_enter(&sr->sr_mutex);
409 	switch (sr->sr_state) {
410 
411 	case SMB_REQ_STATE_SUBMITTED:
412 	case SMB_REQ_STATE_ACTIVE:
413 	case SMB_REQ_STATE_CLEANED_UP:
414 		sr->sr_state = SMB_REQ_STATE_CANCELED;
415 		break;
416 
417 	case SMB_REQ_STATE_WAITING_LOCK:
418 		/*
419 		 * This request is waiting on a lock.  Wakeup everything
420 		 * waiting on the lock so that the relevant thread regains
421 		 * control and notices that is has been canceled.  The
422 		 * other lock request threads waiting on this lock will go
423 		 * back to sleep when they discover they are still blocked.
424 		 */
425 		sr->sr_state = SMB_REQ_STATE_CANCELED;
426 
427 		ASSERT(sr->sr_awaiting != NULL);
428 		mutex_enter(&sr->sr_awaiting->l_mutex);
429 		cv_broadcast(&sr->sr_awaiting->l_cv);
430 		mutex_exit(&sr->sr_awaiting->l_mutex);
431 		break;
432 
433 	case SMB_REQ_STATE_WAITING_EVENT:
434 	case SMB_REQ_STATE_EVENT_OCCURRED:
435 		/*
436 		 * Cancellations for these states are handled by the
437 		 * notify-change code
438 		 */
439 		break;
440 
441 	case SMB_REQ_STATE_COMPLETED:
442 	case SMB_REQ_STATE_CANCELED:
443 		/*
444 		 * No action required for these states since the request
445 		 * is completing.
446 		 */
447 		break;
448 	/*
449 	 * Cases included:
450 	 *	SMB_REQ_STATE_FREE:
451 	 *	SMB_REQ_STATE_INITIALIZING:
452 	 */
453 	default:
454 		SMB_PANIC();
455 	}
456 	mutex_exit(&sr->sr_mutex);
457 }
458 
459 /*
460  * smb_session_receiver
461  *
462  * Receives request from the network and dispatches them to a worker.
463  */
464 void
465 smb_session_receiver(smb_session_t *session)
466 {
467 	int	rc;
468 
469 	SMB_SESSION_VALID(session);
470 
471 	session->s_thread = curthread;
472 
473 	if (session->s_local_port == IPPORT_NETBIOS_SSN) {
474 		rc = smb_session_request(session);
475 		if (rc != 0) {
476 			smb_rwx_rwenter(&session->s_lock, RW_WRITER);
477 			session->s_state = SMB_SESSION_STATE_DISCONNECTED;
478 			smb_rwx_rwexit(&session->s_lock);
479 			return;
480 		}
481 	}
482 
483 	smb_rwx_rwenter(&session->s_lock, RW_WRITER);
484 	session->s_state = SMB_SESSION_STATE_ESTABLISHED;
485 	smb_rwx_rwexit(&session->s_lock);
486 
487 	(void) smb_session_message(session);
488 
489 	smb_rwx_rwenter(&session->s_lock, RW_WRITER);
490 	session->s_state = SMB_SESSION_STATE_DISCONNECTED;
491 	smb_rwx_rwexit(&session->s_lock);
492 
493 	smb_soshutdown(session->sock);
494 
495 	DTRACE_PROBE2(session__drop, struct session *, session, int, rc);
496 
497 	smb_session_cancel(session);
498 	/*
499 	 * At this point everything related to the session should have been
500 	 * cleaned up and we expect that nothing will attempt to use the
501 	 * socket.
502 	 */
503 }
504 
505 /*
506  * smb_session_disconnect
507  *
508  * Disconnects the session passed in.
509  */
510 void
511 smb_session_disconnect(smb_session_t *session)
512 {
513 	SMB_SESSION_VALID(session);
514 
515 	smb_rwx_rwenter(&session->s_lock, RW_WRITER);
516 	switch (session->s_state) {
517 	case SMB_SESSION_STATE_INITIALIZED:
518 	case SMB_SESSION_STATE_CONNECTED:
519 	case SMB_SESSION_STATE_ESTABLISHED:
520 	case SMB_SESSION_STATE_NEGOTIATED:
521 	case SMB_SESSION_STATE_OPLOCK_BREAKING:
522 	case SMB_SESSION_STATE_WRITE_RAW_ACTIVE:
523 	case SMB_SESSION_STATE_READ_RAW_ACTIVE:
524 		smb_soshutdown(session->sock);
525 		session->s_state = SMB_SESSION_STATE_DISCONNECTED;
526 		_NOTE(FALLTHRU)
527 	case SMB_SESSION_STATE_DISCONNECTED:
528 	case SMB_SESSION_STATE_TERMINATED:
529 		break;
530 	}
531 	smb_rwx_rwexit(&session->s_lock);
532 }
533 
534 /*
535  * Read and process SMB requests.
536  *
537  * Returns:
538  *	0	Success
539  *	1	Unable to read transport header
540  *	2	Invalid transport header type
541  *	3	Invalid SMB length (too small)
542  *	4	Unable to read SMB header
543  *	5	Invalid SMB header (bad magic number)
544  *	6	Unable to read SMB data
545  *	2x	Write raw failed
546  */
547 static int
548 smb_session_message(smb_session_t *session)
549 {
550 	smb_server_t	*sv;
551 	smb_request_t	*sr = NULL;
552 	smb_xprt_t	hdr;
553 	uint8_t		*req_buf;
554 	uint32_t	resid;
555 	int		rc;
556 
557 	sv = session->s_server;
558 
559 	for (;;) {
560 
561 		rc = smb_session_xprt_gethdr(session, &hdr);
562 		if (rc)
563 			return (rc);
564 
565 		DTRACE_PROBE2(session__receive__xprthdr, session_t *, session,
566 		    smb_xprt_t *, &hdr);
567 
568 		if (hdr.xh_type != SESSION_MESSAGE) {
569 			/*
570 			 * Anything other than SESSION_MESSAGE or
571 			 * SESSION_KEEP_ALIVE is an error.  A SESSION_REQUEST
572 			 * may indicate a new session request but we need to
573 			 * close this session and we can treat it as an error
574 			 * here.
575 			 */
576 			if (hdr.xh_type == SESSION_KEEP_ALIVE) {
577 				session->keep_alive = smb_keep_alive;
578 				continue;
579 			}
580 			return (EPROTO);
581 		}
582 
583 		if (hdr.xh_length < SMB_HEADER_LEN)
584 			return (EPROTO);
585 
586 		session->keep_alive = smb_keep_alive;
587 		/*
588 		 * Allocate a request context, read the SMB header and validate
589 		 * it. The sr includes a buffer large enough to hold the SMB
590 		 * request payload.  If the header looks valid, read any
591 		 * remaining data.
592 		 */
593 		sr = smb_request_alloc(session, hdr.xh_length);
594 
595 		req_buf = (uint8_t *)sr->sr_request_buf;
596 		resid = hdr.xh_length;
597 
598 		rc = smb_sorecv(session->sock, req_buf, SMB_HEADER_LEN);
599 		if (rc) {
600 			smb_request_free(sr);
601 			return (rc);
602 		}
603 
604 		if (SMB_PROTOCOL_MAGIC_INVALID(sr)) {
605 			smb_request_free(sr);
606 			return (EPROTO);
607 		}
608 
609 		if (resid > SMB_HEADER_LEN) {
610 			req_buf += SMB_HEADER_LEN;
611 			resid -= SMB_HEADER_LEN;
612 
613 			rc = smb_sorecv(session->sock, req_buf, resid);
614 			if (rc) {
615 				smb_request_free(sr);
616 				return (rc);
617 			}
618 		}
619 		smb_server_add_rxb(sv,
620 		    (int64_t)(hdr.xh_length + NETBIOS_HDR_SZ));
621 		/*
622 		 * Initialize command MBC to represent the received data.
623 		 */
624 		smb_request_init_command_mbuf(sr);
625 
626 		DTRACE_PROBE1(session__receive__smb, smb_request_t *, sr);
627 
628 		/*
629 		 * If this is a raw write, hand off the request.  The handler
630 		 * will retrieve the remaining raw data and process the request.
631 		 */
632 		if (SMB_IS_WRITERAW(sr)) {
633 			rc = smb_handle_write_raw(session, sr);
634 			if (rc == 0)
635 				continue;
636 			return (rc);
637 		}
638 		if (sr->session->signing.flags & SMB_SIGNING_ENABLED) {
639 			if (SMB_IS_NT_CANCEL(sr)) {
640 				sr->session->signing.seqnum++;
641 				sr->sr_seqnum = sr->session->signing.seqnum + 1;
642 				sr->reply_seqnum = 0;
643 			} else {
644 				sr->session->signing.seqnum += 2;
645 				sr->sr_seqnum = sr->session->signing.seqnum;
646 				sr->reply_seqnum = sr->sr_seqnum + 1;
647 			}
648 		}
649 		sr->sr_time_submitted = gethrtime();
650 		sr->sr_state = SMB_REQ_STATE_SUBMITTED;
651 		smb_srqueue_waitq_enter(session->s_srqueue);
652 		(void) taskq_dispatch(session->s_server->sv_worker_pool,
653 		    smb_session_worker, sr, TQ_SLEEP);
654 	}
655 }
656 
657 /*
658  * Port will be IPPORT_NETBIOS_SSN or IPPORT_SMB.
659  */
660 smb_session_t *
661 smb_session_create(ksocket_t new_so, uint16_t port, smb_server_t *sv,
662     int family)
663 {
664 	struct sockaddr_in	sin;
665 	socklen_t		slen;
666 	struct sockaddr_in6	sin6;
667 	smb_session_t		*session;
668 	int64_t			now;
669 
670 	session = kmem_cache_alloc(sv->si_cache_session, KM_SLEEP);
671 	bzero(session, sizeof (smb_session_t));
672 
673 	if (smb_idpool_constructor(&session->s_uid_pool)) {
674 		kmem_cache_free(sv->si_cache_session, session);
675 		return (NULL);
676 	}
677 
678 	now = ddi_get_lbolt64();
679 
680 	session->s_kid = SMB_NEW_KID();
681 	session->s_state = SMB_SESSION_STATE_INITIALIZED;
682 	session->native_os = NATIVE_OS_UNKNOWN;
683 	session->opentime = now;
684 	session->keep_alive = smb_keep_alive;
685 	session->activity_timestamp = now;
686 
687 	smb_slist_constructor(&session->s_req_list, sizeof (smb_request_t),
688 	    offsetof(smb_request_t, sr_session_lnd));
689 
690 	smb_llist_constructor(&session->s_user_list, sizeof (smb_user_t),
691 	    offsetof(smb_user_t, u_lnd));
692 
693 	smb_llist_constructor(&session->s_xa_list, sizeof (smb_xa_t),
694 	    offsetof(smb_xa_t, xa_lnd));
695 
696 	list_create(&session->s_oplock_brkreqs, sizeof (mbuf_chain_t),
697 	    offsetof(mbuf_chain_t, mbc_lnd));
698 
699 	smb_net_txl_constructor(&session->s_txlst);
700 
701 	smb_rwx_init(&session->s_lock);
702 
703 	if (new_so != NULL) {
704 		if (family == AF_INET) {
705 			slen = sizeof (sin);
706 			(void) ksocket_getsockname(new_so,
707 			    (struct sockaddr *)&sin, &slen, CRED());
708 			bcopy(&sin.sin_addr,
709 			    &session->local_ipaddr.au_addr.au_ipv4,
710 			    sizeof (in_addr_t));
711 			slen = sizeof (sin);
712 			(void) ksocket_getpeername(new_so,
713 			    (struct sockaddr *)&sin, &slen, CRED());
714 			bcopy(&sin.sin_addr,
715 			    &session->ipaddr.au_addr.au_ipv4,
716 			    sizeof (in_addr_t));
717 		} else {
718 			slen = sizeof (sin6);
719 			(void) ksocket_getsockname(new_so,
720 			    (struct sockaddr *)&sin6, &slen, CRED());
721 			bcopy(&sin6.sin6_addr,
722 			    &session->local_ipaddr.au_addr.au_ipv6,
723 			    sizeof (in6_addr_t));
724 			slen = sizeof (sin6);
725 			(void) ksocket_getpeername(new_so,
726 			    (struct sockaddr *)&sin6, &slen, CRED());
727 			bcopy(&sin6.sin6_addr,
728 			    &session->ipaddr.au_addr.au_ipv6,
729 			    sizeof (in6_addr_t));
730 		}
731 		session->ipaddr.a_family = family;
732 		session->local_ipaddr.a_family = family;
733 		session->s_local_port = port;
734 		session->sock = new_so;
735 		if (port == IPPORT_NETBIOS_SSN)
736 			smb_server_inc_nbt_sess(sv);
737 		else
738 			smb_server_inc_tcp_sess(sv);
739 	}
740 	session->s_server = sv;
741 	smb_server_get_cfg(sv, &session->s_cfg);
742 	session->s_srqueue = &sv->sv_srqueue;
743 
744 	session->s_cache_request = sv->si_cache_request;
745 	session->s_cache = sv->si_cache_session;
746 	session->s_magic = SMB_SESSION_MAGIC;
747 	return (session);
748 }
749 
750 void
751 smb_session_delete(smb_session_t *session)
752 {
753 	mbuf_chain_t	*mbc;
754 
755 	ASSERT(session->s_magic == SMB_SESSION_MAGIC);
756 
757 	session->s_magic = 0;
758 
759 	smb_rwx_destroy(&session->s_lock);
760 	smb_net_txl_destructor(&session->s_txlst);
761 
762 	while ((mbc = list_head(&session->s_oplock_brkreqs)) != NULL) {
763 		SMB_MBC_VALID(mbc);
764 		list_remove(&session->s_oplock_brkreqs, mbc);
765 		smb_mbc_free(mbc);
766 	}
767 	list_destroy(&session->s_oplock_brkreqs);
768 
769 	smb_slist_destructor(&session->s_req_list);
770 	smb_llist_destructor(&session->s_user_list);
771 	smb_llist_destructor(&session->s_xa_list);
772 
773 	ASSERT(session->s_tree_cnt == 0);
774 	ASSERT(session->s_file_cnt == 0);
775 	ASSERT(session->s_dir_cnt == 0);
776 
777 	smb_idpool_destructor(&session->s_uid_pool);
778 	if (session->sock != NULL) {
779 		if (session->s_local_port == IPPORT_NETBIOS_SSN)
780 			smb_server_dec_nbt_sess(session->s_server);
781 		else
782 			smb_server_dec_tcp_sess(session->s_server);
783 		smb_sodestroy(session->sock);
784 	}
785 	kmem_cache_free(session->s_cache, session);
786 }
787 
788 static void
789 smb_session_cancel(smb_session_t *session)
790 {
791 	smb_xa_t	*xa, *nextxa;
792 
793 	/* All the request currently being treated must be canceled. */
794 	smb_session_cancel_requests(session, NULL, NULL);
795 
796 	/*
797 	 * We wait for the completion of all the requests associated with
798 	 * this session.
799 	 */
800 	smb_slist_wait_for_empty(&session->s_req_list);
801 
802 	/*
803 	 * At this point the reference count of the users, trees, files,
804 	 * directories should be zero. It should be possible to destroy them
805 	 * without any problem.
806 	 */
807 	xa = smb_llist_head(&session->s_xa_list);
808 	while (xa) {
809 		nextxa = smb_llist_next(&session->s_xa_list, xa);
810 		smb_xa_close(xa);
811 		xa = nextxa;
812 	}
813 
814 	smb_session_logoff(session);
815 }
816 
817 /*
818  * Cancel requests.  If a non-null tree is specified, only requests specific
819  * to that tree will be cancelled.  If a non-null sr is specified, that sr
820  * will be not be cancelled - this would typically be the caller's sr.
821  */
822 void
823 smb_session_cancel_requests(
824     smb_session_t	*session,
825     smb_tree_t		*tree,
826     smb_request_t	*exclude_sr)
827 {
828 	smb_request_t	*sr;
829 
830 	smb_process_session_notify_change_queue(session, tree);
831 
832 	smb_slist_enter(&session->s_req_list);
833 	sr = smb_slist_head(&session->s_req_list);
834 
835 	while (sr) {
836 		ASSERT(sr->sr_magic == SMB_REQ_MAGIC);
837 		if ((sr != exclude_sr) &&
838 		    (tree == NULL || sr->tid_tree == tree))
839 			smb_request_cancel(sr);
840 
841 		sr = smb_slist_next(&session->s_req_list, sr);
842 	}
843 
844 	smb_slist_exit(&session->s_req_list);
845 }
846 
847 void
848 smb_session_worker(void	*arg)
849 {
850 	smb_request_t	*sr;
851 	smb_srqueue_t	*srq;
852 
853 	sr = (smb_request_t *)arg;
854 	SMB_REQ_VALID(sr);
855 
856 	srq = sr->session->s_srqueue;
857 	smb_srqueue_waitq_to_runq(srq);
858 	sr->sr_worker = curthread;
859 	mutex_enter(&sr->sr_mutex);
860 	sr->sr_time_active = gethrtime();
861 	switch (sr->sr_state) {
862 	case SMB_REQ_STATE_SUBMITTED:
863 		mutex_exit(&sr->sr_mutex);
864 		if (smb_dispatch_request(sr)) {
865 			mutex_enter(&sr->sr_mutex);
866 			sr->sr_state = SMB_REQ_STATE_COMPLETED;
867 			mutex_exit(&sr->sr_mutex);
868 			smb_request_free(sr);
869 		}
870 		break;
871 
872 	default:
873 		ASSERT(sr->sr_state == SMB_REQ_STATE_CANCELED);
874 		sr->sr_state = SMB_REQ_STATE_COMPLETED;
875 		mutex_exit(&sr->sr_mutex);
876 		smb_request_free(sr);
877 		break;
878 	}
879 	smb_srqueue_runq_exit(srq);
880 }
881 
882 /*
883  * smb_session_lookup_user
884  */
885 static smb_user_t *
886 smb_session_lookup_user(smb_session_t *session, char *domain, char *name)
887 {
888 	smb_user_t	*user;
889 	smb_llist_t	*ulist;
890 
891 	ulist = &session->s_user_list;
892 	smb_llist_enter(ulist, RW_READER);
893 	user = smb_llist_head(ulist);
894 	while (user) {
895 		ASSERT(user->u_magic == SMB_USER_MAGIC);
896 		if (!smb_strcasecmp(user->u_name, name, 0) &&
897 		    !smb_strcasecmp(user->u_domain, domain, 0)) {
898 			if (smb_user_hold(user))
899 				break;
900 		}
901 		user = smb_llist_next(ulist, user);
902 	}
903 	smb_llist_exit(ulist);
904 
905 	return (user);
906 }
907 
908 /*
909  * If a user attempts to log in subsequently from the specified session,
910  * duplicates the existing SMB user instance such that all SMB user
911  * instances that corresponds to the same user on the given session
912  * reference the same user's cred.
913  *
914  * Returns NULL if the given user hasn't yet logged in from this
915  * specified session.  Otherwise, returns a user instance that corresponds
916  * to this subsequent login.
917  */
918 smb_user_t *
919 smb_session_dup_user(smb_session_t *session, char *domain, char *account_name)
920 {
921 	smb_user_t *orig_user = NULL;
922 	smb_user_t *user = NULL;
923 
924 	orig_user = smb_session_lookup_user(session, domain,
925 	    account_name);
926 
927 	if (orig_user) {
928 		user = smb_user_dup(orig_user);
929 		smb_user_release(orig_user);
930 	}
931 
932 	return (user);
933 }
934 
935 /*
936  * Find a user on the specified session by SMB UID.
937  */
938 smb_user_t *
939 smb_session_lookup_uid(smb_session_t *session, uint16_t uid)
940 {
941 	smb_user_t	*user;
942 	smb_llist_t	*user_list;
943 
944 	SMB_SESSION_VALID(session);
945 
946 	user_list = &session->s_user_list;
947 	smb_llist_enter(user_list, RW_READER);
948 
949 	user = smb_llist_head(user_list);
950 	while (user) {
951 		SMB_USER_VALID(user);
952 		ASSERT(user->u_session == session);
953 
954 		if (user->u_uid == uid) {
955 			if (!smb_user_hold(user))
956 				break;
957 
958 			smb_llist_exit(user_list);
959 			return (user);
960 		}
961 
962 		user = smb_llist_next(user_list, user);
963 	}
964 
965 	smb_llist_exit(user_list);
966 	return (NULL);
967 }
968 
969 void
970 smb_session_post_user(smb_session_t *session, smb_user_t *user)
971 {
972 	SMB_USER_VALID(user);
973 	ASSERT(user->u_refcnt == 0);
974 	ASSERT(user->u_state == SMB_USER_STATE_LOGGED_OFF);
975 	ASSERT(user->u_session == session);
976 
977 	smb_llist_post(&session->s_user_list, user, smb_user_delete);
978 }
979 
980 /*
981  * Logoff all users associated with the specified session.
982  */
983 static void
984 smb_session_logoff(smb_session_t *session)
985 {
986 	smb_user_t	*user;
987 
988 	SMB_SESSION_VALID(session);
989 
990 	smb_llist_enter(&session->s_user_list, RW_READER);
991 
992 	user = smb_llist_head(&session->s_user_list);
993 	while (user) {
994 		SMB_USER_VALID(user);
995 		ASSERT(user->u_session == session);
996 
997 		if (smb_user_hold(user)) {
998 			smb_user_logoff(user);
999 			smb_user_release(user);
1000 		}
1001 
1002 		user = smb_llist_next(&session->s_user_list, user);
1003 	}
1004 
1005 	smb_llist_exit(&session->s_user_list);
1006 }
1007 
1008 /*
1009  * Disconnect any trees associated with the specified share.
1010  * Iterate through the users on this session and tell each user
1011  * to disconnect from the share.
1012  */
1013 void
1014 smb_session_disconnect_share(smb_session_t *session, const char *sharename)
1015 {
1016 	smb_user_t	*user;
1017 
1018 	SMB_SESSION_VALID(session);
1019 
1020 	smb_llist_enter(&session->s_user_list, RW_READER);
1021 
1022 	user = smb_llist_head(&session->s_user_list);
1023 	while (user) {
1024 		SMB_USER_VALID(user);
1025 		ASSERT(user->u_session == session);
1026 
1027 		if (smb_user_hold(user)) {
1028 			smb_user_disconnect_share(user, sharename);
1029 			smb_user_release(user);
1030 		}
1031 
1032 		user = smb_llist_next(&session->s_user_list, user);
1033 	}
1034 
1035 	smb_llist_exit(&session->s_user_list);
1036 }
1037 
1038 /*
1039  * Copy the session workstation/client name to buf.  If the workstation
1040  * is an empty string (which it will be on TCP connections), use the
1041  * client IP address.
1042  */
1043 void
1044 smb_session_getclient(smb_session_t *sn, char *buf, size_t buflen)
1045 {
1046 	char		ipbuf[INET6_ADDRSTRLEN];
1047 	smb_inaddr_t	*ipaddr;
1048 
1049 	ASSERT(sn);
1050 	ASSERT(buf);
1051 	ASSERT(buflen);
1052 
1053 	*buf = '\0';
1054 
1055 	if (sn->workstation[0] != '\0') {
1056 		(void) strlcpy(buf, sn->workstation, buflen);
1057 		return;
1058 	}
1059 
1060 	ipaddr = &sn->ipaddr;
1061 	if (smb_inet_ntop(ipaddr, ipbuf, SMB_IPSTRLEN(ipaddr->a_family)))
1062 		(void) strlcpy(buf, ipbuf, buflen);
1063 }
1064 
1065 /*
1066  * Check whether or not the specified client name is the client of this
1067  * session.  The name may be in UNC format (\\CLIENT).
1068  *
1069  * A workstation/client name is setup on NBT connections as part of the
1070  * NetBIOS session request but that isn't available on TCP connections.
1071  * If the session doesn't have a client name we typically return the
1072  * client IP address as the workstation name on MSRPC requests.  So we
1073  * check for the IP address here in addition to the workstation name.
1074  */
1075 boolean_t
1076 smb_session_isclient(smb_session_t *sn, const char *client)
1077 {
1078 	char		buf[INET6_ADDRSTRLEN];
1079 	smb_inaddr_t	*ipaddr;
1080 
1081 	client += strspn(client, "\\");
1082 
1083 	if (smb_strcasecmp(client, sn->workstation, 0) == 0)
1084 		return (B_TRUE);
1085 
1086 	ipaddr = &sn->ipaddr;
1087 	if (smb_inet_ntop(ipaddr, buf, SMB_IPSTRLEN(ipaddr->a_family)) == NULL)
1088 		return (B_FALSE);
1089 
1090 	if (smb_strcasecmp(client, buf, 0) == 0)
1091 		return (B_TRUE);
1092 
1093 	return (B_FALSE);
1094 }
1095 
1096 /*
1097  * smb_request_alloc
1098  *
1099  * Allocate an smb_request_t structure from the kmem_cache.  Partially
1100  * initialize the found/new request.
1101  *
1102  * Returns pointer to a request
1103  */
1104 smb_request_t *
1105 smb_request_alloc(smb_session_t *session, int req_length)
1106 {
1107 	smb_request_t	*sr;
1108 
1109 	ASSERT(session->s_magic == SMB_SESSION_MAGIC);
1110 
1111 	sr = kmem_cache_alloc(session->s_cache_request, KM_SLEEP);
1112 
1113 	/*
1114 	 * Future:  Use constructor to pre-initialize some fields.  For now
1115 	 * there are so many fields that it is easiest just to zero the
1116 	 * whole thing and start over.
1117 	 */
1118 	bzero(sr, sizeof (smb_request_t));
1119 
1120 	mutex_init(&sr->sr_mutex, NULL, MUTEX_DEFAULT, NULL);
1121 	smb_srm_init(sr);
1122 	sr->session = session;
1123 	sr->sr_server = session->s_server;
1124 	sr->sr_gmtoff = session->s_server->si_gmtoff;
1125 	sr->sr_cache = session->s_server->si_cache_request;
1126 	sr->sr_cfg = &session->s_cfg;
1127 	sr->command.max_bytes = req_length;
1128 	sr->reply.max_bytes = smb_maxbufsize;
1129 	sr->sr_req_length = req_length;
1130 	if (req_length)
1131 		sr->sr_request_buf = kmem_alloc(req_length, KM_SLEEP);
1132 	sr->sr_magic = SMB_REQ_MAGIC;
1133 	sr->sr_state = SMB_REQ_STATE_INITIALIZING;
1134 	smb_slist_insert_tail(&session->s_req_list, sr);
1135 	return (sr);
1136 }
1137 
1138 /*
1139  * smb_request_free
1140  *
1141  * release the memories which have been allocated for a smb request.
1142  */
1143 void
1144 smb_request_free(smb_request_t *sr)
1145 {
1146 	ASSERT(sr->sr_magic == SMB_REQ_MAGIC);
1147 	ASSERT(sr->session);
1148 	ASSERT(sr->r_xa == NULL);
1149 
1150 	if (sr->fid_ofile != NULL) {
1151 		smb_ofile_request_complete(sr->fid_ofile);
1152 		smb_ofile_release(sr->fid_ofile);
1153 	}
1154 
1155 	if (sr->tid_tree != NULL)
1156 		smb_tree_release(sr->tid_tree);
1157 
1158 	if (sr->uid_user != NULL)
1159 		smb_user_release(sr->uid_user);
1160 
1161 	smb_slist_remove(&sr->session->s_req_list, sr);
1162 
1163 	sr->session = NULL;
1164 
1165 	smb_srm_fini(sr);
1166 
1167 	if (sr->sr_request_buf)
1168 		kmem_free(sr->sr_request_buf, sr->sr_req_length);
1169 	if (sr->command.chain)
1170 		m_freem(sr->command.chain);
1171 	if (sr->reply.chain)
1172 		m_freem(sr->reply.chain);
1173 	if (sr->raw_data.chain)
1174 		m_freem(sr->raw_data.chain);
1175 
1176 	sr->sr_magic = 0;
1177 	mutex_destroy(&sr->sr_mutex);
1178 	kmem_cache_free(sr->sr_cache, sr);
1179 }
1180 
1181 void
1182 dump_smb_inaddr(smb_inaddr_t *ipaddr)
1183 {
1184 	char ipstr[INET6_ADDRSTRLEN];
1185 
1186 	if (smb_inet_ntop(ipaddr, ipstr, SMB_IPSTRLEN(ipaddr->a_family)))
1187 		cmn_err(CE_WARN, "error ipstr=%s", ipstr);
1188 	else
1189 		cmn_err(CE_WARN, "error converting ip address");
1190 }
1191 
1192 boolean_t
1193 smb_session_oplocks_enable(smb_session_t *session)
1194 {
1195 	SMB_SESSION_VALID(session);
1196 	if (session->s_cfg.skc_oplock_enable == 0)
1197 		return (B_FALSE);
1198 	else
1199 		return (B_TRUE);
1200 }
1201 
1202 boolean_t
1203 smb_session_levelII_oplocks(smb_session_t *session)
1204 {
1205 	SMB_SESSION_VALID(session);
1206 	return (session->capabilities & CAP_LEVEL_II_OPLOCKS);
1207 }
1208 
1209 /*
1210  * smb_session_oplock_break
1211  *
1212  * The session lock must NOT be held by the caller of this thread;
1213  * as this would cause a deadlock.
1214  */
1215 void
1216 smb_session_oplock_break(smb_session_t *session,
1217     uint16_t tid, uint16_t fid, uint8_t brk)
1218 {
1219 	mbuf_chain_t	*mbc;
1220 
1221 	SMB_SESSION_VALID(session);
1222 
1223 	mbc = smb_mbc_alloc(MLEN);
1224 
1225 	(void) smb_mbc_encodef(mbc, "Mb19.wwwwbb3.wbb10.",
1226 	    SMB_COM_LOCKING_ANDX,
1227 	    tid,
1228 	    0xFFFF, 0, 0xFFFF, 8, 0xFF,
1229 	    fid,
1230 	    LOCKING_ANDX_OPLOCK_RELEASE,
1231 	    (brk == SMB_OPLOCK_BREAK_TO_LEVEL_II) ? 1 : 0);
1232 
1233 	smb_rwx_rwenter(&session->s_lock, RW_WRITER);
1234 	switch (session->s_state) {
1235 	case SMB_SESSION_STATE_NEGOTIATED:
1236 	case SMB_SESSION_STATE_OPLOCK_BREAKING:
1237 	case SMB_SESSION_STATE_WRITE_RAW_ACTIVE:
1238 		session->s_state = SMB_SESSION_STATE_OPLOCK_BREAKING;
1239 		(void) smb_session_send(session, 0, mbc);
1240 		smb_mbc_free(mbc);
1241 		break;
1242 
1243 	case SMB_SESSION_STATE_READ_RAW_ACTIVE:
1244 		list_insert_tail(&session->s_oplock_brkreqs, mbc);
1245 		break;
1246 
1247 	case SMB_SESSION_STATE_DISCONNECTED:
1248 	case SMB_SESSION_STATE_TERMINATED:
1249 		smb_mbc_free(mbc);
1250 		break;
1251 
1252 	default:
1253 		SMB_PANIC();
1254 	}
1255 	smb_rwx_rwexit(&session->s_lock);
1256 }
1257