Home | History | Annotate | Download | only in smbsrv
      1 /*
      2  * CDDL HEADER START
      3  *
      4  * The contents of this file are subject to the terms of the
      5  * Common Development and Distribution License (the "License").
      6  * You may not use this file except in compliance with the License.
      7  *
      8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
      9  * or http://www.opensolaris.org/os/licensing.
     10  * See the License for the specific language governing permissions
     11  * and limitations under the License.
     12  *
     13  * When distributing Covered Code, include this CDDL HEADER in each
     14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
     15  * If applicable, add the following below this CDDL HEADER, with the
     16  * fields enclosed by brackets "[]" replaced with your own identifying
     17  * information: Portions Copyright [yyyy] [name of copyright owner]
     18  *
     19  * CDDL HEADER END
     20  */
     21 /*
     22  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
     23  * Use is subject to license terms.
     24  */
     25 /*
     26  * SMB: session_setup_andx
     27  *
     28  * This SMB is used to further "Set up" the session normally just
     29  * established via the negotiate protocol.
     30  *
     31  * One primary function is to perform a "user logon" in the case where the
     32  * server is in user level security mode.  The Uid in the SMB header is set
     33  * by the client to be the userid desired for the AccountName and validated
     34  * by the AccountPassword.
     35  *
     36  * If the negotiated protocol is prior to NT LM 0.12, the format of
     37  * SMB_COM_SESSION_SETUP_ANDX is:
     38  *
     39  * Client Request                 Description
     40  * ============================== =====================================
     41  *
     42  * UCHAR WordCount;               Count of parameter words = 10
     43  * UCHAR AndXCommand;             Secondary (X) command; 0xFF = none
     44  * UCHAR AndXReserved;            Reserved (must be 0)
     45  * USHORT AndXOffset;             Offset to next command WordCount
     46  * USHORT MaxBufferSize;          Client maximum buffer size
     47  * USHORT MaxMpxCount;            Actual maximum multiplexed pending
     48  *                                 requests
     49  * USHORT VcNumber;               0 = first (only), nonzero=additional
     50  *                                 VC number
     51  * ULONG SessionKey;              Session key (valid iff VcNumber != 0)
     52  * USHORT PasswordLength;         Account password size
     53  * ULONG Reserved;                Must be 0
     54  * USHORT ByteCount;              Count of data bytes;    min = 0
     55  * UCHAR AccountPassword[];       Account Password
     56  * STRING AccountName[];          Account Name
     57  * STRING PrimaryDomain[];        Client's primary domain
     58  * STRING NativeOS[];             Client's native operating system
     59  * STRING NativeLanMan[];         Client's native LAN Manager type
     60  *
     61  * and the response is:
     62  *
     63  * Server Response                    Description
     64  * ================================== =================================
     65  *
     66  * UCHAR WordCount;                   Count of parameter words = 3
     67  * UCHAR AndXCommand;                 Secondary (X) command;  0xFF =
     68  *                                     none
     69  * UCHAR AndXReserved;                Reserved (must be 0)
     70  * USHORT AndXOffset;                 Offset to next command WordCount
     71  * USHORT Action;                     Request mode:
     72  *                                     bit0 = logged in as GUEST
     73  * USHORT ByteCount;                  Count of data bytes
     74  * STRING NativeOS[];                 Server's native operating system
     75  * STRING NativeLanMan[];             Server's native LAN Manager type
     76  * STRING PrimaryDomain[];            Server's primary domain
     77  *
     78  * If the server is in "share level security mode", the account name and
     79  * passwd should be ignored by the server.
     80  *
     81  * If challenge/response authentication is not being used, AccountPassword
     82  * should be a null terminated ASCII string with PasswordLength set to the
     83  * string size including the null; the password will case insensitive. If
     84  * challenge/response authentication is being used (see section 2.10), then
     85  * AccountPassword will be the response to the server's challenge, and
     86  * PasswordLength should be set to its length.
     87  *
     88  * The server validates the name and password supplied and if valid, it
     89  * registers the user identifier on this session as representing the
     90  * specified AccountName.  The Uid  field in the SMB header will then be
     91  * used to validate access on subsequent SMB requests.  The SMB requests
     92  * where permission checks are required are those which refer to a
     93  * symbolically named resource such as SMB_COM_OPEN, SMB_COM_RENAME,
     94  * SMB_COM_DELETE, etc..  The value of the Uid is relative to a specific
     95  * client/server session so it is possible to have the same Uid value
     96  * represent two different users on two different sessions at the server.
     97  *
     98  * Multiple session setup commands may be sent to register additional users
     99  * on this session.  If the server receives an additional
    100  * SMB_COM_SESSION_SETUP_ANDX, only the Uid, AccountName and
    101  * AccountPassword fields need contain valid values (the server MUST ignore
    102  * the other fields).
    103  *
    104  * The client writes the name of its domain in PrimaryDomain if it knows
    105  * what the domain name is.  If the domain name is unknown, the client
    106  * either encodes it as a NULL string, or as a question mark.
    107  *
    108  * If bit0 of Action is set, this informs the client that although the
    109  * server did not recognize the AccountName, it logged the user in as a
    110  * guest.  This is optional behavior by the server, and in any case one
    111  * would ordinarily expect guest privileges to limited.
    112  *
    113  * Another function of the Session Set Up protocol is to inform the server
    114  * of the maximum values which will be utilized by this client.  Here
    115  * MaxBufferSize is the maximum message size which the client can receive.
    116  * Thus although the server may support 16k buffers (as returned in the
    117  * SMB_COM_NEGOTIATE response), if the client only has 4k buffers, the
    118  * value of MaxBufferSize here would be 4096.  The minimum allowable value
    119  * for MaxBufferSize is 1024.  The SMB_COM_NEGOTIATE response includes the
    120  * server buffer size supported.  Thus this is the maximum SMB message size
    121  * which the client can send to the server.  This size may be larger than
    122  * the size returned to the server from the client via the
    123  * SMB_COM_SESSION_SETUP_AND X protocol which is the maximum SMB message
    124  * size which the server may send to the client.  Thus if the server's
    125  * buffer size were 4k and the client's buffer size were only 2K,  the
    126  * client could send up to 4k (standard) write requests but must only
    127  * request up to 2k for (standard) read requests.
    128  *
    129  * The field, MaxMpxCount informs the server of the maximum number of
    130  * requests which the client will have outstanding to the server
    131  * simultaneously (see sections 5.13 and 5.25).
    132  *
    133  * The VcNumber field specifies whether the client wants this to be the
    134  * first VC or an additional VC.  If the the SMB_COM_SESSION_SETUP_ANDX
    135  * request contains a VcNumber of 0 and other VCs are still connected to
    136  * that client, they should be aborted to free any resources held by the
    137  * server. This condition could occur if the client was rebooted and
    138  * reconnected to the server before the transport level had informed the
    139  * server of the previous VC termination. There is more information on
    140  * VCs in smb_negotiate.c.
    141  *
    142  * The values for MaxBufferSize, MaxMpxCount, and VcNumber must be less
    143  * than or equal to the maximum values supported by the server as returned
    144  * in the SMB_COM_NEGOTIATE response.
    145  *
    146  * If the negotiated SMB dialect is "NT LM 0.12" or later, the format of
    147  * the response SMB is unchanged, but the request is:
    148  *
    149  * Client Request                 Description
    150  * ============================== =====================================
    151  *
    152  * UCHAR WordCount;               Count of parameter words = 13
    153  * UCHAR AndXCommand;             Secondary (X) command;  0xFF = none
    154  * UCHAR AndXReserved;            Reserved (must be 0)
    155  * USHORT AndXOffset;             Offset to next command WordCount
    156  * USHORT MaxBufferSize;          Client's maximum buffer size
    157  * USHORT MaxMpxCount;            Actual maximum multiplexed pending
    158  *                                 requests
    159  * USHORT VcNumber;               0 = first (only), nonzero=additional
    160  *                                 VC number
    161  * ULONG SessionKey;              Session key (valid iff VcNumber != 0)
    162  * USHORT                         Account password size, ANSI
    163  * CaseInsensitivePasswordLength;
    164  * USHORT                         Account password size, Unicode
    165  * CaseSensitivePasswordLength;
    166  * ULONG Reserved;                must be 0
    167  * ULONG Capabilities;            Client capabilities
    168  * USHORT ByteCount;              Count of data bytes;    min = 0
    169  * UCHAR                          Account Password, ANSI
    170  * CaseInsensitivePassword[];
    171  * UCHAR CaseSensitivePassword[]; Account Password, Unicode
    172  * STRING AccountName[];          Account Name, Unicode
    173  * STRING PrimaryDomain[];        Client's primary domain, Unicode
    174  * STRING NativeOS[];             Client's native operating system,
    175  *                                 Unicode
    176  * STRING NativeLanMan[];         Client's native LAN Manager type,
    177  *                                 Unicode
    178  *
    179  * The client expresses its capabilities to the server encoded in the
    180  * Capabilities field:
    181  *
    182  * Capability Name           Encoding  Description
    183  * ========================  ========= ================================
    184  *
    185  * CAP_UNICODE               0x0004    The client can use UNICODE
    186  *                                      strings
    187  * CAP_LARGE_FILES           0x0008    The client can deal with files
    188  *                                      having 64 bit offsets
    189  * CAP_NT_SMBS               0x0010    The client understands the SMBs
    190  *                                      introduced with the NT LM 0.12
    191  *                                      dialect.  Implies CAP_NT_FIND.
    192  * CAP_NT_FIND               0x0200
    193  * CAP_STATUS32              0x0040    The client can receive 32 bit
    194  *                                      errors encoded in Status.Status
    195  * CAP_LEVEL_II_OPLOCKS      0x0080    The client understands Level II
    196  *                                      oplocks
    197  *
    198  * The entire message sent and received including the optional ANDX SMB
    199  * must fit in the negotiated maximum transfer size.  The following are the
    200  * only valid SMB commands for AndXCommand for SMB_COM_SESSION_SETUP_ANDX
    201  *
    202  * SMB_COM_TREE_CONNECT_ANDX     SMB_COM_OPEN
    203  * SMB_COM_OPEN_ANDX             SMB_COM_CREATE
    204  * SMB_COM_CREATE_NEW            SMB_COM_CREATE_DIRECTORY
    205  * SMB_COM_DELETE                SMB_COM_DELETE_DIRECTORY
    206  * SMB_COM_FIND                  SMB_COM_FIND_UNIQUE
    207  * SMB_COM_COPY                  SMB_COM_RENAME
    208  * SMB_COM_NT_RENAME             SMB_COM_CHECK_DIRECTORY
    209  * SMB_COM_QUERY_INFORMATION     SMB_COM_SET_INFORMATION
    210  * SMB_COM_NO_ANDX_COMMAND       SMB_COM_OPEN_PRINT_FILE
    211  * SMB_COM_GET_PRINT_QUEUE       SMB_COM_TRANSACTION
    212  *
    213  * 4.1.2.1   Errors
    214  *
    215  * ERRSRV/ERRerror     - no NEG_PROT issued
    216  * ERRSRV/ERRbadpw     - password not correct for given user name
    217  * ERRSRV/ERRtoomanyuids    - maximum number of users per session exceeded
    218  * ERRSRV/ERRnosupport - chaining of this request to the previous one is
    219  * not supported
    220  */
    221 
    222 #include <sys/types.h>
    223 #include <sys/socket.h>
    224 #include <netinet/in.h>
    225 #include <smbsrv/smb_kproto.h>
    226 #include <smbsrv/smb_token.h>
    227 #include <smbsrv/smb_door_svc.h>
    228 
    229 typedef struct smb_sessionsetup_info {
    230 	char		*ssi_user;
    231 	char		*ssi_domain;
    232 	char		*ssi_native_os;
    233 	char		*ssi_native_lm;
    234 	uint16_t	ssi_cipwlen;
    235 	uint8_t		*ssi_cipwd;
    236 	uint16_t	ssi_cspwlen;
    237 	uint8_t		*ssi_cspwd;
    238 	uint16_t	ssi_maxbufsize;
    239 	uint16_t	ssi_maxmpxcount;
    240 	uint16_t	ssi_vcnumber;
    241 	uint32_t	ssi_capabilities;
    242 	uint32_t	ssi_sesskey;
    243 } smb_sessionsetup_info_t;
    244 
    245 #define	SMB_AUTH_FAILED	-1
    246 #define	SMB_AUTH_USER	0
    247 #define	SMB_AUTH_GUEST	1
    248 
    249 static int smb_authenticate(smb_request_t *, smb_sessionsetup_info_t *,
    250     smb_session_key_t **);
    251 
    252 smb_sdrc_t
    253 smb_pre_session_setup_andx(smb_request_t *sr)
    254 {
    255 	DTRACE_SMB_1(op__SessionSetupX__start, smb_request_t *, sr);
    256 	return (SDRC_SUCCESS);
    257 }
    258 
    259 void
    260 smb_post_session_setup_andx(smb_request_t *sr)
    261 {
    262 	DTRACE_SMB_1(op__SessionSetupX__done, smb_request_t *, sr);
    263 }
    264 
    265 smb_sdrc_t
    266 smb_com_session_setup_andx(smb_request_t *sr)
    267 {
    268 	smb_sessionsetup_info_t sinfo;
    269 	smb_session_key_t *session_key = NULL;
    270 	char ipaddr_buf[INET6_ADDRSTRLEN];
    271 	int native_lm;
    272 	int auth_res;
    273 	int rc;
    274 
    275 	bzero(&sinfo, sizeof (smb_sessionsetup_info_t));
    276 
    277 	if (sr->session->dialect >= NT_LM_0_12) {
    278 		rc = smbsr_decode_vwv(sr, "b.wwwwlww4.l", &sr->andx_com,
    279 		    &sr->andx_off, &sinfo.ssi_maxbufsize,
    280 		    &sinfo.ssi_maxmpxcount, &sinfo.ssi_vcnumber,
    281 		    &sinfo.ssi_sesskey, &sinfo.ssi_cipwlen,
    282 		    &sinfo.ssi_cspwlen, &sinfo.ssi_capabilities);
    283 
    284 		if (rc != 0)
    285 			return (SDRC_ERROR);
    286 
    287 		sinfo.ssi_cipwd = kmem_alloc(sinfo.ssi_cipwlen + 1, KM_SLEEP);
    288 		sinfo.ssi_cspwd = kmem_alloc(sinfo.ssi_cspwlen + 1, KM_SLEEP);
    289 
    290 		/*
    291 		 * The padding between the Native OS and Native LM is a
    292 		 * bit strange. On NT4.0, there is a 2 byte pad between
    293 		 * the OS (Windows NT 1381) and LM (Windows NT 4.0).
    294 		 * On Windows 2000, there is no padding between the OS
    295 		 * (Windows 2000 2195) and LM (Windows 2000 5.0).
    296 		 *
    297 		 * If the padding is removed from this decode string
    298 		 * the NT4.0 LM comes out as an empty string.
    299 		 *
    300 		 * So if the client's native OS is Win NT we consider
    301 		 * the padding otherwise we don't.
    302 		 */
    303 		rc = smbsr_decode_data(sr, "%#c#cuuu",
    304 		    sr,
    305 		    sinfo.ssi_cipwlen, sinfo.ssi_cipwd,
    306 		    sinfo.ssi_cspwlen, sinfo.ssi_cspwd,
    307 		    &sinfo.ssi_user,
    308 		    &sinfo.ssi_domain,
    309 		    &sinfo.ssi_native_os);
    310 
    311 		if (rc != 0) {
    312 			kmem_free(sinfo.ssi_cipwd, sinfo.ssi_cipwlen + 1);
    313 			kmem_free(sinfo.ssi_cspwd, sinfo.ssi_cspwlen + 1);
    314 			return (SDRC_ERROR);
    315 		}
    316 
    317 		sinfo.ssi_cipwd[sinfo.ssi_cipwlen] = 0;
    318 		sinfo.ssi_cspwd[sinfo.ssi_cspwlen] = 0;
    319 
    320 		sr->session->native_os =
    321 		    smbnative_os_value(sinfo.ssi_native_os);
    322 
    323 		if (sr->session->native_os == NATIVE_OS_WINNT)
    324 			rc = smbsr_decode_data(sr, "%,u", sr,
    325 			    &sinfo.ssi_native_lm);
    326 		else
    327 			rc = smbsr_decode_data(sr, "%u", sr,
    328 			    &sinfo.ssi_native_lm);
    329 
    330 		/*
    331 		 * If the Native Lanman cannot be determined,
    332 		 * default to Windows NT.
    333 		 */
    334 		if (rc != 0 || sinfo.ssi_native_lm == NULL)
    335 			sinfo.ssi_native_lm = "NT LAN Manager 4.0";
    336 	} else {
    337 		rc = smbsr_decode_vwv(sr, "b.wwwwlw4.", &sr->andx_com,
    338 		    &sr->andx_off, &sinfo.ssi_maxbufsize,
    339 		    &sinfo.ssi_maxmpxcount,
    340 		    &sinfo.ssi_vcnumber, &sinfo.ssi_sesskey,
    341 		    &sinfo.ssi_cipwlen);
    342 
    343 		if (rc != 0)
    344 			return (SDRC_ERROR);
    345 
    346 		sinfo.ssi_cipwd = kmem_alloc(sinfo.ssi_cipwlen + 1, KM_SLEEP);
    347 		rc = smbsr_decode_data(sr, "%#c", sr, sinfo.ssi_cipwlen,
    348 		    sinfo.ssi_cipwd);
    349 		if (rc != 0) {
    350 			kmem_free(sinfo.ssi_cipwd, sinfo.ssi_cipwlen + 1);
    351 			return (SDRC_ERROR);
    352 		}
    353 
    354 		sinfo.ssi_cipwd[sinfo.ssi_cipwlen] = 0;
    355 
    356 		/*
    357 		 * Despite the CIFS/1.0 spec, the rest of this message is
    358 		 * not always present. We need to try to get the account
    359 		 * name and the primary domain but we don't care about the
    360 		 * the native OS or native LanMan fields.
    361 		 */
    362 		if (smbsr_decode_data(sr, "%u", sr, &sinfo.ssi_user) != 0)
    363 			sinfo.ssi_user = "";
    364 
    365 		if (smbsr_decode_data(sr, "%u", sr, &sinfo.ssi_domain) != 0)
    366 			sinfo.ssi_domain = "";
    367 
    368 		sr->session->native_os = NATIVE_OS_WINNT;
    369 		sinfo.ssi_native_lm = "NT LAN Manager 4.0";
    370 	}
    371 
    372 	/*
    373 	 * If the sinfo.ssi_vcnumber is zero, we can discard any
    374 	 * other connections associated with this client.
    375 	 */
    376 	sr->session->vcnumber = sinfo.ssi_vcnumber;
    377 	if (sinfo.ssi_vcnumber == 0)
    378 		smb_server_reconnection_check(sr->sr_server, sr->session);
    379 
    380 	auth_res = smb_authenticate(sr, &sinfo, &session_key);
    381 
    382 	if (sinfo.ssi_cipwd)
    383 		kmem_free(sinfo.ssi_cipwd, sinfo.ssi_cipwlen + 1);
    384 
    385 	if (auth_res == SMB_AUTH_FAILED) {
    386 		if (sinfo.ssi_cspwd)
    387 			kmem_free(sinfo.ssi_cspwd, sinfo.ssi_cspwlen + 1);
    388 		return (SDRC_ERROR);
    389 	}
    390 
    391 	native_lm = smbnative_lm_value(sinfo.ssi_native_lm);
    392 	if (native_lm == NATIVE_LM_WIN2000)
    393 		sinfo.ssi_capabilities |= CAP_LARGE_FILES |
    394 		    CAP_LARGE_READX | CAP_LARGE_WRITEX;
    395 
    396 	sr->session->smb_msg_size = sinfo.ssi_maxbufsize;
    397 	sr->session->capabilities = sinfo.ssi_capabilities;
    398 
    399 	/*
    400 	 * Check to see if SMB signing is enable, but if it is already turned
    401 	 * on leave it.
    402 	 * The first authenticated logon provides the MAC key and sequence
    403 	 * numbers for signing all further session on the
    404 	 * same network connection.
    405 	 */
    406 	if (!(sr->session->signing.flags & SMB_SIGNING_ENABLED) &&
    407 	    (sr->session->secmode & NEGOTIATE_SECURITY_SIGNATURES_ENABLED) &&
    408 	    (sr->smb_flg2 & SMB_FLAGS2_SMB_SECURITY_SIGNATURE) &&
    409 	    session_key)
    410 		smb_sign_init(sr, session_key, (char *)sinfo.ssi_cspwd,
    411 		    sinfo.ssi_cspwlen);
    412 
    413 	if (sinfo.ssi_cspwd)
    414 		kmem_free(sinfo.ssi_cspwd, sinfo.ssi_cspwlen + 1);
    415 
    416 	if (session_key)
    417 		kmem_free(session_key, sizeof (smb_session_key_t));
    418 
    419 	if (!(sr->smb_flg2 & SMB_FLAGS2_SMB_SECURITY_SIGNATURE) &&
    420 	    (sr->sr_cfg->skc_signing_required)) {
    421 		(void) smb_inet_ntop(&sr->session->ipaddr, ipaddr_buf,
    422 		    SMB_IPSTRLEN(sr->session->ipaddr.a_family));
    423 		cmn_err(CE_NOTE,
    424 		    "SmbSessonSetupX: client %s is not capable of signing",
    425 		    ipaddr_buf);
    426 		smbsr_error(sr, NT_STATUS_LOGON_FAILURE,
    427 		    ERRDOS, ERROR_LOGON_FAILURE);
    428 		return (SDRC_ERROR);
    429 	}
    430 
    431 	/*
    432 	 * NT systems use different native OS and native LanMan values
    433 	 * dependent on whether they are acting as a client or a server.
    434 	 * As a server, NT 4.0 responds with the following values:
    435 	 *
    436 	 *	NativeOS:	Windows NT 4.0
    437 	 *	NativeLM:	NT LAN Manager 4.0
    438 	 *
    439 	 * We should probably use the same values as NT but this code has
    440 	 * been using the product name and "Windows NT 4.0" for a long time
    441 	 * and I don't know if a change would cause any problems (see the
    442 	 * conditional test below).
    443 	 */
    444 	rc = smbsr_encode_result(sr, 3, VAR_BCC, "bb.www%uuu",
    445 	    3,
    446 	    sr->andx_com,
    447 	    -1,			/* andx_off */
    448 	    (auth_res == SMB_AUTH_GUEST) ? 1 : 0,
    449 	    VAR_BCC,
    450 	    sr,
    451 	    "Windows NT 4.0",
    452 	    "NT LAN Manager 4.0",
    453 	    sr->sr_cfg->skc_nbdomain);
    454 
    455 	return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
    456 }
    457 
    458 /*
    459  * Tries to authenticate the connected user.
    460  *
    461  * It first tries to see if the user has already been authenticated.
    462  * If a match is found, the user structure in the session is duplicated
    463  * and the function returns. Otherwise, user information is passed to
    464  * smbd for authentication. If smbd can authenticate the user an access
    465  * token structure is returned. A cred_t and user structure is created
    466  * based on the returned access token.
    467  */
    468 static int
    469 smb_authenticate(smb_request_t *sr, smb_sessionsetup_info_t *sinfo,
    470     smb_session_key_t **session_key)
    471 {
    472 	char *hostname = sr->sr_cfg->skc_hostname;
    473 	int security = sr->sr_cfg->skc_secmode;
    474 	smb_token_t *usr_token = NULL;
    475 	smb_user_t *user = NULL;
    476 	netr_client_t clnt_info;
    477 	boolean_t need_lookup = B_FALSE;
    478 	uint32_t privileges;
    479 	cred_t *cr;
    480 	char *buf = NULL;
    481 	char *p;
    482 
    483 	bzero(&clnt_info, sizeof (netr_client_t));
    484 
    485 	if ((sinfo->ssi_cspwlen == 0) &&
    486 	    (sinfo->ssi_cipwlen == 0 ||
    487 	    (sinfo->ssi_cipwlen == 1 && *sinfo->ssi_cipwd == 0))) {
    488 		clnt_info.e_username = "anonymous";
    489 	} else {
    490 		clnt_info.e_username = sinfo->ssi_user;
    491 	}
    492 	clnt_info.e_domain = sinfo->ssi_domain;
    493 
    494 	/*
    495 	 * Handle user@domain format.
    496 	 *
    497 	 * We need to extract the user and domain names but
    498 	 * should keep the request data as is. This is important
    499 	 * for some forms of authentication.
    500 	 */
    501 	if (*sinfo->ssi_domain == '\0') {
    502 		buf = smb_strdup(sinfo->ssi_user);
    503 		if ((p = strchr(buf, '@')) != NULL) {
    504 			*p = '\0';
    505 			clnt_info.e_username = buf;
    506 			clnt_info.e_domain = p + 1;
    507 		}
    508 	}
    509 
    510 	/*
    511 	 * See if this user has already been authenticated.
    512 	 *
    513 	 * If no domain name is provided we cannot determine whether
    514 	 * this is a local or domain user when server is operating
    515 	 * in domain mode, so lookup will be done after authentication.
    516 	 */
    517 	if (security == SMB_SECMODE_WORKGRP) {
    518 		user = smb_session_dup_user(sr->session, hostname,
    519 		    clnt_info.e_username);
    520 	} else if (*clnt_info.e_domain != '\0') {
    521 		user = smb_session_dup_user(sr->session, clnt_info.e_domain,
    522 		    clnt_info.e_username);
    523 	} else {
    524 		need_lookup = B_TRUE;
    525 	}
    526 
    527 	if (user != NULL) {
    528 		sr->user_cr = user->u_cred;
    529 		sr->smb_uid = user->u_uid;
    530 		sr->uid_user = user;
    531 
    532 		smb_mfree(buf);
    533 
    534 		return ((user->u_flags & SMB_USER_FLAG_GUEST)
    535 		    ? SMB_AUTH_GUEST : SMB_AUTH_USER);
    536 	}
    537 
    538 	clnt_info.logon_level = NETR_NETWORK_LOGON;
    539 	clnt_info.domain = sinfo->ssi_domain;
    540 	clnt_info.username = sinfo->ssi_user;
    541 	clnt_info.workstation = sr->session->workstation;
    542 	clnt_info.ipaddr = sr->session->ipaddr;
    543 	clnt_info.local_ipaddr = sr->session->local_ipaddr;
    544 	clnt_info.challenge_key.challenge_key_val =
    545 	    sr->session->challenge_key;
    546 	clnt_info.challenge_key.challenge_key_len =
    547 	    sr->session->challenge_len;
    548 	clnt_info.nt_password.nt_password_val = sinfo->ssi_cspwd;
    549 	clnt_info.nt_password.nt_password_len = sinfo->ssi_cspwlen;
    550 	clnt_info.lm_password.lm_password_val = sinfo->ssi_cipwd;
    551 	clnt_info.lm_password.lm_password_len = sinfo->ssi_cipwlen;
    552 	clnt_info.native_os = sr->session->native_os;
    553 	clnt_info.native_lm = smbnative_lm_value(sinfo->ssi_native_lm);
    554 	clnt_info.local_port = sr->session->s_local_port;
    555 
    556 	DTRACE_PROBE1(smb__sessionsetup__clntinfo, netr_client_t *,
    557 	    &clnt_info);
    558 
    559 	usr_token = smb_get_token(&clnt_info);
    560 
    561 	smb_mfree(buf);
    562 
    563 	if (usr_token == NULL) {
    564 		smbsr_error(sr, 0, ERRSRV, ERRbadpw);
    565 		return (SMB_AUTH_FAILED);
    566 	}
    567 
    568 	if (need_lookup) {
    569 		user = smb_session_dup_user(sr->session,
    570 		    usr_token->tkn_domain_name, usr_token->tkn_account_name);
    571 
    572 		if (user != NULL) {
    573 			sr->user_cr = user->u_cred;
    574 			sr->smb_uid = user->u_uid;
    575 			sr->uid_user = user;
    576 
    577 			smb_token_free(usr_token);
    578 			return ((user->u_flags & SMB_USER_FLAG_GUEST)
    579 			    ? SMB_AUTH_GUEST : SMB_AUTH_USER);
    580 		}
    581 	}
    582 
    583 	if (usr_token->tkn_session_key) {
    584 		*session_key = kmem_alloc(sizeof (smb_session_key_t),
    585 		    KM_SLEEP);
    586 		(void) memcpy(*session_key, usr_token->tkn_session_key,
    587 		    sizeof (smb_session_key_t));
    588 	}
    589 
    590 	if ((cr = smb_cred_create(usr_token, &privileges)) != NULL) {
    591 		user = smb_user_login(sr->session, cr,
    592 		    usr_token->tkn_domain_name,
    593 		    usr_token->tkn_account_name,
    594 		    usr_token->tkn_flags,
    595 		    privileges,
    596 		    usr_token->tkn_audit_sid);
    597 
    598 		smb_cred_rele(user->u_cred);
    599 		if (user->u_privcred)
    600 			smb_cred_rele(user->u_privcred);
    601 	}
    602 
    603 	smb_token_free(usr_token);
    604 
    605 	if (user == NULL) {
    606 		if (*session_key)
    607 			kmem_free(*session_key, sizeof (smb_session_key_t));
    608 		smbsr_error(sr, 0, ERRDOS, ERROR_INVALID_HANDLE);
    609 		return (SMB_AUTH_FAILED);
    610 	}
    611 
    612 	sr->user_cr = user->u_cred;
    613 	sr->smb_uid = user->u_uid;
    614 	sr->uid_user = user;
    615 
    616 	return ((user->u_flags & SMB_USER_FLAG_GUEST)
    617 	    ? SMB_AUTH_GUEST : SMB_AUTH_USER);
    618 }
    619