blob: ee6bf47b6cfed40f29f1570a14bb24d1e83fcecc [file] [log] [blame]
Steve French39798772006-05-31 22:40:51 +00001/*
2 * fs/cifs/sess.c
3 *
4 * SMB/CIFS session setup handling routines
5 *
Steve Frenchd185cda2009-04-30 17:45:10 +00006 * Copyright (c) International Business Machines Corp., 2006, 2009
Steve French39798772006-05-31 22:40:51 +00007 * Author(s): Steve French (sfrench@us.ibm.com)
8 *
9 * This library is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU Lesser General Public License as published
11 * by the Free Software Foundation; either version 2.1 of the License, or
12 * (at your option) any later version.
13 *
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
17 * the GNU Lesser General Public License for more details.
18 *
19 * You should have received a copy of the GNU Lesser General Public License
20 * along with this library; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 */
23
24#include "cifspdu.h"
25#include "cifsglob.h"
26#include "cifsproto.h"
27#include "cifs_unicode.h"
28#include "cifs_debug.h"
29#include "ntlmssp.h"
30#include "nterr.h"
Steve French9c535882006-06-01 05:09:10 +000031#include <linux/utsname.h>
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090032#include <linux/slab.h>
Steve French24424212007-11-16 23:37:35 +000033#include "cifs_spnego.h"
Aurelien Apteld70e9fa2019-09-20 06:31:10 +020034#include "smb2proto.h"
35
36bool
37is_server_using_iface(struct TCP_Server_Info *server,
38 struct cifs_server_iface *iface)
39{
40 struct sockaddr_in *i4 = (struct sockaddr_in *)&iface->sockaddr;
41 struct sockaddr_in6 *i6 = (struct sockaddr_in6 *)&iface->sockaddr;
42 struct sockaddr_in *s4 = (struct sockaddr_in *)&server->dstaddr;
43 struct sockaddr_in6 *s6 = (struct sockaddr_in6 *)&server->dstaddr;
44
45 if (server->dstaddr.ss_family != iface->sockaddr.ss_family)
46 return false;
47 if (server->dstaddr.ss_family == AF_INET) {
48 if (s4->sin_addr.s_addr != i4->sin_addr.s_addr)
49 return false;
50 } else if (server->dstaddr.ss_family == AF_INET6) {
51 if (memcmp(&s6->sin6_addr, &i6->sin6_addr,
52 sizeof(i6->sin6_addr)) != 0)
53 return false;
54 } else {
55 /* unknown family.. */
56 return false;
57 }
58 return true;
59}
60
61bool is_ses_using_iface(struct cifs_ses *ses, struct cifs_server_iface *iface)
62{
63 int i;
64
65 for (i = 0; i < ses->chan_count; i++) {
66 if (is_server_using_iface(ses->chans[i].server, iface))
67 return true;
68 }
69 return false;
70}
71
72/* returns number of channels added */
73int cifs_try_adding_channels(struct cifs_ses *ses)
74{
75 int old_chan_count = ses->chan_count;
76 int left = ses->chan_max - ses->chan_count;
77 int i = 0;
78 int rc = 0;
79
80 if (left <= 0) {
81 cifs_dbg(FYI,
82 "ses already at max_channels (%zu), nothing to open\n",
83 ses->chan_max);
84 return 0;
85 }
86
87 if (ses->server->dialect < SMB30_PROT_ID) {
88 cifs_dbg(VFS, "multichannel is not supported on this protocol version, use 3.0 or above\n");
89 return 0;
90 }
91
92 /* ifaces are sorted by speed, try them in order */
93 for (i = 0; left > 0 && i < ses->iface_count; i++) {
94 struct cifs_server_iface *iface;
95
96 iface = &ses->iface_list[i];
97 if (is_ses_using_iface(ses, iface) && !iface->rss_capable)
98 continue;
99
100 rc = cifs_ses_add_channel(ses, iface);
101 if (rc) {
102 cifs_dbg(FYI, "failed to open extra channel\n");
103 continue;
104 }
105
106 cifs_dbg(FYI, "successfully opened new channel\n");
107 left--;
108 }
109
110 /*
111 * TODO: if we still have channels left to open try to connect
112 * to same RSS-capable iface multiple times
113 */
114
115 return ses->chan_count - old_chan_count;
116}
117
118int
119cifs_ses_add_channel(struct cifs_ses *ses, struct cifs_server_iface *iface)
120{
121 struct cifs_chan *chan;
122 struct smb_vol vol = {NULL};
123 static const char unc_fmt[] = "\\%s\\foo";
124 char unc[sizeof(unc_fmt)+SERVER_NAME_LEN_WITH_NULL] = {0};
125 struct sockaddr_in *ipv4 = (struct sockaddr_in *)&iface->sockaddr;
126 struct sockaddr_in6 *ipv6 = (struct sockaddr_in6 *)&iface->sockaddr;
127 int rc;
128 unsigned int xid = get_xid();
129
130 cifs_dbg(FYI, "adding channel to ses %p (speed:%zu bps rdma:%s ",
131 ses, iface->speed, iface->rdma_capable ? "yes" : "no");
132 if (iface->sockaddr.ss_family == AF_INET)
133 cifs_dbg(FYI, "ip:%pI4)\n", &ipv4->sin_addr);
134 else
135 cifs_dbg(FYI, "ip:%pI6)\n", &ipv6->sin6_addr);
136
137 /*
138 * Setup a smb_vol with mostly the same info as the existing
139 * session and overwrite it with the requested iface data.
140 *
141 * We need to setup at least the fields used for negprot and
142 * sesssetup.
143 *
144 * We only need the volume here, so we can reuse memory from
145 * the session and server without caring about memory
146 * management.
147 */
148
149 /* Always make new connection for now (TODO?) */
150 vol.nosharesock = true;
151
152 /* Auth */
153 vol.domainauto = ses->domainAuto;
154 vol.domainname = ses->domainName;
155 vol.username = ses->user_name;
156 vol.password = ses->password;
157 vol.sectype = ses->sectype;
158 vol.sign = ses->sign;
159
160 /* UNC and paths */
161 /* XXX: Use ses->server->hostname? */
162 sprintf(unc, unc_fmt, ses->serverName);
163 vol.UNC = unc;
164 vol.prepath = "";
165
166 /* Re-use same version as master connection */
167 vol.vals = ses->server->vals;
168 vol.ops = ses->server->ops;
169
170 vol.noblocksnd = ses->server->noblocksnd;
171 vol.noautotune = ses->server->noautotune;
172 vol.sockopt_tcp_nodelay = ses->server->tcp_nodelay;
173 vol.echo_interval = ses->server->echo_interval / HZ;
174
175 /*
176 * This will be used for encoding/decoding user/domain/pw
177 * during sess setup auth.
178 *
179 * XXX: We use the default for simplicity but the proper way
180 * would be to use the one that ses used, which is not
181 * stored. This might break when dealing with non-ascii
182 * strings.
183 */
184 vol.local_nls = load_nls_default();
185
186 /* Use RDMA if possible */
187 vol.rdma = iface->rdma_capable;
188 memcpy(&vol.dstaddr, &iface->sockaddr, sizeof(struct sockaddr_storage));
189
190 /* reuse master con client guid */
191 memcpy(&vol.client_guid, ses->server->client_guid,
192 SMB2_CLIENT_GUID_SIZE);
193 vol.use_client_guid = true;
194
195 mutex_lock(&ses->session_mutex);
196
197 chan = &ses->chans[ses->chan_count];
198 chan->server = cifs_get_tcp_session(&vol);
199 if (IS_ERR(chan->server)) {
200 rc = PTR_ERR(chan->server);
201 chan->server = NULL;
202 goto out;
203 }
204
205 /*
206 * We need to allocate the server crypto now as we will need
207 * to sign packets before we generate the channel signing key
208 * (we sign with the session key)
209 */
210 rc = smb311_crypto_shash_allocate(chan->server);
211 if (rc) {
212 cifs_dbg(VFS, "%s: crypto alloc failed\n", __func__);
213 goto out;
214 }
215
216 ses->binding = true;
217 rc = cifs_negotiate_protocol(xid, ses);
218 if (rc)
219 goto out;
220
221 rc = cifs_setup_session(xid, ses, vol.local_nls);
222 if (rc)
223 goto out;
224
225 /* success, put it on the list
226 * XXX: sharing ses between 2 tcp server is not possible, the
227 * way "internal" linked lists works in linux makes element
228 * only able to belong to one list
229 *
230 * the binding session is already established so the rest of
231 * the code should be able to look it up, no need to add the
232 * ses to the new server.
233 */
234
235 ses->chan_count++;
236 atomic_set(&ses->chan_seq, 0);
237out:
238 ses->binding = false;
239 mutex_unlock(&ses->session_mutex);
240
241 if (rc && chan->server)
242 cifs_put_tcp_session(chan->server, 0);
243 unload_nls(vol.local_nls);
244
245 return rc;
246}
Steve French39798772006-05-31 22:40:51 +0000247
Steve French96daf2b2011-05-27 04:34:02 +0000248static __u32 cifs_ssetup_hdr(struct cifs_ses *ses, SESSION_SETUP_ANDX *pSMB)
Steve French39798772006-05-31 22:40:51 +0000249{
250 __u32 capabilities = 0;
251
252 /* init fields common to all four types of SessSetup */
Steve Frencheca6acf2009-02-20 05:43:09 +0000253 /* Note that offsets for first seven fields in req struct are same */
254 /* in CIFS Specs so does not matter which of 3 forms of struct */
255 /* that we use in next few lines */
256 /* Note that header is initialized to zero in header_assemble */
Steve French39798772006-05-31 22:40:51 +0000257 pSMB->req.AndXCommand = 0xFF;
Jeff Laytonc974bef2011-10-11 06:41:32 -0400258 pSMB->req.MaxBufferSize = cpu_to_le16(min_t(u32,
259 CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4,
260 USHRT_MAX));
Steve French39798772006-05-31 22:40:51 +0000261 pSMB->req.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
Fabian Frederickbc09d142014-12-10 15:41:15 -0800262 pSMB->req.VcNumber = cpu_to_le16(1);
Steve French39798772006-05-31 22:40:51 +0000263
264 /* Now no need to set SMBFLG_CASELESS or obsolete CANONICAL PATH */
265
Steve French790fe572007-07-07 19:25:05 +0000266 /* BB verify whether signing required on neg or just on auth frame
Steve French39798772006-05-31 22:40:51 +0000267 (and NTLM case) */
268
269 capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
270 CAP_LARGE_WRITE_X | CAP_LARGE_READ_X;
271
Jeff Layton38d77c52013-05-26 07:01:00 -0400272 if (ses->server->sign)
Steve French39798772006-05-31 22:40:51 +0000273 pSMB->req.hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
274
275 if (ses->capabilities & CAP_UNICODE) {
276 pSMB->req.hdr.Flags2 |= SMBFLG2_UNICODE;
277 capabilities |= CAP_UNICODE;
278 }
279 if (ses->capabilities & CAP_STATUS32) {
280 pSMB->req.hdr.Flags2 |= SMBFLG2_ERR_STATUS;
281 capabilities |= CAP_STATUS32;
282 }
283 if (ses->capabilities & CAP_DFS) {
284 pSMB->req.hdr.Flags2 |= SMBFLG2_DFS;
285 capabilities |= CAP_DFS;
286 }
Steve French26f57362007-08-30 22:09:15 +0000287 if (ses->capabilities & CAP_UNIX)
Steve French39798772006-05-31 22:40:51 +0000288 capabilities |= CAP_UNIX;
Steve French39798772006-05-31 22:40:51 +0000289
Steve French39798772006-05-31 22:40:51 +0000290 return capabilities;
291}
292
Jeff Layton0d3a01f2007-10-16 17:32:19 +0000293static void
294unicode_oslm_strings(char **pbcc_area, const struct nls_table *nls_cp)
295{
296 char *bcc_ptr = *pbcc_area;
297 int bytes_ret = 0;
298
299 /* Copy OS version */
Steve Frenchacbbb762012-01-18 22:32:33 -0600300 bytes_ret = cifs_strtoUTF16((__le16 *)bcc_ptr, "Linux version ", 32,
301 nls_cp);
Jeff Layton0d3a01f2007-10-16 17:32:19 +0000302 bcc_ptr += 2 * bytes_ret;
Steve Frenchacbbb762012-01-18 22:32:33 -0600303 bytes_ret = cifs_strtoUTF16((__le16 *) bcc_ptr, init_utsname()->release,
304 32, nls_cp);
Jeff Layton0d3a01f2007-10-16 17:32:19 +0000305 bcc_ptr += 2 * bytes_ret;
306 bcc_ptr += 2; /* trailing null */
307
Steve Frenchacbbb762012-01-18 22:32:33 -0600308 bytes_ret = cifs_strtoUTF16((__le16 *) bcc_ptr, CIFS_NETWORK_OPSYS,
309 32, nls_cp);
Jeff Layton0d3a01f2007-10-16 17:32:19 +0000310 bcc_ptr += 2 * bytes_ret;
311 bcc_ptr += 2; /* trailing null */
312
313 *pbcc_area = bcc_ptr;
314}
315
Steve French96daf2b2011-05-27 04:34:02 +0000316static void unicode_domain_string(char **pbcc_area, struct cifs_ses *ses,
Jeff Layton0d3a01f2007-10-16 17:32:19 +0000317 const struct nls_table *nls_cp)
318{
319 char *bcc_ptr = *pbcc_area;
320 int bytes_ret = 0;
321
322 /* copy domain */
323 if (ses->domainName == NULL) {
324 /* Sending null domain better than using a bogus domain name (as
325 we did briefly in 2.6.18) since server will use its default */
326 *bcc_ptr = 0;
327 *(bcc_ptr+1) = 0;
328 bytes_ret = 0;
329 } else
Steve Frenchacbbb762012-01-18 22:32:33 -0600330 bytes_ret = cifs_strtoUTF16((__le16 *) bcc_ptr, ses->domainName,
Chen Gang057d6332013-07-19 09:01:36 +0800331 CIFS_MAX_DOMAINNAME_LEN, nls_cp);
Jeff Layton0d3a01f2007-10-16 17:32:19 +0000332 bcc_ptr += 2 * bytes_ret;
333 bcc_ptr += 2; /* account for null terminator */
334
335 *pbcc_area = bcc_ptr;
336}
337
338
Steve French96daf2b2011-05-27 04:34:02 +0000339static void unicode_ssetup_strings(char **pbcc_area, struct cifs_ses *ses,
Steve French790fe572007-07-07 19:25:05 +0000340 const struct nls_table *nls_cp)
Steve French39798772006-05-31 22:40:51 +0000341{
Steve French790fe572007-07-07 19:25:05 +0000342 char *bcc_ptr = *pbcc_area;
Steve French39798772006-05-31 22:40:51 +0000343 int bytes_ret = 0;
344
345 /* BB FIXME add check that strings total less
346 than 335 or will need to send them as arrays */
347
Steve French0223cf02006-06-27 19:50:57 +0000348 /* unicode strings, must be word aligned before the call */
349/* if ((long) bcc_ptr % 2) {
Steve French39798772006-05-31 22:40:51 +0000350 *bcc_ptr = 0;
351 bcc_ptr++;
Steve French0223cf02006-06-27 19:50:57 +0000352 } */
Steve French39798772006-05-31 22:40:51 +0000353 /* copy user */
Steve French8727c8a2011-02-25 01:11:56 -0600354 if (ses->user_name == NULL) {
Steve French6e659c62006-11-08 23:10:46 +0000355 /* null user mount */
356 *bcc_ptr = 0;
357 *(bcc_ptr+1) = 0;
Steve French301a6a32010-02-06 07:08:53 +0000358 } else {
Steve Frenchacbbb762012-01-18 22:32:33 -0600359 bytes_ret = cifs_strtoUTF16((__le16 *) bcc_ptr, ses->user_name,
Scott Lovenberg8c3a2b42013-08-09 08:47:17 -0400360 CIFS_MAX_USERNAME_LEN, nls_cp);
Steve French39798772006-05-31 22:40:51 +0000361 }
362 bcc_ptr += 2 * bytes_ret;
363 bcc_ptr += 2; /* account for null termination */
Steve French39798772006-05-31 22:40:51 +0000364
Jeff Layton0d3a01f2007-10-16 17:32:19 +0000365 unicode_domain_string(&bcc_ptr, ses, nls_cp);
366 unicode_oslm_strings(&bcc_ptr, nls_cp);
Steve French39798772006-05-31 22:40:51 +0000367
368 *pbcc_area = bcc_ptr;
369}
370
Steve French96daf2b2011-05-27 04:34:02 +0000371static void ascii_ssetup_strings(char **pbcc_area, struct cifs_ses *ses,
Steve French790fe572007-07-07 19:25:05 +0000372 const struct nls_table *nls_cp)
Steve French39798772006-05-31 22:40:51 +0000373{
Steve French790fe572007-07-07 19:25:05 +0000374 char *bcc_ptr = *pbcc_area;
Ronnie Sahlberg340625e2019-08-27 09:30:14 +1000375 int len;
Steve French39798772006-05-31 22:40:51 +0000376
377 /* copy user */
378 /* BB what about null user mounts - check that we do this BB */
Steve French790fe572007-07-07 19:25:05 +0000379 /* copy user */
Shirish Pargaonkarde47a412012-02-02 15:28:28 -0600380 if (ses->user_name != NULL) {
Ronnie Sahlberg340625e2019-08-27 09:30:14 +1000381 len = strscpy(bcc_ptr, ses->user_name, CIFS_MAX_USERNAME_LEN);
382 if (WARN_ON_ONCE(len < 0))
383 len = CIFS_MAX_USERNAME_LEN - 1;
384 bcc_ptr += len;
Shirish Pargaonkarde47a412012-02-02 15:28:28 -0600385 }
Steve French8727c8a2011-02-25 01:11:56 -0600386 /* else null user mount */
Steve French39798772006-05-31 22:40:51 +0000387 *bcc_ptr = 0;
Steve French790fe572007-07-07 19:25:05 +0000388 bcc_ptr++; /* account for null termination */
Steve French39798772006-05-31 22:40:51 +0000389
Steve French790fe572007-07-07 19:25:05 +0000390 /* copy domain */
Steve French790fe572007-07-07 19:25:05 +0000391 if (ses->domainName != NULL) {
Ronnie Sahlberg340625e2019-08-27 09:30:14 +1000392 len = strscpy(bcc_ptr, ses->domainName, CIFS_MAX_DOMAINNAME_LEN);
393 if (WARN_ON_ONCE(len < 0))
394 len = CIFS_MAX_DOMAINNAME_LEN - 1;
395 bcc_ptr += len;
Steve French790fe572007-07-07 19:25:05 +0000396 } /* else we will send a null domain name
Steve French6e659c62006-11-08 23:10:46 +0000397 so the server will default to its own domain */
Steve French39798772006-05-31 22:40:51 +0000398 *bcc_ptr = 0;
399 bcc_ptr++;
400
401 /* BB check for overflow here */
402
403 strcpy(bcc_ptr, "Linux version ");
404 bcc_ptr += strlen("Linux version ");
Serge E. Hallyn96b644b2006-10-02 02:18:13 -0700405 strcpy(bcc_ptr, init_utsname()->release);
406 bcc_ptr += strlen(init_utsname()->release) + 1;
Steve French39798772006-05-31 22:40:51 +0000407
408 strcpy(bcc_ptr, CIFS_NETWORK_OPSYS);
409 bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1;
410
Steve French790fe572007-07-07 19:25:05 +0000411 *pbcc_area = bcc_ptr;
Steve French39798772006-05-31 22:40:51 +0000412}
413
Jeff Layton59140792009-04-30 07:16:21 -0400414static void
Steve French96daf2b2011-05-27 04:34:02 +0000415decode_unicode_ssetup(char **pbcc_area, int bleft, struct cifs_ses *ses,
Jeff Layton59140792009-04-30 07:16:21 -0400416 const struct nls_table *nls_cp)
Steve French39798772006-05-31 22:40:51 +0000417{
Jeff Layton59140792009-04-30 07:16:21 -0400418 int len;
Steve French790fe572007-07-07 19:25:05 +0000419 char *data = *pbcc_area;
Steve French39798772006-05-31 22:40:51 +0000420
Joe Perchesf96637b2013-05-04 22:12:25 -0500421 cifs_dbg(FYI, "bleft %d\n", bleft);
Steve French39798772006-05-31 22:40:51 +0000422
Steve French26f57362007-08-30 22:09:15 +0000423 kfree(ses->serverOS);
Steve Frenchacbbb762012-01-18 22:32:33 -0600424 ses->serverOS = cifs_strndup_from_utf16(data, bleft, true, nls_cp);
Joe Perchesf96637b2013-05-04 22:12:25 -0500425 cifs_dbg(FYI, "serverOS=%s\n", ses->serverOS);
Jeff Layton59140792009-04-30 07:16:21 -0400426 len = (UniStrnlen((wchar_t *) data, bleft / 2) * 2) + 2;
427 data += len;
428 bleft -= len;
429 if (bleft <= 0)
430 return;
Steve French39798772006-05-31 22:40:51 +0000431
Steve French26f57362007-08-30 22:09:15 +0000432 kfree(ses->serverNOS);
Steve Frenchacbbb762012-01-18 22:32:33 -0600433 ses->serverNOS = cifs_strndup_from_utf16(data, bleft, true, nls_cp);
Joe Perchesf96637b2013-05-04 22:12:25 -0500434 cifs_dbg(FYI, "serverNOS=%s\n", ses->serverNOS);
Jeff Layton59140792009-04-30 07:16:21 -0400435 len = (UniStrnlen((wchar_t *) data, bleft / 2) * 2) + 2;
436 data += len;
437 bleft -= len;
438 if (bleft <= 0)
439 return;
Steve French39798772006-05-31 22:40:51 +0000440
Steve French26f57362007-08-30 22:09:15 +0000441 kfree(ses->serverDomain);
Steve Frenchacbbb762012-01-18 22:32:33 -0600442 ses->serverDomain = cifs_strndup_from_utf16(data, bleft, true, nls_cp);
Joe Perchesf96637b2013-05-04 22:12:25 -0500443 cifs_dbg(FYI, "serverDomain=%s\n", ses->serverDomain);
Steve French790fe572007-07-07 19:25:05 +0000444
Jeff Layton59140792009-04-30 07:16:21 -0400445 return;
Steve French39798772006-05-31 22:40:51 +0000446}
447
Jeff Layton7d066452013-05-24 07:41:00 -0400448static void decode_ascii_ssetup(char **pbcc_area, __u16 bleft,
449 struct cifs_ses *ses,
450 const struct nls_table *nls_cp)
Steve French39798772006-05-31 22:40:51 +0000451{
Steve French39798772006-05-31 22:40:51 +0000452 int len;
Steve French790fe572007-07-07 19:25:05 +0000453 char *bcc_ptr = *pbcc_area;
Steve French39798772006-05-31 22:40:51 +0000454
Joe Perchesf96637b2013-05-04 22:12:25 -0500455 cifs_dbg(FYI, "decode sessetup ascii. bleft %d\n", bleft);
Steve French50c2f752007-07-13 00:33:32 +0000456
Steve French39798772006-05-31 22:40:51 +0000457 len = strnlen(bcc_ptr, bleft);
Steve French790fe572007-07-07 19:25:05 +0000458 if (len >= bleft)
Jeff Layton7d066452013-05-24 07:41:00 -0400459 return;
Steve French50c2f752007-07-13 00:33:32 +0000460
Steve French26f57362007-08-30 22:09:15 +0000461 kfree(ses->serverOS);
Steve French39798772006-05-31 22:40:51 +0000462
Ronnie Sahlberg340625e2019-08-27 09:30:14 +1000463 ses->serverOS = kmalloc(len + 1, GFP_KERNEL);
Namjae Jeon27b7edc2014-08-20 19:39:28 +0900464 if (ses->serverOS) {
Ronnie Sahlberg340625e2019-08-27 09:30:14 +1000465 memcpy(ses->serverOS, bcc_ptr, len);
466 ses->serverOS[len] = 0;
Namjae Jeon27b7edc2014-08-20 19:39:28 +0900467 if (strncmp(ses->serverOS, "OS/2", 4) == 0)
468 cifs_dbg(FYI, "OS/2 server\n");
469 }
Steve French39798772006-05-31 22:40:51 +0000470
471 bcc_ptr += len + 1;
472 bleft -= len + 1;
473
474 len = strnlen(bcc_ptr, bleft);
Steve French790fe572007-07-07 19:25:05 +0000475 if (len >= bleft)
Jeff Layton7d066452013-05-24 07:41:00 -0400476 return;
Steve French39798772006-05-31 22:40:51 +0000477
Steve French26f57362007-08-30 22:09:15 +0000478 kfree(ses->serverNOS);
Steve French39798772006-05-31 22:40:51 +0000479
Ronnie Sahlberg340625e2019-08-27 09:30:14 +1000480 ses->serverNOS = kmalloc(len + 1, GFP_KERNEL);
481 if (ses->serverNOS) {
482 memcpy(ses->serverNOS, bcc_ptr, len);
483 ses->serverNOS[len] = 0;
484 }
Steve French39798772006-05-31 22:40:51 +0000485
486 bcc_ptr += len + 1;
487 bleft -= len + 1;
488
Steve French790fe572007-07-07 19:25:05 +0000489 len = strnlen(bcc_ptr, bleft);
490 if (len > bleft)
Jeff Layton7d066452013-05-24 07:41:00 -0400491 return;
Steve French39798772006-05-31 22:40:51 +0000492
Steve French9ac00b72006-09-30 04:13:17 +0000493 /* No domain field in LANMAN case. Domain is
494 returned by old servers in the SMB negprot response */
495 /* BB For newer servers which do not support Unicode,
496 but thus do return domain here we could add parsing
497 for it later, but it is not very important */
Joe Perchesf96637b2013-05-04 22:12:25 -0500498 cifs_dbg(FYI, "ascii: bytes left %d\n", bleft);
Steve French39798772006-05-31 22:40:51 +0000499}
500
Pavel Shilovsky5478f9b2011-12-27 16:22:00 +0400501int decode_ntlmssp_challenge(char *bcc_ptr, int blob_len,
Steve French96daf2b2011-05-27 04:34:02 +0000502 struct cifs_ses *ses)
Steve French0b3cc8582009-05-04 08:37:12 +0000503{
Shirish Pargaonkar2b149f12010-09-18 22:02:18 -0500504 unsigned int tioffset; /* challenge message target info area */
505 unsigned int tilen; /* challenge message target info area length */
506
Steve French0b3cc8582009-05-04 08:37:12 +0000507 CHALLENGE_MESSAGE *pblob = (CHALLENGE_MESSAGE *)bcc_ptr;
508
509 if (blob_len < sizeof(CHALLENGE_MESSAGE)) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500510 cifs_dbg(VFS, "challenge blob len %d too small\n", blob_len);
Steve French0b3cc8582009-05-04 08:37:12 +0000511 return -EINVAL;
512 }
513
514 if (memcmp(pblob->Signature, "NTLMSSP", 8)) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500515 cifs_dbg(VFS, "blob signature incorrect %s\n",
516 pblob->Signature);
Steve French0b3cc8582009-05-04 08:37:12 +0000517 return -EINVAL;
518 }
519 if (pblob->MessageType != NtLmChallenge) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500520 cifs_dbg(VFS, "Incorrect message type %d\n",
521 pblob->MessageType);
Steve French0b3cc8582009-05-04 08:37:12 +0000522 return -EINVAL;
523 }
524
Shirish Pargaonkard3686d52010-10-28 09:53:07 -0500525 memcpy(ses->ntlmssp->cryptkey, pblob->Challenge, CIFS_CRYPTO_KEY_SIZE);
Steve French0b3cc8582009-05-04 08:37:12 +0000526 /* BB we could decode pblob->NegotiateFlags; some may be useful */
527 /* In particular we can examine sign flags */
528 /* BB spec says that if AvId field of MsvAvTimestamp is populated then
529 we must set the MIC field of the AUTHENTICATE_MESSAGE */
Shirish Pargaonkard3686d52010-10-28 09:53:07 -0500530 ses->ntlmssp->server_flags = le32_to_cpu(pblob->NegotiateFlags);
Steve French5443d132011-03-13 05:08:25 +0000531 tioffset = le32_to_cpu(pblob->TargetInfoArray.BufferOffset);
532 tilen = le16_to_cpu(pblob->TargetInfoArray.Length);
Dan Carpenter4991a5f2012-01-31 11:52:01 +0300533 if (tioffset > blob_len || tioffset + tilen > blob_len) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500534 cifs_dbg(VFS, "tioffset + tilen too high %u + %u",
535 tioffset, tilen);
Dan Carpenter4991a5f2012-01-31 11:52:01 +0300536 return -EINVAL;
537 }
Shirish Pargaonkard3686d52010-10-28 09:53:07 -0500538 if (tilen) {
Silviu-Mihai Popescuf7f7c182013-03-11 18:22:32 +0200539 ses->auth_key.response = kmemdup(bcc_ptr + tioffset, tilen,
540 GFP_KERNEL);
Shirish Pargaonkard3686d52010-10-28 09:53:07 -0500541 if (!ses->auth_key.response) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500542 cifs_dbg(VFS, "Challenge target info alloc failure");
Shirish Pargaonkar2b149f12010-09-18 22:02:18 -0500543 return -ENOMEM;
544 }
Shirish Pargaonkard3686d52010-10-28 09:53:07 -0500545 ses->auth_key.len = tilen;
Shirish Pargaonkar2b149f12010-09-18 22:02:18 -0500546 }
547
Steve French0b3cc8582009-05-04 08:37:12 +0000548 return 0;
549}
550
Steve French0b3cc8582009-05-04 08:37:12 +0000551/* BB Move to ntlmssp.c eventually */
552
553/* We do not malloc the blob, it is passed in pbuffer, because
554 it is fixed size, and small, making this approach cleaner */
Pavel Shilovsky5478f9b2011-12-27 16:22:00 +0400555void build_ntlmssp_negotiate_blob(unsigned char *pbuffer,
Steve French96daf2b2011-05-27 04:34:02 +0000556 struct cifs_ses *ses)
Steve French0b3cc8582009-05-04 08:37:12 +0000557{
Aurelien Aptelf6a6bf72019-09-20 06:22:14 +0200558 struct TCP_Server_Info *server = cifs_ses_server(ses);
Steve French0b3cc8582009-05-04 08:37:12 +0000559 NEGOTIATE_MESSAGE *sec_blob = (NEGOTIATE_MESSAGE *)pbuffer;
560 __u32 flags;
561
Shirish Pargaonkardf8fbc242010-12-11 14:19:22 -0600562 memset(pbuffer, 0, sizeof(NEGOTIATE_MESSAGE));
Steve French0b3cc8582009-05-04 08:37:12 +0000563 memcpy(sec_blob->Signature, NTLMSSP_SIGNATURE, 8);
564 sec_blob->MessageType = NtLmNegotiate;
565
566 /* BB is NTLMV2 session security format easier to use here? */
567 flags = NTLMSSP_NEGOTIATE_56 | NTLMSSP_REQUEST_TARGET |
568 NTLMSSP_NEGOTIATE_128 | NTLMSSP_NEGOTIATE_UNICODE |
Pavel Shilovskycabfb362016-11-07 18:20:50 -0800569 NTLMSSP_NEGOTIATE_NTLM | NTLMSSP_NEGOTIATE_EXTENDED_SEC |
570 NTLMSSP_NEGOTIATE_SEAL;
Aurelien Aptelf6a6bf72019-09-20 06:22:14 +0200571 if (server->sign)
Steve French745e5072010-09-08 21:09:27 +0000572 flags |= NTLMSSP_NEGOTIATE_SIGN;
Aurelien Aptelf6a6bf72019-09-20 06:22:14 +0200573 if (!server->session_estab || ses->ntlmssp->sesskey_per_smbsess)
Pavel Shilovskycabfb362016-11-07 18:20:50 -0800574 flags |= NTLMSSP_NEGOTIATE_KEY_XCH;
Steve French0b3cc8582009-05-04 08:37:12 +0000575
Shirish Pargaonkardf8fbc242010-12-11 14:19:22 -0600576 sec_blob->NegotiateFlags = cpu_to_le32(flags);
Steve French0b3cc8582009-05-04 08:37:12 +0000577
578 sec_blob->WorkstationName.BufferOffset = 0;
579 sec_blob->WorkstationName.Length = 0;
580 sec_blob->WorkstationName.MaximumLength = 0;
581
582 /* Domain name is sent on the Challenge not Negotiate NTLMSSP request */
583 sec_blob->DomainName.BufferOffset = 0;
584 sec_blob->DomainName.Length = 0;
585 sec_blob->DomainName.MaximumLength = 0;
586}
587
Jerome Marchandb8da3442016-05-26 11:52:25 +0200588static int size_of_ntlmssp_blob(struct cifs_ses *ses)
589{
590 int sz = sizeof(AUTHENTICATE_MESSAGE) + ses->auth_key.len
591 - CIFS_SESS_KEY_SIZE + CIFS_CPHTXT_SIZE + 2;
592
593 if (ses->domainName)
594 sz += 2 * strnlen(ses->domainName, CIFS_MAX_DOMAINNAME_LEN);
595 else
596 sz += 2;
597
598 if (ses->user_name)
599 sz += 2 * strnlen(ses->user_name, CIFS_MAX_USERNAME_LEN);
600 else
601 sz += 2;
602
603 return sz;
604}
605
606int build_ntlmssp_auth_blob(unsigned char **pbuffer,
Shirish Pargaonkar89f150f2010-10-19 11:47:52 -0500607 u16 *buflen,
Steve French96daf2b2011-05-27 04:34:02 +0000608 struct cifs_ses *ses,
Shirish Pargaonkar2b149f12010-09-18 22:02:18 -0500609 const struct nls_table *nls_cp)
Steve French0b3cc8582009-05-04 08:37:12 +0000610{
Shirish Pargaonkar2b149f12010-09-18 22:02:18 -0500611 int rc;
Jerome Marchandb8da3442016-05-26 11:52:25 +0200612 AUTHENTICATE_MESSAGE *sec_blob;
Steve French0b3cc8582009-05-04 08:37:12 +0000613 __u32 flags;
614 unsigned char *tmp;
Steve French0b3cc8582009-05-04 08:37:12 +0000615
Jerome Marchandb8da3442016-05-26 11:52:25 +0200616 rc = setup_ntlmv2_rsp(ses, nls_cp);
617 if (rc) {
618 cifs_dbg(VFS, "Error %d during NTLMSSP authentication\n", rc);
619 *buflen = 0;
620 goto setup_ntlmv2_ret;
621 }
622 *pbuffer = kmalloc(size_of_ntlmssp_blob(ses), GFP_KERNEL);
Nicholas Mc Guire126c97f2018-08-23 12:24:02 +0200623 if (!*pbuffer) {
624 rc = -ENOMEM;
625 cifs_dbg(VFS, "Error %d during NTLMSSP allocation\n", rc);
626 *buflen = 0;
627 goto setup_ntlmv2_ret;
628 }
Jerome Marchandb8da3442016-05-26 11:52:25 +0200629 sec_blob = (AUTHENTICATE_MESSAGE *)*pbuffer;
630
Steve French0b3cc8582009-05-04 08:37:12 +0000631 memcpy(sec_blob->Signature, NTLMSSP_SIGNATURE, 8);
632 sec_blob->MessageType = NtLmAuthenticate;
633
634 flags = NTLMSSP_NEGOTIATE_56 |
635 NTLMSSP_REQUEST_TARGET | NTLMSSP_NEGOTIATE_TARGET_INFO |
636 NTLMSSP_NEGOTIATE_128 | NTLMSSP_NEGOTIATE_UNICODE |
Pavel Shilovskycabfb362016-11-07 18:20:50 -0800637 NTLMSSP_NEGOTIATE_NTLM | NTLMSSP_NEGOTIATE_EXTENDED_SEC |
638 NTLMSSP_NEGOTIATE_SEAL;
639 if (ses->server->sign)
Steve French0b3cc8582009-05-04 08:37:12 +0000640 flags |= NTLMSSP_NEGOTIATE_SIGN;
Pavel Shilovskycabfb362016-11-07 18:20:50 -0800641 if (!ses->server->session_estab || ses->ntlmssp->sesskey_per_smbsess)
642 flags |= NTLMSSP_NEGOTIATE_KEY_XCH;
Steve French0b3cc8582009-05-04 08:37:12 +0000643
Jerome Marchandb8da3442016-05-26 11:52:25 +0200644 tmp = *pbuffer + sizeof(AUTHENTICATE_MESSAGE);
Shirish Pargaonkardf8fbc242010-12-11 14:19:22 -0600645 sec_blob->NegotiateFlags = cpu_to_le32(flags);
Steve French0b3cc8582009-05-04 08:37:12 +0000646
647 sec_blob->LmChallengeResponse.BufferOffset =
648 cpu_to_le32(sizeof(AUTHENTICATE_MESSAGE));
649 sec_blob->LmChallengeResponse.Length = 0;
650 sec_blob->LmChallengeResponse.MaximumLength = 0;
651
Jerome Marchandb8da3442016-05-26 11:52:25 +0200652 sec_blob->NtChallengeResponse.BufferOffset =
653 cpu_to_le32(tmp - *pbuffer);
Stefan Metzmachercfda35d2016-05-03 10:52:30 +0200654 if (ses->user_name != NULL) {
Stefan Metzmachercfda35d2016-05-03 10:52:30 +0200655 memcpy(tmp, ses->auth_key.response + CIFS_SESS_KEY_SIZE,
656 ses->auth_key.len - CIFS_SESS_KEY_SIZE);
657 tmp += ses->auth_key.len - CIFS_SESS_KEY_SIZE;
Steve Frenchc8e56f12010-09-08 21:10:58 +0000658
Stefan Metzmachercfda35d2016-05-03 10:52:30 +0200659 sec_blob->NtChallengeResponse.Length =
660 cpu_to_le16(ses->auth_key.len - CIFS_SESS_KEY_SIZE);
661 sec_blob->NtChallengeResponse.MaximumLength =
662 cpu_to_le16(ses->auth_key.len - CIFS_SESS_KEY_SIZE);
663 } else {
664 /*
665 * don't send an NT Response for anonymous access
666 */
667 sec_blob->NtChallengeResponse.Length = 0;
668 sec_blob->NtChallengeResponse.MaximumLength = 0;
669 }
Steve French0b3cc8582009-05-04 08:37:12 +0000670
671 if (ses->domainName == NULL) {
Jerome Marchandb8da3442016-05-26 11:52:25 +0200672 sec_blob->DomainName.BufferOffset = cpu_to_le32(tmp - *pbuffer);
Steve French0b3cc8582009-05-04 08:37:12 +0000673 sec_blob->DomainName.Length = 0;
674 sec_blob->DomainName.MaximumLength = 0;
675 tmp += 2;
676 } else {
677 int len;
Steve Frenchacbbb762012-01-18 22:32:33 -0600678 len = cifs_strtoUTF16((__le16 *)tmp, ses->domainName,
Jerome Marchand202d7722016-05-26 11:52:24 +0200679 CIFS_MAX_DOMAINNAME_LEN, nls_cp);
Steve French0b3cc8582009-05-04 08:37:12 +0000680 len *= 2; /* unicode is 2 bytes each */
Jerome Marchandb8da3442016-05-26 11:52:25 +0200681 sec_blob->DomainName.BufferOffset = cpu_to_le32(tmp - *pbuffer);
Steve French0b3cc8582009-05-04 08:37:12 +0000682 sec_blob->DomainName.Length = cpu_to_le16(len);
683 sec_blob->DomainName.MaximumLength = cpu_to_le16(len);
684 tmp += len;
685 }
686
Steve French8727c8a2011-02-25 01:11:56 -0600687 if (ses->user_name == NULL) {
Jerome Marchandb8da3442016-05-26 11:52:25 +0200688 sec_blob->UserName.BufferOffset = cpu_to_le32(tmp - *pbuffer);
Steve French0b3cc8582009-05-04 08:37:12 +0000689 sec_blob->UserName.Length = 0;
690 sec_blob->UserName.MaximumLength = 0;
691 tmp += 2;
692 } else {
693 int len;
Steve Frenchacbbb762012-01-18 22:32:33 -0600694 len = cifs_strtoUTF16((__le16 *)tmp, ses->user_name,
Scott Lovenberg8c3a2b42013-08-09 08:47:17 -0400695 CIFS_MAX_USERNAME_LEN, nls_cp);
Steve French0b3cc8582009-05-04 08:37:12 +0000696 len *= 2; /* unicode is 2 bytes each */
Jerome Marchandb8da3442016-05-26 11:52:25 +0200697 sec_blob->UserName.BufferOffset = cpu_to_le32(tmp - *pbuffer);
Steve French0b3cc8582009-05-04 08:37:12 +0000698 sec_blob->UserName.Length = cpu_to_le16(len);
699 sec_blob->UserName.MaximumLength = cpu_to_le16(len);
700 tmp += len;
701 }
702
Jerome Marchandb8da3442016-05-26 11:52:25 +0200703 sec_blob->WorkstationName.BufferOffset = cpu_to_le32(tmp - *pbuffer);
Steve French0b3cc8582009-05-04 08:37:12 +0000704 sec_blob->WorkstationName.Length = 0;
705 sec_blob->WorkstationName.MaximumLength = 0;
706 tmp += 2;
707
Shirish Pargaonkardf8fbc242010-12-11 14:19:22 -0600708 if (((ses->ntlmssp->server_flags & NTLMSSP_NEGOTIATE_KEY_XCH) ||
709 (ses->ntlmssp->server_flags & NTLMSSP_NEGOTIATE_EXTENDED_SEC))
710 && !calc_seckey(ses)) {
Shirish Pargaonkard3686d52010-10-28 09:53:07 -0500711 memcpy(tmp, ses->ntlmssp->ciphertext, CIFS_CPHTXT_SIZE);
Jerome Marchandb8da3442016-05-26 11:52:25 +0200712 sec_blob->SessionKey.BufferOffset = cpu_to_le32(tmp - *pbuffer);
Shirish Pargaonkard2b91522010-10-21 14:25:08 -0500713 sec_blob->SessionKey.Length = cpu_to_le16(CIFS_CPHTXT_SIZE);
714 sec_blob->SessionKey.MaximumLength =
715 cpu_to_le16(CIFS_CPHTXT_SIZE);
716 tmp += CIFS_CPHTXT_SIZE;
717 } else {
Jerome Marchandb8da3442016-05-26 11:52:25 +0200718 sec_blob->SessionKey.BufferOffset = cpu_to_le32(tmp - *pbuffer);
Shirish Pargaonkard2b91522010-10-21 14:25:08 -0500719 sec_blob->SessionKey.Length = 0;
720 sec_blob->SessionKey.MaximumLength = 0;
721 }
Shirish Pargaonkar2b149f12010-09-18 22:02:18 -0500722
Jerome Marchandb8da3442016-05-26 11:52:25 +0200723 *buflen = tmp - *pbuffer;
Shirish Pargaonkar2b149f12010-09-18 22:02:18 -0500724setup_ntlmv2_ret:
Shirish Pargaonkar89f150f2010-10-19 11:47:52 -0500725 return rc;
Steve French0b3cc8582009-05-04 08:37:12 +0000726}
Steve French0b3cc8582009-05-04 08:37:12 +0000727
Jeff Layton3f618222013-06-12 19:52:14 -0500728enum securityEnum
Sachin Prabhuef65aae2017-01-18 15:35:57 +0530729cifs_select_sectype(struct TCP_Server_Info *server, enum securityEnum requested)
Jeff Layton3f618222013-06-12 19:52:14 -0500730{
731 switch (server->negflavor) {
732 case CIFS_NEGFLAVOR_EXTENDED:
733 switch (requested) {
734 case Kerberos:
735 case RawNTLMSSP:
736 return requested;
737 case Unspecified:
738 if (server->sec_ntlmssp &&
739 (global_secflags & CIFSSEC_MAY_NTLMSSP))
740 return RawNTLMSSP;
741 if ((server->sec_kerberos || server->sec_mskerberos) &&
742 (global_secflags & CIFSSEC_MAY_KRB5))
743 return Kerberos;
744 /* Fallthrough */
745 default:
746 return Unspecified;
747 }
748 case CIFS_NEGFLAVOR_UNENCAP:
749 switch (requested) {
750 case NTLM:
751 case NTLMv2:
752 return requested;
753 case Unspecified:
754 if (global_secflags & CIFSSEC_MAY_NTLMV2)
755 return NTLMv2;
756 if (global_secflags & CIFSSEC_MAY_NTLM)
757 return NTLM;
Jeff Layton3f618222013-06-12 19:52:14 -0500758 default:
Sachin Prabhudde23562013-09-27 18:35:42 +0100759 break;
Jeff Layton3f618222013-06-12 19:52:14 -0500760 }
Gustavo A. R. Silva07fa6012018-11-27 10:01:51 +1100761 /* Fallthrough - to attempt LANMAN authentication next */
Jeff Layton3f618222013-06-12 19:52:14 -0500762 case CIFS_NEGFLAVOR_LANMAN:
763 switch (requested) {
764 case LANMAN:
765 return requested;
766 case Unspecified:
767 if (global_secflags & CIFSSEC_MAY_LANMAN)
768 return LANMAN;
769 /* Fallthrough */
770 default:
771 return Unspecified;
772 }
773 default:
774 return Unspecified;
775 }
776}
777
Sachin Prabhu80a0e632014-06-16 15:35:25 +0100778struct sess_data {
779 unsigned int xid;
780 struct cifs_ses *ses;
781 struct nls_table *nls_cp;
782 void (*func)(struct sess_data *);
783 int result;
784
785 /* we will send the SMB in three pieces:
786 * a fixed length beginning part, an optional
787 * SPNEGO blob (which can be zero length), and a
788 * last part which will include the strings
789 * and rest of bcc area. This allows us to avoid
790 * a large buffer 17K allocation
791 */
792 int buf0_type;
793 struct kvec iov[3];
794};
795
796static int
797sess_alloc_buffer(struct sess_data *sess_data, int wct)
798{
799 int rc;
800 struct cifs_ses *ses = sess_data->ses;
801 struct smb_hdr *smb_buf;
802
803 rc = small_smb_init_no_tc(SMB_COM_SESSION_SETUP_ANDX, wct, ses,
804 (void **)&smb_buf);
805
806 if (rc)
807 return rc;
808
809 sess_data->iov[0].iov_base = (char *)smb_buf;
810 sess_data->iov[0].iov_len = be32_to_cpu(smb_buf->smb_buf_length) + 4;
811 /*
812 * This variable will be used to clear the buffer
813 * allocated above in case of any error in the calling function.
814 */
815 sess_data->buf0_type = CIFS_SMALL_BUFFER;
816
817 /* 2000 big enough to fit max user, domain, NOS name etc. */
818 sess_data->iov[2].iov_base = kmalloc(2000, GFP_KERNEL);
819 if (!sess_data->iov[2].iov_base) {
820 rc = -ENOMEM;
821 goto out_free_smb_buf;
822 }
823
824 return 0;
825
826out_free_smb_buf:
827 kfree(smb_buf);
828 sess_data->iov[0].iov_base = NULL;
829 sess_data->iov[0].iov_len = 0;
830 sess_data->buf0_type = CIFS_NO_BUFFER;
831 return rc;
832}
833
834static void
835sess_free_buffer(struct sess_data *sess_data)
836{
837
838 free_rsp_buf(sess_data->buf0_type, sess_data->iov[0].iov_base);
839 sess_data->buf0_type = CIFS_NO_BUFFER;
840 kfree(sess_data->iov[2].iov_base);
841}
842
843static int
844sess_establish_session(struct sess_data *sess_data)
845{
846 struct cifs_ses *ses = sess_data->ses;
847
848 mutex_lock(&ses->server->srv_mutex);
849 if (!ses->server->session_estab) {
850 if (ses->server->sign) {
851 ses->server->session_key.response =
852 kmemdup(ses->auth_key.response,
853 ses->auth_key.len, GFP_KERNEL);
854 if (!ses->server->session_key.response) {
855 mutex_unlock(&ses->server->srv_mutex);
856 return -ENOMEM;
857 }
858 ses->server->session_key.len =
859 ses->auth_key.len;
860 }
861 ses->server->sequence_number = 0x2;
862 ses->server->session_estab = true;
863 }
864 mutex_unlock(&ses->server->srv_mutex);
865
866 cifs_dbg(FYI, "CIFS session established successfully\n");
867 spin_lock(&GlobalMid_Lock);
868 ses->status = CifsGood;
869 ses->need_reconnect = false;
870 spin_unlock(&GlobalMid_Lock);
871
872 return 0;
873}
874
875static int
876sess_sendreceive(struct sess_data *sess_data)
877{
878 int rc;
879 struct smb_hdr *smb_buf = (struct smb_hdr *) sess_data->iov[0].iov_base;
880 __u16 count;
Pavel Shilovskyda502f72016-10-25 11:38:47 -0700881 struct kvec rsp_iov = { NULL, 0 };
Sachin Prabhu80a0e632014-06-16 15:35:25 +0100882
883 count = sess_data->iov[1].iov_len + sess_data->iov[2].iov_len;
884 smb_buf->smb_buf_length =
885 cpu_to_be32(be32_to_cpu(smb_buf->smb_buf_length) + count);
886 put_bcc(count, smb_buf);
887
888 rc = SendReceive2(sess_data->xid, sess_data->ses,
889 sess_data->iov, 3 /* num_iovecs */,
890 &sess_data->buf0_type,
Pavel Shilovskyda502f72016-10-25 11:38:47 -0700891 CIFS_LOG_ERROR, &rsp_iov);
892 cifs_small_buf_release(sess_data->iov[0].iov_base);
893 memcpy(&sess_data->iov[0], &rsp_iov, sizeof(struct kvec));
Sachin Prabhu80a0e632014-06-16 15:35:25 +0100894
895 return rc;
896}
897
898/*
899 * LANMAN and plaintext are less secure and off by default.
900 * So we make this explicitly be turned on in kconfig (in the
901 * build) and turned on at runtime (changed from the default)
902 * in proc/fs/cifs or via mount parm. Unfortunately this is
903 * needed for old Win (e.g. Win95), some obscure NAS and OS/2
904 */
905#ifdef CONFIG_CIFS_WEAK_PW_HASH
906static void
907sess_auth_lanman(struct sess_data *sess_data)
908{
909 int rc = 0;
910 struct smb_hdr *smb_buf;
911 SESSION_SETUP_ANDX *pSMB;
912 char *bcc_ptr;
913 struct cifs_ses *ses = sess_data->ses;
914 char lnm_session_key[CIFS_AUTH_RESP_SIZE];
Sachin Prabhu80a0e632014-06-16 15:35:25 +0100915 __u16 bytes_remaining;
916
917 /* lanman 2 style sessionsetup */
918 /* wct = 10 */
919 rc = sess_alloc_buffer(sess_data, 10);
920 if (rc)
921 goto out;
922
923 pSMB = (SESSION_SETUP_ANDX *)sess_data->iov[0].iov_base;
924 bcc_ptr = sess_data->iov[2].iov_base;
zhengbin8559ad82019-09-24 10:13:47 +0800925 (void)cifs_ssetup_hdr(ses, pSMB);
Sachin Prabhu80a0e632014-06-16 15:35:25 +0100926
927 pSMB->req.hdr.Flags2 &= ~SMBFLG2_UNICODE;
928
Stefan Metzmacherfa8f3a32016-05-03 10:52:30 +0200929 if (ses->user_name != NULL) {
930 /* no capabilities flags in old lanman negotiation */
931 pSMB->old_req.PasswordLength = cpu_to_le16(CIFS_AUTH_RESP_SIZE);
Sachin Prabhu80a0e632014-06-16 15:35:25 +0100932
Stefan Metzmacherfa8f3a32016-05-03 10:52:30 +0200933 /* Calculate hash with password and copy into bcc_ptr.
934 * Encryption Key (stored as in cryptkey) gets used if the
935 * security mode bit in Negottiate Protocol response states
936 * to use challenge/response method (i.e. Password bit is 1).
937 */
938 rc = calc_lanman_hash(ses->password, ses->server->cryptkey,
939 ses->server->sec_mode & SECMODE_PW_ENCRYPT ?
940 true : false, lnm_session_key);
Luis de Bethencourta6b6bef2016-06-08 17:02:32 +0100941 if (rc)
942 goto out;
Sachin Prabhu80a0e632014-06-16 15:35:25 +0100943
Stefan Metzmacherfa8f3a32016-05-03 10:52:30 +0200944 memcpy(bcc_ptr, (char *)lnm_session_key, CIFS_AUTH_RESP_SIZE);
945 bcc_ptr += CIFS_AUTH_RESP_SIZE;
946 } else {
947 pSMB->old_req.PasswordLength = 0;
948 }
Sachin Prabhu80a0e632014-06-16 15:35:25 +0100949
950 /*
951 * can not sign if LANMAN negotiated so no need
952 * to calculate signing key? but what if server
953 * changed to do higher than lanman dialect and
954 * we reconnected would we ever calc signing_key?
955 */
956
957 cifs_dbg(FYI, "Negotiating LANMAN setting up strings\n");
958 /* Unicode not allowed for LANMAN dialects */
959 ascii_ssetup_strings(&bcc_ptr, ses, sess_data->nls_cp);
960
961 sess_data->iov[2].iov_len = (long) bcc_ptr -
962 (long) sess_data->iov[2].iov_base;
963
964 rc = sess_sendreceive(sess_data);
965 if (rc)
966 goto out;
967
968 pSMB = (SESSION_SETUP_ANDX *)sess_data->iov[0].iov_base;
969 smb_buf = (struct smb_hdr *)sess_data->iov[0].iov_base;
970
971 /* lanman response has a word count of 3 */
972 if (smb_buf->WordCount != 3) {
973 rc = -EIO;
974 cifs_dbg(VFS, "bad word count %d\n", smb_buf->WordCount);
975 goto out;
976 }
977
978 if (le16_to_cpu(pSMB->resp.Action) & GUEST_LOGIN)
979 cifs_dbg(FYI, "Guest login\n"); /* BB mark SesInfo struct? */
980
981 ses->Suid = smb_buf->Uid; /* UID left in wire format (le) */
982 cifs_dbg(FYI, "UID = %llu\n", ses->Suid);
983
984 bytes_remaining = get_bcc(smb_buf);
985 bcc_ptr = pByteArea(smb_buf);
986
987 /* BB check if Unicode and decode strings */
988 if (bytes_remaining == 0) {
989 /* no string area to decode, do nothing */
990 } else if (smb_buf->Flags2 & SMBFLG2_UNICODE) {
991 /* unicode string area must be word-aligned */
992 if (((unsigned long) bcc_ptr - (unsigned long) smb_buf) % 2) {
993 ++bcc_ptr;
994 --bytes_remaining;
995 }
996 decode_unicode_ssetup(&bcc_ptr, bytes_remaining, ses,
997 sess_data->nls_cp);
998 } else {
999 decode_ascii_ssetup(&bcc_ptr, bytes_remaining, ses,
1000 sess_data->nls_cp);
1001 }
1002
1003 rc = sess_establish_session(sess_data);
1004out:
1005 sess_data->result = rc;
1006 sess_data->func = NULL;
1007 sess_free_buffer(sess_data);
1008}
1009
Sachin Prabhu80a0e632014-06-16 15:35:25 +01001010#endif
1011
Sachin Prabhu583cf7a2014-06-16 15:35:26 +01001012static void
1013sess_auth_ntlm(struct sess_data *sess_data)
1014{
1015 int rc = 0;
1016 struct smb_hdr *smb_buf;
1017 SESSION_SETUP_ANDX *pSMB;
1018 char *bcc_ptr;
1019 struct cifs_ses *ses = sess_data->ses;
1020 __u32 capabilities;
1021 __u16 bytes_remaining;
1022
1023 /* old style NTLM sessionsetup */
1024 /* wct = 13 */
1025 rc = sess_alloc_buffer(sess_data, 13);
1026 if (rc)
1027 goto out;
1028
1029 pSMB = (SESSION_SETUP_ANDX *)sess_data->iov[0].iov_base;
1030 bcc_ptr = sess_data->iov[2].iov_base;
1031 capabilities = cifs_ssetup_hdr(ses, pSMB);
1032
1033 pSMB->req_no_secext.Capabilities = cpu_to_le32(capabilities);
Stefan Metzmacher777f69b2016-05-03 10:52:30 +02001034 if (ses->user_name != NULL) {
1035 pSMB->req_no_secext.CaseInsensitivePasswordLength =
1036 cpu_to_le16(CIFS_AUTH_RESP_SIZE);
1037 pSMB->req_no_secext.CaseSensitivePasswordLength =
1038 cpu_to_le16(CIFS_AUTH_RESP_SIZE);
Sachin Prabhu583cf7a2014-06-16 15:35:26 +01001039
Stefan Metzmacher777f69b2016-05-03 10:52:30 +02001040 /* calculate ntlm response and session key */
1041 rc = setup_ntlm_response(ses, sess_data->nls_cp);
1042 if (rc) {
1043 cifs_dbg(VFS, "Error %d during NTLM authentication\n",
1044 rc);
1045 goto out;
1046 }
1047
1048 /* copy ntlm response */
1049 memcpy(bcc_ptr, ses->auth_key.response + CIFS_SESS_KEY_SIZE,
1050 CIFS_AUTH_RESP_SIZE);
1051 bcc_ptr += CIFS_AUTH_RESP_SIZE;
1052 memcpy(bcc_ptr, ses->auth_key.response + CIFS_SESS_KEY_SIZE,
1053 CIFS_AUTH_RESP_SIZE);
1054 bcc_ptr += CIFS_AUTH_RESP_SIZE;
1055 } else {
1056 pSMB->req_no_secext.CaseInsensitivePasswordLength = 0;
1057 pSMB->req_no_secext.CaseSensitivePasswordLength = 0;
Sachin Prabhu583cf7a2014-06-16 15:35:26 +01001058 }
1059
Sachin Prabhu583cf7a2014-06-16 15:35:26 +01001060 if (ses->capabilities & CAP_UNICODE) {
1061 /* unicode strings must be word aligned */
1062 if (sess_data->iov[0].iov_len % 2) {
1063 *bcc_ptr = 0;
1064 bcc_ptr++;
1065 }
1066 unicode_ssetup_strings(&bcc_ptr, ses, sess_data->nls_cp);
1067 } else {
1068 ascii_ssetup_strings(&bcc_ptr, ses, sess_data->nls_cp);
1069 }
1070
1071
1072 sess_data->iov[2].iov_len = (long) bcc_ptr -
1073 (long) sess_data->iov[2].iov_base;
1074
1075 rc = sess_sendreceive(sess_data);
1076 if (rc)
1077 goto out;
1078
1079 pSMB = (SESSION_SETUP_ANDX *)sess_data->iov[0].iov_base;
1080 smb_buf = (struct smb_hdr *)sess_data->iov[0].iov_base;
1081
1082 if (smb_buf->WordCount != 3) {
1083 rc = -EIO;
1084 cifs_dbg(VFS, "bad word count %d\n", smb_buf->WordCount);
1085 goto out;
1086 }
1087
1088 if (le16_to_cpu(pSMB->resp.Action) & GUEST_LOGIN)
1089 cifs_dbg(FYI, "Guest login\n"); /* BB mark SesInfo struct? */
1090
1091 ses->Suid = smb_buf->Uid; /* UID left in wire format (le) */
1092 cifs_dbg(FYI, "UID = %llu\n", ses->Suid);
1093
1094 bytes_remaining = get_bcc(smb_buf);
1095 bcc_ptr = pByteArea(smb_buf);
1096
1097 /* BB check if Unicode and decode strings */
1098 if (bytes_remaining == 0) {
1099 /* no string area to decode, do nothing */
1100 } else if (smb_buf->Flags2 & SMBFLG2_UNICODE) {
1101 /* unicode string area must be word-aligned */
1102 if (((unsigned long) bcc_ptr - (unsigned long) smb_buf) % 2) {
1103 ++bcc_ptr;
1104 --bytes_remaining;
1105 }
1106 decode_unicode_ssetup(&bcc_ptr, bytes_remaining, ses,
1107 sess_data->nls_cp);
1108 } else {
1109 decode_ascii_ssetup(&bcc_ptr, bytes_remaining, ses,
1110 sess_data->nls_cp);
1111 }
1112
1113 rc = sess_establish_session(sess_data);
1114out:
1115 sess_data->result = rc;
1116 sess_data->func = NULL;
1117 sess_free_buffer(sess_data);
1118 kfree(ses->auth_key.response);
1119 ses->auth_key.response = NULL;
1120}
1121
1122static void
1123sess_auth_ntlmv2(struct sess_data *sess_data)
1124{
1125 int rc = 0;
1126 struct smb_hdr *smb_buf;
1127 SESSION_SETUP_ANDX *pSMB;
1128 char *bcc_ptr;
1129 struct cifs_ses *ses = sess_data->ses;
1130 __u32 capabilities;
1131 __u16 bytes_remaining;
1132
1133 /* old style NTLM sessionsetup */
1134 /* wct = 13 */
1135 rc = sess_alloc_buffer(sess_data, 13);
1136 if (rc)
1137 goto out;
1138
1139 pSMB = (SESSION_SETUP_ANDX *)sess_data->iov[0].iov_base;
1140 bcc_ptr = sess_data->iov[2].iov_base;
1141 capabilities = cifs_ssetup_hdr(ses, pSMB);
1142
1143 pSMB->req_no_secext.Capabilities = cpu_to_le32(capabilities);
1144
1145 /* LM2 password would be here if we supported it */
1146 pSMB->req_no_secext.CaseInsensitivePasswordLength = 0;
1147
Stefan Metzmacher1a967d62016-05-03 10:52:30 +02001148 if (ses->user_name != NULL) {
1149 /* calculate nlmv2 response and session key */
1150 rc = setup_ntlmv2_rsp(ses, sess_data->nls_cp);
1151 if (rc) {
1152 cifs_dbg(VFS, "Error %d during NTLMv2 authentication\n", rc);
1153 goto out;
1154 }
1155
1156 memcpy(bcc_ptr, ses->auth_key.response + CIFS_SESS_KEY_SIZE,
1157 ses->auth_key.len - CIFS_SESS_KEY_SIZE);
1158 bcc_ptr += ses->auth_key.len - CIFS_SESS_KEY_SIZE;
1159
1160 /* set case sensitive password length after tilen may get
1161 * assigned, tilen is 0 otherwise.
1162 */
1163 pSMB->req_no_secext.CaseSensitivePasswordLength =
1164 cpu_to_le16(ses->auth_key.len - CIFS_SESS_KEY_SIZE);
1165 } else {
1166 pSMB->req_no_secext.CaseSensitivePasswordLength = 0;
Sachin Prabhu583cf7a2014-06-16 15:35:26 +01001167 }
1168
Sachin Prabhu583cf7a2014-06-16 15:35:26 +01001169 if (ses->capabilities & CAP_UNICODE) {
1170 if (sess_data->iov[0].iov_len % 2) {
1171 *bcc_ptr = 0;
1172 bcc_ptr++;
1173 }
1174 unicode_ssetup_strings(&bcc_ptr, ses, sess_data->nls_cp);
1175 } else {
1176 ascii_ssetup_strings(&bcc_ptr, ses, sess_data->nls_cp);
1177 }
1178
1179
1180 sess_data->iov[2].iov_len = (long) bcc_ptr -
1181 (long) sess_data->iov[2].iov_base;
1182
1183 rc = sess_sendreceive(sess_data);
1184 if (rc)
1185 goto out;
1186
1187 pSMB = (SESSION_SETUP_ANDX *)sess_data->iov[0].iov_base;
1188 smb_buf = (struct smb_hdr *)sess_data->iov[0].iov_base;
1189
1190 if (smb_buf->WordCount != 3) {
1191 rc = -EIO;
1192 cifs_dbg(VFS, "bad word count %d\n", smb_buf->WordCount);
1193 goto out;
1194 }
1195
1196 if (le16_to_cpu(pSMB->resp.Action) & GUEST_LOGIN)
1197 cifs_dbg(FYI, "Guest login\n"); /* BB mark SesInfo struct? */
1198
1199 ses->Suid = smb_buf->Uid; /* UID left in wire format (le) */
1200 cifs_dbg(FYI, "UID = %llu\n", ses->Suid);
1201
1202 bytes_remaining = get_bcc(smb_buf);
1203 bcc_ptr = pByteArea(smb_buf);
1204
1205 /* BB check if Unicode and decode strings */
1206 if (bytes_remaining == 0) {
1207 /* no string area to decode, do nothing */
1208 } else if (smb_buf->Flags2 & SMBFLG2_UNICODE) {
1209 /* unicode string area must be word-aligned */
1210 if (((unsigned long) bcc_ptr - (unsigned long) smb_buf) % 2) {
1211 ++bcc_ptr;
1212 --bytes_remaining;
1213 }
1214 decode_unicode_ssetup(&bcc_ptr, bytes_remaining, ses,
1215 sess_data->nls_cp);
1216 } else {
1217 decode_ascii_ssetup(&bcc_ptr, bytes_remaining, ses,
1218 sess_data->nls_cp);
1219 }
1220
1221 rc = sess_establish_session(sess_data);
1222out:
1223 sess_data->result = rc;
1224 sess_data->func = NULL;
1225 sess_free_buffer(sess_data);
1226 kfree(ses->auth_key.response);
1227 ses->auth_key.response = NULL;
1228}
1229
Sachin Prabhuee03c642014-06-16 15:35:27 +01001230#ifdef CONFIG_CIFS_UPCALL
1231static void
1232sess_auth_kerberos(struct sess_data *sess_data)
1233{
1234 int rc = 0;
1235 struct smb_hdr *smb_buf;
1236 SESSION_SETUP_ANDX *pSMB;
1237 char *bcc_ptr;
1238 struct cifs_ses *ses = sess_data->ses;
1239 __u32 capabilities;
1240 __u16 bytes_remaining;
1241 struct key *spnego_key = NULL;
1242 struct cifs_spnego_msg *msg;
1243 u16 blob_len;
1244
1245 /* extended security */
1246 /* wct = 12 */
1247 rc = sess_alloc_buffer(sess_data, 12);
1248 if (rc)
1249 goto out;
1250
1251 pSMB = (SESSION_SETUP_ANDX *)sess_data->iov[0].iov_base;
1252 bcc_ptr = sess_data->iov[2].iov_base;
1253 capabilities = cifs_ssetup_hdr(ses, pSMB);
1254
1255 spnego_key = cifs_get_spnego_key(ses);
1256 if (IS_ERR(spnego_key)) {
1257 rc = PTR_ERR(spnego_key);
1258 spnego_key = NULL;
1259 goto out;
1260 }
1261
David Howells146aa8b2015-10-21 14:04:48 +01001262 msg = spnego_key->payload.data[0];
Sachin Prabhuee03c642014-06-16 15:35:27 +01001263 /*
1264 * check version field to make sure that cifs.upcall is
1265 * sending us a response in an expected form
1266 */
1267 if (msg->version != CIFS_SPNEGO_UPCALL_VERSION) {
1268 cifs_dbg(VFS,
1269 "incorrect version of cifs.upcall (expected %d but got %d)",
1270 CIFS_SPNEGO_UPCALL_VERSION, msg->version);
1271 rc = -EKEYREJECTED;
1272 goto out_put_spnego_key;
1273 }
1274
1275 ses->auth_key.response = kmemdup(msg->data, msg->sesskey_len,
1276 GFP_KERNEL);
1277 if (!ses->auth_key.response) {
1278 cifs_dbg(VFS, "Kerberos can't allocate (%u bytes) memory",
1279 msg->sesskey_len);
1280 rc = -ENOMEM;
1281 goto out_put_spnego_key;
1282 }
1283 ses->auth_key.len = msg->sesskey_len;
1284
1285 pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC;
1286 capabilities |= CAP_EXTENDED_SECURITY;
1287 pSMB->req.Capabilities = cpu_to_le32(capabilities);
1288 sess_data->iov[1].iov_base = msg->data + msg->sesskey_len;
1289 sess_data->iov[1].iov_len = msg->secblob_len;
1290 pSMB->req.SecurityBlobLength = cpu_to_le16(sess_data->iov[1].iov_len);
1291
1292 if (ses->capabilities & CAP_UNICODE) {
1293 /* unicode strings must be word aligned */
1294 if ((sess_data->iov[0].iov_len
1295 + sess_data->iov[1].iov_len) % 2) {
1296 *bcc_ptr = 0;
1297 bcc_ptr++;
1298 }
1299 unicode_oslm_strings(&bcc_ptr, sess_data->nls_cp);
1300 unicode_domain_string(&bcc_ptr, ses, sess_data->nls_cp);
1301 } else {
1302 /* BB: is this right? */
1303 ascii_ssetup_strings(&bcc_ptr, ses, sess_data->nls_cp);
1304 }
1305
1306 sess_data->iov[2].iov_len = (long) bcc_ptr -
1307 (long) sess_data->iov[2].iov_base;
1308
1309 rc = sess_sendreceive(sess_data);
1310 if (rc)
1311 goto out_put_spnego_key;
1312
1313 pSMB = (SESSION_SETUP_ANDX *)sess_data->iov[0].iov_base;
1314 smb_buf = (struct smb_hdr *)sess_data->iov[0].iov_base;
1315
1316 if (smb_buf->WordCount != 4) {
1317 rc = -EIO;
1318 cifs_dbg(VFS, "bad word count %d\n", smb_buf->WordCount);
1319 goto out_put_spnego_key;
1320 }
1321
1322 if (le16_to_cpu(pSMB->resp.Action) & GUEST_LOGIN)
1323 cifs_dbg(FYI, "Guest login\n"); /* BB mark SesInfo struct? */
1324
1325 ses->Suid = smb_buf->Uid; /* UID left in wire format (le) */
1326 cifs_dbg(FYI, "UID = %llu\n", ses->Suid);
1327
1328 bytes_remaining = get_bcc(smb_buf);
1329 bcc_ptr = pByteArea(smb_buf);
1330
1331 blob_len = le16_to_cpu(pSMB->resp.SecurityBlobLength);
1332 if (blob_len > bytes_remaining) {
1333 cifs_dbg(VFS, "bad security blob length %d\n",
1334 blob_len);
1335 rc = -EINVAL;
1336 goto out_put_spnego_key;
1337 }
1338 bcc_ptr += blob_len;
1339 bytes_remaining -= blob_len;
1340
1341 /* BB check if Unicode and decode strings */
1342 if (bytes_remaining == 0) {
1343 /* no string area to decode, do nothing */
1344 } else if (smb_buf->Flags2 & SMBFLG2_UNICODE) {
1345 /* unicode string area must be word-aligned */
1346 if (((unsigned long) bcc_ptr - (unsigned long) smb_buf) % 2) {
1347 ++bcc_ptr;
1348 --bytes_remaining;
1349 }
1350 decode_unicode_ssetup(&bcc_ptr, bytes_remaining, ses,
1351 sess_data->nls_cp);
1352 } else {
1353 decode_ascii_ssetup(&bcc_ptr, bytes_remaining, ses,
1354 sess_data->nls_cp);
1355 }
1356
1357 rc = sess_establish_session(sess_data);
1358out_put_spnego_key:
1359 key_invalidate(spnego_key);
1360 key_put(spnego_key);
1361out:
1362 sess_data->result = rc;
1363 sess_data->func = NULL;
1364 sess_free_buffer(sess_data);
1365 kfree(ses->auth_key.response);
1366 ses->auth_key.response = NULL;
1367}
1368
Sachin Prabhuee03c642014-06-16 15:35:27 +01001369#endif /* ! CONFIG_CIFS_UPCALL */
Sachin Prabhu583cf7a2014-06-16 15:35:26 +01001370
Sachin Prabhucc87c472014-06-16 15:35:28 +01001371/*
1372 * The required kvec buffers have to be allocated before calling this
1373 * function.
1374 */
1375static int
1376_sess_auth_rawntlmssp_assemble_req(struct sess_data *sess_data)
Steve French39798772006-05-31 22:40:51 +00001377{
Steve French39798772006-05-31 22:40:51 +00001378 SESSION_SETUP_ANDX *pSMB;
Sachin Prabhucc87c472014-06-16 15:35:28 +01001379 struct cifs_ses *ses = sess_data->ses;
Steve French39798772006-05-31 22:40:51 +00001380 __u32 capabilities;
Sachin Prabhucc87c472014-06-16 15:35:28 +01001381 char *bcc_ptr;
Steve French254e55e2006-06-04 05:53:15 +00001382
Sachin Prabhucc87c472014-06-16 15:35:28 +01001383 pSMB = (SESSION_SETUP_ANDX *)sess_data->iov[0].iov_base;
Sachin Prabhucc87c472014-06-16 15:35:28 +01001384
1385 capabilities = cifs_ssetup_hdr(ses, pSMB);
1386 if ((pSMB->req.hdr.Flags2 & SMBFLG2_UNICODE) == 0) {
1387 cifs_dbg(VFS, "NTLMSSP requires Unicode support\n");
1388 return -ENOSYS;
Jeff Layton3534b852013-05-24 07:41:01 -04001389 }
Steve French39798772006-05-31 22:40:51 +00001390
Sachin Prabhucc87c472014-06-16 15:35:28 +01001391 pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC;
1392 capabilities |= CAP_EXTENDED_SECURITY;
1393 pSMB->req.Capabilities |= cpu_to_le32(capabilities);
1394
1395 bcc_ptr = sess_data->iov[2].iov_base;
1396 /* unicode strings must be word aligned */
1397 if ((sess_data->iov[0].iov_len + sess_data->iov[1].iov_len) % 2) {
1398 *bcc_ptr = 0;
1399 bcc_ptr++;
1400 }
1401 unicode_oslm_strings(&bcc_ptr, sess_data->nls_cp);
1402
1403 sess_data->iov[2].iov_len = (long) bcc_ptr -
1404 (long) sess_data->iov[2].iov_base;
1405
1406 return 0;
1407}
1408
1409static void
1410sess_auth_rawntlmssp_authenticate(struct sess_data *sess_data);
1411
1412static void
1413sess_auth_rawntlmssp_negotiate(struct sess_data *sess_data)
1414{
1415 int rc;
1416 struct smb_hdr *smb_buf;
1417 SESSION_SETUP_ANDX *pSMB;
1418 struct cifs_ses *ses = sess_data->ses;
1419 __u16 bytes_remaining;
1420 char *bcc_ptr;
1421 u16 blob_len;
1422
1423 cifs_dbg(FYI, "rawntlmssp session setup negotiate phase\n");
1424
1425 /*
1426 * if memory allocation is successful, caller of this function
1427 * frees it.
1428 */
1429 ses->ntlmssp = kmalloc(sizeof(struct ntlmssp_auth), GFP_KERNEL);
1430 if (!ses->ntlmssp) {
1431 rc = -ENOMEM;
1432 goto out;
1433 }
1434 ses->ntlmssp->sesskey_per_smbsess = false;
1435
1436 /* wct = 12 */
1437 rc = sess_alloc_buffer(sess_data, 12);
1438 if (rc)
1439 goto out;
1440
1441 pSMB = (SESSION_SETUP_ANDX *)sess_data->iov[0].iov_base;
1442
1443 /* Build security blob before we assemble the request */
1444 build_ntlmssp_negotiate_blob(pSMB->req.SecurityBlob, ses);
1445 sess_data->iov[1].iov_len = sizeof(NEGOTIATE_MESSAGE);
1446 sess_data->iov[1].iov_base = pSMB->req.SecurityBlob;
1447 pSMB->req.SecurityBlobLength = cpu_to_le16(sizeof(NEGOTIATE_MESSAGE));
1448
1449 rc = _sess_auth_rawntlmssp_assemble_req(sess_data);
1450 if (rc)
1451 goto out;
1452
1453 rc = sess_sendreceive(sess_data);
1454
1455 pSMB = (SESSION_SETUP_ANDX *)sess_data->iov[0].iov_base;
1456 smb_buf = (struct smb_hdr *)sess_data->iov[0].iov_base;
1457
1458 /* If true, rc here is expected and not an error */
1459 if (sess_data->buf0_type != CIFS_NO_BUFFER &&
1460 smb_buf->Status.CifsError ==
1461 cpu_to_le32(NT_STATUS_MORE_PROCESSING_REQUIRED))
1462 rc = 0;
1463
1464 if (rc)
1465 goto out;
1466
1467 cifs_dbg(FYI, "rawntlmssp session setup challenge phase\n");
1468
1469 if (smb_buf->WordCount != 4) {
1470 rc = -EIO;
1471 cifs_dbg(VFS, "bad word count %d\n", smb_buf->WordCount);
1472 goto out;
1473 }
1474
1475 ses->Suid = smb_buf->Uid; /* UID left in wire format (le) */
1476 cifs_dbg(FYI, "UID = %llu\n", ses->Suid);
1477
1478 bytes_remaining = get_bcc(smb_buf);
1479 bcc_ptr = pByteArea(smb_buf);
1480
1481 blob_len = le16_to_cpu(pSMB->resp.SecurityBlobLength);
1482 if (blob_len > bytes_remaining) {
1483 cifs_dbg(VFS, "bad security blob length %d\n",
1484 blob_len);
1485 rc = -EINVAL;
1486 goto out;
1487 }
1488
1489 rc = decode_ntlmssp_challenge(bcc_ptr, blob_len, ses);
1490out:
1491 sess_free_buffer(sess_data);
1492
1493 if (!rc) {
1494 sess_data->func = sess_auth_rawntlmssp_authenticate;
1495 return;
1496 }
1497
1498 /* Else error. Cleanup */
1499 kfree(ses->auth_key.response);
1500 ses->auth_key.response = NULL;
1501 kfree(ses->ntlmssp);
1502 ses->ntlmssp = NULL;
1503
1504 sess_data->func = NULL;
1505 sess_data->result = rc;
1506}
1507
1508static void
1509sess_auth_rawntlmssp_authenticate(struct sess_data *sess_data)
1510{
1511 int rc;
1512 struct smb_hdr *smb_buf;
1513 SESSION_SETUP_ANDX *pSMB;
1514 struct cifs_ses *ses = sess_data->ses;
1515 __u16 bytes_remaining;
1516 char *bcc_ptr;
Jerome Marchandb8da3442016-05-26 11:52:25 +02001517 unsigned char *ntlmsspblob = NULL;
Sachin Prabhucc87c472014-06-16 15:35:28 +01001518 u16 blob_len;
1519
1520 cifs_dbg(FYI, "rawntlmssp session setup authenticate phase\n");
1521
1522 /* wct = 12 */
1523 rc = sess_alloc_buffer(sess_data, 12);
1524 if (rc)
1525 goto out;
1526
1527 /* Build security blob before we assemble the request */
1528 pSMB = (SESSION_SETUP_ANDX *)sess_data->iov[0].iov_base;
1529 smb_buf = (struct smb_hdr *)pSMB;
Jerome Marchandb8da3442016-05-26 11:52:25 +02001530 rc = build_ntlmssp_auth_blob(&ntlmsspblob,
Sachin Prabhucc87c472014-06-16 15:35:28 +01001531 &blob_len, ses, sess_data->nls_cp);
1532 if (rc)
1533 goto out_free_ntlmsspblob;
1534 sess_data->iov[1].iov_len = blob_len;
1535 sess_data->iov[1].iov_base = ntlmsspblob;
1536 pSMB->req.SecurityBlobLength = cpu_to_le16(blob_len);
1537 /*
1538 * Make sure that we tell the server that we are using
1539 * the uid that it just gave us back on the response
1540 * (challenge)
1541 */
1542 smb_buf->Uid = ses->Suid;
1543
1544 rc = _sess_auth_rawntlmssp_assemble_req(sess_data);
1545 if (rc)
1546 goto out_free_ntlmsspblob;
1547
1548 rc = sess_sendreceive(sess_data);
1549 if (rc)
1550 goto out_free_ntlmsspblob;
1551
1552 pSMB = (SESSION_SETUP_ANDX *)sess_data->iov[0].iov_base;
1553 smb_buf = (struct smb_hdr *)sess_data->iov[0].iov_base;
1554 if (smb_buf->WordCount != 4) {
1555 rc = -EIO;
1556 cifs_dbg(VFS, "bad word count %d\n", smb_buf->WordCount);
1557 goto out_free_ntlmsspblob;
1558 }
1559
1560 if (le16_to_cpu(pSMB->resp.Action) & GUEST_LOGIN)
1561 cifs_dbg(FYI, "Guest login\n"); /* BB mark SesInfo struct? */
1562
Sachin Prabhuee9bbf42014-12-03 12:26:36 +00001563 if (ses->Suid != smb_buf->Uid) {
1564 ses->Suid = smb_buf->Uid;
1565 cifs_dbg(FYI, "UID changed! new UID = %llu\n", ses->Suid);
1566 }
1567
Sachin Prabhucc87c472014-06-16 15:35:28 +01001568 bytes_remaining = get_bcc(smb_buf);
1569 bcc_ptr = pByteArea(smb_buf);
1570 blob_len = le16_to_cpu(pSMB->resp.SecurityBlobLength);
1571 if (blob_len > bytes_remaining) {
1572 cifs_dbg(VFS, "bad security blob length %d\n",
1573 blob_len);
1574 rc = -EINVAL;
1575 goto out_free_ntlmsspblob;
1576 }
1577 bcc_ptr += blob_len;
1578 bytes_remaining -= blob_len;
1579
1580
1581 /* BB check if Unicode and decode strings */
1582 if (bytes_remaining == 0) {
1583 /* no string area to decode, do nothing */
1584 } else if (smb_buf->Flags2 & SMBFLG2_UNICODE) {
1585 /* unicode string area must be word-aligned */
1586 if (((unsigned long) bcc_ptr - (unsigned long) smb_buf) % 2) {
1587 ++bcc_ptr;
1588 --bytes_remaining;
1589 }
1590 decode_unicode_ssetup(&bcc_ptr, bytes_remaining, ses,
1591 sess_data->nls_cp);
1592 } else {
1593 decode_ascii_ssetup(&bcc_ptr, bytes_remaining, ses,
1594 sess_data->nls_cp);
1595 }
1596
1597out_free_ntlmsspblob:
1598 kfree(ntlmsspblob);
1599out:
1600 sess_free_buffer(sess_data);
1601
1602 if (!rc)
1603 rc = sess_establish_session(sess_data);
1604
1605 /* Cleanup */
1606 kfree(ses->auth_key.response);
1607 ses->auth_key.response = NULL;
1608 kfree(ses->ntlmssp);
1609 ses->ntlmssp = NULL;
1610
1611 sess_data->func = NULL;
1612 sess_data->result = rc;
1613}
1614
Steve French27924072014-07-11 07:47:01 -05001615static int select_sec(struct cifs_ses *ses, struct sess_data *sess_data)
Sachin Prabhucc87c472014-06-16 15:35:28 +01001616{
1617 int type;
Sachin Prabhu80a0e632014-06-16 15:35:25 +01001618
Sachin Prabhuef65aae2017-01-18 15:35:57 +05301619 type = cifs_select_sectype(ses->server, ses->sectype);
Joe Perchesf96637b2013-05-04 22:12:25 -05001620 cifs_dbg(FYI, "sess setup type %d\n", type);
Jeff Layton3f618222013-06-12 19:52:14 -05001621 if (type == Unspecified) {
Shirish Pargaonkard4e63bd2013-08-29 08:35:09 -05001622 cifs_dbg(VFS,
1623 "Unable to select appropriate authentication method!");
Jeff Layton3f618222013-06-12 19:52:14 -05001624 return -EINVAL;
1625 }
1626
Sachin Prabhu80a0e632014-06-16 15:35:25 +01001627 switch (type) {
1628 case LANMAN:
Sachin Prabhucc87c472014-06-16 15:35:28 +01001629 /* LANMAN and plaintext are less secure and off by default.
1630 * So we make this explicitly be turned on in kconfig (in the
1631 * build) and turned on at runtime (changed from the default)
1632 * in proc/fs/cifs or via mount parm. Unfortunately this is
1633 * needed for old Win (e.g. Win95), some obscure NAS and OS/2 */
1634#ifdef CONFIG_CIFS_WEAK_PW_HASH
1635 sess_data->func = sess_auth_lanman;
1636 break;
1637#else
1638 return -EOPNOTSUPP;
1639#endif
Sachin Prabhu583cf7a2014-06-16 15:35:26 +01001640 case NTLM:
Sachin Prabhucc87c472014-06-16 15:35:28 +01001641 sess_data->func = sess_auth_ntlm;
1642 break;
Sachin Prabhu583cf7a2014-06-16 15:35:26 +01001643 case NTLMv2:
Sachin Prabhucc87c472014-06-16 15:35:28 +01001644 sess_data->func = sess_auth_ntlmv2;
1645 break;
Sachin Prabhuee03c642014-06-16 15:35:27 +01001646 case Kerberos:
Sachin Prabhucc87c472014-06-16 15:35:28 +01001647#ifdef CONFIG_CIFS_UPCALL
1648 sess_data->func = sess_auth_kerberos;
1649 break;
1650#else
1651 cifs_dbg(VFS, "Kerberos negotiated but upcall support disabled!\n");
1652 return -ENOSYS;
1653 break;
1654#endif /* CONFIG_CIFS_UPCALL */
1655 case RawNTLMSSP:
1656 sess_data->func = sess_auth_rawntlmssp_negotiate;
1657 break;
Sachin Prabhu80a0e632014-06-16 15:35:25 +01001658 default:
Joe Perchesf96637b2013-05-04 22:12:25 -05001659 cifs_dbg(VFS, "secType %d not supported!\n", type);
Sachin Prabhucc87c472014-06-16 15:35:28 +01001660 return -ENOSYS;
Steve French39798772006-05-31 22:40:51 +00001661 }
1662
Sachin Prabhucc87c472014-06-16 15:35:28 +01001663 return 0;
1664}
Steve French24424212007-11-16 23:37:35 +00001665
Sachin Prabhucc87c472014-06-16 15:35:28 +01001666int CIFS_SessSetup(const unsigned int xid, struct cifs_ses *ses,
1667 const struct nls_table *nls_cp)
1668{
1669 int rc = 0;
1670 struct sess_data *sess_data;
Steve French39798772006-05-31 22:40:51 +00001671
Sachin Prabhucc87c472014-06-16 15:35:28 +01001672 if (ses == NULL) {
1673 WARN(1, "%s: ses == NULL!", __func__);
1674 return -EINVAL;
Steve French0b3cc8582009-05-04 08:37:12 +00001675 }
Sachin Prabhucc87c472014-06-16 15:35:28 +01001676
1677 sess_data = kzalloc(sizeof(struct sess_data), GFP_KERNEL);
1678 if (!sess_data)
1679 return -ENOMEM;
1680
1681 rc = select_sec(ses, sess_data);
Steve French0b3cc8582009-05-04 08:37:12 +00001682 if (rc)
Sachin Prabhucc87c472014-06-16 15:35:28 +01001683 goto out;
Steve French0b3cc8582009-05-04 08:37:12 +00001684
Sachin Prabhucc87c472014-06-16 15:35:28 +01001685 sess_data->xid = xid;
1686 sess_data->ses = ses;
1687 sess_data->buf0_type = CIFS_NO_BUFFER;
1688 sess_data->nls_cp = (struct nls_table *) nls_cp;
Steve French39798772006-05-31 22:40:51 +00001689
Sachin Prabhucc87c472014-06-16 15:35:28 +01001690 while (sess_data->func)
1691 sess_data->func(sess_data);
Steve French39798772006-05-31 22:40:51 +00001692
Sachin Prabhucc87c472014-06-16 15:35:28 +01001693 /* Store result before we free sess_data */
1694 rc = sess_data->result;
Sachin Prabhu80a0e632014-06-16 15:35:25 +01001695
1696out:
Sachin Prabhu80a0e632014-06-16 15:35:25 +01001697 kfree(sess_data);
1698 return rc;
Steve French39798772006-05-31 22:40:51 +00001699}