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