blob: 3f8b43e775392b603bc559cc5b7b0cfe29fe7ed8 [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;
Aurelien Aptel65a37a32019-11-20 17:15:59 +010079 int tries = 0;
Aurelien Aptel9a7d5a92019-12-04 16:14:54 +010080 struct cifs_server_iface *ifaces = NULL;
81 size_t iface_count;
Aurelien Apteld70e9fa2019-09-20 06:31:10 +020082
83 if (left <= 0) {
84 cifs_dbg(FYI,
85 "ses already at max_channels (%zu), nothing to open\n",
86 ses->chan_max);
87 return 0;
88 }
89
90 if (ses->server->dialect < SMB30_PROT_ID) {
91 cifs_dbg(VFS, "multichannel is not supported on this protocol version, use 3.0 or above\n");
92 return 0;
93 }
94
Aurelien Aptel65a37a32019-11-20 17:15:59 +010095 /*
Aurelien Aptel9a7d5a92019-12-04 16:14:54 +010096 * Make a copy of the iface list at the time and use that
97 * instead so as to not hold the iface spinlock for opening
98 * channels
99 */
100 spin_lock(&ses->iface_lock);
101 iface_count = ses->iface_count;
102 if (iface_count <= 0) {
103 spin_unlock(&ses->iface_lock);
Aurelien Aptel343a1b72020-02-06 10:19:11 +0100104 cifs_dbg(VFS, "no iface list available to open channels\n");
Aurelien Aptel9a7d5a92019-12-04 16:14:54 +0100105 return 0;
106 }
107 ifaces = kmemdup(ses->iface_list, iface_count*sizeof(*ifaces),
108 GFP_ATOMIC);
109 if (!ifaces) {
110 spin_unlock(&ses->iface_lock);
111 return 0;
112 }
113 spin_unlock(&ses->iface_lock);
114
115 /*
Aurelien Aptel65a37a32019-11-20 17:15:59 +0100116 * Keep connecting to same, fastest, iface for all channels as
117 * long as its RSS. Try next fastest one if not RSS or channel
118 * creation fails.
119 */
120 while (left > 0) {
Aurelien Apteld70e9fa2019-09-20 06:31:10 +0200121 struct cifs_server_iface *iface;
122
Aurelien Aptel65a37a32019-11-20 17:15:59 +0100123 tries++;
124 if (tries > 3*ses->chan_max) {
125 cifs_dbg(FYI, "too many attempt at opening channels (%d channels left to open)\n",
126 left);
127 break;
128 }
Aurelien Apteld70e9fa2019-09-20 06:31:10 +0200129
Aurelien Aptel9a7d5a92019-12-04 16:14:54 +0100130 iface = &ifaces[i];
Aurelien Aptel65a37a32019-11-20 17:15:59 +0100131 if (is_ses_using_iface(ses, iface) && !iface->rss_capable) {
Aurelien Aptel9a7d5a92019-12-04 16:14:54 +0100132 i = (i+1) % iface_count;
Aurelien Apteld70e9fa2019-09-20 06:31:10 +0200133 continue;
134 }
135
Aurelien Aptel65a37a32019-11-20 17:15:59 +0100136 rc = cifs_ses_add_channel(ses, iface);
137 if (rc) {
138 cifs_dbg(FYI, "failed to open extra channel on iface#%d rc=%d\n",
139 i, rc);
Aurelien Aptel9a7d5a92019-12-04 16:14:54 +0100140 i = (i+1) % iface_count;
Aurelien Aptel65a37a32019-11-20 17:15:59 +0100141 continue;
142 }
143
144 cifs_dbg(FYI, "successfully opened new channel on iface#%d\n",
145 i);
Aurelien Apteld70e9fa2019-09-20 06:31:10 +0200146 left--;
147 }
148
Aurelien Aptel9a7d5a92019-12-04 16:14:54 +0100149 kfree(ifaces);
Aurelien Apteld70e9fa2019-09-20 06:31:10 +0200150 return ses->chan_count - old_chan_count;
151}
152
153int
154cifs_ses_add_channel(struct cifs_ses *ses, struct cifs_server_iface *iface)
155{
156 struct cifs_chan *chan;
157 struct smb_vol vol = {NULL};
158 static const char unc_fmt[] = "\\%s\\foo";
159 char unc[sizeof(unc_fmt)+SERVER_NAME_LEN_WITH_NULL] = {0};
160 struct sockaddr_in *ipv4 = (struct sockaddr_in *)&iface->sockaddr;
161 struct sockaddr_in6 *ipv6 = (struct sockaddr_in6 *)&iface->sockaddr;
162 int rc;
163 unsigned int xid = get_xid();
164
Aurelien Apteld70e9fa2019-09-20 06:31:10 +0200165 if (iface->sockaddr.ss_family == AF_INET)
Joe Perchesa0a30362020-04-14 22:42:53 -0700166 cifs_dbg(FYI, "adding channel to ses %p (speed:%zu bps rdma:%s ip:%pI4)\n",
167 ses, iface->speed, iface->rdma_capable ? "yes" : "no",
168 &ipv4->sin_addr);
Aurelien Apteld70e9fa2019-09-20 06:31:10 +0200169 else
Joe Perchesa0a30362020-04-14 22:42:53 -0700170 cifs_dbg(FYI, "adding channel to ses %p (speed:%zu bps rdma:%s ip:%pI4)\n",
171 ses, iface->speed, iface->rdma_capable ? "yes" : "no",
172 &ipv6->sin6_addr);
Aurelien Apteld70e9fa2019-09-20 06:31:10 +0200173
174 /*
175 * Setup a smb_vol with mostly the same info as the existing
176 * session and overwrite it with the requested iface data.
177 *
178 * We need to setup at least the fields used for negprot and
179 * sesssetup.
180 *
181 * We only need the volume here, so we can reuse memory from
182 * the session and server without caring about memory
183 * management.
184 */
185
186 /* Always make new connection for now (TODO?) */
187 vol.nosharesock = true;
188
189 /* Auth */
190 vol.domainauto = ses->domainAuto;
191 vol.domainname = ses->domainName;
192 vol.username = ses->user_name;
193 vol.password = ses->password;
194 vol.sectype = ses->sectype;
195 vol.sign = ses->sign;
196
197 /* UNC and paths */
198 /* XXX: Use ses->server->hostname? */
199 sprintf(unc, unc_fmt, ses->serverName);
200 vol.UNC = unc;
201 vol.prepath = "";
202
203 /* Re-use same version as master connection */
204 vol.vals = ses->server->vals;
205 vol.ops = ses->server->ops;
206
207 vol.noblocksnd = ses->server->noblocksnd;
208 vol.noautotune = ses->server->noautotune;
209 vol.sockopt_tcp_nodelay = ses->server->tcp_nodelay;
210 vol.echo_interval = ses->server->echo_interval / HZ;
211
212 /*
213 * This will be used for encoding/decoding user/domain/pw
214 * during sess setup auth.
215 *
216 * XXX: We use the default for simplicity but the proper way
217 * would be to use the one that ses used, which is not
218 * stored. This might break when dealing with non-ascii
219 * strings.
220 */
221 vol.local_nls = load_nls_default();
222
223 /* Use RDMA if possible */
224 vol.rdma = iface->rdma_capable;
225 memcpy(&vol.dstaddr, &iface->sockaddr, sizeof(struct sockaddr_storage));
226
227 /* reuse master con client guid */
228 memcpy(&vol.client_guid, ses->server->client_guid,
229 SMB2_CLIENT_GUID_SIZE);
230 vol.use_client_guid = true;
231
232 mutex_lock(&ses->session_mutex);
233
234 chan = &ses->chans[ses->chan_count];
235 chan->server = cifs_get_tcp_session(&vol);
236 if (IS_ERR(chan->server)) {
237 rc = PTR_ERR(chan->server);
238 chan->server = NULL;
239 goto out;
240 }
Paulo Alcantara (SUSE)3345bb42019-12-04 11:25:06 -0300241 spin_lock(&cifs_tcp_ses_lock);
242 chan->server->is_channel = true;
243 spin_unlock(&cifs_tcp_ses_lock);
Aurelien Apteld70e9fa2019-09-20 06:31:10 +0200244
245 /*
246 * We need to allocate the server crypto now as we will need
247 * to sign packets before we generate the channel signing key
248 * (we sign with the session key)
249 */
250 rc = smb311_crypto_shash_allocate(chan->server);
251 if (rc) {
252 cifs_dbg(VFS, "%s: crypto alloc failed\n", __func__);
253 goto out;
254 }
255
256 ses->binding = true;
257 rc = cifs_negotiate_protocol(xid, ses);
258 if (rc)
259 goto out;
260
261 rc = cifs_setup_session(xid, ses, vol.local_nls);
262 if (rc)
263 goto out;
264
265 /* success, put it on the list
266 * XXX: sharing ses between 2 tcp server is not possible, the
267 * way "internal" linked lists works in linux makes element
268 * only able to belong to one list
269 *
270 * the binding session is already established so the rest of
271 * the code should be able to look it up, no need to add the
272 * ses to the new server.
273 */
274
275 ses->chan_count++;
276 atomic_set(&ses->chan_seq, 0);
277out:
278 ses->binding = false;
279 mutex_unlock(&ses->session_mutex);
280
281 if (rc && chan->server)
282 cifs_put_tcp_session(chan->server, 0);
283 unload_nls(vol.local_nls);
284
285 return rc;
286}
Steve French39798772006-05-31 22:40:51 +0000287
Steve French96daf2b2011-05-27 04:34:02 +0000288static __u32 cifs_ssetup_hdr(struct cifs_ses *ses, SESSION_SETUP_ANDX *pSMB)
Steve French39798772006-05-31 22:40:51 +0000289{
290 __u32 capabilities = 0;
291
292 /* init fields common to all four types of SessSetup */
Steve Frencheca6acf2009-02-20 05:43:09 +0000293 /* Note that offsets for first seven fields in req struct are same */
294 /* in CIFS Specs so does not matter which of 3 forms of struct */
295 /* that we use in next few lines */
296 /* Note that header is initialized to zero in header_assemble */
Steve French39798772006-05-31 22:40:51 +0000297 pSMB->req.AndXCommand = 0xFF;
Jeff Laytonc974bef2011-10-11 06:41:32 -0400298 pSMB->req.MaxBufferSize = cpu_to_le16(min_t(u32,
299 CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4,
300 USHRT_MAX));
Steve French39798772006-05-31 22:40:51 +0000301 pSMB->req.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
Fabian Frederickbc09d142014-12-10 15:41:15 -0800302 pSMB->req.VcNumber = cpu_to_le16(1);
Steve French39798772006-05-31 22:40:51 +0000303
304 /* Now no need to set SMBFLG_CASELESS or obsolete CANONICAL PATH */
305
Steve French790fe572007-07-07 19:25:05 +0000306 /* BB verify whether signing required on neg or just on auth frame
Steve French39798772006-05-31 22:40:51 +0000307 (and NTLM case) */
308
309 capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
310 CAP_LARGE_WRITE_X | CAP_LARGE_READ_X;
311
Jeff Layton38d77c52013-05-26 07:01:00 -0400312 if (ses->server->sign)
Steve French39798772006-05-31 22:40:51 +0000313 pSMB->req.hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
314
315 if (ses->capabilities & CAP_UNICODE) {
316 pSMB->req.hdr.Flags2 |= SMBFLG2_UNICODE;
317 capabilities |= CAP_UNICODE;
318 }
319 if (ses->capabilities & CAP_STATUS32) {
320 pSMB->req.hdr.Flags2 |= SMBFLG2_ERR_STATUS;
321 capabilities |= CAP_STATUS32;
322 }
323 if (ses->capabilities & CAP_DFS) {
324 pSMB->req.hdr.Flags2 |= SMBFLG2_DFS;
325 capabilities |= CAP_DFS;
326 }
Steve French26f57362007-08-30 22:09:15 +0000327 if (ses->capabilities & CAP_UNIX)
Steve French39798772006-05-31 22:40:51 +0000328 capabilities |= CAP_UNIX;
Steve French39798772006-05-31 22:40:51 +0000329
Steve French39798772006-05-31 22:40:51 +0000330 return capabilities;
331}
332
Jeff Layton0d3a01f2007-10-16 17:32:19 +0000333static void
334unicode_oslm_strings(char **pbcc_area, const struct nls_table *nls_cp)
335{
336 char *bcc_ptr = *pbcc_area;
337 int bytes_ret = 0;
338
339 /* Copy OS version */
Steve Frenchacbbb762012-01-18 22:32:33 -0600340 bytes_ret = cifs_strtoUTF16((__le16 *)bcc_ptr, "Linux version ", 32,
341 nls_cp);
Jeff Layton0d3a01f2007-10-16 17:32:19 +0000342 bcc_ptr += 2 * bytes_ret;
Steve Frenchacbbb762012-01-18 22:32:33 -0600343 bytes_ret = cifs_strtoUTF16((__le16 *) bcc_ptr, init_utsname()->release,
344 32, nls_cp);
Jeff Layton0d3a01f2007-10-16 17:32:19 +0000345 bcc_ptr += 2 * bytes_ret;
346 bcc_ptr += 2; /* trailing null */
347
Steve Frenchacbbb762012-01-18 22:32:33 -0600348 bytes_ret = cifs_strtoUTF16((__le16 *) bcc_ptr, CIFS_NETWORK_OPSYS,
349 32, nls_cp);
Jeff Layton0d3a01f2007-10-16 17:32:19 +0000350 bcc_ptr += 2 * bytes_ret;
351 bcc_ptr += 2; /* trailing null */
352
353 *pbcc_area = bcc_ptr;
354}
355
Steve French96daf2b2011-05-27 04:34:02 +0000356static void unicode_domain_string(char **pbcc_area, struct cifs_ses *ses,
Jeff Layton0d3a01f2007-10-16 17:32:19 +0000357 const struct nls_table *nls_cp)
358{
359 char *bcc_ptr = *pbcc_area;
360 int bytes_ret = 0;
361
362 /* copy domain */
363 if (ses->domainName == NULL) {
364 /* Sending null domain better than using a bogus domain name (as
365 we did briefly in 2.6.18) since server will use its default */
366 *bcc_ptr = 0;
367 *(bcc_ptr+1) = 0;
368 bytes_ret = 0;
369 } else
Steve Frenchacbbb762012-01-18 22:32:33 -0600370 bytes_ret = cifs_strtoUTF16((__le16 *) bcc_ptr, ses->domainName,
Chen Gang057d6332013-07-19 09:01:36 +0800371 CIFS_MAX_DOMAINNAME_LEN, nls_cp);
Jeff Layton0d3a01f2007-10-16 17:32:19 +0000372 bcc_ptr += 2 * bytes_ret;
373 bcc_ptr += 2; /* account for null terminator */
374
375 *pbcc_area = bcc_ptr;
376}
377
378
Steve French96daf2b2011-05-27 04:34:02 +0000379static void unicode_ssetup_strings(char **pbcc_area, struct cifs_ses *ses,
Steve French790fe572007-07-07 19:25:05 +0000380 const struct nls_table *nls_cp)
Steve French39798772006-05-31 22:40:51 +0000381{
Steve French790fe572007-07-07 19:25:05 +0000382 char *bcc_ptr = *pbcc_area;
Steve French39798772006-05-31 22:40:51 +0000383 int bytes_ret = 0;
384
385 /* BB FIXME add check that strings total less
386 than 335 or will need to send them as arrays */
387
Steve French0223cf02006-06-27 19:50:57 +0000388 /* unicode strings, must be word aligned before the call */
389/* if ((long) bcc_ptr % 2) {
Steve French39798772006-05-31 22:40:51 +0000390 *bcc_ptr = 0;
391 bcc_ptr++;
Steve French0223cf02006-06-27 19:50:57 +0000392 } */
Steve French39798772006-05-31 22:40:51 +0000393 /* copy user */
Steve French8727c8a2011-02-25 01:11:56 -0600394 if (ses->user_name == NULL) {
Steve French6e659c62006-11-08 23:10:46 +0000395 /* null user mount */
396 *bcc_ptr = 0;
397 *(bcc_ptr+1) = 0;
Steve French301a6a32010-02-06 07:08:53 +0000398 } else {
Steve Frenchacbbb762012-01-18 22:32:33 -0600399 bytes_ret = cifs_strtoUTF16((__le16 *) bcc_ptr, ses->user_name,
Scott Lovenberg8c3a2b42013-08-09 08:47:17 -0400400 CIFS_MAX_USERNAME_LEN, nls_cp);
Steve French39798772006-05-31 22:40:51 +0000401 }
402 bcc_ptr += 2 * bytes_ret;
403 bcc_ptr += 2; /* account for null termination */
Steve French39798772006-05-31 22:40:51 +0000404
Jeff Layton0d3a01f2007-10-16 17:32:19 +0000405 unicode_domain_string(&bcc_ptr, ses, nls_cp);
406 unicode_oslm_strings(&bcc_ptr, nls_cp);
Steve French39798772006-05-31 22:40:51 +0000407
408 *pbcc_area = bcc_ptr;
409}
410
Steve French96daf2b2011-05-27 04:34:02 +0000411static void ascii_ssetup_strings(char **pbcc_area, struct cifs_ses *ses,
Steve French790fe572007-07-07 19:25:05 +0000412 const struct nls_table *nls_cp)
Steve French39798772006-05-31 22:40:51 +0000413{
Steve French790fe572007-07-07 19:25:05 +0000414 char *bcc_ptr = *pbcc_area;
Ronnie Sahlberg340625e2019-08-27 09:30:14 +1000415 int len;
Steve French39798772006-05-31 22:40:51 +0000416
417 /* copy user */
418 /* BB what about null user mounts - check that we do this BB */
Steve French790fe572007-07-07 19:25:05 +0000419 /* copy user */
Shirish Pargaonkarde47a412012-02-02 15:28:28 -0600420 if (ses->user_name != NULL) {
Ronnie Sahlberg340625e2019-08-27 09:30:14 +1000421 len = strscpy(bcc_ptr, ses->user_name, CIFS_MAX_USERNAME_LEN);
422 if (WARN_ON_ONCE(len < 0))
423 len = CIFS_MAX_USERNAME_LEN - 1;
424 bcc_ptr += len;
Shirish Pargaonkarde47a412012-02-02 15:28:28 -0600425 }
Steve French8727c8a2011-02-25 01:11:56 -0600426 /* else null user mount */
Steve French39798772006-05-31 22:40:51 +0000427 *bcc_ptr = 0;
Steve French790fe572007-07-07 19:25:05 +0000428 bcc_ptr++; /* account for null termination */
Steve French39798772006-05-31 22:40:51 +0000429
Steve French790fe572007-07-07 19:25:05 +0000430 /* copy domain */
Steve French790fe572007-07-07 19:25:05 +0000431 if (ses->domainName != NULL) {
Ronnie Sahlberg340625e2019-08-27 09:30:14 +1000432 len = strscpy(bcc_ptr, ses->domainName, CIFS_MAX_DOMAINNAME_LEN);
433 if (WARN_ON_ONCE(len < 0))
434 len = CIFS_MAX_DOMAINNAME_LEN - 1;
435 bcc_ptr += len;
Steve French790fe572007-07-07 19:25:05 +0000436 } /* else we will send a null domain name
Steve French6e659c62006-11-08 23:10:46 +0000437 so the server will default to its own domain */
Steve French39798772006-05-31 22:40:51 +0000438 *bcc_ptr = 0;
439 bcc_ptr++;
440
441 /* BB check for overflow here */
442
443 strcpy(bcc_ptr, "Linux version ");
444 bcc_ptr += strlen("Linux version ");
Serge E. Hallyn96b644b2006-10-02 02:18:13 -0700445 strcpy(bcc_ptr, init_utsname()->release);
446 bcc_ptr += strlen(init_utsname()->release) + 1;
Steve French39798772006-05-31 22:40:51 +0000447
448 strcpy(bcc_ptr, CIFS_NETWORK_OPSYS);
449 bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1;
450
Steve French790fe572007-07-07 19:25:05 +0000451 *pbcc_area = bcc_ptr;
Steve French39798772006-05-31 22:40:51 +0000452}
453
Jeff Layton59140792009-04-30 07:16:21 -0400454static void
Steve French96daf2b2011-05-27 04:34:02 +0000455decode_unicode_ssetup(char **pbcc_area, int bleft, struct cifs_ses *ses,
Jeff Layton59140792009-04-30 07:16:21 -0400456 const struct nls_table *nls_cp)
Steve French39798772006-05-31 22:40:51 +0000457{
Jeff Layton59140792009-04-30 07:16:21 -0400458 int len;
Steve French790fe572007-07-07 19:25:05 +0000459 char *data = *pbcc_area;
Steve French39798772006-05-31 22:40:51 +0000460
Joe Perchesf96637b2013-05-04 22:12:25 -0500461 cifs_dbg(FYI, "bleft %d\n", bleft);
Steve French39798772006-05-31 22:40:51 +0000462
Steve French26f57362007-08-30 22:09:15 +0000463 kfree(ses->serverOS);
Steve Frenchacbbb762012-01-18 22:32:33 -0600464 ses->serverOS = cifs_strndup_from_utf16(data, bleft, true, nls_cp);
Joe Perchesf96637b2013-05-04 22:12:25 -0500465 cifs_dbg(FYI, "serverOS=%s\n", ses->serverOS);
Jeff Layton59140792009-04-30 07:16:21 -0400466 len = (UniStrnlen((wchar_t *) data, bleft / 2) * 2) + 2;
467 data += len;
468 bleft -= len;
469 if (bleft <= 0)
470 return;
Steve French39798772006-05-31 22:40:51 +0000471
Steve French26f57362007-08-30 22:09:15 +0000472 kfree(ses->serverNOS);
Steve Frenchacbbb762012-01-18 22:32:33 -0600473 ses->serverNOS = cifs_strndup_from_utf16(data, bleft, true, nls_cp);
Joe Perchesf96637b2013-05-04 22:12:25 -0500474 cifs_dbg(FYI, "serverNOS=%s\n", ses->serverNOS);
Jeff Layton59140792009-04-30 07:16:21 -0400475 len = (UniStrnlen((wchar_t *) data, bleft / 2) * 2) + 2;
476 data += len;
477 bleft -= len;
478 if (bleft <= 0)
479 return;
Steve French39798772006-05-31 22:40:51 +0000480
Steve French26f57362007-08-30 22:09:15 +0000481 kfree(ses->serverDomain);
Steve Frenchacbbb762012-01-18 22:32:33 -0600482 ses->serverDomain = cifs_strndup_from_utf16(data, bleft, true, nls_cp);
Joe Perchesf96637b2013-05-04 22:12:25 -0500483 cifs_dbg(FYI, "serverDomain=%s\n", ses->serverDomain);
Steve French790fe572007-07-07 19:25:05 +0000484
Jeff Layton59140792009-04-30 07:16:21 -0400485 return;
Steve French39798772006-05-31 22:40:51 +0000486}
487
Jeff Layton7d066452013-05-24 07:41:00 -0400488static void decode_ascii_ssetup(char **pbcc_area, __u16 bleft,
489 struct cifs_ses *ses,
490 const struct nls_table *nls_cp)
Steve French39798772006-05-31 22:40:51 +0000491{
Steve French39798772006-05-31 22:40:51 +0000492 int len;
Steve French790fe572007-07-07 19:25:05 +0000493 char *bcc_ptr = *pbcc_area;
Steve French39798772006-05-31 22:40:51 +0000494
Joe Perchesf96637b2013-05-04 22:12:25 -0500495 cifs_dbg(FYI, "decode sessetup ascii. bleft %d\n", bleft);
Steve French50c2f752007-07-13 00:33:32 +0000496
Steve French39798772006-05-31 22:40:51 +0000497 len = strnlen(bcc_ptr, bleft);
Steve French790fe572007-07-07 19:25:05 +0000498 if (len >= bleft)
Jeff Layton7d066452013-05-24 07:41:00 -0400499 return;
Steve French50c2f752007-07-13 00:33:32 +0000500
Steve French26f57362007-08-30 22:09:15 +0000501 kfree(ses->serverOS);
Steve French39798772006-05-31 22:40:51 +0000502
Ronnie Sahlberg340625e2019-08-27 09:30:14 +1000503 ses->serverOS = kmalloc(len + 1, GFP_KERNEL);
Namjae Jeon27b7edc2014-08-20 19:39:28 +0900504 if (ses->serverOS) {
Ronnie Sahlberg340625e2019-08-27 09:30:14 +1000505 memcpy(ses->serverOS, bcc_ptr, len);
506 ses->serverOS[len] = 0;
Namjae Jeon27b7edc2014-08-20 19:39:28 +0900507 if (strncmp(ses->serverOS, "OS/2", 4) == 0)
508 cifs_dbg(FYI, "OS/2 server\n");
509 }
Steve French39798772006-05-31 22:40:51 +0000510
511 bcc_ptr += len + 1;
512 bleft -= len + 1;
513
514 len = strnlen(bcc_ptr, bleft);
Steve French790fe572007-07-07 19:25:05 +0000515 if (len >= bleft)
Jeff Layton7d066452013-05-24 07:41:00 -0400516 return;
Steve French39798772006-05-31 22:40:51 +0000517
Steve French26f57362007-08-30 22:09:15 +0000518 kfree(ses->serverNOS);
Steve French39798772006-05-31 22:40:51 +0000519
Ronnie Sahlberg340625e2019-08-27 09:30:14 +1000520 ses->serverNOS = kmalloc(len + 1, GFP_KERNEL);
521 if (ses->serverNOS) {
522 memcpy(ses->serverNOS, bcc_ptr, len);
523 ses->serverNOS[len] = 0;
524 }
Steve French39798772006-05-31 22:40:51 +0000525
526 bcc_ptr += len + 1;
527 bleft -= len + 1;
528
Steve French790fe572007-07-07 19:25:05 +0000529 len = strnlen(bcc_ptr, bleft);
530 if (len > bleft)
Jeff Layton7d066452013-05-24 07:41:00 -0400531 return;
Steve French39798772006-05-31 22:40:51 +0000532
Steve French9ac00b72006-09-30 04:13:17 +0000533 /* No domain field in LANMAN case. Domain is
534 returned by old servers in the SMB negprot response */
535 /* BB For newer servers which do not support Unicode,
536 but thus do return domain here we could add parsing
537 for it later, but it is not very important */
Joe Perchesf96637b2013-05-04 22:12:25 -0500538 cifs_dbg(FYI, "ascii: bytes left %d\n", bleft);
Steve French39798772006-05-31 22:40:51 +0000539}
540
Pavel Shilovsky5478f9b2011-12-27 16:22:00 +0400541int decode_ntlmssp_challenge(char *bcc_ptr, int blob_len,
Steve French96daf2b2011-05-27 04:34:02 +0000542 struct cifs_ses *ses)
Steve French0b3cc8582009-05-04 08:37:12 +0000543{
Shirish Pargaonkar2b149f12010-09-18 22:02:18 -0500544 unsigned int tioffset; /* challenge message target info area */
545 unsigned int tilen; /* challenge message target info area length */
546
Steve French0b3cc8582009-05-04 08:37:12 +0000547 CHALLENGE_MESSAGE *pblob = (CHALLENGE_MESSAGE *)bcc_ptr;
548
549 if (blob_len < sizeof(CHALLENGE_MESSAGE)) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500550 cifs_dbg(VFS, "challenge blob len %d too small\n", blob_len);
Steve French0b3cc8582009-05-04 08:37:12 +0000551 return -EINVAL;
552 }
553
554 if (memcmp(pblob->Signature, "NTLMSSP", 8)) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500555 cifs_dbg(VFS, "blob signature incorrect %s\n",
556 pblob->Signature);
Steve French0b3cc8582009-05-04 08:37:12 +0000557 return -EINVAL;
558 }
559 if (pblob->MessageType != NtLmChallenge) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500560 cifs_dbg(VFS, "Incorrect message type %d\n",
561 pblob->MessageType);
Steve French0b3cc8582009-05-04 08:37:12 +0000562 return -EINVAL;
563 }
564
Shirish Pargaonkard3686d52010-10-28 09:53:07 -0500565 memcpy(ses->ntlmssp->cryptkey, pblob->Challenge, CIFS_CRYPTO_KEY_SIZE);
Steve French0b3cc8582009-05-04 08:37:12 +0000566 /* BB we could decode pblob->NegotiateFlags; some may be useful */
567 /* In particular we can examine sign flags */
568 /* BB spec says that if AvId field of MsvAvTimestamp is populated then
569 we must set the MIC field of the AUTHENTICATE_MESSAGE */
Shirish Pargaonkard3686d52010-10-28 09:53:07 -0500570 ses->ntlmssp->server_flags = le32_to_cpu(pblob->NegotiateFlags);
Steve French5443d132011-03-13 05:08:25 +0000571 tioffset = le32_to_cpu(pblob->TargetInfoArray.BufferOffset);
572 tilen = le16_to_cpu(pblob->TargetInfoArray.Length);
Dan Carpenter4991a5f2012-01-31 11:52:01 +0300573 if (tioffset > blob_len || tioffset + tilen > blob_len) {
Joe Perchesa0a30362020-04-14 22:42:53 -0700574 cifs_dbg(VFS, "tioffset + tilen too high %u + %u\n",
575 tioffset, tilen);
Dan Carpenter4991a5f2012-01-31 11:52:01 +0300576 return -EINVAL;
577 }
Shirish Pargaonkard3686d52010-10-28 09:53:07 -0500578 if (tilen) {
Silviu-Mihai Popescuf7f7c182013-03-11 18:22:32 +0200579 ses->auth_key.response = kmemdup(bcc_ptr + tioffset, tilen,
580 GFP_KERNEL);
Shirish Pargaonkard3686d52010-10-28 09:53:07 -0500581 if (!ses->auth_key.response) {
Joe Perchesa0a30362020-04-14 22:42:53 -0700582 cifs_dbg(VFS, "Challenge target info alloc failure\n");
Shirish Pargaonkar2b149f12010-09-18 22:02:18 -0500583 return -ENOMEM;
584 }
Shirish Pargaonkard3686d52010-10-28 09:53:07 -0500585 ses->auth_key.len = tilen;
Shirish Pargaonkar2b149f12010-09-18 22:02:18 -0500586 }
587
Steve French0b3cc8582009-05-04 08:37:12 +0000588 return 0;
589}
590
Steve French0b3cc8582009-05-04 08:37:12 +0000591/* BB Move to ntlmssp.c eventually */
592
593/* We do not malloc the blob, it is passed in pbuffer, because
594 it is fixed size, and small, making this approach cleaner */
Pavel Shilovsky5478f9b2011-12-27 16:22:00 +0400595void build_ntlmssp_negotiate_blob(unsigned char *pbuffer,
Steve French96daf2b2011-05-27 04:34:02 +0000596 struct cifs_ses *ses)
Steve French0b3cc8582009-05-04 08:37:12 +0000597{
Aurelien Aptelf6a6bf72019-09-20 06:22:14 +0200598 struct TCP_Server_Info *server = cifs_ses_server(ses);
Steve French0b3cc8582009-05-04 08:37:12 +0000599 NEGOTIATE_MESSAGE *sec_blob = (NEGOTIATE_MESSAGE *)pbuffer;
600 __u32 flags;
601
Shirish Pargaonkardf8fbc242010-12-11 14:19:22 -0600602 memset(pbuffer, 0, sizeof(NEGOTIATE_MESSAGE));
Steve French0b3cc8582009-05-04 08:37:12 +0000603 memcpy(sec_blob->Signature, NTLMSSP_SIGNATURE, 8);
604 sec_blob->MessageType = NtLmNegotiate;
605
606 /* BB is NTLMV2 session security format easier to use here? */
607 flags = NTLMSSP_NEGOTIATE_56 | NTLMSSP_REQUEST_TARGET |
608 NTLMSSP_NEGOTIATE_128 | NTLMSSP_NEGOTIATE_UNICODE |
Pavel Shilovskycabfb362016-11-07 18:20:50 -0800609 NTLMSSP_NEGOTIATE_NTLM | NTLMSSP_NEGOTIATE_EXTENDED_SEC |
610 NTLMSSP_NEGOTIATE_SEAL;
Aurelien Aptelf6a6bf72019-09-20 06:22:14 +0200611 if (server->sign)
Steve French745e5072010-09-08 21:09:27 +0000612 flags |= NTLMSSP_NEGOTIATE_SIGN;
Aurelien Aptelf6a6bf72019-09-20 06:22:14 +0200613 if (!server->session_estab || ses->ntlmssp->sesskey_per_smbsess)
Pavel Shilovskycabfb362016-11-07 18:20:50 -0800614 flags |= NTLMSSP_NEGOTIATE_KEY_XCH;
Steve French0b3cc8582009-05-04 08:37:12 +0000615
Shirish Pargaonkardf8fbc242010-12-11 14:19:22 -0600616 sec_blob->NegotiateFlags = cpu_to_le32(flags);
Steve French0b3cc8582009-05-04 08:37:12 +0000617
618 sec_blob->WorkstationName.BufferOffset = 0;
619 sec_blob->WorkstationName.Length = 0;
620 sec_blob->WorkstationName.MaximumLength = 0;
621
622 /* Domain name is sent on the Challenge not Negotiate NTLMSSP request */
623 sec_blob->DomainName.BufferOffset = 0;
624 sec_blob->DomainName.Length = 0;
625 sec_blob->DomainName.MaximumLength = 0;
626}
627
Jerome Marchandb8da3442016-05-26 11:52:25 +0200628static int size_of_ntlmssp_blob(struct cifs_ses *ses)
629{
630 int sz = sizeof(AUTHENTICATE_MESSAGE) + ses->auth_key.len
631 - CIFS_SESS_KEY_SIZE + CIFS_CPHTXT_SIZE + 2;
632
633 if (ses->domainName)
634 sz += 2 * strnlen(ses->domainName, CIFS_MAX_DOMAINNAME_LEN);
635 else
636 sz += 2;
637
638 if (ses->user_name)
639 sz += 2 * strnlen(ses->user_name, CIFS_MAX_USERNAME_LEN);
640 else
641 sz += 2;
642
643 return sz;
644}
645
646int build_ntlmssp_auth_blob(unsigned char **pbuffer,
Shirish Pargaonkar89f150f2010-10-19 11:47:52 -0500647 u16 *buflen,
Steve French96daf2b2011-05-27 04:34:02 +0000648 struct cifs_ses *ses,
Shirish Pargaonkar2b149f12010-09-18 22:02:18 -0500649 const struct nls_table *nls_cp)
Steve French0b3cc8582009-05-04 08:37:12 +0000650{
Shirish Pargaonkar2b149f12010-09-18 22:02:18 -0500651 int rc;
Jerome Marchandb8da3442016-05-26 11:52:25 +0200652 AUTHENTICATE_MESSAGE *sec_blob;
Steve French0b3cc8582009-05-04 08:37:12 +0000653 __u32 flags;
654 unsigned char *tmp;
Steve French0b3cc8582009-05-04 08:37:12 +0000655
Jerome Marchandb8da3442016-05-26 11:52:25 +0200656 rc = setup_ntlmv2_rsp(ses, nls_cp);
657 if (rc) {
658 cifs_dbg(VFS, "Error %d during NTLMSSP authentication\n", rc);
659 *buflen = 0;
660 goto setup_ntlmv2_ret;
661 }
662 *pbuffer = kmalloc(size_of_ntlmssp_blob(ses), GFP_KERNEL);
Nicholas Mc Guire126c97f2018-08-23 12:24:02 +0200663 if (!*pbuffer) {
664 rc = -ENOMEM;
665 cifs_dbg(VFS, "Error %d during NTLMSSP allocation\n", rc);
666 *buflen = 0;
667 goto setup_ntlmv2_ret;
668 }
Jerome Marchandb8da3442016-05-26 11:52:25 +0200669 sec_blob = (AUTHENTICATE_MESSAGE *)*pbuffer;
670
Steve French0b3cc8582009-05-04 08:37:12 +0000671 memcpy(sec_blob->Signature, NTLMSSP_SIGNATURE, 8);
672 sec_blob->MessageType = NtLmAuthenticate;
673
674 flags = NTLMSSP_NEGOTIATE_56 |
675 NTLMSSP_REQUEST_TARGET | NTLMSSP_NEGOTIATE_TARGET_INFO |
676 NTLMSSP_NEGOTIATE_128 | NTLMSSP_NEGOTIATE_UNICODE |
Pavel Shilovskycabfb362016-11-07 18:20:50 -0800677 NTLMSSP_NEGOTIATE_NTLM | NTLMSSP_NEGOTIATE_EXTENDED_SEC |
678 NTLMSSP_NEGOTIATE_SEAL;
679 if (ses->server->sign)
Steve French0b3cc8582009-05-04 08:37:12 +0000680 flags |= NTLMSSP_NEGOTIATE_SIGN;
Pavel Shilovskycabfb362016-11-07 18:20:50 -0800681 if (!ses->server->session_estab || ses->ntlmssp->sesskey_per_smbsess)
682 flags |= NTLMSSP_NEGOTIATE_KEY_XCH;
Steve French0b3cc8582009-05-04 08:37:12 +0000683
Jerome Marchandb8da3442016-05-26 11:52:25 +0200684 tmp = *pbuffer + sizeof(AUTHENTICATE_MESSAGE);
Shirish Pargaonkardf8fbc242010-12-11 14:19:22 -0600685 sec_blob->NegotiateFlags = cpu_to_le32(flags);
Steve French0b3cc8582009-05-04 08:37:12 +0000686
687 sec_blob->LmChallengeResponse.BufferOffset =
688 cpu_to_le32(sizeof(AUTHENTICATE_MESSAGE));
689 sec_blob->LmChallengeResponse.Length = 0;
690 sec_blob->LmChallengeResponse.MaximumLength = 0;
691
Jerome Marchandb8da3442016-05-26 11:52:25 +0200692 sec_blob->NtChallengeResponse.BufferOffset =
693 cpu_to_le32(tmp - *pbuffer);
Stefan Metzmachercfda35d2016-05-03 10:52:30 +0200694 if (ses->user_name != NULL) {
Stefan Metzmachercfda35d2016-05-03 10:52:30 +0200695 memcpy(tmp, ses->auth_key.response + CIFS_SESS_KEY_SIZE,
696 ses->auth_key.len - CIFS_SESS_KEY_SIZE);
697 tmp += ses->auth_key.len - CIFS_SESS_KEY_SIZE;
Steve Frenchc8e56f12010-09-08 21:10:58 +0000698
Stefan Metzmachercfda35d2016-05-03 10:52:30 +0200699 sec_blob->NtChallengeResponse.Length =
700 cpu_to_le16(ses->auth_key.len - CIFS_SESS_KEY_SIZE);
701 sec_blob->NtChallengeResponse.MaximumLength =
702 cpu_to_le16(ses->auth_key.len - CIFS_SESS_KEY_SIZE);
703 } else {
704 /*
705 * don't send an NT Response for anonymous access
706 */
707 sec_blob->NtChallengeResponse.Length = 0;
708 sec_blob->NtChallengeResponse.MaximumLength = 0;
709 }
Steve French0b3cc8582009-05-04 08:37:12 +0000710
711 if (ses->domainName == NULL) {
Jerome Marchandb8da3442016-05-26 11:52:25 +0200712 sec_blob->DomainName.BufferOffset = cpu_to_le32(tmp - *pbuffer);
Steve French0b3cc8582009-05-04 08:37:12 +0000713 sec_blob->DomainName.Length = 0;
714 sec_blob->DomainName.MaximumLength = 0;
715 tmp += 2;
716 } else {
717 int len;
Steve Frenchacbbb762012-01-18 22:32:33 -0600718 len = cifs_strtoUTF16((__le16 *)tmp, ses->domainName,
Jerome Marchand202d7722016-05-26 11:52:24 +0200719 CIFS_MAX_DOMAINNAME_LEN, nls_cp);
Steve French0b3cc8582009-05-04 08:37:12 +0000720 len *= 2; /* unicode is 2 bytes each */
Jerome Marchandb8da3442016-05-26 11:52:25 +0200721 sec_blob->DomainName.BufferOffset = cpu_to_le32(tmp - *pbuffer);
Steve French0b3cc8582009-05-04 08:37:12 +0000722 sec_blob->DomainName.Length = cpu_to_le16(len);
723 sec_blob->DomainName.MaximumLength = cpu_to_le16(len);
724 tmp += len;
725 }
726
Steve French8727c8a2011-02-25 01:11:56 -0600727 if (ses->user_name == NULL) {
Jerome Marchandb8da3442016-05-26 11:52:25 +0200728 sec_blob->UserName.BufferOffset = cpu_to_le32(tmp - *pbuffer);
Steve French0b3cc8582009-05-04 08:37:12 +0000729 sec_blob->UserName.Length = 0;
730 sec_blob->UserName.MaximumLength = 0;
731 tmp += 2;
732 } else {
733 int len;
Steve Frenchacbbb762012-01-18 22:32:33 -0600734 len = cifs_strtoUTF16((__le16 *)tmp, ses->user_name,
Scott Lovenberg8c3a2b42013-08-09 08:47:17 -0400735 CIFS_MAX_USERNAME_LEN, nls_cp);
Steve French0b3cc8582009-05-04 08:37:12 +0000736 len *= 2; /* unicode is 2 bytes each */
Jerome Marchandb8da3442016-05-26 11:52:25 +0200737 sec_blob->UserName.BufferOffset = cpu_to_le32(tmp - *pbuffer);
Steve French0b3cc8582009-05-04 08:37:12 +0000738 sec_blob->UserName.Length = cpu_to_le16(len);
739 sec_blob->UserName.MaximumLength = cpu_to_le16(len);
740 tmp += len;
741 }
742
Jerome Marchandb8da3442016-05-26 11:52:25 +0200743 sec_blob->WorkstationName.BufferOffset = cpu_to_le32(tmp - *pbuffer);
Steve French0b3cc8582009-05-04 08:37:12 +0000744 sec_blob->WorkstationName.Length = 0;
745 sec_blob->WorkstationName.MaximumLength = 0;
746 tmp += 2;
747
Shirish Pargaonkardf8fbc242010-12-11 14:19:22 -0600748 if (((ses->ntlmssp->server_flags & NTLMSSP_NEGOTIATE_KEY_XCH) ||
749 (ses->ntlmssp->server_flags & NTLMSSP_NEGOTIATE_EXTENDED_SEC))
750 && !calc_seckey(ses)) {
Shirish Pargaonkard3686d52010-10-28 09:53:07 -0500751 memcpy(tmp, ses->ntlmssp->ciphertext, CIFS_CPHTXT_SIZE);
Jerome Marchandb8da3442016-05-26 11:52:25 +0200752 sec_blob->SessionKey.BufferOffset = cpu_to_le32(tmp - *pbuffer);
Shirish Pargaonkard2b91522010-10-21 14:25:08 -0500753 sec_blob->SessionKey.Length = cpu_to_le16(CIFS_CPHTXT_SIZE);
754 sec_blob->SessionKey.MaximumLength =
755 cpu_to_le16(CIFS_CPHTXT_SIZE);
756 tmp += CIFS_CPHTXT_SIZE;
757 } else {
Jerome Marchandb8da3442016-05-26 11:52:25 +0200758 sec_blob->SessionKey.BufferOffset = cpu_to_le32(tmp - *pbuffer);
Shirish Pargaonkard2b91522010-10-21 14:25:08 -0500759 sec_blob->SessionKey.Length = 0;
760 sec_blob->SessionKey.MaximumLength = 0;
761 }
Shirish Pargaonkar2b149f12010-09-18 22:02:18 -0500762
Jerome Marchandb8da3442016-05-26 11:52:25 +0200763 *buflen = tmp - *pbuffer;
Shirish Pargaonkar2b149f12010-09-18 22:02:18 -0500764setup_ntlmv2_ret:
Shirish Pargaonkar89f150f2010-10-19 11:47:52 -0500765 return rc;
Steve French0b3cc8582009-05-04 08:37:12 +0000766}
Steve French0b3cc8582009-05-04 08:37:12 +0000767
Jeff Layton3f618222013-06-12 19:52:14 -0500768enum securityEnum
Sachin Prabhuef65aae2017-01-18 15:35:57 +0530769cifs_select_sectype(struct TCP_Server_Info *server, enum securityEnum requested)
Jeff Layton3f618222013-06-12 19:52:14 -0500770{
771 switch (server->negflavor) {
772 case CIFS_NEGFLAVOR_EXTENDED:
773 switch (requested) {
774 case Kerberos:
775 case RawNTLMSSP:
776 return requested;
777 case Unspecified:
778 if (server->sec_ntlmssp &&
779 (global_secflags & CIFSSEC_MAY_NTLMSSP))
780 return RawNTLMSSP;
781 if ((server->sec_kerberos || server->sec_mskerberos) &&
782 (global_secflags & CIFSSEC_MAY_KRB5))
783 return Kerberos;
784 /* Fallthrough */
785 default:
786 return Unspecified;
787 }
788 case CIFS_NEGFLAVOR_UNENCAP:
789 switch (requested) {
790 case NTLM:
791 case NTLMv2:
792 return requested;
793 case Unspecified:
794 if (global_secflags & CIFSSEC_MAY_NTLMV2)
795 return NTLMv2;
796 if (global_secflags & CIFSSEC_MAY_NTLM)
797 return NTLM;
Jeff Layton3f618222013-06-12 19:52:14 -0500798 default:
Sachin Prabhudde23562013-09-27 18:35:42 +0100799 break;
Jeff Layton3f618222013-06-12 19:52:14 -0500800 }
Gustavo A. R. Silva07fa6012018-11-27 10:01:51 +1100801 /* Fallthrough - to attempt LANMAN authentication next */
Jeff Layton3f618222013-06-12 19:52:14 -0500802 case CIFS_NEGFLAVOR_LANMAN:
803 switch (requested) {
804 case LANMAN:
805 return requested;
806 case Unspecified:
807 if (global_secflags & CIFSSEC_MAY_LANMAN)
808 return LANMAN;
809 /* Fallthrough */
810 default:
811 return Unspecified;
812 }
813 default:
814 return Unspecified;
815 }
816}
817
Sachin Prabhu80a0e632014-06-16 15:35:25 +0100818struct sess_data {
819 unsigned int xid;
820 struct cifs_ses *ses;
821 struct nls_table *nls_cp;
822 void (*func)(struct sess_data *);
823 int result;
824
825 /* we will send the SMB in three pieces:
826 * a fixed length beginning part, an optional
827 * SPNEGO blob (which can be zero length), and a
828 * last part which will include the strings
829 * and rest of bcc area. This allows us to avoid
830 * a large buffer 17K allocation
831 */
832 int buf0_type;
833 struct kvec iov[3];
834};
835
836static int
837sess_alloc_buffer(struct sess_data *sess_data, int wct)
838{
839 int rc;
840 struct cifs_ses *ses = sess_data->ses;
841 struct smb_hdr *smb_buf;
842
843 rc = small_smb_init_no_tc(SMB_COM_SESSION_SETUP_ANDX, wct, ses,
844 (void **)&smb_buf);
845
846 if (rc)
847 return rc;
848
849 sess_data->iov[0].iov_base = (char *)smb_buf;
850 sess_data->iov[0].iov_len = be32_to_cpu(smb_buf->smb_buf_length) + 4;
851 /*
852 * This variable will be used to clear the buffer
853 * allocated above in case of any error in the calling function.
854 */
855 sess_data->buf0_type = CIFS_SMALL_BUFFER;
856
857 /* 2000 big enough to fit max user, domain, NOS name etc. */
858 sess_data->iov[2].iov_base = kmalloc(2000, GFP_KERNEL);
859 if (!sess_data->iov[2].iov_base) {
860 rc = -ENOMEM;
861 goto out_free_smb_buf;
862 }
863
864 return 0;
865
866out_free_smb_buf:
867 kfree(smb_buf);
868 sess_data->iov[0].iov_base = NULL;
869 sess_data->iov[0].iov_len = 0;
870 sess_data->buf0_type = CIFS_NO_BUFFER;
871 return rc;
872}
873
874static void
875sess_free_buffer(struct sess_data *sess_data)
876{
877
878 free_rsp_buf(sess_data->buf0_type, sess_data->iov[0].iov_base);
879 sess_data->buf0_type = CIFS_NO_BUFFER;
880 kfree(sess_data->iov[2].iov_base);
881}
882
883static int
884sess_establish_session(struct sess_data *sess_data)
885{
886 struct cifs_ses *ses = sess_data->ses;
887
888 mutex_lock(&ses->server->srv_mutex);
889 if (!ses->server->session_estab) {
890 if (ses->server->sign) {
891 ses->server->session_key.response =
892 kmemdup(ses->auth_key.response,
893 ses->auth_key.len, GFP_KERNEL);
894 if (!ses->server->session_key.response) {
895 mutex_unlock(&ses->server->srv_mutex);
896 return -ENOMEM;
897 }
898 ses->server->session_key.len =
899 ses->auth_key.len;
900 }
901 ses->server->sequence_number = 0x2;
902 ses->server->session_estab = true;
903 }
904 mutex_unlock(&ses->server->srv_mutex);
905
906 cifs_dbg(FYI, "CIFS session established successfully\n");
907 spin_lock(&GlobalMid_Lock);
908 ses->status = CifsGood;
909 ses->need_reconnect = false;
910 spin_unlock(&GlobalMid_Lock);
911
912 return 0;
913}
914
915static int
916sess_sendreceive(struct sess_data *sess_data)
917{
918 int rc;
919 struct smb_hdr *smb_buf = (struct smb_hdr *) sess_data->iov[0].iov_base;
920 __u16 count;
Pavel Shilovskyda502f72016-10-25 11:38:47 -0700921 struct kvec rsp_iov = { NULL, 0 };
Sachin Prabhu80a0e632014-06-16 15:35:25 +0100922
923 count = sess_data->iov[1].iov_len + sess_data->iov[2].iov_len;
924 smb_buf->smb_buf_length =
925 cpu_to_be32(be32_to_cpu(smb_buf->smb_buf_length) + count);
926 put_bcc(count, smb_buf);
927
928 rc = SendReceive2(sess_data->xid, sess_data->ses,
929 sess_data->iov, 3 /* num_iovecs */,
930 &sess_data->buf0_type,
Pavel Shilovskyda502f72016-10-25 11:38:47 -0700931 CIFS_LOG_ERROR, &rsp_iov);
932 cifs_small_buf_release(sess_data->iov[0].iov_base);
933 memcpy(&sess_data->iov[0], &rsp_iov, sizeof(struct kvec));
Sachin Prabhu80a0e632014-06-16 15:35:25 +0100934
935 return rc;
936}
937
938/*
939 * LANMAN and plaintext are less secure and off by default.
940 * So we make this explicitly be turned on in kconfig (in the
941 * build) and turned on at runtime (changed from the default)
942 * in proc/fs/cifs or via mount parm. Unfortunately this is
943 * needed for old Win (e.g. Win95), some obscure NAS and OS/2
944 */
945#ifdef CONFIG_CIFS_WEAK_PW_HASH
946static void
947sess_auth_lanman(struct sess_data *sess_data)
948{
949 int rc = 0;
950 struct smb_hdr *smb_buf;
951 SESSION_SETUP_ANDX *pSMB;
952 char *bcc_ptr;
953 struct cifs_ses *ses = sess_data->ses;
954 char lnm_session_key[CIFS_AUTH_RESP_SIZE];
Sachin Prabhu80a0e632014-06-16 15:35:25 +0100955 __u16 bytes_remaining;
956
957 /* lanman 2 style sessionsetup */
958 /* wct = 10 */
959 rc = sess_alloc_buffer(sess_data, 10);
960 if (rc)
961 goto out;
962
963 pSMB = (SESSION_SETUP_ANDX *)sess_data->iov[0].iov_base;
964 bcc_ptr = sess_data->iov[2].iov_base;
zhengbin8559ad82019-09-24 10:13:47 +0800965 (void)cifs_ssetup_hdr(ses, pSMB);
Sachin Prabhu80a0e632014-06-16 15:35:25 +0100966
967 pSMB->req.hdr.Flags2 &= ~SMBFLG2_UNICODE;
968
Stefan Metzmacherfa8f3a32016-05-03 10:52:30 +0200969 if (ses->user_name != NULL) {
970 /* no capabilities flags in old lanman negotiation */
971 pSMB->old_req.PasswordLength = cpu_to_le16(CIFS_AUTH_RESP_SIZE);
Sachin Prabhu80a0e632014-06-16 15:35:25 +0100972
Stefan Metzmacherfa8f3a32016-05-03 10:52:30 +0200973 /* Calculate hash with password and copy into bcc_ptr.
974 * Encryption Key (stored as in cryptkey) gets used if the
975 * security mode bit in Negottiate Protocol response states
976 * to use challenge/response method (i.e. Password bit is 1).
977 */
978 rc = calc_lanman_hash(ses->password, ses->server->cryptkey,
979 ses->server->sec_mode & SECMODE_PW_ENCRYPT ?
980 true : false, lnm_session_key);
Luis de Bethencourta6b6bef2016-06-08 17:02:32 +0100981 if (rc)
982 goto out;
Sachin Prabhu80a0e632014-06-16 15:35:25 +0100983
Stefan Metzmacherfa8f3a32016-05-03 10:52:30 +0200984 memcpy(bcc_ptr, (char *)lnm_session_key, CIFS_AUTH_RESP_SIZE);
985 bcc_ptr += CIFS_AUTH_RESP_SIZE;
986 } else {
987 pSMB->old_req.PasswordLength = 0;
988 }
Sachin Prabhu80a0e632014-06-16 15:35:25 +0100989
990 /*
991 * can not sign if LANMAN negotiated so no need
992 * to calculate signing key? but what if server
993 * changed to do higher than lanman dialect and
994 * we reconnected would we ever calc signing_key?
995 */
996
997 cifs_dbg(FYI, "Negotiating LANMAN setting up strings\n");
998 /* Unicode not allowed for LANMAN dialects */
999 ascii_ssetup_strings(&bcc_ptr, ses, sess_data->nls_cp);
1000
1001 sess_data->iov[2].iov_len = (long) bcc_ptr -
1002 (long) sess_data->iov[2].iov_base;
1003
1004 rc = sess_sendreceive(sess_data);
1005 if (rc)
1006 goto out;
1007
1008 pSMB = (SESSION_SETUP_ANDX *)sess_data->iov[0].iov_base;
1009 smb_buf = (struct smb_hdr *)sess_data->iov[0].iov_base;
1010
1011 /* lanman response has a word count of 3 */
1012 if (smb_buf->WordCount != 3) {
1013 rc = -EIO;
1014 cifs_dbg(VFS, "bad word count %d\n", smb_buf->WordCount);
1015 goto out;
1016 }
1017
1018 if (le16_to_cpu(pSMB->resp.Action) & GUEST_LOGIN)
1019 cifs_dbg(FYI, "Guest login\n"); /* BB mark SesInfo struct? */
1020
1021 ses->Suid = smb_buf->Uid; /* UID left in wire format (le) */
1022 cifs_dbg(FYI, "UID = %llu\n", ses->Suid);
1023
1024 bytes_remaining = get_bcc(smb_buf);
1025 bcc_ptr = pByteArea(smb_buf);
1026
1027 /* BB check if Unicode and decode strings */
1028 if (bytes_remaining == 0) {
1029 /* no string area to decode, do nothing */
1030 } else if (smb_buf->Flags2 & SMBFLG2_UNICODE) {
1031 /* unicode string area must be word-aligned */
1032 if (((unsigned long) bcc_ptr - (unsigned long) smb_buf) % 2) {
1033 ++bcc_ptr;
1034 --bytes_remaining;
1035 }
1036 decode_unicode_ssetup(&bcc_ptr, bytes_remaining, ses,
1037 sess_data->nls_cp);
1038 } else {
1039 decode_ascii_ssetup(&bcc_ptr, bytes_remaining, ses,
1040 sess_data->nls_cp);
1041 }
1042
1043 rc = sess_establish_session(sess_data);
1044out:
1045 sess_data->result = rc;
1046 sess_data->func = NULL;
1047 sess_free_buffer(sess_data);
1048}
1049
Sachin Prabhu80a0e632014-06-16 15:35:25 +01001050#endif
1051
Sachin Prabhu583cf7a2014-06-16 15:35:26 +01001052static void
1053sess_auth_ntlm(struct sess_data *sess_data)
1054{
1055 int rc = 0;
1056 struct smb_hdr *smb_buf;
1057 SESSION_SETUP_ANDX *pSMB;
1058 char *bcc_ptr;
1059 struct cifs_ses *ses = sess_data->ses;
1060 __u32 capabilities;
1061 __u16 bytes_remaining;
1062
1063 /* old style NTLM sessionsetup */
1064 /* wct = 13 */
1065 rc = sess_alloc_buffer(sess_data, 13);
1066 if (rc)
1067 goto out;
1068
1069 pSMB = (SESSION_SETUP_ANDX *)sess_data->iov[0].iov_base;
1070 bcc_ptr = sess_data->iov[2].iov_base;
1071 capabilities = cifs_ssetup_hdr(ses, pSMB);
1072
1073 pSMB->req_no_secext.Capabilities = cpu_to_le32(capabilities);
Stefan Metzmacher777f69b2016-05-03 10:52:30 +02001074 if (ses->user_name != NULL) {
1075 pSMB->req_no_secext.CaseInsensitivePasswordLength =
1076 cpu_to_le16(CIFS_AUTH_RESP_SIZE);
1077 pSMB->req_no_secext.CaseSensitivePasswordLength =
1078 cpu_to_le16(CIFS_AUTH_RESP_SIZE);
Sachin Prabhu583cf7a2014-06-16 15:35:26 +01001079
Stefan Metzmacher777f69b2016-05-03 10:52:30 +02001080 /* calculate ntlm response and session key */
1081 rc = setup_ntlm_response(ses, sess_data->nls_cp);
1082 if (rc) {
1083 cifs_dbg(VFS, "Error %d during NTLM authentication\n",
1084 rc);
1085 goto out;
1086 }
1087
1088 /* copy ntlm response */
1089 memcpy(bcc_ptr, ses->auth_key.response + CIFS_SESS_KEY_SIZE,
1090 CIFS_AUTH_RESP_SIZE);
1091 bcc_ptr += CIFS_AUTH_RESP_SIZE;
1092 memcpy(bcc_ptr, ses->auth_key.response + CIFS_SESS_KEY_SIZE,
1093 CIFS_AUTH_RESP_SIZE);
1094 bcc_ptr += CIFS_AUTH_RESP_SIZE;
1095 } else {
1096 pSMB->req_no_secext.CaseInsensitivePasswordLength = 0;
1097 pSMB->req_no_secext.CaseSensitivePasswordLength = 0;
Sachin Prabhu583cf7a2014-06-16 15:35:26 +01001098 }
1099
Sachin Prabhu583cf7a2014-06-16 15:35:26 +01001100 if (ses->capabilities & CAP_UNICODE) {
1101 /* unicode strings must be word aligned */
1102 if (sess_data->iov[0].iov_len % 2) {
1103 *bcc_ptr = 0;
1104 bcc_ptr++;
1105 }
1106 unicode_ssetup_strings(&bcc_ptr, ses, sess_data->nls_cp);
1107 } else {
1108 ascii_ssetup_strings(&bcc_ptr, ses, sess_data->nls_cp);
1109 }
1110
1111
1112 sess_data->iov[2].iov_len = (long) bcc_ptr -
1113 (long) sess_data->iov[2].iov_base;
1114
1115 rc = sess_sendreceive(sess_data);
1116 if (rc)
1117 goto out;
1118
1119 pSMB = (SESSION_SETUP_ANDX *)sess_data->iov[0].iov_base;
1120 smb_buf = (struct smb_hdr *)sess_data->iov[0].iov_base;
1121
1122 if (smb_buf->WordCount != 3) {
1123 rc = -EIO;
1124 cifs_dbg(VFS, "bad word count %d\n", smb_buf->WordCount);
1125 goto out;
1126 }
1127
1128 if (le16_to_cpu(pSMB->resp.Action) & GUEST_LOGIN)
1129 cifs_dbg(FYI, "Guest login\n"); /* BB mark SesInfo struct? */
1130
1131 ses->Suid = smb_buf->Uid; /* UID left in wire format (le) */
1132 cifs_dbg(FYI, "UID = %llu\n", ses->Suid);
1133
1134 bytes_remaining = get_bcc(smb_buf);
1135 bcc_ptr = pByteArea(smb_buf);
1136
1137 /* BB check if Unicode and decode strings */
1138 if (bytes_remaining == 0) {
1139 /* no string area to decode, do nothing */
1140 } else if (smb_buf->Flags2 & SMBFLG2_UNICODE) {
1141 /* unicode string area must be word-aligned */
1142 if (((unsigned long) bcc_ptr - (unsigned long) smb_buf) % 2) {
1143 ++bcc_ptr;
1144 --bytes_remaining;
1145 }
1146 decode_unicode_ssetup(&bcc_ptr, bytes_remaining, ses,
1147 sess_data->nls_cp);
1148 } else {
1149 decode_ascii_ssetup(&bcc_ptr, bytes_remaining, ses,
1150 sess_data->nls_cp);
1151 }
1152
1153 rc = sess_establish_session(sess_data);
1154out:
1155 sess_data->result = rc;
1156 sess_data->func = NULL;
1157 sess_free_buffer(sess_data);
1158 kfree(ses->auth_key.response);
1159 ses->auth_key.response = NULL;
1160}
1161
1162static void
1163sess_auth_ntlmv2(struct sess_data *sess_data)
1164{
1165 int rc = 0;
1166 struct smb_hdr *smb_buf;
1167 SESSION_SETUP_ANDX *pSMB;
1168 char *bcc_ptr;
1169 struct cifs_ses *ses = sess_data->ses;
1170 __u32 capabilities;
1171 __u16 bytes_remaining;
1172
1173 /* old style NTLM sessionsetup */
1174 /* wct = 13 */
1175 rc = sess_alloc_buffer(sess_data, 13);
1176 if (rc)
1177 goto out;
1178
1179 pSMB = (SESSION_SETUP_ANDX *)sess_data->iov[0].iov_base;
1180 bcc_ptr = sess_data->iov[2].iov_base;
1181 capabilities = cifs_ssetup_hdr(ses, pSMB);
1182
1183 pSMB->req_no_secext.Capabilities = cpu_to_le32(capabilities);
1184
1185 /* LM2 password would be here if we supported it */
1186 pSMB->req_no_secext.CaseInsensitivePasswordLength = 0;
1187
Stefan Metzmacher1a967d62016-05-03 10:52:30 +02001188 if (ses->user_name != NULL) {
1189 /* calculate nlmv2 response and session key */
1190 rc = setup_ntlmv2_rsp(ses, sess_data->nls_cp);
1191 if (rc) {
1192 cifs_dbg(VFS, "Error %d during NTLMv2 authentication\n", rc);
1193 goto out;
1194 }
1195
1196 memcpy(bcc_ptr, ses->auth_key.response + CIFS_SESS_KEY_SIZE,
1197 ses->auth_key.len - CIFS_SESS_KEY_SIZE);
1198 bcc_ptr += ses->auth_key.len - CIFS_SESS_KEY_SIZE;
1199
1200 /* set case sensitive password length after tilen may get
1201 * assigned, tilen is 0 otherwise.
1202 */
1203 pSMB->req_no_secext.CaseSensitivePasswordLength =
1204 cpu_to_le16(ses->auth_key.len - CIFS_SESS_KEY_SIZE);
1205 } else {
1206 pSMB->req_no_secext.CaseSensitivePasswordLength = 0;
Sachin Prabhu583cf7a2014-06-16 15:35:26 +01001207 }
1208
Sachin Prabhu583cf7a2014-06-16 15:35:26 +01001209 if (ses->capabilities & CAP_UNICODE) {
1210 if (sess_data->iov[0].iov_len % 2) {
1211 *bcc_ptr = 0;
1212 bcc_ptr++;
1213 }
1214 unicode_ssetup_strings(&bcc_ptr, ses, sess_data->nls_cp);
1215 } else {
1216 ascii_ssetup_strings(&bcc_ptr, ses, sess_data->nls_cp);
1217 }
1218
1219
1220 sess_data->iov[2].iov_len = (long) bcc_ptr -
1221 (long) sess_data->iov[2].iov_base;
1222
1223 rc = sess_sendreceive(sess_data);
1224 if (rc)
1225 goto out;
1226
1227 pSMB = (SESSION_SETUP_ANDX *)sess_data->iov[0].iov_base;
1228 smb_buf = (struct smb_hdr *)sess_data->iov[0].iov_base;
1229
1230 if (smb_buf->WordCount != 3) {
1231 rc = -EIO;
1232 cifs_dbg(VFS, "bad word count %d\n", smb_buf->WordCount);
1233 goto out;
1234 }
1235
1236 if (le16_to_cpu(pSMB->resp.Action) & GUEST_LOGIN)
1237 cifs_dbg(FYI, "Guest login\n"); /* BB mark SesInfo struct? */
1238
1239 ses->Suid = smb_buf->Uid; /* UID left in wire format (le) */
1240 cifs_dbg(FYI, "UID = %llu\n", ses->Suid);
1241
1242 bytes_remaining = get_bcc(smb_buf);
1243 bcc_ptr = pByteArea(smb_buf);
1244
1245 /* BB check if Unicode and decode strings */
1246 if (bytes_remaining == 0) {
1247 /* no string area to decode, do nothing */
1248 } else if (smb_buf->Flags2 & SMBFLG2_UNICODE) {
1249 /* unicode string area must be word-aligned */
1250 if (((unsigned long) bcc_ptr - (unsigned long) smb_buf) % 2) {
1251 ++bcc_ptr;
1252 --bytes_remaining;
1253 }
1254 decode_unicode_ssetup(&bcc_ptr, bytes_remaining, ses,
1255 sess_data->nls_cp);
1256 } else {
1257 decode_ascii_ssetup(&bcc_ptr, bytes_remaining, ses,
1258 sess_data->nls_cp);
1259 }
1260
1261 rc = sess_establish_session(sess_data);
1262out:
1263 sess_data->result = rc;
1264 sess_data->func = NULL;
1265 sess_free_buffer(sess_data);
1266 kfree(ses->auth_key.response);
1267 ses->auth_key.response = NULL;
1268}
1269
Sachin Prabhuee03c642014-06-16 15:35:27 +01001270#ifdef CONFIG_CIFS_UPCALL
1271static void
1272sess_auth_kerberos(struct sess_data *sess_data)
1273{
1274 int rc = 0;
1275 struct smb_hdr *smb_buf;
1276 SESSION_SETUP_ANDX *pSMB;
1277 char *bcc_ptr;
1278 struct cifs_ses *ses = sess_data->ses;
1279 __u32 capabilities;
1280 __u16 bytes_remaining;
1281 struct key *spnego_key = NULL;
1282 struct cifs_spnego_msg *msg;
1283 u16 blob_len;
1284
1285 /* extended security */
1286 /* wct = 12 */
1287 rc = sess_alloc_buffer(sess_data, 12);
1288 if (rc)
1289 goto out;
1290
1291 pSMB = (SESSION_SETUP_ANDX *)sess_data->iov[0].iov_base;
1292 bcc_ptr = sess_data->iov[2].iov_base;
1293 capabilities = cifs_ssetup_hdr(ses, pSMB);
1294
1295 spnego_key = cifs_get_spnego_key(ses);
1296 if (IS_ERR(spnego_key)) {
1297 rc = PTR_ERR(spnego_key);
1298 spnego_key = NULL;
1299 goto out;
1300 }
1301
David Howells146aa8b2015-10-21 14:04:48 +01001302 msg = spnego_key->payload.data[0];
Sachin Prabhuee03c642014-06-16 15:35:27 +01001303 /*
1304 * check version field to make sure that cifs.upcall is
1305 * sending us a response in an expected form
1306 */
1307 if (msg->version != CIFS_SPNEGO_UPCALL_VERSION) {
Joe Perchesa0a30362020-04-14 22:42:53 -07001308 cifs_dbg(VFS, "incorrect version of cifs.upcall (expected %d but got %d)\n",
1309 CIFS_SPNEGO_UPCALL_VERSION, msg->version);
Sachin Prabhuee03c642014-06-16 15:35:27 +01001310 rc = -EKEYREJECTED;
1311 goto out_put_spnego_key;
1312 }
1313
1314 ses->auth_key.response = kmemdup(msg->data, msg->sesskey_len,
1315 GFP_KERNEL);
1316 if (!ses->auth_key.response) {
Joe Perchesa0a30362020-04-14 22:42:53 -07001317 cifs_dbg(VFS, "Kerberos can't allocate (%u bytes) memory\n",
1318 msg->sesskey_len);
Sachin Prabhuee03c642014-06-16 15:35:27 +01001319 rc = -ENOMEM;
1320 goto out_put_spnego_key;
1321 }
1322 ses->auth_key.len = msg->sesskey_len;
1323
1324 pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC;
1325 capabilities |= CAP_EXTENDED_SECURITY;
1326 pSMB->req.Capabilities = cpu_to_le32(capabilities);
1327 sess_data->iov[1].iov_base = msg->data + msg->sesskey_len;
1328 sess_data->iov[1].iov_len = msg->secblob_len;
1329 pSMB->req.SecurityBlobLength = cpu_to_le16(sess_data->iov[1].iov_len);
1330
1331 if (ses->capabilities & CAP_UNICODE) {
1332 /* unicode strings must be word aligned */
1333 if ((sess_data->iov[0].iov_len
1334 + sess_data->iov[1].iov_len) % 2) {
1335 *bcc_ptr = 0;
1336 bcc_ptr++;
1337 }
1338 unicode_oslm_strings(&bcc_ptr, sess_data->nls_cp);
1339 unicode_domain_string(&bcc_ptr, ses, sess_data->nls_cp);
1340 } else {
1341 /* BB: is this right? */
1342 ascii_ssetup_strings(&bcc_ptr, ses, sess_data->nls_cp);
1343 }
1344
1345 sess_data->iov[2].iov_len = (long) bcc_ptr -
1346 (long) sess_data->iov[2].iov_base;
1347
1348 rc = sess_sendreceive(sess_data);
1349 if (rc)
1350 goto out_put_spnego_key;
1351
1352 pSMB = (SESSION_SETUP_ANDX *)sess_data->iov[0].iov_base;
1353 smb_buf = (struct smb_hdr *)sess_data->iov[0].iov_base;
1354
1355 if (smb_buf->WordCount != 4) {
1356 rc = -EIO;
1357 cifs_dbg(VFS, "bad word count %d\n", smb_buf->WordCount);
1358 goto out_put_spnego_key;
1359 }
1360
1361 if (le16_to_cpu(pSMB->resp.Action) & GUEST_LOGIN)
1362 cifs_dbg(FYI, "Guest login\n"); /* BB mark SesInfo struct? */
1363
1364 ses->Suid = smb_buf->Uid; /* UID left in wire format (le) */
1365 cifs_dbg(FYI, "UID = %llu\n", ses->Suid);
1366
1367 bytes_remaining = get_bcc(smb_buf);
1368 bcc_ptr = pByteArea(smb_buf);
1369
1370 blob_len = le16_to_cpu(pSMB->resp.SecurityBlobLength);
1371 if (blob_len > bytes_remaining) {
1372 cifs_dbg(VFS, "bad security blob length %d\n",
1373 blob_len);
1374 rc = -EINVAL;
1375 goto out_put_spnego_key;
1376 }
1377 bcc_ptr += blob_len;
1378 bytes_remaining -= blob_len;
1379
1380 /* BB check if Unicode and decode strings */
1381 if (bytes_remaining == 0) {
1382 /* no string area to decode, do nothing */
1383 } else if (smb_buf->Flags2 & SMBFLG2_UNICODE) {
1384 /* unicode string area must be word-aligned */
1385 if (((unsigned long) bcc_ptr - (unsigned long) smb_buf) % 2) {
1386 ++bcc_ptr;
1387 --bytes_remaining;
1388 }
1389 decode_unicode_ssetup(&bcc_ptr, bytes_remaining, ses,
1390 sess_data->nls_cp);
1391 } else {
1392 decode_ascii_ssetup(&bcc_ptr, bytes_remaining, ses,
1393 sess_data->nls_cp);
1394 }
1395
1396 rc = sess_establish_session(sess_data);
1397out_put_spnego_key:
1398 key_invalidate(spnego_key);
1399 key_put(spnego_key);
1400out:
1401 sess_data->result = rc;
1402 sess_data->func = NULL;
1403 sess_free_buffer(sess_data);
1404 kfree(ses->auth_key.response);
1405 ses->auth_key.response = NULL;
1406}
1407
Sachin Prabhuee03c642014-06-16 15:35:27 +01001408#endif /* ! CONFIG_CIFS_UPCALL */
Sachin Prabhu583cf7a2014-06-16 15:35:26 +01001409
Sachin Prabhucc87c472014-06-16 15:35:28 +01001410/*
1411 * The required kvec buffers have to be allocated before calling this
1412 * function.
1413 */
1414static int
1415_sess_auth_rawntlmssp_assemble_req(struct sess_data *sess_data)
Steve French39798772006-05-31 22:40:51 +00001416{
Steve French39798772006-05-31 22:40:51 +00001417 SESSION_SETUP_ANDX *pSMB;
Sachin Prabhucc87c472014-06-16 15:35:28 +01001418 struct cifs_ses *ses = sess_data->ses;
Steve French39798772006-05-31 22:40:51 +00001419 __u32 capabilities;
Sachin Prabhucc87c472014-06-16 15:35:28 +01001420 char *bcc_ptr;
Steve French254e55e2006-06-04 05:53:15 +00001421
Sachin Prabhucc87c472014-06-16 15:35:28 +01001422 pSMB = (SESSION_SETUP_ANDX *)sess_data->iov[0].iov_base;
Sachin Prabhucc87c472014-06-16 15:35:28 +01001423
1424 capabilities = cifs_ssetup_hdr(ses, pSMB);
1425 if ((pSMB->req.hdr.Flags2 & SMBFLG2_UNICODE) == 0) {
1426 cifs_dbg(VFS, "NTLMSSP requires Unicode support\n");
1427 return -ENOSYS;
Jeff Layton3534b852013-05-24 07:41:01 -04001428 }
Steve French39798772006-05-31 22:40:51 +00001429
Sachin Prabhucc87c472014-06-16 15:35:28 +01001430 pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC;
1431 capabilities |= CAP_EXTENDED_SECURITY;
1432 pSMB->req.Capabilities |= cpu_to_le32(capabilities);
1433
1434 bcc_ptr = sess_data->iov[2].iov_base;
1435 /* unicode strings must be word aligned */
1436 if ((sess_data->iov[0].iov_len + sess_data->iov[1].iov_len) % 2) {
1437 *bcc_ptr = 0;
1438 bcc_ptr++;
1439 }
1440 unicode_oslm_strings(&bcc_ptr, sess_data->nls_cp);
1441
1442 sess_data->iov[2].iov_len = (long) bcc_ptr -
1443 (long) sess_data->iov[2].iov_base;
1444
1445 return 0;
1446}
1447
1448static void
1449sess_auth_rawntlmssp_authenticate(struct sess_data *sess_data);
1450
1451static void
1452sess_auth_rawntlmssp_negotiate(struct sess_data *sess_data)
1453{
1454 int rc;
1455 struct smb_hdr *smb_buf;
1456 SESSION_SETUP_ANDX *pSMB;
1457 struct cifs_ses *ses = sess_data->ses;
1458 __u16 bytes_remaining;
1459 char *bcc_ptr;
1460 u16 blob_len;
1461
1462 cifs_dbg(FYI, "rawntlmssp session setup negotiate phase\n");
1463
1464 /*
1465 * if memory allocation is successful, caller of this function
1466 * frees it.
1467 */
1468 ses->ntlmssp = kmalloc(sizeof(struct ntlmssp_auth), GFP_KERNEL);
1469 if (!ses->ntlmssp) {
1470 rc = -ENOMEM;
1471 goto out;
1472 }
1473 ses->ntlmssp->sesskey_per_smbsess = false;
1474
1475 /* wct = 12 */
1476 rc = sess_alloc_buffer(sess_data, 12);
1477 if (rc)
1478 goto out;
1479
1480 pSMB = (SESSION_SETUP_ANDX *)sess_data->iov[0].iov_base;
1481
1482 /* Build security blob before we assemble the request */
1483 build_ntlmssp_negotiate_blob(pSMB->req.SecurityBlob, ses);
1484 sess_data->iov[1].iov_len = sizeof(NEGOTIATE_MESSAGE);
1485 sess_data->iov[1].iov_base = pSMB->req.SecurityBlob;
1486 pSMB->req.SecurityBlobLength = cpu_to_le16(sizeof(NEGOTIATE_MESSAGE));
1487
1488 rc = _sess_auth_rawntlmssp_assemble_req(sess_data);
1489 if (rc)
1490 goto out;
1491
1492 rc = sess_sendreceive(sess_data);
1493
1494 pSMB = (SESSION_SETUP_ANDX *)sess_data->iov[0].iov_base;
1495 smb_buf = (struct smb_hdr *)sess_data->iov[0].iov_base;
1496
1497 /* If true, rc here is expected and not an error */
1498 if (sess_data->buf0_type != CIFS_NO_BUFFER &&
1499 smb_buf->Status.CifsError ==
1500 cpu_to_le32(NT_STATUS_MORE_PROCESSING_REQUIRED))
1501 rc = 0;
1502
1503 if (rc)
1504 goto out;
1505
1506 cifs_dbg(FYI, "rawntlmssp session setup challenge phase\n");
1507
1508 if (smb_buf->WordCount != 4) {
1509 rc = -EIO;
1510 cifs_dbg(VFS, "bad word count %d\n", smb_buf->WordCount);
1511 goto out;
1512 }
1513
1514 ses->Suid = smb_buf->Uid; /* UID left in wire format (le) */
1515 cifs_dbg(FYI, "UID = %llu\n", ses->Suid);
1516
1517 bytes_remaining = get_bcc(smb_buf);
1518 bcc_ptr = pByteArea(smb_buf);
1519
1520 blob_len = le16_to_cpu(pSMB->resp.SecurityBlobLength);
1521 if (blob_len > bytes_remaining) {
1522 cifs_dbg(VFS, "bad security blob length %d\n",
1523 blob_len);
1524 rc = -EINVAL;
1525 goto out;
1526 }
1527
1528 rc = decode_ntlmssp_challenge(bcc_ptr, blob_len, ses);
1529out:
1530 sess_free_buffer(sess_data);
1531
1532 if (!rc) {
1533 sess_data->func = sess_auth_rawntlmssp_authenticate;
1534 return;
1535 }
1536
1537 /* Else error. Cleanup */
1538 kfree(ses->auth_key.response);
1539 ses->auth_key.response = NULL;
1540 kfree(ses->ntlmssp);
1541 ses->ntlmssp = NULL;
1542
1543 sess_data->func = NULL;
1544 sess_data->result = rc;
1545}
1546
1547static void
1548sess_auth_rawntlmssp_authenticate(struct sess_data *sess_data)
1549{
1550 int rc;
1551 struct smb_hdr *smb_buf;
1552 SESSION_SETUP_ANDX *pSMB;
1553 struct cifs_ses *ses = sess_data->ses;
1554 __u16 bytes_remaining;
1555 char *bcc_ptr;
Jerome Marchandb8da3442016-05-26 11:52:25 +02001556 unsigned char *ntlmsspblob = NULL;
Sachin Prabhucc87c472014-06-16 15:35:28 +01001557 u16 blob_len;
1558
1559 cifs_dbg(FYI, "rawntlmssp session setup authenticate phase\n");
1560
1561 /* wct = 12 */
1562 rc = sess_alloc_buffer(sess_data, 12);
1563 if (rc)
1564 goto out;
1565
1566 /* Build security blob before we assemble the request */
1567 pSMB = (SESSION_SETUP_ANDX *)sess_data->iov[0].iov_base;
1568 smb_buf = (struct smb_hdr *)pSMB;
Jerome Marchandb8da3442016-05-26 11:52:25 +02001569 rc = build_ntlmssp_auth_blob(&ntlmsspblob,
Sachin Prabhucc87c472014-06-16 15:35:28 +01001570 &blob_len, ses, sess_data->nls_cp);
1571 if (rc)
1572 goto out_free_ntlmsspblob;
1573 sess_data->iov[1].iov_len = blob_len;
1574 sess_data->iov[1].iov_base = ntlmsspblob;
1575 pSMB->req.SecurityBlobLength = cpu_to_le16(blob_len);
1576 /*
1577 * Make sure that we tell the server that we are using
1578 * the uid that it just gave us back on the response
1579 * (challenge)
1580 */
1581 smb_buf->Uid = ses->Suid;
1582
1583 rc = _sess_auth_rawntlmssp_assemble_req(sess_data);
1584 if (rc)
1585 goto out_free_ntlmsspblob;
1586
1587 rc = sess_sendreceive(sess_data);
1588 if (rc)
1589 goto out_free_ntlmsspblob;
1590
1591 pSMB = (SESSION_SETUP_ANDX *)sess_data->iov[0].iov_base;
1592 smb_buf = (struct smb_hdr *)sess_data->iov[0].iov_base;
1593 if (smb_buf->WordCount != 4) {
1594 rc = -EIO;
1595 cifs_dbg(VFS, "bad word count %d\n", smb_buf->WordCount);
1596 goto out_free_ntlmsspblob;
1597 }
1598
1599 if (le16_to_cpu(pSMB->resp.Action) & GUEST_LOGIN)
1600 cifs_dbg(FYI, "Guest login\n"); /* BB mark SesInfo struct? */
1601
Sachin Prabhuee9bbf42014-12-03 12:26:36 +00001602 if (ses->Suid != smb_buf->Uid) {
1603 ses->Suid = smb_buf->Uid;
1604 cifs_dbg(FYI, "UID changed! new UID = %llu\n", ses->Suid);
1605 }
1606
Sachin Prabhucc87c472014-06-16 15:35:28 +01001607 bytes_remaining = get_bcc(smb_buf);
1608 bcc_ptr = pByteArea(smb_buf);
1609 blob_len = le16_to_cpu(pSMB->resp.SecurityBlobLength);
1610 if (blob_len > bytes_remaining) {
1611 cifs_dbg(VFS, "bad security blob length %d\n",
1612 blob_len);
1613 rc = -EINVAL;
1614 goto out_free_ntlmsspblob;
1615 }
1616 bcc_ptr += blob_len;
1617 bytes_remaining -= blob_len;
1618
1619
1620 /* BB check if Unicode and decode strings */
1621 if (bytes_remaining == 0) {
1622 /* no string area to decode, do nothing */
1623 } else if (smb_buf->Flags2 & SMBFLG2_UNICODE) {
1624 /* unicode string area must be word-aligned */
1625 if (((unsigned long) bcc_ptr - (unsigned long) smb_buf) % 2) {
1626 ++bcc_ptr;
1627 --bytes_remaining;
1628 }
1629 decode_unicode_ssetup(&bcc_ptr, bytes_remaining, ses,
1630 sess_data->nls_cp);
1631 } else {
1632 decode_ascii_ssetup(&bcc_ptr, bytes_remaining, ses,
1633 sess_data->nls_cp);
1634 }
1635
1636out_free_ntlmsspblob:
1637 kfree(ntlmsspblob);
1638out:
1639 sess_free_buffer(sess_data);
1640
1641 if (!rc)
1642 rc = sess_establish_session(sess_data);
1643
1644 /* Cleanup */
1645 kfree(ses->auth_key.response);
1646 ses->auth_key.response = NULL;
1647 kfree(ses->ntlmssp);
1648 ses->ntlmssp = NULL;
1649
1650 sess_data->func = NULL;
1651 sess_data->result = rc;
1652}
1653
Steve French27924072014-07-11 07:47:01 -05001654static int select_sec(struct cifs_ses *ses, struct sess_data *sess_data)
Sachin Prabhucc87c472014-06-16 15:35:28 +01001655{
1656 int type;
Sachin Prabhu80a0e632014-06-16 15:35:25 +01001657
Sachin Prabhuef65aae2017-01-18 15:35:57 +05301658 type = cifs_select_sectype(ses->server, ses->sectype);
Joe Perchesf96637b2013-05-04 22:12:25 -05001659 cifs_dbg(FYI, "sess setup type %d\n", type);
Jeff Layton3f618222013-06-12 19:52:14 -05001660 if (type == Unspecified) {
Joe Perchesa0a30362020-04-14 22:42:53 -07001661 cifs_dbg(VFS, "Unable to select appropriate authentication method!\n");
Jeff Layton3f618222013-06-12 19:52:14 -05001662 return -EINVAL;
1663 }
1664
Sachin Prabhu80a0e632014-06-16 15:35:25 +01001665 switch (type) {
1666 case LANMAN:
Sachin Prabhucc87c472014-06-16 15:35:28 +01001667 /* LANMAN and plaintext are less secure and off by default.
1668 * So we make this explicitly be turned on in kconfig (in the
1669 * build) and turned on at runtime (changed from the default)
1670 * in proc/fs/cifs or via mount parm. Unfortunately this is
1671 * needed for old Win (e.g. Win95), some obscure NAS and OS/2 */
1672#ifdef CONFIG_CIFS_WEAK_PW_HASH
1673 sess_data->func = sess_auth_lanman;
1674 break;
1675#else
1676 return -EOPNOTSUPP;
1677#endif
Sachin Prabhu583cf7a2014-06-16 15:35:26 +01001678 case NTLM:
Sachin Prabhucc87c472014-06-16 15:35:28 +01001679 sess_data->func = sess_auth_ntlm;
1680 break;
Sachin Prabhu583cf7a2014-06-16 15:35:26 +01001681 case NTLMv2:
Sachin Prabhucc87c472014-06-16 15:35:28 +01001682 sess_data->func = sess_auth_ntlmv2;
1683 break;
Sachin Prabhuee03c642014-06-16 15:35:27 +01001684 case Kerberos:
Sachin Prabhucc87c472014-06-16 15:35:28 +01001685#ifdef CONFIG_CIFS_UPCALL
1686 sess_data->func = sess_auth_kerberos;
1687 break;
1688#else
1689 cifs_dbg(VFS, "Kerberos negotiated but upcall support disabled!\n");
1690 return -ENOSYS;
1691 break;
1692#endif /* CONFIG_CIFS_UPCALL */
1693 case RawNTLMSSP:
1694 sess_data->func = sess_auth_rawntlmssp_negotiate;
1695 break;
Sachin Prabhu80a0e632014-06-16 15:35:25 +01001696 default:
Joe Perchesf96637b2013-05-04 22:12:25 -05001697 cifs_dbg(VFS, "secType %d not supported!\n", type);
Sachin Prabhucc87c472014-06-16 15:35:28 +01001698 return -ENOSYS;
Steve French39798772006-05-31 22:40:51 +00001699 }
1700
Sachin Prabhucc87c472014-06-16 15:35:28 +01001701 return 0;
1702}
Steve French24424212007-11-16 23:37:35 +00001703
Sachin Prabhucc87c472014-06-16 15:35:28 +01001704int CIFS_SessSetup(const unsigned int xid, struct cifs_ses *ses,
1705 const struct nls_table *nls_cp)
1706{
1707 int rc = 0;
1708 struct sess_data *sess_data;
Steve French39798772006-05-31 22:40:51 +00001709
Sachin Prabhucc87c472014-06-16 15:35:28 +01001710 if (ses == NULL) {
1711 WARN(1, "%s: ses == NULL!", __func__);
1712 return -EINVAL;
Steve French0b3cc8582009-05-04 08:37:12 +00001713 }
Sachin Prabhucc87c472014-06-16 15:35:28 +01001714
1715 sess_data = kzalloc(sizeof(struct sess_data), GFP_KERNEL);
1716 if (!sess_data)
1717 return -ENOMEM;
1718
1719 rc = select_sec(ses, sess_data);
Steve French0b3cc8582009-05-04 08:37:12 +00001720 if (rc)
Sachin Prabhucc87c472014-06-16 15:35:28 +01001721 goto out;
Steve French0b3cc8582009-05-04 08:37:12 +00001722
Sachin Prabhucc87c472014-06-16 15:35:28 +01001723 sess_data->xid = xid;
1724 sess_data->ses = ses;
1725 sess_data->buf0_type = CIFS_NO_BUFFER;
1726 sess_data->nls_cp = (struct nls_table *) nls_cp;
Steve French39798772006-05-31 22:40:51 +00001727
Sachin Prabhucc87c472014-06-16 15:35:28 +01001728 while (sess_data->func)
1729 sess_data->func(sess_data);
Steve French39798772006-05-31 22:40:51 +00001730
Sachin Prabhucc87c472014-06-16 15:35:28 +01001731 /* Store result before we free sess_data */
1732 rc = sess_data->result;
Sachin Prabhu80a0e632014-06-16 15:35:25 +01001733
1734out:
Sachin Prabhu80a0e632014-06-16 15:35:25 +01001735 kfree(sess_data);
1736 return rc;
Steve French39798772006-05-31 22:40:51 +00001737}