xref: /onnv-gate/usr/src/uts/common/fs/smbsrv/smb_negotiate.c (revision 10966:37e5dcdf36d3)
15331Samw /*
25331Samw  * CDDL HEADER START
35331Samw  *
45331Samw  * The contents of this file are subject to the terms of the
55331Samw  * Common Development and Distribution License (the "License").
65331Samw  * You may not use this file except in compliance with the License.
75331Samw  *
85331Samw  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
95331Samw  * or http://www.opensolaris.org/os/licensing.
105331Samw  * See the License for the specific language governing permissions
115331Samw  * and limitations under the License.
125331Samw  *
135331Samw  * When distributing Covered Code, include this CDDL HEADER in each
145331Samw  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
155331Samw  * If applicable, add the following below this CDDL HEADER, with the
165331Samw  * fields enclosed by brackets "[]" replaced with your own identifying
175331Samw  * information: Portions Copyright [yyyy] [name of copyright owner]
185331Samw  *
195331Samw  * CDDL HEADER END
205331Samw  */
215331Samw /*
228670SJose.Borrego@Sun.COM  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
235331Samw  * Use is subject to license terms.
245331Samw  */
255331Samw 
265331Samw /*
275331Samw  * Notes on the virtual circuit (VC) values in the SMB Negotiate
285331Samw  * response and SessionSetupAndx request.
295331Samw  *
305331Samw  * A virtual circuit (VC) represents a connection between a client and a
315331Samw  * server using a reliable, session oriented transport protocol, such as
325331Samw  * NetBIOS or TCP/IP. Originally, each SMB session was restricted to a
335331Samw  * single underlying transport connection, i.e. a single NetBIOS session,
345331Samw  * which limited performance for raw data transfers.
355331Samw  *
365331Samw  * The intention behind multiple VCs was to improve performance by
375331Samw  * allowing parallelism over each NetBIOS session. For example, raw data
385331Samw  * could be transmitted using a different VC from other types of SMB
395331Samw  * requests to remove the interleaving restriction while a raw transfer
405331Samw  * is in progress. So the MaxNumberVcs field was added to the negotiate
415331Samw  * response to make the number of VCs configurable and to allow servers
425331Samw  * to specify how many they were prepared to support per session
435331Samw  * connection. This turned out to be difficult to manage and, with
445331Samw  * technology improvements, it has become obsolete.
455331Samw  *
465331Samw  * Servers should set the MaxNumberVcs value in the Negotiate response
475331Samw  * to 1. Clients should probably ignore it. If a server receives a
485331Samw  * SessionSetupAndx with a VC value of 0, it should close all other
495331Samw  * VCs to that client. If it receives a non-zero VC, it should leave
505331Samw  * other VCs in tact.
515331Samw  *
525331Samw  */
535331Samw 
545331Samw /*
555331Samw  * SMB: negotiate
565331Samw  *
575331Samw  * Client Request                Description
585331Samw  * ============================  =======================================
595331Samw  *
605331Samw  * UCHAR WordCount;              Count of parameter words = 0
615331Samw  * USHORT ByteCount;             Count of data bytes; min = 2
625331Samw  * struct {
635331Samw  *    UCHAR BufferFormat;        0x02 -- Dialect
645331Samw  *    UCHAR DialectName[];       ASCII null-terminated string
655331Samw  * } Dialects[];
665331Samw  *
675331Samw  * The Client sends a list of dialects that it can communicate with.  The
685331Samw  * response is a selection of one of those dialects (numbered 0 through n)
695331Samw  * or -1 (hex FFFF) indicating that none of the dialects were acceptable.
705331Samw  * The negotiate message is binding on the virtual circuit and must be
715331Samw  * sent.  One and only one negotiate message may be sent, subsequent
725331Samw  * negotiate requests will be rejected with an error response and no action
735331Samw  * will be taken.
745331Samw  *
755331Samw  * The protocol does not impose any particular structure to the dialect
765331Samw  * strings.  Implementors of particular protocols may choose to include,
775331Samw  * for example, version numbers in the string.
785331Samw  *
795331Samw  * If the server does not understand any of the dialect strings, or if PC
805331Samw  * NETWORK PROGRAM 1.0 is the chosen dialect, the response format is
815331Samw  *
825331Samw  * Server Response               Description
835331Samw  * ============================  =======================================
845331Samw  *
855331Samw  * UCHAR WordCount;              Count of parameter words = 1
865331Samw  * USHORT DialectIndex;          Index of selected dialect
875331Samw  * USHORT ByteCount;             Count of data bytes = 0
885331Samw  *
895331Samw  * If the chosen dialect is greater than core up to and including
905331Samw  * LANMAN2.1, the protocol response format is
915331Samw  *
925331Samw  * Server Response               Description
935331Samw  * ============================  =======================================
945331Samw  *
955331Samw  * UCHAR WordCount;              Count of parameter words = 13
965331Samw  * USHORT  DialectIndex;         Index of selected dialect
975331Samw  * USHORT  SecurityMode;         Security mode:
985331Samw  *                               bit 0: 0 = share, 1 = user
995331Samw  *                               bit 1: 1 = use challenge/response
1005331Samw  *                               authentication
1015331Samw  * USHORT  MaxBufferSize;        Max transmit buffer size (>= 1024)
1025331Samw  * USHORT  MaxMpxCount;          Max pending multiplexed requests
1035331Samw  * USHORT  MaxNumberVcs;         Max VCs between client and server
1045331Samw  * USHORT  RawMode;              Raw modes supported:
1055331Samw  *                                bit 0: 1 = Read Raw supported
1065331Samw  *                                bit 1: 1 = Write Raw supported
1075331Samw  * ULONG SessionKey;             Unique token identifying this session
1085331Samw  * SMB_TIME ServerTime;          Current time at server
1095331Samw  * SMB_DATE ServerDate;          Current date at server
1105331Samw  * USHORT ServerTimeZone;        Current time zone at server
1115331Samw  * USHORT  EncryptionKeyLength;  MBZ if this is not LM2.1
1125331Samw  * USHORT  Reserved;             MBZ
1135331Samw  * USHORT  ByteCount             Count of data bytes
1145331Samw  * UCHAR EncryptionKey[];        The challenge encryption key
1155331Samw  * STRING PrimaryDomain[];       The server's primary domain
1165331Samw  *
1175331Samw  * MaxBufferSize is the size of the largest message which the client can
1185331Samw  * legitimately send to the server
1195331Samw  *
1205331Samw  * If  bit0 of the Flags field is set in the negotiate response, this
1215331Samw  * indicates the server supports the SMB_COM_LOCK_AND_READ and
1225331Samw  * SMB_COM_WRITE_AND_UNLOCK client requests.
1235331Samw  *
1245331Samw  * If the SecurityMode field indicates the server is running in user mode,
1255331Samw  * the client must send appropriate SMB_COM_SESSION_SETUP_ANDX requests
1265331Samw  * before the server will allow the client to access resources.   If the
1275331Samw  * SecurityMode fields indicates the client should use challenge/response
1285331Samw  * authentication, the client should use the authentication mechanism
1295331Samw  * specified in section 2.10.
1305331Samw  *
1315331Samw  * Clients should submit no more than MaxMpxCount distinct unanswered SMBs
1325331Samw  * to the server when using multiplexed reads or writes (see sections 5.13
1335331Samw  * and 5.25)
1345331Samw  *
1355331Samw  * Clients using the  "MICROSOFT NETWORKS 1.03" dialect use a different
1365331Samw  * form of raw reads than documented here, and servers are better off
1375331Samw  * setting RawMode in this response to 0 for such sessions.
1385331Samw  *
1395331Samw  * If the negotiated dialect is "DOS LANMAN2.1" or "LANMAN2.1", then
1405331Samw  * PrimaryDomain string should be included in this response.
1415331Samw  *
1425331Samw  * If the negotiated dialect is NT LM 0.12, the response format is
1435331Samw  *
1445331Samw  * Server Response            Description
1455331Samw  * ========================== =========================================
1465331Samw  *
1475331Samw  * UCHAR WordCount;           Count of parameter words = 17
1485331Samw  * USHORT DialectIndex;       Index of selected dialect
1495331Samw  * UCHAR SecurityMode;        Security mode:
1505331Samw  *                             bit 0: 0 = share, 1 = user
1515331Samw  *                             bit 1: 1 = encrypt passwords
1525331Samw  * USHORT MaxMpxCount;        Max pending multiplexed requests
1535331Samw  * USHORT MaxNumberVcs;       Max VCs between client and server
1545331Samw  * ULONG MaxBufferSize;       Max transmit buffer size
1555331Samw  * ULONG MaxRawSize;          Maximum raw buffer size
1565331Samw  * ULONG SessionKey;          Unique token identifying this session
1575331Samw  * ULONG Capabilities;        Server capabilities
1585331Samw  * ULONG SystemTimeLow;       System (UTC) time of the server (low).
1595331Samw  * ULONG SystemTimeHigh;      System (UTC) time of the server (high).
1605331Samw  * USHORT ServerTimeZone;     Time zone of server (min from UTC)
1615331Samw  * UCHAR EncryptionKeyLength; Length of encryption key.
1625331Samw  * USHORT ByteCount;          Count of data bytes
1635331Samw  * UCHAR EncryptionKey[];     The challenge encryption key
1645331Samw  * UCHAR OemDomainName[];     The name of the domain (in OEM chars)
1655331Samw  *
1665331Samw  * In addition to the definitions above, MaxBufferSize is the size of the
1675331Samw  * largest message which the client can legitimately send to the server.
1685331Samw  * If the client is using a connectionless protocol,  MaxBufferSize must be
1695331Samw  * set to the smaller of the server's internal buffer size and the amount
1705331Samw  * of data which can be placed in a response packet.
1715331Samw  *
1725331Samw  * MaxRawSize specifies the maximum message size the server can send or
1735331Samw  * receive for SMB_COM_WRITE_RAW or SMB_COM_READ_RAW.
1745331Samw  *
1755331Samw  * Connectionless clients must set Sid to 0 in the SMB request header.
1765331Samw  *
1775331Samw  * Capabilities allows the server to tell the client what it supports.
178*10966SJordan.Brown@Sun.COM  * The bit definitions defined in smb.h. Bit 0x2000 used to be set in
1795331Samw  * the negotiate response capabilities but it caused problems with
1805331Samw  * Windows 2000. It is probably not valid, it doesn't appear in the
1815331Samw  * CIFS spec.
1825331Samw  *
1835331Samw  * 4.1.1.1   Errors
1845331Samw  *
1855331Samw  * SUCCESS/SUCCESS
1865331Samw  * ERRSRV/ERRerror
1875331Samw  */
1885331Samw #include <sys/types.h>
1895331Samw #include <sys/strsubr.h>
1905331Samw #include <sys/socketvar.h>
1915331Samw #include <sys/socket.h>
1925331Samw #include <sys/random.h>
1935331Samw #include <netinet/in.h>
194*10966SJordan.Brown@Sun.COM #include <smbsrv/smb_kproto.h>
1955331Samw #include <smbsrv/smbinfo.h>
1965331Samw 
1975331Samw /*
1985331Samw  * Maximum buffer size for DOS: chosen to be the same as NT.
1995331Samw  * Do not change this value, DOS is very sensitive to it.
2005331Samw  */
2015331Samw #define	SMB_DOS_MAXBUF			0x1104
2025331Samw 
2035331Samw /*
2045331Samw  * The DOS TCP rcvbuf is set to 8700 because DOS 6.1 seems to have problems
2055331Samw  * with other values. DOS 6.1 seems to depend on a window value of 8700 to
2065331Samw  * send the next set of data. If we return a window value of 40KB, after
2075331Samw  * sending 8700 bytes of data, it will start the next set of data from 40KB
2085331Samw  * instead of 8.7k. Why 8.7k? We have no idea; it is the value that NT uses.
2095331Samw  * September 2000.
2105331Samw  *
2115331Samw  * IR104720 Increased smb_nt_tcp_rcvbuf from 40KB to just under 1MB to allow
2125331Samw  * for a larger TCP window sizei based on observations of Windows 2000 and
2135331Samw  * performance testing. March 2003.
2145331Samw  */
2156139Sjb150015 static uint32_t	smb_dos_tcp_rcvbuf = 8700;
2166139Sjb150015 static uint32_t	smb_nt_tcp_rcvbuf = 1048560;	/* scale factor of 4 */
2175331Samw 
2186139Sjb150015 static void smb_get_security_info(smb_request_t *, unsigned short *,
2196139Sjb150015     unsigned char *, unsigned char *, uint32_t *);
2205331Samw 
2215331Samw /*
2225331Samw  * Function: int smb_com_negotiate(struct smb_request *)
2235331Samw  */
2246139Sjb150015 smb_sdrc_t
2256139Sjb150015 smb_pre_negotiate(smb_request_t *sr)
2266139Sjb150015 {
2276139Sjb150015 	DTRACE_SMB_1(op__Negotiate__start, smb_request_t *, sr);
2289343SAfshin.Ardakani@Sun.COM 	smb_rwx_rwenter(&sr->session->s_lock, RW_WRITER);
2296139Sjb150015 	return (SDRC_SUCCESS);
2306139Sjb150015 }
2316139Sjb150015 
2326139Sjb150015 void
2336139Sjb150015 smb_post_negotiate(smb_request_t *sr)
2346139Sjb150015 {
2356139Sjb150015 	DTRACE_SMB_1(op__Negotiate__done, smb_request_t *, sr);
2369343SAfshin.Ardakani@Sun.COM 	smb_rwx_rwexit(&sr->session->s_lock);
2376139Sjb150015 }
2385331Samw 
2396030Sjb150015 smb_sdrc_t
2406139Sjb150015 smb_com_negotiate(smb_request_t *sr)
2415331Samw {
2425331Samw 	int			dialect = 0;
2435331Samw 	int			this_dialect;
2445331Samw 	unsigned char		keylen;
2455331Samw 	int			sel_pos = -1;
2465331Samw 	int			pos;
2475331Samw 	char 			key[32];
2485331Samw 	char			*p;
2495331Samw 	timestruc_t		time_val;
2505331Samw 	unsigned short		secmode;
2515331Samw 	uint32_t		sesskey;
2525331Samw 	uint32_t		capabilities = 0;
2536030Sjb150015 	int			rc;
2546139Sjb150015 	unsigned short		max_mpx_count;
2557348SJose.Borrego@Sun.COM 	int16_t			tz_correction;
2568670SJose.Borrego@Sun.COM 	char			ipaddr_buf[INET6_ADDRSTRLEN];
2577961SNatalie.Li@Sun.COM 	char			*tmpbuf;
2587961SNatalie.Li@Sun.COM 	int			buflen;
2597961SNatalie.Li@Sun.COM 	smb_msgbuf_t		mb;
2605331Samw 
2615331Samw 	if (sr->session->s_state != SMB_SESSION_STATE_ESTABLISHED) {
2625331Samw 		/* The protocol has already been negotiated. */
2635772Sas200622 		smbsr_error(sr, 0, ERRSRV, ERRerror);
2646139Sjb150015 		return (SDRC_ERROR);
2655331Samw 	}
2665331Samw 
2675331Samw 	for (pos = 0;
2685331Samw 	    sr->smb_data.chain_offset < sr->smb_data.max_bytes;
2695331Samw 	    pos++) {
2707052Samw 		if (smb_mbc_decodef(&sr->smb_data, "%L", sr, &p) != 0) {
2715772Sas200622 			smbsr_error(sr, 0, ERRSRV, ERRerror);
2726139Sjb150015 			return (SDRC_ERROR);
2735331Samw 		}
2745331Samw 
2755331Samw 		this_dialect = smb_xlate_dialect_str_to_cd(p);
2765331Samw 
2775331Samw 		if (this_dialect < 0)
2785331Samw 			continue;
2795331Samw 
2805331Samw 		if (dialect < this_dialect) {
2815331Samw 			dialect = this_dialect;
2825331Samw 			sel_pos = pos;
2835331Samw 		}
2845331Samw 	}
2855331Samw 
2865331Samw 	smb_get_security_info(sr, &secmode, (unsigned char *)key,
2875331Samw 	    &keylen, &sesskey);
2885331Samw 
2895331Samw 	(void) microtime(&time_val);
2907348SJose.Borrego@Sun.COM 	tz_correction = sr->sr_gmtoff / 60;
2915331Samw 
2925331Samw 	switch (dialect) {
2935331Samw 	case PC_NETWORK_PROGRAM_1_0:	/* core */
2948348SEric.Yu@Sun.COM 		(void) ksocket_setsockopt(sr->session->sock, SOL_SOCKET,
2958348SEric.Yu@Sun.COM 		    SO_RCVBUF, (const void *)&smb_dos_tcp_rcvbuf,
2968348SEric.Yu@Sun.COM 		    sizeof (smb_dos_tcp_rcvbuf), CRED());
2976030Sjb150015 		rc = smbsr_encode_result(sr, 1, 0, "bww", 1, sel_pos, 0);
2985331Samw 		break;
2995331Samw 
3005331Samw 	case Windows_for_Workgroups_3_1a:
3015331Samw 	case PCLAN1_0:
3025331Samw 	case MICROSOFT_NETWORKS_1_03:
3035331Samw 	case MICROSOFT_NETWORKS_3_0:
3045331Samw 	case LANMAN1_0:
3055331Samw 	case LM1_2X002:
3065331Samw 	case DOS_LM1_2X002:
3078348SEric.Yu@Sun.COM 		(void) ksocket_setsockopt(sr->session->sock, SOL_SOCKET,
3088348SEric.Yu@Sun.COM 		    SO_RCVBUF, (const void *)&smb_dos_tcp_rcvbuf,
3098348SEric.Yu@Sun.COM 		    sizeof (smb_dos_tcp_rcvbuf), CRED());
3105331Samw 		sr->smb_flg |= SMB_FLAGS_LOCK_AND_READ_OK;
3116030Sjb150015 		rc = smbsr_encode_result(sr, 13, VAR_BCC,
3127052Samw 		    "bwwwwwwlYww2.w#c",
3135331Samw 		    13,		/* wct */
3145331Samw 		    sel_pos,	/* dialect index */
3155331Samw 		    secmode,		/* security mode */
3165331Samw 		    SMB_DOS_MAXBUF,	/* max buffer size */
3175331Samw 		    1,		/* max MPX (temporary) */
3185331Samw 		    1,		/* max VCs (temporary, ambiguous) */
3195331Samw 		    3,		/* raw mode (s/b 3) */
3205331Samw 		    sesskey,	/* session key */
3215331Samw 		    time_val.tv_sec, /* server time/date */
3227348SJose.Borrego@Sun.COM 		    tz_correction,
3235331Samw 		    (short)keylen,	/* Encryption Key Length */
3245331Samw 				/* reserved field handled 2. */
3255331Samw 		    VAR_BCC,
3265331Samw 		    (int)keylen,
3275331Samw 		    key);		/* encryption key */
3285331Samw 		break;
3295331Samw 
3305331Samw 	case DOS_LANMAN2_1:
3315331Samw 	case LANMAN2_1:
3328348SEric.Yu@Sun.COM 		(void) ksocket_setsockopt(sr->session->sock, SOL_SOCKET,
3338348SEric.Yu@Sun.COM 		    SO_RCVBUF, (const void *)&smb_dos_tcp_rcvbuf,
3348348SEric.Yu@Sun.COM 		    sizeof (smb_dos_tcp_rcvbuf), CRED());
3355331Samw 		sr->smb_flg |= SMB_FLAGS_LOCK_AND_READ_OK;
3366030Sjb150015 		rc = smbsr_encode_result(sr, 13, VAR_BCC,
3377052Samw 		    "bwwwwwwlYww2.w#cs",
3385331Samw 		    13,		/* wct */
3395331Samw 		    sel_pos,	/* dialect index */
3405331Samw 		    secmode,		/* security mode */
3415331Samw 		    SMB_DOS_MAXBUF,	/* max buffer size */
3425331Samw 		    1,		/* max MPX (temporary) */
3435331Samw 		    1,		/* max VCs (temporary, ambiguous) */
3445331Samw 		    3,		/* raw mode (s/b 3) */
3455331Samw 		    sesskey,	/* session key */
3465331Samw 		    time_val.tv_sec, /* server time/date */
3475331Samw 		    tz_correction,
3485331Samw 		    (short)keylen,	/* Encryption Key Length */
3495331Samw 				/* reserved field handled 2. */
3505331Samw 		    VAR_BCC,
3515331Samw 		    (int)keylen,
3525331Samw 		    key,		/* encryption key */
3537961SNatalie.Li@Sun.COM 		    sr->sr_cfg->skc_nbdomain);
3545331Samw 		break;
3555331Samw 
3565331Samw 	case NT_LM_0_12:
3578348SEric.Yu@Sun.COM 		(void) ksocket_setsockopt(sr->session->sock, SOL_SOCKET,
3588348SEric.Yu@Sun.COM 		    SO_RCVBUF, (const void *)&smb_nt_tcp_rcvbuf,
3598348SEric.Yu@Sun.COM 		    sizeof (smb_nt_tcp_rcvbuf), CRED());
3608934SJose.Borrego@Sun.COM 		/*
3618934SJose.Borrego@Sun.COM 		 * UNICODE support is required for long share names,
3628934SJose.Borrego@Sun.COM 		 * long file names and streams.
3638934SJose.Borrego@Sun.COM 		 */
3645331Samw 		capabilities = CAP_LARGE_FILES
3658934SJose.Borrego@Sun.COM 		    | CAP_UNICODE
3665331Samw 		    | CAP_NT_SMBS
3675331Samw 		    | CAP_STATUS32
3685331Samw 		    | CAP_NT_FIND
3695331Samw 		    | CAP_RAW_MODE
3705331Samw 		    | CAP_LEVEL_II_OPLOCKS
3715331Samw 		    | CAP_LOCK_AND_READ
3725331Samw 		    | CAP_RPC_REMOTE_APIS
3738934SJose.Borrego@Sun.COM 		    | CAP_LARGE_READX
3748934SJose.Borrego@Sun.COM 		    | CAP_LARGE_WRITEX;
3755331Samw 
3765331Samw 		/*
3775331Samw 		 * Turn off Extended Security Negotiation
3785331Samw 		 */
3795331Samw 		sr->smb_flg2 &= ~SMB_FLAGS2_EXT_SEC;
3805331Samw 
3815331Samw 		/*
3825331Samw 		 * Allow SMB signatures if security challenge response enabled
3835331Samw 		 */
3845331Samw 		if ((secmode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) &&
3856139Sjb150015 		    sr->sr_cfg->skc_signing_enable) {
3865331Samw 			secmode |= NEGOTIATE_SECURITY_SIGNATURES_ENABLED;
3876139Sjb150015 			if (sr->sr_cfg->skc_signing_required)
3885331Samw 				secmode |=
3895331Samw 				    NEGOTIATE_SECURITY_SIGNATURES_REQUIRED;
3905331Samw 
3915331Samw 			sr->session->secmode = secmode;
3925331Samw 		}
3938670SJose.Borrego@Sun.COM 		(void) smb_inet_ntop(&sr->session->ipaddr, ipaddr_buf,
3948670SJose.Borrego@Sun.COM 		    SMB_IPSTRLEN(sr->session->ipaddr.a_family));
3956139Sjb150015 
3966139Sjb150015 		max_mpx_count = sr->sr_cfg->skc_maxworkers;
3975331Samw 
3987961SNatalie.Li@Sun.COM 		/*
3997961SNatalie.Li@Sun.COM 		 * skc_nbdomain is not expected to be aligned.
4007961SNatalie.Li@Sun.COM 		 * Use temporary buffer to avoid alignment padding
4017961SNatalie.Li@Sun.COM 		 */
402*10966SJordan.Brown@Sun.COM 		buflen = smb_wcequiv_strlen(sr->sr_cfg->skc_nbdomain) +
403*10966SJordan.Brown@Sun.COM 		    sizeof (smb_wchar_t);
4047961SNatalie.Li@Sun.COM 		tmpbuf = kmem_zalloc(buflen, KM_SLEEP);
4057961SNatalie.Li@Sun.COM 		smb_msgbuf_init(&mb, (uint8_t *)tmpbuf, buflen,
4067961SNatalie.Li@Sun.COM 		    SMB_MSGBUF_UNICODE);
4077961SNatalie.Li@Sun.COM 		if (smb_msgbuf_encode(&mb, "U",
4087961SNatalie.Li@Sun.COM 		    sr->sr_cfg->skc_nbdomain) < 0) {
4097961SNatalie.Li@Sun.COM 			smb_msgbuf_term(&mb);
4107961SNatalie.Li@Sun.COM 			kmem_free(tmpbuf, buflen);
4117961SNatalie.Li@Sun.COM 			smbsr_error(sr, 0, ERRSRV, ERRerror);
4127961SNatalie.Li@Sun.COM 			return (SDRC_ERROR);
4137961SNatalie.Li@Sun.COM 		}
4147961SNatalie.Li@Sun.COM 
4156030Sjb150015 		rc = smbsr_encode_result(sr, 17, VAR_BCC,
4167961SNatalie.Li@Sun.COM 		    "bwbwwllllTwbw#c#c",
4175331Samw 		    17,		/* wct */
4185331Samw 		    sel_pos,	/* dialect index */
4195331Samw 		    secmode,	/* security mode */
4205331Samw 		    max_mpx_count,		/* max MPX (temporary) */
4215331Samw 		    1,		/* max VCs (temporary, ambiguous) */
4225331Samw 		    (DWORD)smb_maxbufsize,	/* max buffer size */
4235331Samw 		    0xFFFF,	/* max raw size */
4245331Samw 		    sesskey,	/* session key */
4255331Samw 		    capabilities,
4267961SNatalie.Li@Sun.COM 		    &time_val,	/* system time */
4275331Samw 		    tz_correction,
4287961SNatalie.Li@Sun.COM 		    keylen,	/* Encryption Key Length */
4295331Samw 		    VAR_BCC,
4305331Samw 		    (int)keylen,
4317961SNatalie.Li@Sun.COM 		    key,	/* encryption key */
4327961SNatalie.Li@Sun.COM 		    buflen,
4337961SNatalie.Li@Sun.COM 		    tmpbuf);	/* skc_nbdomain */
4347961SNatalie.Li@Sun.COM 
4357961SNatalie.Li@Sun.COM 		smb_msgbuf_term(&mb);
4367961SNatalie.Li@Sun.COM 		kmem_free(tmpbuf, buflen);
4375331Samw 		break;
4385331Samw 
4395331Samw 	default:
4407961SNatalie.Li@Sun.COM 		sel_pos = -1;
4417961SNatalie.Li@Sun.COM 		rc = smbsr_encode_result(sr, 1, 0, "bww", 1, sel_pos, 0);
4427961SNatalie.Li@Sun.COM 		return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
4435331Samw 	}
4445331Samw 
4456030Sjb150015 	if (rc != 0)
4466139Sjb150015 		return (SDRC_ERROR);
4476030Sjb150015 
4485331Samw 	/*
4495331Samw 	 * Save the agreed dialect. Note that this value is also
4505331Samw 	 * used to detect and reject attempts to re-negotiate.
4515331Samw 	 */
4525331Samw 	sr->session->dialect = dialect;
4535331Samw 	sr->session->s_state = SMB_SESSION_STATE_NEGOTIATED;
4546139Sjb150015 	return (SDRC_SUCCESS);
4555331Samw }
4565331Samw 
4575331Samw static void
4585331Samw smb_get_security_info(
4595331Samw     struct smb_request *sr,
4605331Samw     unsigned short *secmode,
4615331Samw     unsigned char *key,
4625331Samw     unsigned char *keylen,
4635331Samw     uint32_t *sesskey)
4645331Samw {
4655331Samw 	uchar_t tmp_key[8];
4665331Samw 
4675331Samw 	(void) random_get_pseudo_bytes(tmp_key, 8);
4685331Samw 	bcopy(tmp_key, &sr->session->challenge_key, 8);
4695331Samw 	sr->session->challenge_len = 8;
4705331Samw 	*keylen = 8;
4715331Samw 	bcopy(tmp_key, key, 8);
4725331Samw 
4735331Samw 	sr->session->secmode = NEGOTIATE_SECURITY_CHALLENGE_RESPONSE|
4745331Samw 	    NEGOTIATE_SECURITY_USER_LEVEL;
4755331Samw 
4765331Samw 	(void) random_get_pseudo_bytes(tmp_key, 4);
4775331Samw 	sr->session->sesskey = tmp_key[0] | tmp_key[1] << 8 |
4785331Samw 	    tmp_key[2] << 16 | tmp_key[3] << 24;
4795331Samw 
4805331Samw 	*secmode = sr->session->secmode;
4815331Samw 	*sesskey = sr->session->sesskey;
4825331Samw }
483