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