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 2014 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_2(op__SessionSetupX__start, smb_request_t *, sr,
193 smb_arg_sessionsetup_t, sinfo);
194 return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
195 }
196
197 void
smb_post_session_setup_andx(smb_request_t * sr)198 smb_post_session_setup_andx(smb_request_t *sr)
199 {
200 smb_arg_sessionsetup_t *sinfo = sr->sr_ssetup;
201
202 DTRACE_SMB_2(op__SessionSetupX__done, smb_request_t *, sr,
203 smb_arg_sessionsetup_t, sinfo);
204
205 if (sinfo->ssi_lmpwd != NULL)
206 bzero(sinfo->ssi_lmpwd, sinfo->ssi_lmpwlen);
207
208 if (sinfo->ssi_ntpwd != NULL)
209 bzero(sinfo->ssi_ntpwd, sinfo->ssi_ntpwlen);
210 }
211
212 /*
213 *
214 * NT systems use different native OS and native LanMan values dependent on
215 * whether they are acting as a client or a server. NT 4.0 server responds
216 * with the following values:
217 *
218 * NativeOS: Windows NT 4.0
219 * NativeLM: NT LAN Manager 4.0
220 */
221 smb_sdrc_t
smb_com_session_setup_andx(smb_request_t * sr)222 smb_com_session_setup_andx(smb_request_t *sr)
223 {
224 smb_arg_sessionsetup_t *sinfo = sr->sr_ssetup;
225 uint32_t status;
226 uint16_t action;
227 int rc;
228
229 /*
230 * Some stuff we do only in the first in a (possible)
231 * sequence of session setup requests.
232 */
233 if (sinfo->ssi_type != SMB_SSNSETUP_NTLM012_EXTSEC ||
234 sr->smb_uid == 0 || sr->smb_uid == 0xFFFF) {
235
236 /* This is a first (or only) call */
237 sr->session->smb_msg_size = sinfo->ssi_maxbufsize;
238 sr->session->smb_max_mpx = sinfo->ssi_maxmpxcount;
239 sr->session->capabilities = sinfo->ssi_capabilities;
240
241 if (!smb_oplock_levelII)
242 sr->session->capabilities &= ~CAP_LEVEL_II_OPLOCKS;
243
244 sr->session->native_os = sinfo->ssi_native_os;
245 sr->session->native_lm = sinfo->ssi_native_lm;
246 }
247
248 /*
249 * The "meat" of authentication happens here.
250 */
251 if (sinfo->ssi_type == SMB_SSNSETUP_NTLM012_EXTSEC)
252 status = smb_authenticate_ext(sr);
253 else
254 status = smb_authenticate_old(sr);
255
256 switch (status) {
257
258 case NT_STATUS_SUCCESS:
259 break;
260
261 /*
262 * This is not really an error, but tells the client
263 * it should send another session setup request.
264 */
265 case NT_STATUS_MORE_PROCESSING_REQUIRED:
266 smbsr_error(sr, status, 0, 0);
267 break;
268
269 case NT_STATUS_ACCESS_DENIED:
270 smbsr_error(sr, status, ERRDOS, ERROR_ACCESS_DENIED);
271 return (SDRC_ERROR);
272
273 case NT_STATUS_TOO_MANY_SESSIONS:
274 smbsr_error(sr, status, ERRSRV, ERRtoomanyuids);
275 return (SDRC_ERROR);
276
277 case NT_STATUS_NO_LOGON_SERVERS:
278 smbsr_error(sr, status, ERRDOS, ERROR_NO_LOGON_SERVERS);
279 return (SDRC_ERROR);
280
281 case NT_STATUS_NETLOGON_NOT_STARTED:
282 smbsr_error(sr, status, ERRDOS, ERROR_NETLOGON_NOT_STARTED);
283 return (SDRC_ERROR);
284
285 case NT_STATUS_USER_SESSION_DELETED:
286 smbsr_error(sr, status, ERRSRV, ERRbaduid);
287 return (SDRC_ERROR);
288
289 case NT_STATUS_INSUFF_SERVER_RESOURCES:
290 smbsr_error(sr, status, ERRSRV, ERRnoresource);
291 return (SDRC_ERROR);
292
293 case NT_STATUS_INTERNAL_ERROR:
294 default:
295 smbsr_error(sr, status, ERRSRV, ERRsrverror);
296 return (SDRC_ERROR);
297 }
298
299 action = SMB_USER_IS_GUEST(sr->uid_user) ? 1 : 0;
300
301 switch (sinfo->ssi_type) {
302
303 default:
304 case SMB_SSNSETUP_PRE_NTLM012:
305 case SMB_SSNSETUP_NTLM012_NOEXT:
306
307 rc = smbsr_encode_result(sr, 3, VAR_BCC, "bb.www%uuu",
308 3,
309 sr->andx_com,
310 -1, /* andx_off */
311 action,
312 VAR_BCC,
313 sr,
314 sr->sr_cfg->skc_native_os,
315 sr->sr_cfg->skc_native_lm,
316 sr->sr_cfg->skc_nbdomain);
317 break;
318
319 case SMB_SSNSETUP_NTLM012_EXTSEC:
320
321 rc = smbsr_encode_result(sr, 4, VAR_BCC, "bb.wwww%#cuuu",
322 4,
323 sr->andx_com,
324 -1, /* andx_off */
325 action,
326 sinfo->ssi_oseclen,
327 VAR_BCC,
328 sr,
329 sinfo->ssi_oseclen,
330 sinfo->ssi_osecblob,
331 sr->sr_cfg->skc_native_os,
332 sr->sr_cfg->skc_native_lm,
333 sr->sr_cfg->skc_nbdomain);
334 break;
335 }
336
337 return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
338 }
339