xref: /illumos-gate/usr/src/uts/common/fs/smbsrv/smb_session_setup_andx.c (revision 94047d49916b669576decf2f622a1ee718646882)
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
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
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
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 	/*
243 	 * The "meat" of authentication happens here.
244 	 */
245 	if (sinfo->ssi_type == SMB_SSNSETUP_NTLM012_EXTSEC)
246 		status = smb_authenticate_ext(sr);
247 	else
248 		status = smb_authenticate_old(sr);
249 
250 	switch (status) {
251 
252 	case NT_STATUS_SUCCESS:
253 		break;
254 
255 	/*
256 	 * This is not really an error, but tells the client
257 	 * it should send another session setup request.
258 	 */
259 	case NT_STATUS_MORE_PROCESSING_REQUIRED:
260 		smbsr_error(sr, status, 0, 0);
261 		break;
262 
263 	case NT_STATUS_ACCESS_DENIED:
264 		smbsr_error(sr, status, ERRDOS, ERROR_ACCESS_DENIED);
265 		return (SDRC_ERROR);
266 
267 	case NT_STATUS_TOO_MANY_SESSIONS:
268 		smbsr_error(sr, status, ERRSRV, ERRtoomanyuids);
269 		return (SDRC_ERROR);
270 
271 	case NT_STATUS_NO_LOGON_SERVERS:
272 		smbsr_error(sr, status, ERRDOS, ERROR_NO_LOGON_SERVERS);
273 		return (SDRC_ERROR);
274 
275 	case NT_STATUS_NETLOGON_NOT_STARTED:
276 		smbsr_error(sr, status, ERRDOS, ERROR_NETLOGON_NOT_STARTED);
277 		return (SDRC_ERROR);
278 
279 	case NT_STATUS_USER_SESSION_DELETED:
280 		smbsr_error(sr, status, ERRSRV, ERRbaduid);
281 		return (SDRC_ERROR);
282 
283 	case NT_STATUS_INSUFF_SERVER_RESOURCES:
284 		smbsr_error(sr, status, ERRSRV, ERRnoresource);
285 		return (SDRC_ERROR);
286 
287 	case NT_STATUS_INTERNAL_ERROR:
288 	default:
289 		smbsr_error(sr, status, ERRSRV, ERRsrverror);
290 		return (SDRC_ERROR);
291 	}
292 
293 	action = SMB_USER_IS_GUEST(sr->uid_user) ? 1 : 0;
294 
295 	switch (sinfo->ssi_type) {
296 
297 	default:
298 	case SMB_SSNSETUP_PRE_NTLM012:
299 	case SMB_SSNSETUP_NTLM012_NOEXT:
300 
301 		rc = smbsr_encode_result(sr, 3, VAR_BCC, "bb.www%uuu",
302 		    3,
303 		    sr->andx_com,
304 		    -1,			/* andx_off */
305 		    action,
306 		    VAR_BCC,
307 		    sr,
308 		    sr->sr_cfg->skc_native_os,
309 		    sr->sr_cfg->skc_native_lm,
310 		    sr->sr_cfg->skc_nbdomain);
311 		break;
312 
313 	case SMB_SSNSETUP_NTLM012_EXTSEC:
314 
315 		rc = smbsr_encode_result(sr, 4, VAR_BCC, "bb.wwww%#cuuu",
316 		    4,
317 		    sr->andx_com,
318 		    -1,			/* andx_off */
319 		    action,
320 		    sinfo->ssi_oseclen,
321 		    VAR_BCC,
322 		    sr,
323 		    sinfo->ssi_oseclen,
324 		    sinfo->ssi_osecblob,
325 		    sr->sr_cfg->skc_native_os,
326 		    sr->sr_cfg->skc_native_lm,
327 		    sr->sr_cfg->skc_nbdomain);
328 		break;
329 	}
330 
331 	return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
332 }
333