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