xref: /illumos-gate/usr/src/uts/common/fs/smbsrv/smb_session_setup_andx.c (revision 1160dcf7283d2485f2b9c32da573db0275558d9b)
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 (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
23  * Copyright 2017 Nexenta Systems, Inc.  All rights reserved.
24  */
25 
26 #include <sys/types.h>
27 #include <sys/sid.h>
28 #include <sys/priv_names.h>
29 #include <sys/socket.h>
30 #include <netinet/in.h>
31 #include <smbsrv/smb_idmap.h>
32 #include <smbsrv/smb_kproto.h>
33 #include <smbsrv/smb_token.h>
34 
35 smb_sdrc_t
smb_pre_session_setup_andx(smb_request_t * sr)36 smb_pre_session_setup_andx(smb_request_t *sr)
37 {
38 	smb_arg_sessionsetup_t	*sinfo;
39 	char			*native_os;
40 	char			*native_lm;
41 	int			rc = 0;
42 
43 	sinfo = smb_srm_zalloc(sr, sizeof (smb_arg_sessionsetup_t));
44 	sr->sr_ssetup = sinfo;
45 
46 	/*
47 	 * Enforce the minimum word count seen in the old protocol,
48 	 * to make sure we have enough to decode the common stuff.
49 	 * Further wcnt checks below.
50 	 */
51 	if (sr->smb_wct < 10) {
52 		rc = -1;
53 		goto done;
54 	}
55 
56 	/*
57 	 * Parse common part of SMB session setup.
58 	 * skip: vcnumber(2), sesskey(4)
59 	 */
60 	rc = smbsr_decode_vwv(sr, "b.www6.",
61 	    &sr->andx_com, &sr->andx_off,
62 	    &sinfo->ssi_maxbufsize, &sinfo->ssi_maxmpxcount);
63 	if (rc != 0)
64 		goto done;
65 
66 	if (sr->session->dialect < NT_LM_0_12) {
67 
68 		sinfo->ssi_type = SMB_SSNSETUP_PRE_NTLM012;
69 		sinfo->ssi_capabilities = 0;
70 
71 		rc = smbsr_decode_vwv(sr, "w4.",
72 		    &sinfo->ssi_lmpwlen);
73 		if (rc != 0)
74 			goto done;
75 
76 		sinfo->ssi_lmpwd = smb_srm_zalloc(sr, sinfo->ssi_lmpwlen + 1);
77 		rc = smbsr_decode_data(sr, "%#c", sr, sinfo->ssi_lmpwlen,
78 		    sinfo->ssi_lmpwd);
79 		if (rc != 0)
80 			goto done;
81 
82 		sinfo->ssi_lmpwd[sinfo->ssi_lmpwlen] = 0;
83 
84 		if (smbsr_decode_data(sr, "%u", sr, &sinfo->ssi_user) != 0)
85 			sinfo->ssi_user = "";
86 
87 		if (smbsr_decode_data(sr, "%u", sr, &sinfo->ssi_domain) != 0)
88 			sinfo->ssi_domain = "";
89 
90 		goto part2;
91 	}
92 
93 	/*
94 	 * We have dialect >= NT_LM_0_12
95 	 */
96 	if (sr->smb_wct == 13) {
97 		/* Old style (non-extended) request. */
98 		sinfo->ssi_type = SMB_SSNSETUP_NTLM012_NOEXT;
99 
100 		rc = smbsr_decode_vwv(sr, "ww4.l",
101 		    &sinfo->ssi_lmpwlen,
102 		    &sinfo->ssi_ntpwlen,
103 		    &sinfo->ssi_capabilities);
104 		if (rc != 0)
105 			goto done;
106 
107 		/* paranoid: ignore cap. ext. sec. here */
108 		sinfo->ssi_capabilities &= ~CAP_EXTENDED_SECURITY;
109 
110 		sinfo->ssi_lmpwd = smb_srm_zalloc(sr, sinfo->ssi_lmpwlen + 1);
111 		sinfo->ssi_ntpwd = smb_srm_zalloc(sr, sinfo->ssi_ntpwlen + 1);
112 
113 		rc = smbsr_decode_data(sr, "%#c#cuu", sr,
114 		    sinfo->ssi_lmpwlen, sinfo->ssi_lmpwd,
115 		    sinfo->ssi_ntpwlen, sinfo->ssi_ntpwd,
116 		    &sinfo->ssi_user, &sinfo->ssi_domain);
117 		if (rc != 0)
118 			goto done;
119 
120 		sinfo->ssi_lmpwd[sinfo->ssi_lmpwlen] = 0;
121 		sinfo->ssi_ntpwd[sinfo->ssi_ntpwlen] = 0;
122 
123 		goto part2;
124 	}
125 
126 	if (sr->smb_wct == 12) {
127 		/* New style (extended) request. */
128 		sinfo->ssi_type = SMB_SSNSETUP_NTLM012_EXTSEC;
129 
130 		rc = smbsr_decode_vwv(sr, "w4.l",
131 		    &sinfo->ssi_iseclen,
132 		    &sinfo->ssi_capabilities);
133 		if (rc != 0)
134 			goto done;
135 
136 		if ((sinfo->ssi_capabilities & CAP_EXTENDED_SECURITY) == 0) {
137 			rc = -1;
138 			goto done;
139 		}
140 
141 		sinfo->ssi_isecblob = smb_srm_zalloc(sr, sinfo->ssi_iseclen);
142 		rc = smbsr_decode_data(sr, "%#c", sr,
143 		    sinfo->ssi_iseclen, sinfo->ssi_isecblob);
144 		if (rc != 0)
145 			goto done;
146 
147 		goto part2;
148 	}
149 
150 	/* Invalid message */
151 	rc = -1;
152 	goto done;
153 
154 part2:
155 	/*
156 	 * Get the "Native OS" and "Native LanMan" strings.
157 	 * These are not critical to protocol function, so
158 	 * if we can't parse them, just guess "NT".
159 	 * These strings are free'd with the sr.
160 	 *
161 	 * In NTLM 0.12, the padding between the Native OS and Native LM
162 	 * is a bit strange.  On NT4.0, there is a 2 byte pad between the
163 	 * OS (Windows NT 1381) and LM (Windows NT 4.0).  On Windows 2000,
164 	 * there is no padding between the OS (Windows 2000 2195) and LM
165 	 * (Windows 2000 5.0). If the padding is removed from the decode
166 	 * string the NT4.0 LM comes out as an empty string.  So if the
167 	 * client's native OS is Win NT, assume extra padding.
168 	 */
169 	rc = smbsr_decode_data(sr, "%u", sr, &native_os);
170 	if (rc != 0 || native_os == NULL)
171 		sinfo->ssi_native_os = NATIVE_OS_WINNT;
172 	else
173 		sinfo->ssi_native_os = smbnative_os_value(native_os);
174 
175 	if (sinfo->ssi_native_os == NATIVE_OS_WINNT)
176 		rc = smbsr_decode_data(sr, "%,u", sr, &native_lm);
177 	else
178 		rc = smbsr_decode_data(sr, "%u", sr, &native_lm);
179 	if (rc != 0 || native_lm == NULL)
180 		sinfo->ssi_native_lm = NATIVE_LM_NT;
181 	else
182 		sinfo->ssi_native_lm = smbnative_lm_value(native_lm);
183 	rc = 0;
184 
185 done:
186 	if (rc != 0) {
187 		cmn_err(CE_NOTE,
188 		    "SmbSessonSetupX: client %s invalid request",
189 		    sr->session->ip_addr_str);
190 	}
191 
192 	DTRACE_SMB_START(op__SessionSetupX, smb_request_t *, sr);
193 	return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
194 }
195 
196 void
smb_post_session_setup_andx(smb_request_t * sr)197 smb_post_session_setup_andx(smb_request_t *sr)
198 {
199 	smb_arg_sessionsetup_t	*sinfo = sr->sr_ssetup;
200 
201 	DTRACE_SMB_DONE(op__SessionSetupX, smb_request_t *, sr);
202 
203 	if (sinfo->ssi_lmpwd != NULL)
204 		bzero(sinfo->ssi_lmpwd, sinfo->ssi_lmpwlen);
205 
206 	if (sinfo->ssi_ntpwd != NULL)
207 		bzero(sinfo->ssi_ntpwd, sinfo->ssi_ntpwlen);
208 }
209 
210 /*
211  *
212  * NT systems use different native OS and native LanMan values dependent on
213  * whether they are acting as a client or a server.  NT 4.0 server responds
214  * with the following values:
215  *
216  *      NativeOS:       Windows NT 4.0
217  *      NativeLM:       NT LAN Manager 4.0
218  */
219 smb_sdrc_t
smb_com_session_setup_andx(smb_request_t * sr)220 smb_com_session_setup_andx(smb_request_t *sr)
221 {
222 	smb_arg_sessionsetup_t	*sinfo = sr->sr_ssetup;
223 	uint32_t		status;
224 	uint16_t		action;
225 	int			rc;
226 
227 	/*
228 	 * Some stuff we do only in the first in a (possible)
229 	 * sequence of session setup requests.
230 	 */
231 	if (sinfo->ssi_type != SMB_SSNSETUP_NTLM012_EXTSEC ||
232 	    sr->smb_uid == 0 || sr->smb_uid == 0xFFFF) {
233 
234 		/* This is a first (or only) call */
235 		sr->session->smb_msg_size = sinfo->ssi_maxbufsize;
236 		sr->session->smb_max_mpx = sinfo->ssi_maxmpxcount;
237 		sr->session->capabilities = sinfo->ssi_capabilities;
238 		sr->session->native_os = sinfo->ssi_native_os;
239 		sr->session->native_lm = sinfo->ssi_native_lm;
240 	}
241 
242 	/* RejectUnencryptedAccess precludes SMB1 access */
243 	if (sr->sr_server->sv_cfg.skc_encrypt == SMB_CONFIG_REQUIRED) {
244 		smbsr_error(sr, NT_STATUS_ACCESS_DENIED,
245 		    ERRDOS, ERROR_ACCESS_DENIED);
246 		return (SDRC_ERROR);
247 	}
248 
249 	/*
250 	 * The "meat" of authentication happens here.
251 	 */
252 	if (sinfo->ssi_type == SMB_SSNSETUP_NTLM012_EXTSEC)
253 		status = smb_authenticate_ext(sr);
254 	else
255 		status = smb_authenticate_old(sr);
256 
257 	switch (status) {
258 
259 	case NT_STATUS_SUCCESS:
260 		break;
261 
262 	/*
263 	 * This is not really an error, but tells the client
264 	 * it should send another session setup request.
265 	 */
266 	case NT_STATUS_MORE_PROCESSING_REQUIRED:
267 		smbsr_error(sr, status, 0, 0);
268 		break;
269 
270 	case NT_STATUS_ACCESS_DENIED:
271 		smbsr_error(sr, status, ERRDOS, ERROR_ACCESS_DENIED);
272 		return (SDRC_ERROR);
273 
274 	case NT_STATUS_TOO_MANY_SESSIONS:
275 		smbsr_error(sr, status, ERRSRV, ERRtoomanyuids);
276 		return (SDRC_ERROR);
277 
278 	case NT_STATUS_NO_LOGON_SERVERS:
279 		smbsr_error(sr, status, ERRDOS, ERROR_NO_LOGON_SERVERS);
280 		return (SDRC_ERROR);
281 
282 	case NT_STATUS_NETLOGON_NOT_STARTED:
283 		smbsr_error(sr, status, ERRDOS, ERROR_NETLOGON_NOT_STARTED);
284 		return (SDRC_ERROR);
285 
286 	case NT_STATUS_USER_SESSION_DELETED:
287 		smbsr_error(sr, status, ERRSRV, ERRbaduid);
288 		return (SDRC_ERROR);
289 
290 	case NT_STATUS_INSUFF_SERVER_RESOURCES:
291 		smbsr_error(sr, status, ERRSRV, ERRnoresource);
292 		return (SDRC_ERROR);
293 
294 	case NT_STATUS_INTERNAL_ERROR:
295 	default:
296 		smbsr_error(sr, status, ERRSRV, ERRsrverror);
297 		return (SDRC_ERROR);
298 	}
299 
300 	action = SMB_USER_IS_GUEST(sr->uid_user) ? 1 : 0;
301 
302 	switch (sinfo->ssi_type) {
303 
304 	default:
305 	case SMB_SSNSETUP_PRE_NTLM012:
306 	case SMB_SSNSETUP_NTLM012_NOEXT:
307 
308 		rc = smbsr_encode_result(sr, 3, VAR_BCC, "bb.www%uuu",
309 		    3,
310 		    sr->andx_com,
311 		    -1,			/* andx_off */
312 		    action,
313 		    VAR_BCC,
314 		    sr,
315 		    sr->sr_cfg->skc_native_os,
316 		    sr->sr_cfg->skc_native_lm,
317 		    sr->sr_cfg->skc_nbdomain);
318 		break;
319 
320 	case SMB_SSNSETUP_NTLM012_EXTSEC:
321 
322 		rc = smbsr_encode_result(sr, 4, VAR_BCC, "bb.wwww%#cuuu",
323 		    4,
324 		    sr->andx_com,
325 		    -1,			/* andx_off */
326 		    action,
327 		    sinfo->ssi_oseclen,
328 		    VAR_BCC,
329 		    sr,
330 		    sinfo->ssi_oseclen,
331 		    sinfo->ssi_osecblob,
332 		    sr->sr_cfg->skc_native_os,
333 		    sr->sr_cfg->skc_native_lm,
334 		    sr->sr_cfg->skc_nbdomain);
335 		break;
336 	}
337 
338 	return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
339 }
340