da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw/*
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * CDDL HEADER START
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * The contents of this file are subject to the terms of the
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Common Development and Distribution License (the "License").
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * You may not use this file except in compliance with the License.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * or http://www.opensolaris.org/os/licensing.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * See the License for the specific language governing permissions
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * and limitations under the License.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * When distributing Covered Code, include this CDDL HEADER in each
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * If applicable, add the following below this CDDL HEADER, with the
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * fields enclosed by brackets "[]" replaced with your own identifying
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * information: Portions Copyright [yyyy] [name of copyright owner]
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * CDDL HEADER END
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw/*
148c5f43199ca0b43fc8e3b643aab11cd66ea327Alan Wright * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * Copyright 2015 Nexenta Systems, Inc. All rights reserved.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw/*
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Notes on the virtual circuit (VC) values in the SMB Negotiate
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * response and SessionSetupAndx request.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * A virtual circuit (VC) represents a connection between a client and a
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * server using a reliable, session oriented transport protocol, such as
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * NetBIOS or TCP/IP. Originally, each SMB session was restricted to a
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * single underlying transport connection, i.e. a single NetBIOS session,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * which limited performance for raw data transfers.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * The intention behind multiple VCs was to improve performance by
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * allowing parallelism over each NetBIOS session. For example, raw data
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * could be transmitted using a different VC from other types of SMB
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * requests to remove the interleaving restriction while a raw transfer
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * is in progress. So the MaxNumberVcs field was added to the negotiate
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * response to make the number of VCs configurable and to allow servers
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * to specify how many they were prepared to support per session
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * connection. This turned out to be difficult to manage and, with
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * technology improvements, it has become obsolete.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Servers should set the MaxNumberVcs value in the Negotiate response
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * to 1. Clients should probably ignore it. If a server receives a
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * SessionSetupAndx with a VC value of 0, it should close all other
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * VCs to that client. If it receives a non-zero VC, it should leave
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * other VCs in tact.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw/*
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * SMB: negotiate
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Client Request Description
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * ============================ =======================================
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * UCHAR WordCount; Count of parameter words = 0
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * USHORT ByteCount; Count of data bytes; min = 2
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * struct {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * UCHAR BufferFormat; 0x02 -- Dialect
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * UCHAR DialectName[]; ASCII null-terminated string
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * } Dialects[];
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * The Client sends a list of dialects that it can communicate with. The
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * response is a selection of one of those dialects (numbered 0 through n)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * or -1 (hex FFFF) indicating that none of the dialects were acceptable.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * The negotiate message is binding on the virtual circuit and must be
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * sent. One and only one negotiate message may be sent, subsequent
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * negotiate requests will be rejected with an error response and no action
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * will be taken.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * The protocol does not impose any particular structure to the dialect
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * strings. Implementors of particular protocols may choose to include,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * for example, version numbers in the string.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * If the server does not understand any of the dialect strings, or if PC
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * NETWORK PROGRAM 1.0 is the chosen dialect, the response format is
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Server Response Description
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * ============================ =======================================
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * UCHAR WordCount; Count of parameter words = 1
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * USHORT DialectIndex; Index of selected dialect
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * USHORT ByteCount; Count of data bytes = 0
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * If the chosen dialect is greater than core up to and including
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * LANMAN2.1, the protocol response format is
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Server Response Description
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * ============================ =======================================
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * UCHAR WordCount; Count of parameter words = 13
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * USHORT DialectIndex; Index of selected dialect
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * USHORT SecurityMode; Security mode:
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * bit 0: 0 = share, 1 = user
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * bit 1: 1 = use challenge/response
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * authentication
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * USHORT MaxBufferSize; Max transmit buffer size (>= 1024)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * USHORT MaxMpxCount; Max pending multiplexed requests
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * USHORT MaxNumberVcs; Max VCs between client and server
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * USHORT RawMode; Raw modes supported:
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * bit 0: 1 = Read Raw supported
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * bit 1: 1 = Write Raw supported
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * ULONG SessionKey; Unique token identifying this session
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * SMB_TIME ServerTime; Current time at server
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * SMB_DATE ServerDate; Current date at server
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * USHORT ServerTimeZone; Current time zone at server
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * USHORT EncryptionKeyLength; MBZ if this is not LM2.1
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * USHORT Reserved; MBZ
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * USHORT ByteCount Count of data bytes
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * UCHAR EncryptionKey[]; The challenge encryption key
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * STRING PrimaryDomain[]; The server's primary domain
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * MaxBufferSize is the size of the largest message which the client can
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * legitimately send to the server
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * If bit0 of the Flags field is set in the negotiate response, this
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * indicates the server supports the SMB_COM_LOCK_AND_READ and
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * SMB_COM_WRITE_AND_UNLOCK client requests.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * If the SecurityMode field indicates the server is running in user mode,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * the client must send appropriate SMB_COM_SESSION_SETUP_ANDX requests
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * before the server will allow the client to access resources. If the
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * SecurityMode fields indicates the client should use challenge/response
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * authentication, the client should use the authentication mechanism
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * specified in section 2.10.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Clients should submit no more than MaxMpxCount distinct unanswered SMBs
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * to the server when using multiplexed reads or writes (see sections 5.13
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * and 5.25)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Clients using the "MICROSOFT NETWORKS 1.03" dialect use a different
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * form of raw reads than documented here, and servers are better off
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * setting RawMode in this response to 0 for such sessions.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * If the negotiated dialect is "DOS LANMAN2.1" or "LANMAN2.1", then
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * PrimaryDomain string should be included in this response.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * If the negotiated dialect is NT LM 0.12, the response format is
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Server Response Description
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * ========================== =========================================
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * UCHAR WordCount; Count of parameter words = 17
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * USHORT DialectIndex; Index of selected dialect
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * UCHAR SecurityMode; Security mode:
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * bit 0: 0 = share, 1 = user
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * bit 1: 1 = encrypt passwords
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * USHORT MaxMpxCount; Max pending multiplexed requests
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * USHORT MaxNumberVcs; Max VCs between client and server
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * ULONG MaxBufferSize; Max transmit buffer size
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * ULONG MaxRawSize; Maximum raw buffer size
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * ULONG SessionKey; Unique token identifying this session
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * ULONG Capabilities; Server capabilities
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * ULONG SystemTimeLow; System (UTC) time of the server (low).
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * ULONG SystemTimeHigh; System (UTC) time of the server (high).
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * USHORT ServerTimeZone; Time zone of server (min from UTC)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * UCHAR EncryptionKeyLength; Length of encryption key.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * USHORT ByteCount; Count of data bytes
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * UCHAR EncryptionKey[]; The challenge encryption key
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * UCHAR OemDomainName[]; The name of the domain (in OEM chars)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * In addition to the definitions above, MaxBufferSize is the size of the
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * largest message which the client can legitimately send to the server.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * If the client is using a connectionless protocol, MaxBufferSize must be
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * set to the smaller of the server's internal buffer size and the amount
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * of data which can be placed in a response packet.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * MaxRawSize specifies the maximum message size the server can send or
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * receive for SMB_COM_WRITE_RAW or SMB_COM_READ_RAW.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Connectionless clients must set Sid to 0 in the SMB request header.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Capabilities allows the server to tell the client what it supports.
bbf6f00c25b6a2bed23c35eac6d62998ecdb338cJordan Brown * The bit definitions defined in smb.h. Bit 0x2000 used to be set in
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * the negotiate response capabilities but it caused problems with
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Windows 2000. It is probably not valid, it doesn't appear in the
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * CIFS spec.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * 4.1.1.1 Errors
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * SUCCESS/SUCCESS
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * ERRSRV/ERRerror
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw#include <sys/types.h>
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw#include <sys/socket.h>
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw#include <netinet/in.h>
bbf6f00c25b6a2bed23c35eac6d62998ecdb338cJordan Brown#include <smbsrv/smb_kproto.h>
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw#include <smbsrv/smbinfo.h>
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
8622ec4569457733001d4982ef7f5b44427069beGordon Rossstatic const smb_xlate_t smb_dialect[] = {
148c5f43199ca0b43fc8e3b643aab11cd66ea327Alan Wright { DIALECT_UNKNOWN, "DIALECT_UNKNOWN" },
148c5f43199ca0b43fc8e3b643aab11cd66ea327Alan Wright { PC_NETWORK_PROGRAM_1_0, "PC NETWORK PROGRAM 1.0" },
148c5f43199ca0b43fc8e3b643aab11cd66ea327Alan Wright { PCLAN1_0, "PCLAN1.0" },
148c5f43199ca0b43fc8e3b643aab11cd66ea327Alan Wright { MICROSOFT_NETWORKS_1_03, "MICROSOFT NETWORKS 1.03" },
148c5f43199ca0b43fc8e3b643aab11cd66ea327Alan Wright { MICROSOFT_NETWORKS_3_0, "MICROSOFT NETWORKS 3.0" },
148c5f43199ca0b43fc8e3b643aab11cd66ea327Alan Wright { LANMAN1_0, "LANMAN1.0" },
148c5f43199ca0b43fc8e3b643aab11cd66ea327Alan Wright { LM1_2X002, "LM1.2X002" },
148c5f43199ca0b43fc8e3b643aab11cd66ea327Alan Wright { DOS_LM1_2X002, "DOS LM1.2X002" },
148c5f43199ca0b43fc8e3b643aab11cd66ea327Alan Wright { DOS_LANMAN2_1, "DOS LANMAN2.1" },
148c5f43199ca0b43fc8e3b643aab11cd66ea327Alan Wright { LANMAN2_1, "LANMAN2.1" },
148c5f43199ca0b43fc8e3b643aab11cd66ea327Alan Wright { Windows_for_Workgroups_3_1a, "Windows for Workgroups 3.1a" },
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross { NT_LM_0_12, "NT LM 0.12" },
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross { DIALECT_SMB2002, "SMB 2.002" },
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross { DIALECT_SMB2XXX, "SMB 2.???" },
148c5f43199ca0b43fc8e3b643aab11cd66ea327Alan Wright};
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Rossstatic int smb_ndialects = sizeof (smb_dialect) / sizeof (smb_dialect[0]);
148c5f43199ca0b43fc8e3b643aab11cd66ea327Alan Wright
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw/*
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Maximum buffer size for DOS: chosen to be the same as NT.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Do not change this value, DOS is very sensitive to it.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw#define SMB_DOS_MAXBUF 0x1104
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw/*
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * The DOS TCP rcvbuf is set to 8700 because DOS 6.1 seems to have problems
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * with other values. DOS 6.1 seems to depend on a window value of 8700 to
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * send the next set of data. If we return a window value of 40KB, after
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * sending 8700 bytes of data, it will start the next set of data from 40KB
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * instead of 8.7k. Why 8.7k? We have no idea; it is the value that NT uses.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * September 2000.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * IR104720 Increased smb_nt_tcp_rcvbuf from 40KB to just under 1MB to allow
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * for a larger TCP window sizei based on observations of Windows 2000 and
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * performance testing. March 2003.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw */
faa1795a28a5c712eed6d0a3f84d98c368a316c6jbstatic uint32_t smb_dos_tcp_rcvbuf = 8700;
faa1795a28a5c712eed6d0a3f84d98c368a316c6jbstatic uint32_t smb_nt_tcp_rcvbuf = 1048560; /* scale factor of 4 */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross/*
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * Maximum number of simultaneously pending SMB requests allowed on
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * one connection. This is like "credits" in SMB2, but SMB1 uses a
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * fixed limit, having no way to request an increase like SMB2 does.
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * Note: Some older clients only handle the low byte of this value,
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * so this value should be less than 256.
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross */
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Rossstatic uint16_t smb_maxmpxcount = 64;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross
148c5f43199ca0b43fc8e3b643aab11cd66ea327Alan Wrightstatic int smb_xlate_dialect(const char *);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
12b65585e720714b31036daaa2b30eb76014048eGordon Ross/*
12b65585e720714b31036daaa2b30eb76014048eGordon Ross * "Capabilities" offered by SMB1 Negotiate Protocol.
12b65585e720714b31036daaa2b30eb76014048eGordon Ross * See smb.h for descriptions.
12b65585e720714b31036daaa2b30eb76014048eGordon Ross *
12b65585e720714b31036daaa2b30eb76014048eGordon Ross * CAP_RAW_MODE, CAP_MPX_MODE are obsolete.
12b65585e720714b31036daaa2b30eb76014048eGordon Ross * UNICODE support is required for long share names,
12b65585e720714b31036daaa2b30eb76014048eGordon Ross * long file names and streams.
12b65585e720714b31036daaa2b30eb76014048eGordon Ross *
12b65585e720714b31036daaa2b30eb76014048eGordon Ross * For testing, one can patch this, i.e. remove the high bit to
12b65585e720714b31036daaa2b30eb76014048eGordon Ross * temporarily disable extended security, etc.
12b65585e720714b31036daaa2b30eb76014048eGordon Ross */
12b65585e720714b31036daaa2b30eb76014048eGordon Rossuint32_t smb1srv_capabilities =
12b65585e720714b31036daaa2b30eb76014048eGordon Ross CAP_UNICODE |
12b65585e720714b31036daaa2b30eb76014048eGordon Ross CAP_LARGE_FILES |
12b65585e720714b31036daaa2b30eb76014048eGordon Ross CAP_NT_SMBS |
12b65585e720714b31036daaa2b30eb76014048eGordon Ross CAP_RPC_REMOTE_APIS |
12b65585e720714b31036daaa2b30eb76014048eGordon Ross CAP_STATUS32 |
12b65585e720714b31036daaa2b30eb76014048eGordon Ross CAP_LEVEL_II_OPLOCKS |
12b65585e720714b31036daaa2b30eb76014048eGordon Ross CAP_LOCK_AND_READ |
12b65585e720714b31036daaa2b30eb76014048eGordon Ross CAP_NT_FIND |
12b65585e720714b31036daaa2b30eb76014048eGordon Ross CAP_DFS |
12b65585e720714b31036daaa2b30eb76014048eGordon Ross CAP_INFOLEVEL_PASSTHRU |
12b65585e720714b31036daaa2b30eb76014048eGordon Ross CAP_LARGE_READX |
12b65585e720714b31036daaa2b30eb76014048eGordon Ross CAP_LARGE_WRITEX |
12b65585e720714b31036daaa2b30eb76014048eGordon Ross CAP_EXTENDED_SECURITY;
9fb67ea305c66b6a297583b9b0db6796b0dfe497afshin salek ardakani - Sun Microsystems - Irvine United States
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross/*
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * SMB Negotiate gets special handling. This is called directly by
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * the reader thread (see smbsr_newrq_initial) with what _should_ be
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * an SMB1 Negotiate. Only the "\ffSMB" header has been checked
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * when this is called, so this needs to check the SMB command,
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * if it's Negotiate execute it, then send the reply, etc.
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross *
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * Since this is called directly from the reader thread, we
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * know this is the only thread currently using this session.
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * This has to duplicate some of what smb1sr_work does as a
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * result of bypassing the normal dispatch mechanism.
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross *
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * The caller always frees this request.
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross */
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Rossint
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Rosssmb1_newrq_negotiate(smb_request_t *sr)
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross{
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross smb_sdrc_t sdrc;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross uint16_t pid_hi, pid_lo;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross /*
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * Decode the header
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross */
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross if (smb_mbc_decodef(&sr->command, SMB_HEADER_ED_FMT,
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross &sr->smb_com,
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross &sr->smb_rcls,
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross &sr->smb_reh,
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross &sr->smb_err,
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross &sr->smb_flg,
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross &sr->smb_flg2,
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross &pid_hi,
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross sr->smb_sig,
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross &sr->smb_tid,
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross &pid_lo,
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross &sr->smb_uid,
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross &sr->smb_mid) != 0)
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross return (-1);
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross if (sr->smb_com != SMB_COM_NEGOTIATE)
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross return (-1);
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross sr->smb_pid = (pid_hi << 16) | pid_lo;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross /*
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * Reserve space for the reply header.
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross */
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross (void) smb_mbc_encodef(&sr->reply, "#.", SMB_HEADER_LEN);
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross sr->first_smb_com = sr->smb_com;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross if (smb_mbc_decodef(&sr->command, "b", &sr->smb_wct) != 0)
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross return (-1);
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross (void) MBC_SHADOW_CHAIN(&sr->smb_vwv, &sr->command,
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross sr->command.chain_offset, sr->smb_wct * 2);
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross if (smb_mbc_decodef(&sr->command, "#.w", sr->smb_wct*2, &sr->smb_bcc))
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross return (-1);
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross (void) MBC_SHADOW_CHAIN(&sr->smb_data, &sr->command,
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross sr->command.chain_offset, sr->smb_bcc);
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross sr->command.chain_offset += sr->smb_bcc;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross if (sr->command.chain_offset > sr->command.max_bytes)
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross return (-1);
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross /* Store pointers for later */
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross sr->cur_reply_offset = sr->reply.chain_offset;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross sdrc = smb_pre_negotiate(sr);
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross if (sdrc == SDRC_SUCCESS)
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross sdrc = smb_com_negotiate(sr);
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross smb_post_negotiate(sr);
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross if (sdrc != SDRC_NO_REPLY)
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross smbsr_send_reply(sr);
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross if (sdrc == SDRC_DROP_VC)
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross return (-1);
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross return (0);
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross}
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross
faa1795a28a5c712eed6d0a3f84d98c368a316c6jbsmb_sdrc_t
faa1795a28a5c712eed6d0a3f84d98c368a316c6jbsmb_pre_negotiate(smb_request_t *sr)
faa1795a28a5c712eed6d0a3f84d98c368a316c6jb{
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross smb_kmod_cfg_t *skc;
148c5f43199ca0b43fc8e3b643aab11cd66ea327Alan Wright smb_arg_negotiate_t *negprot;
148c5f43199ca0b43fc8e3b643aab11cd66ea327Alan Wright int dialect;
148c5f43199ca0b43fc8e3b643aab11cd66ea327Alan Wright int pos;
148c5f43199ca0b43fc8e3b643aab11cd66ea327Alan Wright int rc = 0;
148c5f43199ca0b43fc8e3b643aab11cd66ea327Alan Wright
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross skc = &sr->session->s_cfg;
148c5f43199ca0b43fc8e3b643aab11cd66ea327Alan Wright negprot = smb_srm_zalloc(sr, sizeof (smb_arg_negotiate_t));
148c5f43199ca0b43fc8e3b643aab11cd66ea327Alan Wright negprot->ni_index = -1;
148c5f43199ca0b43fc8e3b643aab11cd66ea327Alan Wright sr->sr_negprot = negprot;
148c5f43199ca0b43fc8e3b643aab11cd66ea327Alan Wright
148c5f43199ca0b43fc8e3b643aab11cd66ea327Alan Wright for (pos = 0; smbsr_decode_data_avail(sr); pos++) {
148c5f43199ca0b43fc8e3b643aab11cd66ea327Alan Wright if (smbsr_decode_data(sr, "%L", sr, &negprot->ni_name) != 0) {
148c5f43199ca0b43fc8e3b643aab11cd66ea327Alan Wright smbsr_error(sr, 0, ERRSRV, ERRerror);
148c5f43199ca0b43fc8e3b643aab11cd66ea327Alan Wright rc = -1;
148c5f43199ca0b43fc8e3b643aab11cd66ea327Alan Wright break;
148c5f43199ca0b43fc8e3b643aab11cd66ea327Alan Wright }
148c5f43199ca0b43fc8e3b643aab11cd66ea327Alan Wright
148c5f43199ca0b43fc8e3b643aab11cd66ea327Alan Wright if ((dialect = smb_xlate_dialect(negprot->ni_name)) < 0)
148c5f43199ca0b43fc8e3b643aab11cd66ea327Alan Wright continue;
148c5f43199ca0b43fc8e3b643aab11cd66ea327Alan Wright
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross /*
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * Conditionally recognize the SMB2 dialects.
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross */
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross if (dialect >= DIALECT_SMB2002 &&
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross skc->skc_max_protocol < SMB_VERS_2_BASE)
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross continue;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross
148c5f43199ca0b43fc8e3b643aab11cd66ea327Alan Wright if (negprot->ni_dialect < dialect) {
148c5f43199ca0b43fc8e3b643aab11cd66ea327Alan Wright negprot->ni_dialect = dialect;
148c5f43199ca0b43fc8e3b643aab11cd66ea327Alan Wright negprot->ni_index = pos;
148c5f43199ca0b43fc8e3b643aab11cd66ea327Alan Wright }
148c5f43199ca0b43fc8e3b643aab11cd66ea327Alan Wright }
148c5f43199ca0b43fc8e3b643aab11cd66ea327Alan Wright
148c5f43199ca0b43fc8e3b643aab11cd66ea327Alan Wright DTRACE_SMB_2(op__Negotiate__start, smb_request_t *, sr,
148c5f43199ca0b43fc8e3b643aab11cd66ea327Alan Wright smb_arg_negotiate_t, negprot);
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross
148c5f43199ca0b43fc8e3b643aab11cd66ea327Alan Wright return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
faa1795a28a5c712eed6d0a3f84d98c368a316c6jb}
faa1795a28a5c712eed6d0a3f84d98c368a316c6jb
faa1795a28a5c712eed6d0a3f84d98c368a316c6jbvoid
faa1795a28a5c712eed6d0a3f84d98c368a316c6jbsmb_post_negotiate(smb_request_t *sr)
faa1795a28a5c712eed6d0a3f84d98c368a316c6jb{
148c5f43199ca0b43fc8e3b643aab11cd66ea327Alan Wright smb_arg_negotiate_t *negprot = sr->sr_negprot;
148c5f43199ca0b43fc8e3b643aab11cd66ea327Alan Wright
148c5f43199ca0b43fc8e3b643aab11cd66ea327Alan Wright DTRACE_SMB_2(op__Negotiate__done, smb_request_t *, sr,
148c5f43199ca0b43fc8e3b643aab11cd66ea327Alan Wright smb_arg_negotiate_t, negprot);
148c5f43199ca0b43fc8e3b643aab11cd66ea327Alan Wright
148c5f43199ca0b43fc8e3b643aab11cd66ea327Alan Wright bzero(negprot, sizeof (smb_arg_negotiate_t));
faa1795a28a5c712eed6d0a3f84d98c368a316c6jb}
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
7b59d02d2a384be9a08087b14defadd214b3c1ddjbsmb_sdrc_t
faa1795a28a5c712eed6d0a3f84d98c368a316c6jbsmb_com_negotiate(smb_request_t *sr)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw{
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross smb_session_t *session = sr->session;
148c5f43199ca0b43fc8e3b643aab11cd66ea327Alan Wright smb_arg_negotiate_t *negprot = sr->sr_negprot;
148c5f43199ca0b43fc8e3b643aab11cd66ea327Alan Wright uint16_t secmode;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw uint32_t sesskey;
148c5f43199ca0b43fc8e3b643aab11cd66ea327Alan Wright char *nbdomain;
148c5f43199ca0b43fc8e3b643aab11cd66ea327Alan Wright uint8_t *wcbuf;
148c5f43199ca0b43fc8e3b643aab11cd66ea327Alan Wright int wclen;
b89a8333f5e1f75ec0c269b22524bd2eccb972banatalie li - Sun Microsystems - Irvine United States smb_msgbuf_t mb;
148c5f43199ca0b43fc8e3b643aab11cd66ea327Alan Wright int rc;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross if (session->s_state != SMB_SESSION_STATE_ESTABLISHED) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /* The protocol has already been negotiated. */
dc20a3024900c47dd2ee44b9707e6df38f7d62a5as smbsr_error(sr, 0, ERRSRV, ERRerror);
faa1795a28a5c712eed6d0a3f84d98c368a316c6jb return (SDRC_ERROR);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross /*
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * Special case for negotiating SMB2 from SMB1. The client
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * includes the "SMB 2..." dialects in the SMB1 negotiate,
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * and if SMB2 is enabled, we choose one of those and then
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * send an SMB2 reply to that SMB1 request. Yes, it's very
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * strange, but this SMB1 request can have an SMB2 reply!
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * To accomplish this, we let the SMB2 code send the reply
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * and return the special code SDRC_NO_REPLY to the SMB1
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * dispatch logic so it will NOT send an SMB1 reply.
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * (Or possibly send an SMB1 error reply.)
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross */
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross if (negprot->ni_dialect >= DIALECT_SMB2002) {
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross rc = smb1_negotiate_smb2(sr);
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross ASSERT(rc == SDRC_NO_REPLY ||
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross rc == SDRC_DROP_VC || rc == SDRC_ERROR);
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross return (rc);
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross }
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross session->secmode = NEGOTIATE_ENCRYPT_PASSWORDS |
12b65585e720714b31036daaa2b30eb76014048eGordon Ross NEGOTIATE_USER_SECURITY;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross secmode = session->secmode;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross sesskey = session->sesskey;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross negprot->ni_servertime.tv_sec = gethrestime_sec();
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross negprot->ni_servertime.tv_nsec = 0;
148c5f43199ca0b43fc8e3b643aab11cd66ea327Alan Wright negprot->ni_tzcorrection = sr->sr_gmtoff / 60;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross negprot->ni_maxmpxcount = smb_maxmpxcount;
f9bc6dadd79442185db5c8eb201c7475554fc7d7Dmitry.Savitsky@nexenta.com negprot->ni_keylen = SMB_CHALLENGE_SZ;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross bcopy(&session->challenge_key, negprot->ni_key, SMB_CHALLENGE_SZ);
148c5f43199ca0b43fc8e3b643aab11cd66ea327Alan Wright nbdomain = sr->sr_cfg->skc_nbdomain;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
12b65585e720714b31036daaa2b30eb76014048eGordon Ross negprot->ni_capabilities = smb1srv_capabilities;
148c5f43199ca0b43fc8e3b643aab11cd66ea327Alan Wright
148c5f43199ca0b43fc8e3b643aab11cd66ea327Alan Wright switch (negprot->ni_dialect) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw case PC_NETWORK_PROGRAM_1_0: /* core */
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross (void) ksocket_setsockopt(session->sock, SOL_SOCKET,
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning SO_RCVBUF, (const void *)&smb_dos_tcp_rcvbuf,
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning sizeof (smb_dos_tcp_rcvbuf), CRED());
148c5f43199ca0b43fc8e3b643aab11cd66ea327Alan Wright rc = smbsr_encode_result(sr, 1, 0, "bww", 1,
148c5f43199ca0b43fc8e3b643aab11cd66ea327Alan Wright negprot->ni_index, 0);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw break;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw case Windows_for_Workgroups_3_1a:
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw case PCLAN1_0:
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw case MICROSOFT_NETWORKS_1_03:
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw case MICROSOFT_NETWORKS_3_0:
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw case LANMAN1_0:
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw case LM1_2X002:
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw case DOS_LM1_2X002:
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross (void) ksocket_setsockopt(session->sock, SOL_SOCKET,
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning SO_RCVBUF, (const void *)&smb_dos_tcp_rcvbuf,
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning sizeof (smb_dos_tcp_rcvbuf), CRED());
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw sr->smb_flg |= SMB_FLAGS_LOCK_AND_READ_OK;
7b59d02d2a384be9a08087b14defadd214b3c1ddjb rc = smbsr_encode_result(sr, 13, VAR_BCC,
3db3f65c6274eb042354801a308c8e9bc4994553amw "bwwwwwwlYww2.w#c",
148c5f43199ca0b43fc8e3b643aab11cd66ea327Alan Wright 13, /* wct */
148c5f43199ca0b43fc8e3b643aab11cd66ea327Alan Wright negprot->ni_index, /* dialect index */
148c5f43199ca0b43fc8e3b643aab11cd66ea327Alan Wright secmode, /* security mode */
148c5f43199ca0b43fc8e3b643aab11cd66ea327Alan Wright SMB_DOS_MAXBUF, /* max buffer size */
148c5f43199ca0b43fc8e3b643aab11cd66ea327Alan Wright 1, /* max MPX */
148c5f43199ca0b43fc8e3b643aab11cd66ea327Alan Wright 1, /* max VCs */
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross 0, /* read/write raw */
148c5f43199ca0b43fc8e3b643aab11cd66ea327Alan Wright sesskey, /* session key */
148c5f43199ca0b43fc8e3b643aab11cd66ea327Alan Wright negprot->ni_servertime.tv_sec, /* server date/time */
148c5f43199ca0b43fc8e3b643aab11cd66ea327Alan Wright negprot->ni_tzcorrection,
148c5f43199ca0b43fc8e3b643aab11cd66ea327Alan Wright (uint16_t)negprot->ni_keylen, /* encryption key length */
148c5f43199ca0b43fc8e3b643aab11cd66ea327Alan Wright /* reserved field handled 2. */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw VAR_BCC,
148c5f43199ca0b43fc8e3b643aab11cd66ea327Alan Wright (int)negprot->ni_keylen,
148c5f43199ca0b43fc8e3b643aab11cd66ea327Alan Wright negprot->ni_key); /* encryption key */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw break;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw case DOS_LANMAN2_1:
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw case LANMAN2_1:
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross (void) ksocket_setsockopt(session->sock, SOL_SOCKET,
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning SO_RCVBUF, (const void *)&smb_dos_tcp_rcvbuf,
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning sizeof (smb_dos_tcp_rcvbuf), CRED());
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw sr->smb_flg |= SMB_FLAGS_LOCK_AND_READ_OK;
7b59d02d2a384be9a08087b14defadd214b3c1ddjb rc = smbsr_encode_result(sr, 13, VAR_BCC,
3db3f65c6274eb042354801a308c8e9bc4994553amw "bwwwwwwlYww2.w#cs",
148c5f43199ca0b43fc8e3b643aab11cd66ea327Alan Wright 13, /* wct */
148c5f43199ca0b43fc8e3b643aab11cd66ea327Alan Wright negprot->ni_index, /* dialect index */
148c5f43199ca0b43fc8e3b643aab11cd66ea327Alan Wright secmode, /* security mode */
148c5f43199ca0b43fc8e3b643aab11cd66ea327Alan Wright SMB_DOS_MAXBUF, /* max buffer size */
148c5f43199ca0b43fc8e3b643aab11cd66ea327Alan Wright 1, /* max MPX */
148c5f43199ca0b43fc8e3b643aab11cd66ea327Alan Wright 1, /* max VCs */
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross 0, /* read/write raw */
148c5f43199ca0b43fc8e3b643aab11cd66ea327Alan Wright sesskey, /* session key */
148c5f43199ca0b43fc8e3b643aab11cd66ea327Alan Wright negprot->ni_servertime.tv_sec, /* server date/time */
148c5f43199ca0b43fc8e3b643aab11cd66ea327Alan Wright negprot->ni_tzcorrection,
148c5f43199ca0b43fc8e3b643aab11cd66ea327Alan Wright (uint16_t)negprot->ni_keylen, /* encryption key length */
148c5f43199ca0b43fc8e3b643aab11cd66ea327Alan Wright /* reserved field handled 2. */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw VAR_BCC,
148c5f43199ca0b43fc8e3b643aab11cd66ea327Alan Wright (int)negprot->ni_keylen,
148c5f43199ca0b43fc8e3b643aab11cd66ea327Alan Wright negprot->ni_key, /* encryption key */
148c5f43199ca0b43fc8e3b643aab11cd66ea327Alan Wright nbdomain);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw break;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw case NT_LM_0_12:
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross (void) ksocket_setsockopt(session->sock, SOL_SOCKET,
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning SO_RCVBUF, (const void *)&smb_nt_tcp_rcvbuf,
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning sizeof (smb_nt_tcp_rcvbuf), CRED());
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /*
12b65585e720714b31036daaa2b30eb76014048eGordon Ross * Allow SMB signatures if using encrypted passwords
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw */
12b65585e720714b31036daaa2b30eb76014048eGordon Ross if ((secmode & NEGOTIATE_ENCRYPT_PASSWORDS) &&
faa1795a28a5c712eed6d0a3f84d98c368a316c6jb sr->sr_cfg->skc_signing_enable) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw secmode |= NEGOTIATE_SECURITY_SIGNATURES_ENABLED;
faa1795a28a5c712eed6d0a3f84d98c368a316c6jb if (sr->sr_cfg->skc_signing_required)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw secmode |=
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw NEGOTIATE_SECURITY_SIGNATURES_REQUIRED;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross session->secmode = secmode;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
12b65585e720714b31036daaa2b30eb76014048eGordon Ross /*
12b65585e720714b31036daaa2b30eb76014048eGordon Ross * Does the client want Extended Security?
12b65585e720714b31036daaa2b30eb76014048eGordon Ross * (and if we have it enabled)
12b65585e720714b31036daaa2b30eb76014048eGordon Ross * If so, handle as if a different dialect.
12b65585e720714b31036daaa2b30eb76014048eGordon Ross */
12b65585e720714b31036daaa2b30eb76014048eGordon Ross if ((sr->smb_flg2 & SMB_FLAGS2_EXT_SEC) != 0 &&
12b65585e720714b31036daaa2b30eb76014048eGordon Ross (negprot->ni_capabilities & CAP_EXTENDED_SECURITY) != 0)
12b65585e720714b31036daaa2b30eb76014048eGordon Ross goto NT_LM_0_12_ext_sec;
12b65585e720714b31036daaa2b30eb76014048eGordon Ross
12b65585e720714b31036daaa2b30eb76014048eGordon Ross /* Else deny knowledge of extended security. */
12b65585e720714b31036daaa2b30eb76014048eGordon Ross sr->smb_flg2 &= ~SMB_FLAGS2_EXT_SEC;
12b65585e720714b31036daaa2b30eb76014048eGordon Ross negprot->ni_capabilities &= ~CAP_EXTENDED_SECURITY;
12b65585e720714b31036daaa2b30eb76014048eGordon Ross
b89a8333f5e1f75ec0c269b22524bd2eccb972banatalie li - Sun Microsystems - Irvine United States /*
148c5f43199ca0b43fc8e3b643aab11cd66ea327Alan Wright * nbdomain is not expected to be aligned.
b89a8333f5e1f75ec0c269b22524bd2eccb972banatalie li - Sun Microsystems - Irvine United States * Use temporary buffer to avoid alignment padding
b89a8333f5e1f75ec0c269b22524bd2eccb972banatalie li - Sun Microsystems - Irvine United States */
148c5f43199ca0b43fc8e3b643aab11cd66ea327Alan Wright wclen = smb_wcequiv_strlen(nbdomain) + sizeof (smb_wchar_t);
148c5f43199ca0b43fc8e3b643aab11cd66ea327Alan Wright wcbuf = smb_srm_zalloc(sr, wclen);
148c5f43199ca0b43fc8e3b643aab11cd66ea327Alan Wright smb_msgbuf_init(&mb, wcbuf, wclen, SMB_MSGBUF_UNICODE);
148c5f43199ca0b43fc8e3b643aab11cd66ea327Alan Wright if (smb_msgbuf_encode(&mb, "U", nbdomain) < 0) {
b89a8333f5e1f75ec0c269b22524bd2eccb972banatalie li - Sun Microsystems - Irvine United States smb_msgbuf_term(&mb);
b89a8333f5e1f75ec0c269b22524bd2eccb972banatalie li - Sun Microsystems - Irvine United States smbsr_error(sr, 0, ERRSRV, ERRerror);
b89a8333f5e1f75ec0c269b22524bd2eccb972banatalie li - Sun Microsystems - Irvine United States return (SDRC_ERROR);
b89a8333f5e1f75ec0c269b22524bd2eccb972banatalie li - Sun Microsystems - Irvine United States }
b89a8333f5e1f75ec0c269b22524bd2eccb972banatalie li - Sun Microsystems - Irvine United States
7b59d02d2a384be9a08087b14defadd214b3c1ddjb rc = smbsr_encode_result(sr, 17, VAR_BCC,
b89a8333f5e1f75ec0c269b22524bd2eccb972banatalie li - Sun Microsystems - Irvine United States "bwbwwllllTwbw#c#c",
148c5f43199ca0b43fc8e3b643aab11cd66ea327Alan Wright 17, /* wct */
148c5f43199ca0b43fc8e3b643aab11cd66ea327Alan Wright negprot->ni_index, /* dialect index */
148c5f43199ca0b43fc8e3b643aab11cd66ea327Alan Wright secmode, /* security mode */
148c5f43199ca0b43fc8e3b643aab11cd66ea327Alan Wright negprot->ni_maxmpxcount, /* max MPX */
148c5f43199ca0b43fc8e3b643aab11cd66ea327Alan Wright 1, /* max VCs */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw (DWORD)smb_maxbufsize, /* max buffer size */
148c5f43199ca0b43fc8e3b643aab11cd66ea327Alan Wright 0xFFFF, /* max raw size */
148c5f43199ca0b43fc8e3b643aab11cd66ea327Alan Wright sesskey, /* session key */
148c5f43199ca0b43fc8e3b643aab11cd66ea327Alan Wright negprot->ni_capabilities,
148c5f43199ca0b43fc8e3b643aab11cd66ea327Alan Wright &negprot->ni_servertime, /* system time */
148c5f43199ca0b43fc8e3b643aab11cd66ea327Alan Wright negprot->ni_tzcorrection,
148c5f43199ca0b43fc8e3b643aab11cd66ea327Alan Wright negprot->ni_keylen, /* encryption key length */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw VAR_BCC,
148c5f43199ca0b43fc8e3b643aab11cd66ea327Alan Wright (int)negprot->ni_keylen,
148c5f43199ca0b43fc8e3b643aab11cd66ea327Alan Wright negprot->ni_key, /* encryption key */
148c5f43199ca0b43fc8e3b643aab11cd66ea327Alan Wright wclen,
148c5f43199ca0b43fc8e3b643aab11cd66ea327Alan Wright wcbuf); /* nbdomain (unicode) */
b89a8333f5e1f75ec0c269b22524bd2eccb972banatalie li - Sun Microsystems - Irvine United States
b89a8333f5e1f75ec0c269b22524bd2eccb972banatalie li - Sun Microsystems - Irvine United States smb_msgbuf_term(&mb);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw break;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
12b65585e720714b31036daaa2b30eb76014048eGordon RossNT_LM_0_12_ext_sec:
12b65585e720714b31036daaa2b30eb76014048eGordon Ross /*
12b65585e720714b31036daaa2b30eb76014048eGordon Ross * This is the "Extended Security" variant of
12b65585e720714b31036daaa2b30eb76014048eGordon Ross * dialect NT_LM_0_12.
12b65585e720714b31036daaa2b30eb76014048eGordon Ross */
12b65585e720714b31036daaa2b30eb76014048eGordon Ross rc = smbsr_encode_result(sr, 17, VAR_BCC,
12b65585e720714b31036daaa2b30eb76014048eGordon Ross "bwbwwllllTwbw#c#c",
12b65585e720714b31036daaa2b30eb76014048eGordon Ross 17, /* wct */
12b65585e720714b31036daaa2b30eb76014048eGordon Ross negprot->ni_index, /* dialect index */
12b65585e720714b31036daaa2b30eb76014048eGordon Ross secmode, /* security mode */
12b65585e720714b31036daaa2b30eb76014048eGordon Ross negprot->ni_maxmpxcount, /* max MPX */
12b65585e720714b31036daaa2b30eb76014048eGordon Ross 1, /* max VCs */
12b65585e720714b31036daaa2b30eb76014048eGordon Ross (DWORD)smb_maxbufsize, /* max buffer size */
12b65585e720714b31036daaa2b30eb76014048eGordon Ross 0xFFFF, /* max raw size */
12b65585e720714b31036daaa2b30eb76014048eGordon Ross sesskey, /* session key */
12b65585e720714b31036daaa2b30eb76014048eGordon Ross negprot->ni_capabilities,
12b65585e720714b31036daaa2b30eb76014048eGordon Ross &negprot->ni_servertime, /* system time */
12b65585e720714b31036daaa2b30eb76014048eGordon Ross negprot->ni_tzcorrection,
12b65585e720714b31036daaa2b30eb76014048eGordon Ross 0, /* encryption key length (MBZ) */
12b65585e720714b31036daaa2b30eb76014048eGordon Ross VAR_BCC,
12b65585e720714b31036daaa2b30eb76014048eGordon Ross UUID_LEN,
12b65585e720714b31036daaa2b30eb76014048eGordon Ross sr->sr_cfg->skc_machine_uuid,
12b65585e720714b31036daaa2b30eb76014048eGordon Ross sr->sr_cfg->skc_negtok_len,
12b65585e720714b31036daaa2b30eb76014048eGordon Ross sr->sr_cfg->skc_negtok);
12b65585e720714b31036daaa2b30eb76014048eGordon Ross break;
12b65585e720714b31036daaa2b30eb76014048eGordon Ross
12b65585e720714b31036daaa2b30eb76014048eGordon Ross
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw default:
148c5f43199ca0b43fc8e3b643aab11cd66ea327Alan Wright rc = smbsr_encode_result(sr, 1, 0, "bww", 1, -1, 0);
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross break;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
7b59d02d2a384be9a08087b14defadd214b3c1ddjb if (rc != 0)
faa1795a28a5c712eed6d0a3f84d98c368a316c6jb return (SDRC_ERROR);
7b59d02d2a384be9a08087b14defadd214b3c1ddjb
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /*
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * Save the agreed dialect. Note that the state is also
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * used to detect and reject attempts to re-negotiate.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw */
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross session->dialect = negprot->ni_dialect;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross session->s_state = SMB_SESSION_STATE_NEGOTIATED;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross /* Allow normal SMB1 requests now. */
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross session->newrq_func = smb1sr_newrq;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross
faa1795a28a5c712eed6d0a3f84d98c368a316c6jb return (SDRC_SUCCESS);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw}
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
148c5f43199ca0b43fc8e3b643aab11cd66ea327Alan Wrightstatic int
148c5f43199ca0b43fc8e3b643aab11cd66ea327Alan Wrightsmb_xlate_dialect(const char *dialect)
148c5f43199ca0b43fc8e3b643aab11cd66ea327Alan Wright{
8622ec4569457733001d4982ef7f5b44427069beGordon Ross const smb_xlate_t *dp;
148c5f43199ca0b43fc8e3b643aab11cd66ea327Alan Wright int i;
148c5f43199ca0b43fc8e3b643aab11cd66ea327Alan Wright
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross for (i = 0; i < smb_ndialects; ++i) {
148c5f43199ca0b43fc8e3b643aab11cd66ea327Alan Wright dp = &smb_dialect[i];
148c5f43199ca0b43fc8e3b643aab11cd66ea327Alan Wright
148c5f43199ca0b43fc8e3b643aab11cd66ea327Alan Wright if (strcmp(dp->str, dialect) == 0)
148c5f43199ca0b43fc8e3b643aab11cd66ea327Alan Wright return (dp->code);
148c5f43199ca0b43fc8e3b643aab11cd66ea327Alan Wright }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
148c5f43199ca0b43fc8e3b643aab11cd66ea327Alan Wright return (-1);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw}