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 2015 Nexenta Systems, Inc. All rights reserved.
24 */
25
26 /*
27 * Notes on the virtual circuit (VC) values in the SMB Negotiate
28 * response and SessionSetupAndx request.
29 *
30 * A virtual circuit (VC) represents a connection between a client and a
31 * server using a reliable, session oriented transport protocol, such as
32 * NetBIOS or TCP/IP. Originally, each SMB session was restricted to a
33 * single underlying transport connection, i.e. a single NetBIOS session,
34 * which limited performance for raw data transfers.
35 *
36 * The intention behind multiple VCs was to improve performance by
37 * allowing parallelism over each NetBIOS session. For example, raw data
38 * could be transmitted using a different VC from other types of SMB
39 * requests to remove the interleaving restriction while a raw transfer
40 * is in progress. So the MaxNumberVcs field was added to the negotiate
41 * response to make the number of VCs configurable and to allow servers
42 * to specify how many they were prepared to support per session
43 * connection. This turned out to be difficult to manage and, with
263 CAP_NT_FIND |
264 CAP_DFS |
265 CAP_INFOLEVEL_PASSTHRU |
266 CAP_LARGE_READX |
267 CAP_LARGE_WRITEX |
268 CAP_EXTENDED_SECURITY;
269
270 /*
271 * SMB Negotiate gets special handling. This is called directly by
272 * the reader thread (see smbsr_newrq_initial) with what _should_ be
273 * an SMB1 Negotiate. Only the "\ffSMB" header has been checked
274 * when this is called, so this needs to check the SMB command,
275 * if it's Negotiate execute it, then send the reply, etc.
276 *
277 * Since this is called directly from the reader thread, we
278 * know this is the only thread currently using this session.
279 * This has to duplicate some of what smb1sr_work does as a
280 * result of bypassing the normal dispatch mechanism.
281 *
282 * The caller always frees this request.
283 */
284 int
285 smb1_newrq_negotiate(smb_request_t *sr)
286 {
287 smb_sdrc_t sdrc;
288 uint16_t pid_hi, pid_lo;
289
290 /*
291 * Decode the header
292 */
293 if (smb_mbc_decodef(&sr->command, SMB_HEADER_ED_FMT,
294 &sr->smb_com,
295 &sr->smb_rcls,
296 &sr->smb_reh,
297 &sr->smb_err,
298 &sr->smb_flg,
299 &sr->smb_flg2,
300 &pid_hi,
301 sr->smb_sig,
302 &sr->smb_tid,
359 negprot->ni_index = -1;
360 sr->sr_negprot = negprot;
361
362 for (pos = 0; smbsr_decode_data_avail(sr); pos++) {
363 if (smbsr_decode_data(sr, "%L", sr, &negprot->ni_name) != 0) {
364 smbsr_error(sr, 0, ERRSRV, ERRerror);
365 rc = -1;
366 break;
367 }
368
369 if ((dialect = smb_xlate_dialect(negprot->ni_name)) < 0)
370 continue;
371
372 /*
373 * Conditionally recognize the SMB2 dialects.
374 */
375 if (dialect >= DIALECT_SMB2002 &&
376 skc->skc_max_protocol < SMB_VERS_2_BASE)
377 continue;
378
379 if (negprot->ni_dialect < dialect) {
380 negprot->ni_dialect = dialect;
381 negprot->ni_index = pos;
382 }
383 }
384
385 DTRACE_SMB_2(op__Negotiate__start, smb_request_t *, sr,
386 smb_arg_negotiate_t, negprot);
387
388 return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
389 }
390
391 void
392 smb_post_negotiate(smb_request_t *sr)
393 {
394 smb_arg_negotiate_t *negprot = sr->sr_negprot;
395
396 DTRACE_SMB_2(op__Negotiate__done, smb_request_t *, sr,
397 smb_arg_negotiate_t, negprot);
398
399 bzero(negprot, sizeof (smb_arg_negotiate_t));
400 }
401
402 smb_sdrc_t
403 smb_com_negotiate(smb_request_t *sr)
404 {
405 smb_session_t *session = sr->session;
406 smb_arg_negotiate_t *negprot = sr->sr_negprot;
407 uint16_t secmode;
408 uint32_t sesskey;
409 char *nbdomain;
410 uint8_t *wcbuf;
411 int wclen;
412 smb_msgbuf_t mb;
413 int rc;
414
415 if (session->s_state != SMB_SESSION_STATE_ESTABLISHED) {
416 /* The protocol has already been negotiated. */
417 smbsr_error(sr, 0, ERRSRV, ERRerror);
418 return (SDRC_ERROR);
419 }
420
421 /*
422 * Special case for negotiating SMB2 from SMB1. The client
423 * includes the "SMB 2..." dialects in the SMB1 negotiate,
424 * and if SMB2 is enabled, we choose one of those and then
425 * send an SMB2 reply to that SMB1 request. Yes, it's very
426 * strange, but this SMB1 request can have an SMB2 reply!
427 * To accomplish this, we let the SMB2 code send the reply
428 * and return the special code SDRC_NO_REPLY to the SMB1
429 * dispatch logic so it will NOT send an SMB1 reply.
430 * (Or possibly send an SMB1 error reply.)
431 */
432 if (negprot->ni_dialect >= DIALECT_SMB2002) {
433 rc = smb1_negotiate_smb2(sr);
434 ASSERT(rc == SDRC_NO_REPLY ||
435 rc == SDRC_DROP_VC || rc == SDRC_ERROR);
436 return (rc);
437 }
438
439 session->secmode = NEGOTIATE_ENCRYPT_PASSWORDS |
440 NEGOTIATE_USER_SECURITY;
441 secmode = session->secmode;
442 sesskey = session->sesskey;
443
444 negprot->ni_servertime.tv_sec = gethrestime_sec();
445 negprot->ni_servertime.tv_nsec = 0;
446 negprot->ni_tzcorrection = sr->sr_gmtoff / 60;
447 negprot->ni_maxmpxcount = smb_maxmpxcount;
448 negprot->ni_keylen = SMB_CHALLENGE_SZ;
449 bcopy(&session->challenge_key, negprot->ni_key, SMB_CHALLENGE_SZ);
450 nbdomain = sr->sr_cfg->skc_nbdomain;
451
452 negprot->ni_capabilities = smb1srv_capabilities;
453
454 switch (negprot->ni_dialect) {
455 case PC_NETWORK_PROGRAM_1_0: /* core */
456 (void) ksocket_setsockopt(session->sock, SOL_SOCKET,
457 SO_RCVBUF, (const void *)&smb_dos_tcp_rcvbuf,
458 sizeof (smb_dos_tcp_rcvbuf), CRED());
459 rc = smbsr_encode_result(sr, 1, 0, "bww", 1,
460 negprot->ni_index, 0);
461 break;
514 (int)negprot->ni_keylen,
515 negprot->ni_key, /* encryption key */
516 nbdomain);
517 break;
518
519 case NT_LM_0_12:
520 (void) ksocket_setsockopt(session->sock, SOL_SOCKET,
521 SO_RCVBUF, (const void *)&smb_nt_tcp_rcvbuf,
522 sizeof (smb_nt_tcp_rcvbuf), CRED());
523
524 /*
525 * Allow SMB signatures if using encrypted passwords
526 */
527 if ((secmode & NEGOTIATE_ENCRYPT_PASSWORDS) &&
528 sr->sr_cfg->skc_signing_enable) {
529 secmode |= NEGOTIATE_SECURITY_SIGNATURES_ENABLED;
530 if (sr->sr_cfg->skc_signing_required)
531 secmode |=
532 NEGOTIATE_SECURITY_SIGNATURES_REQUIRED;
533
534 session->secmode = secmode;
535 }
536
537 /*
538 * Does the client want Extended Security?
539 * (and if we have it enabled)
540 * If so, handle as if a different dialect.
541 */
542 if ((sr->smb_flg2 & SMB_FLAGS2_EXT_SEC) != 0 &&
543 (negprot->ni_capabilities & CAP_EXTENDED_SECURITY) != 0)
544 goto NT_LM_0_12_ext_sec;
545
546 /* Else deny knowledge of extended security. */
547 sr->smb_flg2 &= ~SMB_FLAGS2_EXT_SEC;
548 negprot->ni_capabilities &= ~CAP_EXTENDED_SECURITY;
549
550 /*
551 * nbdomain is not expected to be aligned.
552 * Use temporary buffer to avoid alignment padding
553 */
554 wclen = smb_wcequiv_strlen(nbdomain) + sizeof (smb_wchar_t);
|
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 2017 Nexenta Systems, Inc. All rights reserved.
24 */
25
26 /*
27 * Notes on the virtual circuit (VC) values in the SMB Negotiate
28 * response and SessionSetupAndx request.
29 *
30 * A virtual circuit (VC) represents a connection between a client and a
31 * server using a reliable, session oriented transport protocol, such as
32 * NetBIOS or TCP/IP. Originally, each SMB session was restricted to a
33 * single underlying transport connection, i.e. a single NetBIOS session,
34 * which limited performance for raw data transfers.
35 *
36 * The intention behind multiple VCs was to improve performance by
37 * allowing parallelism over each NetBIOS session. For example, raw data
38 * could be transmitted using a different VC from other types of SMB
39 * requests to remove the interleaving restriction while a raw transfer
40 * is in progress. So the MaxNumberVcs field was added to the negotiate
41 * response to make the number of VCs configurable and to allow servers
42 * to specify how many they were prepared to support per session
43 * connection. This turned out to be difficult to manage and, with
263 CAP_NT_FIND |
264 CAP_DFS |
265 CAP_INFOLEVEL_PASSTHRU |
266 CAP_LARGE_READX |
267 CAP_LARGE_WRITEX |
268 CAP_EXTENDED_SECURITY;
269
270 /*
271 * SMB Negotiate gets special handling. This is called directly by
272 * the reader thread (see smbsr_newrq_initial) with what _should_ be
273 * an SMB1 Negotiate. Only the "\ffSMB" header has been checked
274 * when this is called, so this needs to check the SMB command,
275 * if it's Negotiate execute it, then send the reply, etc.
276 *
277 * Since this is called directly from the reader thread, we
278 * know this is the only thread currently using this session.
279 * This has to duplicate some of what smb1sr_work does as a
280 * result of bypassing the normal dispatch mechanism.
281 *
282 * The caller always frees this request.
283 *
284 * Return value is 0 for success, and anything else will
285 * terminate the reader thread (drop the connection).
286 */
287 int
288 smb1_newrq_negotiate(smb_request_t *sr)
289 {
290 smb_sdrc_t sdrc;
291 uint16_t pid_hi, pid_lo;
292
293 /*
294 * Decode the header
295 */
296 if (smb_mbc_decodef(&sr->command, SMB_HEADER_ED_FMT,
297 &sr->smb_com,
298 &sr->smb_rcls,
299 &sr->smb_reh,
300 &sr->smb_err,
301 &sr->smb_flg,
302 &sr->smb_flg2,
303 &pid_hi,
304 sr->smb_sig,
305 &sr->smb_tid,
362 negprot->ni_index = -1;
363 sr->sr_negprot = negprot;
364
365 for (pos = 0; smbsr_decode_data_avail(sr); pos++) {
366 if (smbsr_decode_data(sr, "%L", sr, &negprot->ni_name) != 0) {
367 smbsr_error(sr, 0, ERRSRV, ERRerror);
368 rc = -1;
369 break;
370 }
371
372 if ((dialect = smb_xlate_dialect(negprot->ni_name)) < 0)
373 continue;
374
375 /*
376 * Conditionally recognize the SMB2 dialects.
377 */
378 if (dialect >= DIALECT_SMB2002 &&
379 skc->skc_max_protocol < SMB_VERS_2_BASE)
380 continue;
381
382 /*
383 * We may not support SMB1; skip those dialects if true.
384 */
385 if (dialect < DIALECT_SMB2002 &&
386 skc->skc_min_protocol > SMB_VERS_1)
387 continue;
388
389 if (dialect == DIALECT_SMB2002 &&
390 skc->skc_min_protocol > SMB_VERS_2_002)
391 continue;
392
393 if (negprot->ni_dialect < dialect) {
394 negprot->ni_dialect = dialect;
395 negprot->ni_index = pos;
396 }
397 }
398
399 DTRACE_SMB_START(op__Negotiate, smb_request_t *, sr);
400
401 return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
402 }
403
404 void
405 smb_post_negotiate(smb_request_t *sr)
406 {
407 smb_arg_negotiate_t *negprot = sr->sr_negprot;
408
409 DTRACE_SMB_DONE(op__Negotiate, smb_request_t *, sr);
410
411 bzero(negprot, sizeof (smb_arg_negotiate_t));
412 }
413
414 smb_sdrc_t
415 smb_com_negotiate(smb_request_t *sr)
416 {
417 smb_session_t *session = sr->session;
418 smb_arg_negotiate_t *negprot = sr->sr_negprot;
419 uint16_t secmode;
420 uint32_t sesskey;
421 char *nbdomain;
422 uint8_t *wcbuf;
423 int wclen;
424 smb_msgbuf_t mb;
425 int rc;
426
427 if (session->s_state != SMB_SESSION_STATE_ESTABLISHED) {
428 /* The protocol has already been negotiated. */
429 smbsr_error(sr, 0, ERRSRV, ERRerror);
430 return (SDRC_ERROR);
431 }
432
433 if (negprot->ni_index < 0) {
434 cmn_err(CE_NOTE, "clnt %s no supported dialect",
435 sr->session->ip_addr_str);
436 smbsr_error(sr, 0, ERRSRV, ERRerror);
437 return (SDRC_DROP_VC);
438 }
439
440 /*
441 * Special case for negotiating SMB2 from SMB1. The client
442 * includes the "SMB 2..." dialects in the SMB1 negotiate,
443 * and if SMB2 is enabled, we choose one of those and then
444 * send an SMB2 reply to that SMB1 request. Yes, it's very
445 * strange, but this SMB1 request can have an SMB2 reply!
446 * To accomplish this, we let the SMB2 code send the reply
447 * and return the special code SDRC_NO_REPLY to the SMB1
448 * dispatch logic so it will NOT send an SMB1 reply.
449 * (Or possibly send an SMB1 error reply.)
450 */
451 if (negprot->ni_dialect >= DIALECT_SMB2002) {
452 rc = smb1_negotiate_smb2(sr);
453 ASSERT(rc == SDRC_NO_REPLY ||
454 rc == SDRC_DROP_VC || rc == SDRC_ERROR);
455 return (rc);
456 }
457
458 session->srv_secmode = NEGOTIATE_ENCRYPT_PASSWORDS |
459 NEGOTIATE_USER_SECURITY;
460 secmode = session->srv_secmode;
461 sesskey = session->sesskey;
462
463 negprot->ni_servertime.tv_sec = gethrestime_sec();
464 negprot->ni_servertime.tv_nsec = 0;
465 negprot->ni_tzcorrection = sr->sr_gmtoff / 60;
466 negprot->ni_maxmpxcount = smb_maxmpxcount;
467 negprot->ni_keylen = SMB_CHALLENGE_SZ;
468 bcopy(&session->challenge_key, negprot->ni_key, SMB_CHALLENGE_SZ);
469 nbdomain = sr->sr_cfg->skc_nbdomain;
470
471 negprot->ni_capabilities = smb1srv_capabilities;
472
473 switch (negprot->ni_dialect) {
474 case PC_NETWORK_PROGRAM_1_0: /* core */
475 (void) ksocket_setsockopt(session->sock, SOL_SOCKET,
476 SO_RCVBUF, (const void *)&smb_dos_tcp_rcvbuf,
477 sizeof (smb_dos_tcp_rcvbuf), CRED());
478 rc = smbsr_encode_result(sr, 1, 0, "bww", 1,
479 negprot->ni_index, 0);
480 break;
533 (int)negprot->ni_keylen,
534 negprot->ni_key, /* encryption key */
535 nbdomain);
536 break;
537
538 case NT_LM_0_12:
539 (void) ksocket_setsockopt(session->sock, SOL_SOCKET,
540 SO_RCVBUF, (const void *)&smb_nt_tcp_rcvbuf,
541 sizeof (smb_nt_tcp_rcvbuf), CRED());
542
543 /*
544 * Allow SMB signatures if using encrypted passwords
545 */
546 if ((secmode & NEGOTIATE_ENCRYPT_PASSWORDS) &&
547 sr->sr_cfg->skc_signing_enable) {
548 secmode |= NEGOTIATE_SECURITY_SIGNATURES_ENABLED;
549 if (sr->sr_cfg->skc_signing_required)
550 secmode |=
551 NEGOTIATE_SECURITY_SIGNATURES_REQUIRED;
552
553 session->srv_secmode = secmode;
554 }
555
556 /*
557 * Does the client want Extended Security?
558 * (and if we have it enabled)
559 * If so, handle as if a different dialect.
560 */
561 if ((sr->smb_flg2 & SMB_FLAGS2_EXT_SEC) != 0 &&
562 (negprot->ni_capabilities & CAP_EXTENDED_SECURITY) != 0)
563 goto NT_LM_0_12_ext_sec;
564
565 /* Else deny knowledge of extended security. */
566 sr->smb_flg2 &= ~SMB_FLAGS2_EXT_SEC;
567 negprot->ni_capabilities &= ~CAP_EXTENDED_SECURITY;
568
569 /*
570 * nbdomain is not expected to be aligned.
571 * Use temporary buffer to avoid alignment padding
572 */
573 wclen = smb_wcequiv_strlen(nbdomain) + sizeof (smb_wchar_t);
|