blob: d95137304224463e7ac0ca0b3aa4e785011d7269 [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 Apteld70e9fa2019-09-20 06:31:10 +020080
81 if (left <= 0) {
82 cifs_dbg(FYI,
83 "ses already at max_channels (%zu), nothing to open\n",
84 ses->chan_max);
85 return 0;
86 }
87
88 if (ses->server->dialect < SMB30_PROT_ID) {
89 cifs_dbg(VFS, "multichannel is not supported on this protocol version, use 3.0 or above\n");
90 return 0;
91 }
92
Aurelien Aptel65a37a32019-11-20 17:15:59 +010093 /*
94 * Keep connecting to same, fastest, iface for all channels as
95 * long as its RSS. Try next fastest one if not RSS or channel
96 * creation fails.
97 */
98 while (left > 0) {
Aurelien Apteld70e9fa2019-09-20 06:31:10 +020099 struct cifs_server_iface *iface;
100
Aurelien Aptel65a37a32019-11-20 17:15:59 +0100101 tries++;
102 if (tries > 3*ses->chan_max) {
103 cifs_dbg(FYI, "too many attempt at opening channels (%d channels left to open)\n",
104 left);
105 break;
106 }
Aurelien Apteld70e9fa2019-09-20 06:31:10 +0200107
Aurelien Aptel65a37a32019-11-20 17:15:59 +0100108 iface = &ses->iface_list[i];
109 if (is_ses_using_iface(ses, iface) && !iface->rss_capable) {
110 i = (i+1) % ses->iface_count;
Aurelien Apteld70e9fa2019-09-20 06:31:10 +0200111 continue;
112 }
113
Aurelien Aptel65a37a32019-11-20 17:15:59 +0100114 rc = cifs_ses_add_channel(ses, iface);
115 if (rc) {
116 cifs_dbg(FYI, "failed to open extra channel on iface#%d rc=%d\n",
117 i, rc);
118 i = (i+1) % ses->iface_count;
119 continue;
120 }
121
122 cifs_dbg(FYI, "successfully opened new channel on iface#%d\n",
123 i);
Aurelien Apteld70e9fa2019-09-20 06:31:10 +0200124 left--;
125 }
126
Aurelien Apteld70e9fa2019-09-20 06:31:10 +0200127 return ses->chan_count - old_chan_count;
128}
129
130int
131cifs_ses_add_channel(struct cifs_ses *ses, struct cifs_server_iface *iface)
132{
133 struct cifs_chan *chan;
134 struct smb_vol vol = {NULL};
135 static const char unc_fmt[] = "\\%s\\foo";
136 char unc[sizeof(unc_fmt)+SERVER_NAME_LEN_WITH_NULL] = {0};
137 struct sockaddr_in *ipv4 = (struct sockaddr_in *)&iface->sockaddr;
138 struct sockaddr_in6 *ipv6 = (struct sockaddr_in6 *)&iface->sockaddr;
139 int rc;
140 unsigned int xid = get_xid();
141
142 cifs_dbg(FYI, "adding channel to ses %p (speed:%zu bps rdma:%s ",
143 ses, iface->speed, iface->rdma_capable ? "yes" : "no");
144 if (iface->sockaddr.ss_family == AF_INET)
145 cifs_dbg(FYI, "ip:%pI4)\n", &ipv4->sin_addr);
146 else
147 cifs_dbg(FYI, "ip:%pI6)\n", &ipv6->sin6_addr);
148
149 /*
150 * Setup a smb_vol with mostly the same info as the existing
151 * session and overwrite it with the requested iface data.
152 *
153 * We need to setup at least the fields used for negprot and
154 * sesssetup.
155 *
156 * We only need the volume here, so we can reuse memory from
157 * the session and server without caring about memory
158 * management.
159 */
160
161 /* Always make new connection for now (TODO?) */
162 vol.nosharesock = true;
163
164 /* Auth */
165 vol.domainauto = ses->domainAuto;
166 vol.domainname = ses->domainName;
167 vol.username = ses->user_name;
168 vol.password = ses->password;
169 vol.sectype = ses->sectype;
170 vol.sign = ses->sign;
171
172 /* UNC and paths */
173 /* XXX: Use ses->server->hostname? */
174 sprintf(unc, unc_fmt, ses->serverName);
175 vol.UNC = unc;
176 vol.prepath = "";
177
178 /* Re-use same version as master connection */
179 vol.vals = ses->server->vals;
180 vol.ops = ses->server->ops;
181
182 vol.noblocksnd = ses->server->noblocksnd;
183 vol.noautotune = ses->server->noautotune;
184 vol.sockopt_tcp_nodelay = ses->server->tcp_nodelay;
185 vol.echo_interval = ses->server->echo_interval / HZ;
186
187 /*
188 * This will be used for encoding/decoding user/domain/pw
189 * during sess setup auth.
190 *
191 * XXX: We use the default for simplicity but the proper way
192 * would be to use the one that ses used, which is not
193 * stored. This might break when dealing with non-ascii
194 * strings.
195 */
196 vol.local_nls = load_nls_default();
197
198 /* Use RDMA if possible */
199 vol.rdma = iface->rdma_capable;
200 memcpy(&vol.dstaddr, &iface->sockaddr, sizeof(struct sockaddr_storage));
201
202 /* reuse master con client guid */
203 memcpy(&vol.client_guid, ses->server->client_guid,
204 SMB2_CLIENT_GUID_SIZE);
205 vol.use_client_guid = true;
206
207 mutex_lock(&ses->session_mutex);
208
209 chan = &ses->chans[ses->chan_count];
210 chan->server = cifs_get_tcp_session(&vol);
211 if (IS_ERR(chan->server)) {
212 rc = PTR_ERR(chan->server);
213 chan->server = NULL;
214 goto out;
215 }
Paulo Alcantara (SUSE)3345bb42019-12-04 11:25:06 -0300216 spin_lock(&cifs_tcp_ses_lock);
217 chan->server->is_channel = true;
218 spin_unlock(&cifs_tcp_ses_lock);
Aurelien Apteld70e9fa2019-09-20 06:31:10 +0200219
220 /*
221 * We need to allocate the server crypto now as we will need
222 * to sign packets before we generate the channel signing key
223 * (we sign with the session key)
224 */
225 rc = smb311_crypto_shash_allocate(chan->server);
226 if (rc) {
227 cifs_dbg(VFS, "%s: crypto alloc failed\n", __func__);
228 goto out;
229 }
230
231 ses->binding = true;
232 rc = cifs_negotiate_protocol(xid, ses);
233 if (rc)
234 goto out;
235
236 rc = cifs_setup_session(xid, ses, vol.local_nls);
237 if (rc)
238 goto out;
239
240 /* success, put it on the list
241 * XXX: sharing ses between 2 tcp server is not possible, the
242 * way "internal" linked lists works in linux makes element
243 * only able to belong to one list
244 *
245 * the binding session is already established so the rest of
246 * the code should be able to look it up, no need to add the
247 * ses to the new server.
248 */
249
250 ses->chan_count++;
251 atomic_set(&ses->chan_seq, 0);
252out:
253 ses->binding = false;
254 mutex_unlock(&ses->session_mutex);
255
256 if (rc && chan->server)
257 cifs_put_tcp_session(chan->server, 0);
258 unload_nls(vol.local_nls);
259
260 return rc;
261}
Steve French39798772006-05-31 22:40:51 +0000262
Steve French96daf2b2011-05-27 04:34:02 +0000263static __u32 cifs_ssetup_hdr(struct cifs_ses *ses, SESSION_SETUP_ANDX *pSMB)
Steve French39798772006-05-31 22:40:51 +0000264{
265 __u32 capabilities = 0;
266
267 /* init fields common to all four types of SessSetup */
Steve Frencheca6acf2009-02-20 05:43:09 +0000268 /* Note that offsets for first seven fields in req struct are same */
269 /* in CIFS Specs so does not matter which of 3 forms of struct */
270 /* that we use in next few lines */
271 /* Note that header is initialized to zero in header_assemble */
Steve French39798772006-05-31 22:40:51 +0000272 pSMB->req.AndXCommand = 0xFF;
Jeff Laytonc974bef2011-10-11 06:41:32 -0400273 pSMB->req.MaxBufferSize = cpu_to_le16(min_t(u32,
274 CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4,
275 USHRT_MAX));
Steve French39798772006-05-31 22:40:51 +0000276 pSMB->req.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
Fabian Frederickbc09d142014-12-10 15:41:15 -0800277 pSMB->req.VcNumber = cpu_to_le16(1);
Steve French39798772006-05-31 22:40:51 +0000278
279 /* Now no need to set SMBFLG_CASELESS or obsolete CANONICAL PATH */
280
Steve French790fe572007-07-07 19:25:05 +0000281 /* BB verify whether signing required on neg or just on auth frame
Steve French39798772006-05-31 22:40:51 +0000282 (and NTLM case) */
283
284 capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
285 CAP_LARGE_WRITE_X | CAP_LARGE_READ_X;
286
Jeff Layton38d77c52013-05-26 07:01:00 -0400287 if (ses->server->sign)
Steve French39798772006-05-31 22:40:51 +0000288 pSMB->req.hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
289
290 if (ses->capabilities & CAP_UNICODE) {
291 pSMB->req.hdr.Flags2 |= SMBFLG2_UNICODE;
292 capabilities |= CAP_UNICODE;
293 }
294 if (ses->capabilities & CAP_STATUS32) {
295 pSMB->req.hdr.Flags2 |= SMBFLG2_ERR_STATUS;
296 capabilities |= CAP_STATUS32;
297 }
298 if (ses->capabilities & CAP_DFS) {
299 pSMB->req.hdr.Flags2 |= SMBFLG2_DFS;
300 capabilities |= CAP_DFS;
301 }
Steve French26f57362007-08-30 22:09:15 +0000302 if (ses->capabilities & CAP_UNIX)
Steve French39798772006-05-31 22:40:51 +0000303 capabilities |= CAP_UNIX;
Steve French39798772006-05-31 22:40:51 +0000304
Steve French39798772006-05-31 22:40:51 +0000305 return capabilities;
306}
307
Jeff Layton0d3a01f2007-10-16 17:32:19 +0000308static void
309unicode_oslm_strings(char **pbcc_area, const struct nls_table *nls_cp)
310{
311 char *bcc_ptr = *pbcc_area;
312 int bytes_ret = 0;
313
314 /* Copy OS version */
Steve Frenchacbbb762012-01-18 22:32:33 -0600315 bytes_ret = cifs_strtoUTF16((__le16 *)bcc_ptr, "Linux version ", 32,
316 nls_cp);
Jeff Layton0d3a01f2007-10-16 17:32:19 +0000317 bcc_ptr += 2 * bytes_ret;
Steve Frenchacbbb762012-01-18 22:32:33 -0600318 bytes_ret = cifs_strtoUTF16((__le16 *) bcc_ptr, init_utsname()->release,
319 32, nls_cp);
Jeff Layton0d3a01f2007-10-16 17:32:19 +0000320 bcc_ptr += 2 * bytes_ret;
321 bcc_ptr += 2; /* trailing null */
322
Steve Frenchacbbb762012-01-18 22:32:33 -0600323 bytes_ret = cifs_strtoUTF16((__le16 *) bcc_ptr, CIFS_NETWORK_OPSYS,
324 32, nls_cp);
Jeff Layton0d3a01f2007-10-16 17:32:19 +0000325 bcc_ptr += 2 * bytes_ret;
326 bcc_ptr += 2; /* trailing null */
327
328 *pbcc_area = bcc_ptr;
329}
330
Steve French96daf2b2011-05-27 04:34:02 +0000331static void unicode_domain_string(char **pbcc_area, struct cifs_ses *ses,
Jeff Layton0d3a01f2007-10-16 17:32:19 +0000332 const struct nls_table *nls_cp)
333{
334 char *bcc_ptr = *pbcc_area;
335 int bytes_ret = 0;
336
337 /* copy domain */
338 if (ses->domainName == NULL) {
339 /* Sending null domain better than using a bogus domain name (as
340 we did briefly in 2.6.18) since server will use its default */
341 *bcc_ptr = 0;
342 *(bcc_ptr+1) = 0;
343 bytes_ret = 0;
344 } else
Steve Frenchacbbb762012-01-18 22:32:33 -0600345 bytes_ret = cifs_strtoUTF16((__le16 *) bcc_ptr, ses->domainName,
Chen Gang057d6332013-07-19 09:01:36 +0800346 CIFS_MAX_DOMAINNAME_LEN, nls_cp);
Jeff Layton0d3a01f2007-10-16 17:32:19 +0000347 bcc_ptr += 2 * bytes_ret;
348 bcc_ptr += 2; /* account for null terminator */
349
350 *pbcc_area = bcc_ptr;
351}
352
353
Steve French96daf2b2011-05-27 04:34:02 +0000354static void unicode_ssetup_strings(char **pbcc_area, struct cifs_ses *ses,
Steve French790fe572007-07-07 19:25:05 +0000355 const struct nls_table *nls_cp)
Steve French39798772006-05-31 22:40:51 +0000356{
Steve French790fe572007-07-07 19:25:05 +0000357 char *bcc_ptr = *pbcc_area;
Steve French39798772006-05-31 22:40:51 +0000358 int bytes_ret = 0;
359
360 /* BB FIXME add check that strings total less
361 than 335 or will need to send them as arrays */
362
Steve French0223cf02006-06-27 19:50:57 +0000363 /* unicode strings, must be word aligned before the call */
364/* if ((long) bcc_ptr % 2) {
Steve French39798772006-05-31 22:40:51 +0000365 *bcc_ptr = 0;
366 bcc_ptr++;
Steve French0223cf02006-06-27 19:50:57 +0000367 } */
Steve French39798772006-05-31 22:40:51 +0000368 /* copy user */
Steve French8727c8a2011-02-25 01:11:56 -0600369 if (ses->user_name == NULL) {
Steve French6e659c62006-11-08 23:10:46 +0000370 /* null user mount */
371 *bcc_ptr = 0;
372 *(bcc_ptr+1) = 0;
Steve French301a6a32010-02-06 07:08:53 +0000373 } else {
Steve Frenchacbbb762012-01-18 22:32:33 -0600374 bytes_ret = cifs_strtoUTF16((__le16 *) bcc_ptr, ses->user_name,
Scott Lovenberg8c3a2b42013-08-09 08:47:17 -0400375 CIFS_MAX_USERNAME_LEN, nls_cp);
Steve French39798772006-05-31 22:40:51 +0000376 }
377 bcc_ptr += 2 * bytes_ret;
378 bcc_ptr += 2; /* account for null termination */
Steve French39798772006-05-31 22:40:51 +0000379
Jeff Layton0d3a01f2007-10-16 17:32:19 +0000380 unicode_domain_string(&bcc_ptr, ses, nls_cp);
381 unicode_oslm_strings(&bcc_ptr, nls_cp);
Steve French39798772006-05-31 22:40:51 +0000382
383 *pbcc_area = bcc_ptr;
384}
385
Steve French96daf2b2011-05-27 04:34:02 +0000386static void ascii_ssetup_strings(char **pbcc_area, struct cifs_ses *ses,
Steve French790fe572007-07-07 19:25:05 +0000387 const struct nls_table *nls_cp)
Steve French39798772006-05-31 22:40:51 +0000388{
Steve French790fe572007-07-07 19:25:05 +0000389 char *bcc_ptr = *pbcc_area;
Ronnie Sahlberg340625e2019-08-27 09:30:14 +1000390 int len;
Steve French39798772006-05-31 22:40:51 +0000391
392 /* copy user */
393 /* BB what about null user mounts - check that we do this BB */
Steve French790fe572007-07-07 19:25:05 +0000394 /* copy user */
Shirish Pargaonkarde47a412012-02-02 15:28:28 -0600395 if (ses->user_name != NULL) {
Ronnie Sahlberg340625e2019-08-27 09:30:14 +1000396 len = strscpy(bcc_ptr, ses->user_name, CIFS_MAX_USERNAME_LEN);
397 if (WARN_ON_ONCE(len < 0))
398 len = CIFS_MAX_USERNAME_LEN - 1;
399 bcc_ptr += len;
Shirish Pargaonkarde47a412012-02-02 15:28:28 -0600400 }
Steve French8727c8a2011-02-25 01:11:56 -0600401 /* else null user mount */
Steve French39798772006-05-31 22:40:51 +0000402 *bcc_ptr = 0;
Steve French790fe572007-07-07 19:25:05 +0000403 bcc_ptr++; /* account for null termination */
Steve French39798772006-05-31 22:40:51 +0000404
Steve French790fe572007-07-07 19:25:05 +0000405 /* copy domain */
Steve French790fe572007-07-07 19:25:05 +0000406 if (ses->domainName != NULL) {
Ronnie Sahlberg340625e2019-08-27 09:30:14 +1000407 len = strscpy(bcc_ptr, ses->domainName, CIFS_MAX_DOMAINNAME_LEN);
408 if (WARN_ON_ONCE(len < 0))
409 len = CIFS_MAX_DOMAINNAME_LEN - 1;
410 bcc_ptr += len;
Steve French790fe572007-07-07 19:25:05 +0000411 } /* else we will send a null domain name
Steve French6e659c62006-11-08 23:10:46 +0000412 so the server will default to its own domain */
Steve French39798772006-05-31 22:40:51 +0000413 *bcc_ptr = 0;
414 bcc_ptr++;
415
416 /* BB check for overflow here */
417
418 strcpy(bcc_ptr, "Linux version ");
419 bcc_ptr += strlen("Linux version ");
Serge E. Hallyn96b644b2006-10-02 02:18:13 -0700420 strcpy(bcc_ptr, init_utsname()->release);
421 bcc_ptr += strlen(init_utsname()->release) + 1;
Steve French39798772006-05-31 22:40:51 +0000422
423 strcpy(bcc_ptr, CIFS_NETWORK_OPSYS);
424 bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1;
425
Steve French790fe572007-07-07 19:25:05 +0000426 *pbcc_area = bcc_ptr;
Steve French39798772006-05-31 22:40:51 +0000427}
428
Jeff Layton59140792009-04-30 07:16:21 -0400429static void
Steve French96daf2b2011-05-27 04:34:02 +0000430decode_unicode_ssetup(char **pbcc_area, int bleft, struct cifs_ses *ses,
Jeff Layton59140792009-04-30 07:16:21 -0400431 const struct nls_table *nls_cp)
Steve French39798772006-05-31 22:40:51 +0000432{
Jeff Layton59140792009-04-30 07:16:21 -0400433 int len;
Steve French790fe572007-07-07 19:25:05 +0000434 char *data = *pbcc_area;
Steve French39798772006-05-31 22:40:51 +0000435
Joe Perchesf96637b2013-05-04 22:12:25 -0500436 cifs_dbg(FYI, "bleft %d\n", bleft);
Steve French39798772006-05-31 22:40:51 +0000437
Steve French26f57362007-08-30 22:09:15 +0000438 kfree(ses->serverOS);
Steve Frenchacbbb762012-01-18 22:32:33 -0600439 ses->serverOS = cifs_strndup_from_utf16(data, bleft, true, nls_cp);
Joe Perchesf96637b2013-05-04 22:12:25 -0500440 cifs_dbg(FYI, "serverOS=%s\n", ses->serverOS);
Jeff Layton59140792009-04-30 07:16:21 -0400441 len = (UniStrnlen((wchar_t *) data, bleft / 2) * 2) + 2;
442 data += len;
443 bleft -= len;
444 if (bleft <= 0)
445 return;
Steve French39798772006-05-31 22:40:51 +0000446
Steve French26f57362007-08-30 22:09:15 +0000447 kfree(ses->serverNOS);
Steve Frenchacbbb762012-01-18 22:32:33 -0600448 ses->serverNOS = cifs_strndup_from_utf16(data, bleft, true, nls_cp);
Joe Perchesf96637b2013-05-04 22:12:25 -0500449 cifs_dbg(FYI, "serverNOS=%s\n", ses->serverNOS);
Jeff Layton59140792009-04-30 07:16:21 -0400450 len = (UniStrnlen((wchar_t *) data, bleft / 2) * 2) + 2;
451 data += len;
452 bleft -= len;
453 if (bleft <= 0)
454 return;
Steve French39798772006-05-31 22:40:51 +0000455
Steve French26f57362007-08-30 22:09:15 +0000456 kfree(ses->serverDomain);
Steve Frenchacbbb762012-01-18 22:32:33 -0600457 ses->serverDomain = cifs_strndup_from_utf16(data, bleft, true, nls_cp);
Joe Perchesf96637b2013-05-04 22:12:25 -0500458 cifs_dbg(FYI, "serverDomain=%s\n", ses->serverDomain);
Steve French790fe572007-07-07 19:25:05 +0000459
Jeff Layton59140792009-04-30 07:16:21 -0400460 return;
Steve French39798772006-05-31 22:40:51 +0000461}
462
Jeff Layton7d066452013-05-24 07:41:00 -0400463static void decode_ascii_ssetup(char **pbcc_area, __u16 bleft,
464 struct cifs_ses *ses,
465 const struct nls_table *nls_cp)
Steve French39798772006-05-31 22:40:51 +0000466{
Steve French39798772006-05-31 22:40:51 +0000467 int len;
Steve French790fe572007-07-07 19:25:05 +0000468 char *bcc_ptr = *pbcc_area;
Steve French39798772006-05-31 22:40:51 +0000469
Joe Perchesf96637b2013-05-04 22:12:25 -0500470 cifs_dbg(FYI, "decode sessetup ascii. bleft %d\n", bleft);
Steve French50c2f752007-07-13 00:33:32 +0000471
Steve French39798772006-05-31 22:40:51 +0000472 len = strnlen(bcc_ptr, bleft);
Steve French790fe572007-07-07 19:25:05 +0000473 if (len >= bleft)
Jeff Layton7d066452013-05-24 07:41:00 -0400474 return;
Steve French50c2f752007-07-13 00:33:32 +0000475
Steve French26f57362007-08-30 22:09:15 +0000476 kfree(ses->serverOS);
Steve French39798772006-05-31 22:40:51 +0000477
Ronnie Sahlberg340625e2019-08-27 09:30:14 +1000478 ses->serverOS = kmalloc(len + 1, GFP_KERNEL);
Namjae Jeon27b7edc2014-08-20 19:39:28 +0900479 if (ses->serverOS) {
Ronnie Sahlberg340625e2019-08-27 09:30:14 +1000480 memcpy(ses->serverOS, bcc_ptr, len);
481 ses->serverOS[len] = 0;
Namjae Jeon27b7edc2014-08-20 19:39:28 +0900482 if (strncmp(ses->serverOS, "OS/2", 4) == 0)
483 cifs_dbg(FYI, "OS/2 server\n");
484 }
Steve French39798772006-05-31 22:40:51 +0000485
486 bcc_ptr += len + 1;
487 bleft -= len + 1;
488
489 len = strnlen(bcc_ptr, bleft);
Steve French790fe572007-07-07 19:25:05 +0000490 if (len >= bleft)
Jeff Layton7d066452013-05-24 07:41:00 -0400491 return;
Steve French39798772006-05-31 22:40:51 +0000492
Steve French26f57362007-08-30 22:09:15 +0000493 kfree(ses->serverNOS);
Steve French39798772006-05-31 22:40:51 +0000494
Ronnie Sahlberg340625e2019-08-27 09:30:14 +1000495 ses->serverNOS = kmalloc(len + 1, GFP_KERNEL);
496 if (ses->serverNOS) {
497 memcpy(ses->serverNOS, bcc_ptr, len);
498 ses->serverNOS[len] = 0;
499 }
Steve French39798772006-05-31 22:40:51 +0000500
501 bcc_ptr += len + 1;
502 bleft -= len + 1;
503
Steve French790fe572007-07-07 19:25:05 +0000504 len = strnlen(bcc_ptr, bleft);
505 if (len > bleft)
Jeff Layton7d066452013-05-24 07:41:00 -0400506 return;
Steve French39798772006-05-31 22:40:51 +0000507
Steve French9ac00b72006-09-30 04:13:17 +0000508 /* No domain field in LANMAN case. Domain is
509 returned by old servers in the SMB negprot response */
510 /* BB For newer servers which do not support Unicode,
511 but thus do return domain here we could add parsing
512 for it later, but it is not very important */
Joe Perchesf96637b2013-05-04 22:12:25 -0500513 cifs_dbg(FYI, "ascii: bytes left %d\n", bleft);
Steve French39798772006-05-31 22:40:51 +0000514}
515
Pavel Shilovsky5478f9b2011-12-27 16:22:00 +0400516int decode_ntlmssp_challenge(char *bcc_ptr, int blob_len,
Steve French96daf2b2011-05-27 04:34:02 +0000517 struct cifs_ses *ses)
Steve French0b3cc8582009-05-04 08:37:12 +0000518{
Shirish Pargaonkar2b149f12010-09-18 22:02:18 -0500519 unsigned int tioffset; /* challenge message target info area */
520 unsigned int tilen; /* challenge message target info area length */
521
Steve French0b3cc8582009-05-04 08:37:12 +0000522 CHALLENGE_MESSAGE *pblob = (CHALLENGE_MESSAGE *)bcc_ptr;
523
524 if (blob_len < sizeof(CHALLENGE_MESSAGE)) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500525 cifs_dbg(VFS, "challenge blob len %d too small\n", blob_len);
Steve French0b3cc8582009-05-04 08:37:12 +0000526 return -EINVAL;
527 }
528
529 if (memcmp(pblob->Signature, "NTLMSSP", 8)) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500530 cifs_dbg(VFS, "blob signature incorrect %s\n",
531 pblob->Signature);
Steve French0b3cc8582009-05-04 08:37:12 +0000532 return -EINVAL;
533 }
534 if (pblob->MessageType != NtLmChallenge) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500535 cifs_dbg(VFS, "Incorrect message type %d\n",
536 pblob->MessageType);
Steve French0b3cc8582009-05-04 08:37:12 +0000537 return -EINVAL;
538 }
539
Shirish Pargaonkard3686d52010-10-28 09:53:07 -0500540 memcpy(ses->ntlmssp->cryptkey, pblob->Challenge, CIFS_CRYPTO_KEY_SIZE);
Steve French0b3cc8582009-05-04 08:37:12 +0000541 /* BB we could decode pblob->NegotiateFlags; some may be useful */
542 /* In particular we can examine sign flags */
543 /* BB spec says that if AvId field of MsvAvTimestamp is populated then
544 we must set the MIC field of the AUTHENTICATE_MESSAGE */
Shirish Pargaonkard3686d52010-10-28 09:53:07 -0500545 ses->ntlmssp->server_flags = le32_to_cpu(pblob->NegotiateFlags);
Steve French5443d132011-03-13 05:08:25 +0000546 tioffset = le32_to_cpu(pblob->TargetInfoArray.BufferOffset);
547 tilen = le16_to_cpu(pblob->TargetInfoArray.Length);
Dan Carpenter4991a5f2012-01-31 11:52:01 +0300548 if (tioffset > blob_len || tioffset + tilen > blob_len) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500549 cifs_dbg(VFS, "tioffset + tilen too high %u + %u",
550 tioffset, tilen);
Dan Carpenter4991a5f2012-01-31 11:52:01 +0300551 return -EINVAL;
552 }
Shirish Pargaonkard3686d52010-10-28 09:53:07 -0500553 if (tilen) {
Silviu-Mihai Popescuf7f7c182013-03-11 18:22:32 +0200554 ses->auth_key.response = kmemdup(bcc_ptr + tioffset, tilen,
555 GFP_KERNEL);
Shirish Pargaonkard3686d52010-10-28 09:53:07 -0500556 if (!ses->auth_key.response) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500557 cifs_dbg(VFS, "Challenge target info alloc failure");
Shirish Pargaonkar2b149f12010-09-18 22:02:18 -0500558 return -ENOMEM;
559 }
Shirish Pargaonkard3686d52010-10-28 09:53:07 -0500560 ses->auth_key.len = tilen;
Shirish Pargaonkar2b149f12010-09-18 22:02:18 -0500561 }
562
Steve French0b3cc8582009-05-04 08:37:12 +0000563 return 0;
564}
565
Steve French0b3cc8582009-05-04 08:37:12 +0000566/* BB Move to ntlmssp.c eventually */
567
568/* We do not malloc the blob, it is passed in pbuffer, because
569 it is fixed size, and small, making this approach cleaner */
Pavel Shilovsky5478f9b2011-12-27 16:22:00 +0400570void build_ntlmssp_negotiate_blob(unsigned char *pbuffer,
Steve French96daf2b2011-05-27 04:34:02 +0000571 struct cifs_ses *ses)
Steve French0b3cc8582009-05-04 08:37:12 +0000572{
Aurelien Aptelf6a6bf72019-09-20 06:22:14 +0200573 struct TCP_Server_Info *server = cifs_ses_server(ses);
Steve French0b3cc8582009-05-04 08:37:12 +0000574 NEGOTIATE_MESSAGE *sec_blob = (NEGOTIATE_MESSAGE *)pbuffer;
575 __u32 flags;
576
Shirish Pargaonkardf8fbc242010-12-11 14:19:22 -0600577 memset(pbuffer, 0, sizeof(NEGOTIATE_MESSAGE));
Steve French0b3cc8582009-05-04 08:37:12 +0000578 memcpy(sec_blob->Signature, NTLMSSP_SIGNATURE, 8);
579 sec_blob->MessageType = NtLmNegotiate;
580
581 /* BB is NTLMV2 session security format easier to use here? */
582 flags = NTLMSSP_NEGOTIATE_56 | NTLMSSP_REQUEST_TARGET |
583 NTLMSSP_NEGOTIATE_128 | NTLMSSP_NEGOTIATE_UNICODE |
Pavel Shilovskycabfb362016-11-07 18:20:50 -0800584 NTLMSSP_NEGOTIATE_NTLM | NTLMSSP_NEGOTIATE_EXTENDED_SEC |
585 NTLMSSP_NEGOTIATE_SEAL;
Aurelien Aptelf6a6bf72019-09-20 06:22:14 +0200586 if (server->sign)
Steve French745e5072010-09-08 21:09:27 +0000587 flags |= NTLMSSP_NEGOTIATE_SIGN;
Aurelien Aptelf6a6bf72019-09-20 06:22:14 +0200588 if (!server->session_estab || ses->ntlmssp->sesskey_per_smbsess)
Pavel Shilovskycabfb362016-11-07 18:20:50 -0800589 flags |= NTLMSSP_NEGOTIATE_KEY_XCH;
Steve French0b3cc8582009-05-04 08:37:12 +0000590
Shirish Pargaonkardf8fbc242010-12-11 14:19:22 -0600591 sec_blob->NegotiateFlags = cpu_to_le32(flags);
Steve French0b3cc8582009-05-04 08:37:12 +0000592
593 sec_blob->WorkstationName.BufferOffset = 0;
594 sec_blob->WorkstationName.Length = 0;
595 sec_blob->WorkstationName.MaximumLength = 0;
596
597 /* Domain name is sent on the Challenge not Negotiate NTLMSSP request */
598 sec_blob->DomainName.BufferOffset = 0;
599 sec_blob->DomainName.Length = 0;
600 sec_blob->DomainName.MaximumLength = 0;
601}
602
Jerome Marchandb8da3442016-05-26 11:52:25 +0200603static int size_of_ntlmssp_blob(struct cifs_ses *ses)
604{
605 int sz = sizeof(AUTHENTICATE_MESSAGE) + ses->auth_key.len
606 - CIFS_SESS_KEY_SIZE + CIFS_CPHTXT_SIZE + 2;
607
608 if (ses->domainName)
609 sz += 2 * strnlen(ses->domainName, CIFS_MAX_DOMAINNAME_LEN);
610 else
611 sz += 2;
612
613 if (ses->user_name)
614 sz += 2 * strnlen(ses->user_name, CIFS_MAX_USERNAME_LEN);
615 else
616 sz += 2;
617
618 return sz;
619}
620
621int build_ntlmssp_auth_blob(unsigned char **pbuffer,
Shirish Pargaonkar89f150f2010-10-19 11:47:52 -0500622 u16 *buflen,
Steve French96daf2b2011-05-27 04:34:02 +0000623 struct cifs_ses *ses,
Shirish Pargaonkar2b149f12010-09-18 22:02:18 -0500624 const struct nls_table *nls_cp)
Steve French0b3cc8582009-05-04 08:37:12 +0000625{
Shirish Pargaonkar2b149f12010-09-18 22:02:18 -0500626 int rc;
Jerome Marchandb8da3442016-05-26 11:52:25 +0200627 AUTHENTICATE_MESSAGE *sec_blob;
Steve French0b3cc8582009-05-04 08:37:12 +0000628 __u32 flags;
629 unsigned char *tmp;
Steve French0b3cc8582009-05-04 08:37:12 +0000630
Jerome Marchandb8da3442016-05-26 11:52:25 +0200631 rc = setup_ntlmv2_rsp(ses, nls_cp);
632 if (rc) {
633 cifs_dbg(VFS, "Error %d during NTLMSSP authentication\n", rc);
634 *buflen = 0;
635 goto setup_ntlmv2_ret;
636 }
637 *pbuffer = kmalloc(size_of_ntlmssp_blob(ses), GFP_KERNEL);
Nicholas Mc Guire126c97f2018-08-23 12:24:02 +0200638 if (!*pbuffer) {
639 rc = -ENOMEM;
640 cifs_dbg(VFS, "Error %d during NTLMSSP allocation\n", rc);
641 *buflen = 0;
642 goto setup_ntlmv2_ret;
643 }
Jerome Marchandb8da3442016-05-26 11:52:25 +0200644 sec_blob = (AUTHENTICATE_MESSAGE *)*pbuffer;
645
Steve French0b3cc8582009-05-04 08:37:12 +0000646 memcpy(sec_blob->Signature, NTLMSSP_SIGNATURE, 8);
647 sec_blob->MessageType = NtLmAuthenticate;
648
649 flags = NTLMSSP_NEGOTIATE_56 |
650 NTLMSSP_REQUEST_TARGET | NTLMSSP_NEGOTIATE_TARGET_INFO |
651 NTLMSSP_NEGOTIATE_128 | NTLMSSP_NEGOTIATE_UNICODE |
Pavel Shilovskycabfb362016-11-07 18:20:50 -0800652 NTLMSSP_NEGOTIATE_NTLM | NTLMSSP_NEGOTIATE_EXTENDED_SEC |
653 NTLMSSP_NEGOTIATE_SEAL;
654 if (ses->server->sign)
Steve French0b3cc8582009-05-04 08:37:12 +0000655 flags |= NTLMSSP_NEGOTIATE_SIGN;
Pavel Shilovskycabfb362016-11-07 18:20:50 -0800656 if (!ses->server->session_estab || ses->ntlmssp->sesskey_per_smbsess)
657 flags |= NTLMSSP_NEGOTIATE_KEY_XCH;
Steve French0b3cc8582009-05-04 08:37:12 +0000658
Jerome Marchandb8da3442016-05-26 11:52:25 +0200659 tmp = *pbuffer + sizeof(AUTHENTICATE_MESSAGE);
Shirish Pargaonkardf8fbc242010-12-11 14:19:22 -0600660 sec_blob->NegotiateFlags = cpu_to_le32(flags);
Steve French0b3cc8582009-05-04 08:37:12 +0000661
662 sec_blob->LmChallengeResponse.BufferOffset =
663 cpu_to_le32(sizeof(AUTHENTICATE_MESSAGE));
664 sec_blob->LmChallengeResponse.Length = 0;
665 sec_blob->LmChallengeResponse.MaximumLength = 0;
666
Jerome Marchandb8da3442016-05-26 11:52:25 +0200667 sec_blob->NtChallengeResponse.BufferOffset =
668 cpu_to_le32(tmp - *pbuffer);
Stefan Metzmachercfda35d2016-05-03 10:52:30 +0200669 if (ses->user_name != NULL) {
Stefan Metzmachercfda35d2016-05-03 10:52:30 +0200670 memcpy(tmp, ses->auth_key.response + CIFS_SESS_KEY_SIZE,
671 ses->auth_key.len - CIFS_SESS_KEY_SIZE);
672 tmp += ses->auth_key.len - CIFS_SESS_KEY_SIZE;
Steve Frenchc8e56f12010-09-08 21:10:58 +0000673
Stefan Metzmachercfda35d2016-05-03 10:52:30 +0200674 sec_blob->NtChallengeResponse.Length =
675 cpu_to_le16(ses->auth_key.len - CIFS_SESS_KEY_SIZE);
676 sec_blob->NtChallengeResponse.MaximumLength =
677 cpu_to_le16(ses->auth_key.len - CIFS_SESS_KEY_SIZE);
678 } else {
679 /*
680 * don't send an NT Response for anonymous access
681 */
682 sec_blob->NtChallengeResponse.Length = 0;
683 sec_blob->NtChallengeResponse.MaximumLength = 0;
684 }
Steve French0b3cc8582009-05-04 08:37:12 +0000685
686 if (ses->domainName == NULL) {
Jerome Marchandb8da3442016-05-26 11:52:25 +0200687 sec_blob->DomainName.BufferOffset = cpu_to_le32(tmp - *pbuffer);
Steve French0b3cc8582009-05-04 08:37:12 +0000688 sec_blob->DomainName.Length = 0;
689 sec_blob->DomainName.MaximumLength = 0;
690 tmp += 2;
691 } else {
692 int len;
Steve Frenchacbbb762012-01-18 22:32:33 -0600693 len = cifs_strtoUTF16((__le16 *)tmp, ses->domainName,
Jerome Marchand202d7722016-05-26 11:52:24 +0200694 CIFS_MAX_DOMAINNAME_LEN, nls_cp);
Steve French0b3cc8582009-05-04 08:37:12 +0000695 len *= 2; /* unicode is 2 bytes each */
Jerome Marchandb8da3442016-05-26 11:52:25 +0200696 sec_blob->DomainName.BufferOffset = cpu_to_le32(tmp - *pbuffer);
Steve French0b3cc8582009-05-04 08:37:12 +0000697 sec_blob->DomainName.Length = cpu_to_le16(len);
698 sec_blob->DomainName.MaximumLength = cpu_to_le16(len);
699 tmp += len;
700 }
701
Steve French8727c8a2011-02-25 01:11:56 -0600702 if (ses->user_name == NULL) {
Jerome Marchandb8da3442016-05-26 11:52:25 +0200703 sec_blob->UserName.BufferOffset = cpu_to_le32(tmp - *pbuffer);
Steve French0b3cc8582009-05-04 08:37:12 +0000704 sec_blob->UserName.Length = 0;
705 sec_blob->UserName.MaximumLength = 0;
706 tmp += 2;
707 } else {
708 int len;
Steve Frenchacbbb762012-01-18 22:32:33 -0600709 len = cifs_strtoUTF16((__le16 *)tmp, ses->user_name,
Scott Lovenberg8c3a2b42013-08-09 08:47:17 -0400710 CIFS_MAX_USERNAME_LEN, nls_cp);
Steve French0b3cc8582009-05-04 08:37:12 +0000711 len *= 2; /* unicode is 2 bytes each */
Jerome Marchandb8da3442016-05-26 11:52:25 +0200712 sec_blob->UserName.BufferOffset = cpu_to_le32(tmp - *pbuffer);
Steve French0b3cc8582009-05-04 08:37:12 +0000713 sec_blob->UserName.Length = cpu_to_le16(len);
714 sec_blob->UserName.MaximumLength = cpu_to_le16(len);
715 tmp += len;
716 }
717
Jerome Marchandb8da3442016-05-26 11:52:25 +0200718 sec_blob->WorkstationName.BufferOffset = cpu_to_le32(tmp - *pbuffer);
Steve French0b3cc8582009-05-04 08:37:12 +0000719 sec_blob->WorkstationName.Length = 0;
720 sec_blob->WorkstationName.MaximumLength = 0;
721 tmp += 2;
722
Shirish Pargaonkardf8fbc242010-12-11 14:19:22 -0600723 if (((ses->ntlmssp->server_flags & NTLMSSP_NEGOTIATE_KEY_XCH) ||
724 (ses->ntlmssp->server_flags & NTLMSSP_NEGOTIATE_EXTENDED_SEC))
725 && !calc_seckey(ses)) {
Shirish Pargaonkard3686d52010-10-28 09:53:07 -0500726 memcpy(tmp, ses->ntlmssp->ciphertext, CIFS_CPHTXT_SIZE);
Jerome Marchandb8da3442016-05-26 11:52:25 +0200727 sec_blob->SessionKey.BufferOffset = cpu_to_le32(tmp - *pbuffer);
Shirish Pargaonkard2b91522010-10-21 14:25:08 -0500728 sec_blob->SessionKey.Length = cpu_to_le16(CIFS_CPHTXT_SIZE);
729 sec_blob->SessionKey.MaximumLength =
730 cpu_to_le16(CIFS_CPHTXT_SIZE);
731 tmp += CIFS_CPHTXT_SIZE;
732 } else {
Jerome Marchandb8da3442016-05-26 11:52:25 +0200733 sec_blob->SessionKey.BufferOffset = cpu_to_le32(tmp - *pbuffer);
Shirish Pargaonkard2b91522010-10-21 14:25:08 -0500734 sec_blob->SessionKey.Length = 0;
735 sec_blob->SessionKey.MaximumLength = 0;
736 }
Shirish Pargaonkar2b149f12010-09-18 22:02:18 -0500737
Jerome Marchandb8da3442016-05-26 11:52:25 +0200738 *buflen = tmp - *pbuffer;
Shirish Pargaonkar2b149f12010-09-18 22:02:18 -0500739setup_ntlmv2_ret:
Shirish Pargaonkar89f150f2010-10-19 11:47:52 -0500740 return rc;
Steve French0b3cc8582009-05-04 08:37:12 +0000741}
Steve French0b3cc8582009-05-04 08:37:12 +0000742
Jeff Layton3f618222013-06-12 19:52:14 -0500743enum securityEnum
Sachin Prabhuef65aae2017-01-18 15:35:57 +0530744cifs_select_sectype(struct TCP_Server_Info *server, enum securityEnum requested)
Jeff Layton3f618222013-06-12 19:52:14 -0500745{
746 switch (server->negflavor) {
747 case CIFS_NEGFLAVOR_EXTENDED:
748 switch (requested) {
749 case Kerberos:
750 case RawNTLMSSP:
751 return requested;
752 case Unspecified:
753 if (server->sec_ntlmssp &&
754 (global_secflags & CIFSSEC_MAY_NTLMSSP))
755 return RawNTLMSSP;
756 if ((server->sec_kerberos || server->sec_mskerberos) &&
757 (global_secflags & CIFSSEC_MAY_KRB5))
758 return Kerberos;
759 /* Fallthrough */
760 default:
761 return Unspecified;
762 }
763 case CIFS_NEGFLAVOR_UNENCAP:
764 switch (requested) {
765 case NTLM:
766 case NTLMv2:
767 return requested;
768 case Unspecified:
769 if (global_secflags & CIFSSEC_MAY_NTLMV2)
770 return NTLMv2;
771 if (global_secflags & CIFSSEC_MAY_NTLM)
772 return NTLM;
Jeff Layton3f618222013-06-12 19:52:14 -0500773 default:
Sachin Prabhudde23562013-09-27 18:35:42 +0100774 break;
Jeff Layton3f618222013-06-12 19:52:14 -0500775 }
Gustavo A. R. Silva07fa6012018-11-27 10:01:51 +1100776 /* Fallthrough - to attempt LANMAN authentication next */
Jeff Layton3f618222013-06-12 19:52:14 -0500777 case CIFS_NEGFLAVOR_LANMAN:
778 switch (requested) {
779 case LANMAN:
780 return requested;
781 case Unspecified:
782 if (global_secflags & CIFSSEC_MAY_LANMAN)
783 return LANMAN;
784 /* Fallthrough */
785 default:
786 return Unspecified;
787 }
788 default:
789 return Unspecified;
790 }
791}
792
Sachin Prabhu80a0e632014-06-16 15:35:25 +0100793struct sess_data {
794 unsigned int xid;
795 struct cifs_ses *ses;
796 struct nls_table *nls_cp;
797 void (*func)(struct sess_data *);
798 int result;
799
800 /* we will send the SMB in three pieces:
801 * a fixed length beginning part, an optional
802 * SPNEGO blob (which can be zero length), and a
803 * last part which will include the strings
804 * and rest of bcc area. This allows us to avoid
805 * a large buffer 17K allocation
806 */
807 int buf0_type;
808 struct kvec iov[3];
809};
810
811static int
812sess_alloc_buffer(struct sess_data *sess_data, int wct)
813{
814 int rc;
815 struct cifs_ses *ses = sess_data->ses;
816 struct smb_hdr *smb_buf;
817
818 rc = small_smb_init_no_tc(SMB_COM_SESSION_SETUP_ANDX, wct, ses,
819 (void **)&smb_buf);
820
821 if (rc)
822 return rc;
823
824 sess_data->iov[0].iov_base = (char *)smb_buf;
825 sess_data->iov[0].iov_len = be32_to_cpu(smb_buf->smb_buf_length) + 4;
826 /*
827 * This variable will be used to clear the buffer
828 * allocated above in case of any error in the calling function.
829 */
830 sess_data->buf0_type = CIFS_SMALL_BUFFER;
831
832 /* 2000 big enough to fit max user, domain, NOS name etc. */
833 sess_data->iov[2].iov_base = kmalloc(2000, GFP_KERNEL);
834 if (!sess_data->iov[2].iov_base) {
835 rc = -ENOMEM;
836 goto out_free_smb_buf;
837 }
838
839 return 0;
840
841out_free_smb_buf:
842 kfree(smb_buf);
843 sess_data->iov[0].iov_base = NULL;
844 sess_data->iov[0].iov_len = 0;
845 sess_data->buf0_type = CIFS_NO_BUFFER;
846 return rc;
847}
848
849static void
850sess_free_buffer(struct sess_data *sess_data)
851{
852
853 free_rsp_buf(sess_data->buf0_type, sess_data->iov[0].iov_base);
854 sess_data->buf0_type = CIFS_NO_BUFFER;
855 kfree(sess_data->iov[2].iov_base);
856}
857
858static int
859sess_establish_session(struct sess_data *sess_data)
860{
861 struct cifs_ses *ses = sess_data->ses;
862
863 mutex_lock(&ses->server->srv_mutex);
864 if (!ses->server->session_estab) {
865 if (ses->server->sign) {
866 ses->server->session_key.response =
867 kmemdup(ses->auth_key.response,
868 ses->auth_key.len, GFP_KERNEL);
869 if (!ses->server->session_key.response) {
870 mutex_unlock(&ses->server->srv_mutex);
871 return -ENOMEM;
872 }
873 ses->server->session_key.len =
874 ses->auth_key.len;
875 }
876 ses->server->sequence_number = 0x2;
877 ses->server->session_estab = true;
878 }
879 mutex_unlock(&ses->server->srv_mutex);
880
881 cifs_dbg(FYI, "CIFS session established successfully\n");
882 spin_lock(&GlobalMid_Lock);
883 ses->status = CifsGood;
884 ses->need_reconnect = false;
885 spin_unlock(&GlobalMid_Lock);
886
887 return 0;
888}
889
890static int
891sess_sendreceive(struct sess_data *sess_data)
892{
893 int rc;
894 struct smb_hdr *smb_buf = (struct smb_hdr *) sess_data->iov[0].iov_base;
895 __u16 count;
Pavel Shilovskyda502f72016-10-25 11:38:47 -0700896 struct kvec rsp_iov = { NULL, 0 };
Sachin Prabhu80a0e632014-06-16 15:35:25 +0100897
898 count = sess_data->iov[1].iov_len + sess_data->iov[2].iov_len;
899 smb_buf->smb_buf_length =
900 cpu_to_be32(be32_to_cpu(smb_buf->smb_buf_length) + count);
901 put_bcc(count, smb_buf);
902
903 rc = SendReceive2(sess_data->xid, sess_data->ses,
904 sess_data->iov, 3 /* num_iovecs */,
905 &sess_data->buf0_type,
Pavel Shilovskyda502f72016-10-25 11:38:47 -0700906 CIFS_LOG_ERROR, &rsp_iov);
907 cifs_small_buf_release(sess_data->iov[0].iov_base);
908 memcpy(&sess_data->iov[0], &rsp_iov, sizeof(struct kvec));
Sachin Prabhu80a0e632014-06-16 15:35:25 +0100909
910 return rc;
911}
912
913/*
914 * LANMAN and plaintext are less secure and off by default.
915 * So we make this explicitly be turned on in kconfig (in the
916 * build) and turned on at runtime (changed from the default)
917 * in proc/fs/cifs or via mount parm. Unfortunately this is
918 * needed for old Win (e.g. Win95), some obscure NAS and OS/2
919 */
920#ifdef CONFIG_CIFS_WEAK_PW_HASH
921static void
922sess_auth_lanman(struct sess_data *sess_data)
923{
924 int rc = 0;
925 struct smb_hdr *smb_buf;
926 SESSION_SETUP_ANDX *pSMB;
927 char *bcc_ptr;
928 struct cifs_ses *ses = sess_data->ses;
929 char lnm_session_key[CIFS_AUTH_RESP_SIZE];
Sachin Prabhu80a0e632014-06-16 15:35:25 +0100930 __u16 bytes_remaining;
931
932 /* lanman 2 style sessionsetup */
933 /* wct = 10 */
934 rc = sess_alloc_buffer(sess_data, 10);
935 if (rc)
936 goto out;
937
938 pSMB = (SESSION_SETUP_ANDX *)sess_data->iov[0].iov_base;
939 bcc_ptr = sess_data->iov[2].iov_base;
zhengbin8559ad82019-09-24 10:13:47 +0800940 (void)cifs_ssetup_hdr(ses, pSMB);
Sachin Prabhu80a0e632014-06-16 15:35:25 +0100941
942 pSMB->req.hdr.Flags2 &= ~SMBFLG2_UNICODE;
943
Stefan Metzmacherfa8f3a32016-05-03 10:52:30 +0200944 if (ses->user_name != NULL) {
945 /* no capabilities flags in old lanman negotiation */
946 pSMB->old_req.PasswordLength = cpu_to_le16(CIFS_AUTH_RESP_SIZE);
Sachin Prabhu80a0e632014-06-16 15:35:25 +0100947
Stefan Metzmacherfa8f3a32016-05-03 10:52:30 +0200948 /* Calculate hash with password and copy into bcc_ptr.
949 * Encryption Key (stored as in cryptkey) gets used if the
950 * security mode bit in Negottiate Protocol response states
951 * to use challenge/response method (i.e. Password bit is 1).
952 */
953 rc = calc_lanman_hash(ses->password, ses->server->cryptkey,
954 ses->server->sec_mode & SECMODE_PW_ENCRYPT ?
955 true : false, lnm_session_key);
Luis de Bethencourta6b6bef2016-06-08 17:02:32 +0100956 if (rc)
957 goto out;
Sachin Prabhu80a0e632014-06-16 15:35:25 +0100958
Stefan Metzmacherfa8f3a32016-05-03 10:52:30 +0200959 memcpy(bcc_ptr, (char *)lnm_session_key, CIFS_AUTH_RESP_SIZE);
960 bcc_ptr += CIFS_AUTH_RESP_SIZE;
961 } else {
962 pSMB->old_req.PasswordLength = 0;
963 }
Sachin Prabhu80a0e632014-06-16 15:35:25 +0100964
965 /*
966 * can not sign if LANMAN negotiated so no need
967 * to calculate signing key? but what if server
968 * changed to do higher than lanman dialect and
969 * we reconnected would we ever calc signing_key?
970 */
971
972 cifs_dbg(FYI, "Negotiating LANMAN setting up strings\n");
973 /* Unicode not allowed for LANMAN dialects */
974 ascii_ssetup_strings(&bcc_ptr, ses, sess_data->nls_cp);
975
976 sess_data->iov[2].iov_len = (long) bcc_ptr -
977 (long) sess_data->iov[2].iov_base;
978
979 rc = sess_sendreceive(sess_data);
980 if (rc)
981 goto out;
982
983 pSMB = (SESSION_SETUP_ANDX *)sess_data->iov[0].iov_base;
984 smb_buf = (struct smb_hdr *)sess_data->iov[0].iov_base;
985
986 /* lanman response has a word count of 3 */
987 if (smb_buf->WordCount != 3) {
988 rc = -EIO;
989 cifs_dbg(VFS, "bad word count %d\n", smb_buf->WordCount);
990 goto out;
991 }
992
993 if (le16_to_cpu(pSMB->resp.Action) & GUEST_LOGIN)
994 cifs_dbg(FYI, "Guest login\n"); /* BB mark SesInfo struct? */
995
996 ses->Suid = smb_buf->Uid; /* UID left in wire format (le) */
997 cifs_dbg(FYI, "UID = %llu\n", ses->Suid);
998
999 bytes_remaining = get_bcc(smb_buf);
1000 bcc_ptr = pByteArea(smb_buf);
1001
1002 /* BB check if Unicode and decode strings */
1003 if (bytes_remaining == 0) {
1004 /* no string area to decode, do nothing */
1005 } else if (smb_buf->Flags2 & SMBFLG2_UNICODE) {
1006 /* unicode string area must be word-aligned */
1007 if (((unsigned long) bcc_ptr - (unsigned long) smb_buf) % 2) {
1008 ++bcc_ptr;
1009 --bytes_remaining;
1010 }
1011 decode_unicode_ssetup(&bcc_ptr, bytes_remaining, ses,
1012 sess_data->nls_cp);
1013 } else {
1014 decode_ascii_ssetup(&bcc_ptr, bytes_remaining, ses,
1015 sess_data->nls_cp);
1016 }
1017
1018 rc = sess_establish_session(sess_data);
1019out:
1020 sess_data->result = rc;
1021 sess_data->func = NULL;
1022 sess_free_buffer(sess_data);
1023}
1024
Sachin Prabhu80a0e632014-06-16 15:35:25 +01001025#endif
1026
Sachin Prabhu583cf7a2014-06-16 15:35:26 +01001027static void
1028sess_auth_ntlm(struct sess_data *sess_data)
1029{
1030 int rc = 0;
1031 struct smb_hdr *smb_buf;
1032 SESSION_SETUP_ANDX *pSMB;
1033 char *bcc_ptr;
1034 struct cifs_ses *ses = sess_data->ses;
1035 __u32 capabilities;
1036 __u16 bytes_remaining;
1037
1038 /* old style NTLM sessionsetup */
1039 /* wct = 13 */
1040 rc = sess_alloc_buffer(sess_data, 13);
1041 if (rc)
1042 goto out;
1043
1044 pSMB = (SESSION_SETUP_ANDX *)sess_data->iov[0].iov_base;
1045 bcc_ptr = sess_data->iov[2].iov_base;
1046 capabilities = cifs_ssetup_hdr(ses, pSMB);
1047
1048 pSMB->req_no_secext.Capabilities = cpu_to_le32(capabilities);
Stefan Metzmacher777f69b2016-05-03 10:52:30 +02001049 if (ses->user_name != NULL) {
1050 pSMB->req_no_secext.CaseInsensitivePasswordLength =
1051 cpu_to_le16(CIFS_AUTH_RESP_SIZE);
1052 pSMB->req_no_secext.CaseSensitivePasswordLength =
1053 cpu_to_le16(CIFS_AUTH_RESP_SIZE);
Sachin Prabhu583cf7a2014-06-16 15:35:26 +01001054
Stefan Metzmacher777f69b2016-05-03 10:52:30 +02001055 /* calculate ntlm response and session key */
1056 rc = setup_ntlm_response(ses, sess_data->nls_cp);
1057 if (rc) {
1058 cifs_dbg(VFS, "Error %d during NTLM authentication\n",
1059 rc);
1060 goto out;
1061 }
1062
1063 /* copy ntlm response */
1064 memcpy(bcc_ptr, ses->auth_key.response + CIFS_SESS_KEY_SIZE,
1065 CIFS_AUTH_RESP_SIZE);
1066 bcc_ptr += CIFS_AUTH_RESP_SIZE;
1067 memcpy(bcc_ptr, ses->auth_key.response + CIFS_SESS_KEY_SIZE,
1068 CIFS_AUTH_RESP_SIZE);
1069 bcc_ptr += CIFS_AUTH_RESP_SIZE;
1070 } else {
1071 pSMB->req_no_secext.CaseInsensitivePasswordLength = 0;
1072 pSMB->req_no_secext.CaseSensitivePasswordLength = 0;
Sachin Prabhu583cf7a2014-06-16 15:35:26 +01001073 }
1074
Sachin Prabhu583cf7a2014-06-16 15:35:26 +01001075 if (ses->capabilities & CAP_UNICODE) {
1076 /* unicode strings must be word aligned */
1077 if (sess_data->iov[0].iov_len % 2) {
1078 *bcc_ptr = 0;
1079 bcc_ptr++;
1080 }
1081 unicode_ssetup_strings(&bcc_ptr, ses, sess_data->nls_cp);
1082 } else {
1083 ascii_ssetup_strings(&bcc_ptr, ses, sess_data->nls_cp);
1084 }
1085
1086
1087 sess_data->iov[2].iov_len = (long) bcc_ptr -
1088 (long) sess_data->iov[2].iov_base;
1089
1090 rc = sess_sendreceive(sess_data);
1091 if (rc)
1092 goto out;
1093
1094 pSMB = (SESSION_SETUP_ANDX *)sess_data->iov[0].iov_base;
1095 smb_buf = (struct smb_hdr *)sess_data->iov[0].iov_base;
1096
1097 if (smb_buf->WordCount != 3) {
1098 rc = -EIO;
1099 cifs_dbg(VFS, "bad word count %d\n", smb_buf->WordCount);
1100 goto out;
1101 }
1102
1103 if (le16_to_cpu(pSMB->resp.Action) & GUEST_LOGIN)
1104 cifs_dbg(FYI, "Guest login\n"); /* BB mark SesInfo struct? */
1105
1106 ses->Suid = smb_buf->Uid; /* UID left in wire format (le) */
1107 cifs_dbg(FYI, "UID = %llu\n", ses->Suid);
1108
1109 bytes_remaining = get_bcc(smb_buf);
1110 bcc_ptr = pByteArea(smb_buf);
1111
1112 /* BB check if Unicode and decode strings */
1113 if (bytes_remaining == 0) {
1114 /* no string area to decode, do nothing */
1115 } else if (smb_buf->Flags2 & SMBFLG2_UNICODE) {
1116 /* unicode string area must be word-aligned */
1117 if (((unsigned long) bcc_ptr - (unsigned long) smb_buf) % 2) {
1118 ++bcc_ptr;
1119 --bytes_remaining;
1120 }
1121 decode_unicode_ssetup(&bcc_ptr, bytes_remaining, ses,
1122 sess_data->nls_cp);
1123 } else {
1124 decode_ascii_ssetup(&bcc_ptr, bytes_remaining, ses,
1125 sess_data->nls_cp);
1126 }
1127
1128 rc = sess_establish_session(sess_data);
1129out:
1130 sess_data->result = rc;
1131 sess_data->func = NULL;
1132 sess_free_buffer(sess_data);
1133 kfree(ses->auth_key.response);
1134 ses->auth_key.response = NULL;
1135}
1136
1137static void
1138sess_auth_ntlmv2(struct sess_data *sess_data)
1139{
1140 int rc = 0;
1141 struct smb_hdr *smb_buf;
1142 SESSION_SETUP_ANDX *pSMB;
1143 char *bcc_ptr;
1144 struct cifs_ses *ses = sess_data->ses;
1145 __u32 capabilities;
1146 __u16 bytes_remaining;
1147
1148 /* old style NTLM sessionsetup */
1149 /* wct = 13 */
1150 rc = sess_alloc_buffer(sess_data, 13);
1151 if (rc)
1152 goto out;
1153
1154 pSMB = (SESSION_SETUP_ANDX *)sess_data->iov[0].iov_base;
1155 bcc_ptr = sess_data->iov[2].iov_base;
1156 capabilities = cifs_ssetup_hdr(ses, pSMB);
1157
1158 pSMB->req_no_secext.Capabilities = cpu_to_le32(capabilities);
1159
1160 /* LM2 password would be here if we supported it */
1161 pSMB->req_no_secext.CaseInsensitivePasswordLength = 0;
1162
Stefan Metzmacher1a967d62016-05-03 10:52:30 +02001163 if (ses->user_name != NULL) {
1164 /* calculate nlmv2 response and session key */
1165 rc = setup_ntlmv2_rsp(ses, sess_data->nls_cp);
1166 if (rc) {
1167 cifs_dbg(VFS, "Error %d during NTLMv2 authentication\n", rc);
1168 goto out;
1169 }
1170
1171 memcpy(bcc_ptr, ses->auth_key.response + CIFS_SESS_KEY_SIZE,
1172 ses->auth_key.len - CIFS_SESS_KEY_SIZE);
1173 bcc_ptr += ses->auth_key.len - CIFS_SESS_KEY_SIZE;
1174
1175 /* set case sensitive password length after tilen may get
1176 * assigned, tilen is 0 otherwise.
1177 */
1178 pSMB->req_no_secext.CaseSensitivePasswordLength =
1179 cpu_to_le16(ses->auth_key.len - CIFS_SESS_KEY_SIZE);
1180 } else {
1181 pSMB->req_no_secext.CaseSensitivePasswordLength = 0;
Sachin Prabhu583cf7a2014-06-16 15:35:26 +01001182 }
1183
Sachin Prabhu583cf7a2014-06-16 15:35:26 +01001184 if (ses->capabilities & CAP_UNICODE) {
1185 if (sess_data->iov[0].iov_len % 2) {
1186 *bcc_ptr = 0;
1187 bcc_ptr++;
1188 }
1189 unicode_ssetup_strings(&bcc_ptr, ses, sess_data->nls_cp);
1190 } else {
1191 ascii_ssetup_strings(&bcc_ptr, ses, sess_data->nls_cp);
1192 }
1193
1194
1195 sess_data->iov[2].iov_len = (long) bcc_ptr -
1196 (long) sess_data->iov[2].iov_base;
1197
1198 rc = sess_sendreceive(sess_data);
1199 if (rc)
1200 goto out;
1201
1202 pSMB = (SESSION_SETUP_ANDX *)sess_data->iov[0].iov_base;
1203 smb_buf = (struct smb_hdr *)sess_data->iov[0].iov_base;
1204
1205 if (smb_buf->WordCount != 3) {
1206 rc = -EIO;
1207 cifs_dbg(VFS, "bad word count %d\n", smb_buf->WordCount);
1208 goto out;
1209 }
1210
1211 if (le16_to_cpu(pSMB->resp.Action) & GUEST_LOGIN)
1212 cifs_dbg(FYI, "Guest login\n"); /* BB mark SesInfo struct? */
1213
1214 ses->Suid = smb_buf->Uid; /* UID left in wire format (le) */
1215 cifs_dbg(FYI, "UID = %llu\n", ses->Suid);
1216
1217 bytes_remaining = get_bcc(smb_buf);
1218 bcc_ptr = pByteArea(smb_buf);
1219
1220 /* BB check if Unicode and decode strings */
1221 if (bytes_remaining == 0) {
1222 /* no string area to decode, do nothing */
1223 } else if (smb_buf->Flags2 & SMBFLG2_UNICODE) {
1224 /* unicode string area must be word-aligned */
1225 if (((unsigned long) bcc_ptr - (unsigned long) smb_buf) % 2) {
1226 ++bcc_ptr;
1227 --bytes_remaining;
1228 }
1229 decode_unicode_ssetup(&bcc_ptr, bytes_remaining, ses,
1230 sess_data->nls_cp);
1231 } else {
1232 decode_ascii_ssetup(&bcc_ptr, bytes_remaining, ses,
1233 sess_data->nls_cp);
1234 }
1235
1236 rc = sess_establish_session(sess_data);
1237out:
1238 sess_data->result = rc;
1239 sess_data->func = NULL;
1240 sess_free_buffer(sess_data);
1241 kfree(ses->auth_key.response);
1242 ses->auth_key.response = NULL;
1243}
1244
Sachin Prabhuee03c642014-06-16 15:35:27 +01001245#ifdef CONFIG_CIFS_UPCALL
1246static void
1247sess_auth_kerberos(struct sess_data *sess_data)
1248{
1249 int rc = 0;
1250 struct smb_hdr *smb_buf;
1251 SESSION_SETUP_ANDX *pSMB;
1252 char *bcc_ptr;
1253 struct cifs_ses *ses = sess_data->ses;
1254 __u32 capabilities;
1255 __u16 bytes_remaining;
1256 struct key *spnego_key = NULL;
1257 struct cifs_spnego_msg *msg;
1258 u16 blob_len;
1259
1260 /* extended security */
1261 /* wct = 12 */
1262 rc = sess_alloc_buffer(sess_data, 12);
1263 if (rc)
1264 goto out;
1265
1266 pSMB = (SESSION_SETUP_ANDX *)sess_data->iov[0].iov_base;
1267 bcc_ptr = sess_data->iov[2].iov_base;
1268 capabilities = cifs_ssetup_hdr(ses, pSMB);
1269
1270 spnego_key = cifs_get_spnego_key(ses);
1271 if (IS_ERR(spnego_key)) {
1272 rc = PTR_ERR(spnego_key);
1273 spnego_key = NULL;
1274 goto out;
1275 }
1276
David Howells146aa8b2015-10-21 14:04:48 +01001277 msg = spnego_key->payload.data[0];
Sachin Prabhuee03c642014-06-16 15:35:27 +01001278 /*
1279 * check version field to make sure that cifs.upcall is
1280 * sending us a response in an expected form
1281 */
1282 if (msg->version != CIFS_SPNEGO_UPCALL_VERSION) {
1283 cifs_dbg(VFS,
1284 "incorrect version of cifs.upcall (expected %d but got %d)",
1285 CIFS_SPNEGO_UPCALL_VERSION, msg->version);
1286 rc = -EKEYREJECTED;
1287 goto out_put_spnego_key;
1288 }
1289
1290 ses->auth_key.response = kmemdup(msg->data, msg->sesskey_len,
1291 GFP_KERNEL);
1292 if (!ses->auth_key.response) {
1293 cifs_dbg(VFS, "Kerberos can't allocate (%u bytes) memory",
1294 msg->sesskey_len);
1295 rc = -ENOMEM;
1296 goto out_put_spnego_key;
1297 }
1298 ses->auth_key.len = msg->sesskey_len;
1299
1300 pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC;
1301 capabilities |= CAP_EXTENDED_SECURITY;
1302 pSMB->req.Capabilities = cpu_to_le32(capabilities);
1303 sess_data->iov[1].iov_base = msg->data + msg->sesskey_len;
1304 sess_data->iov[1].iov_len = msg->secblob_len;
1305 pSMB->req.SecurityBlobLength = cpu_to_le16(sess_data->iov[1].iov_len);
1306
1307 if (ses->capabilities & CAP_UNICODE) {
1308 /* unicode strings must be word aligned */
1309 if ((sess_data->iov[0].iov_len
1310 + sess_data->iov[1].iov_len) % 2) {
1311 *bcc_ptr = 0;
1312 bcc_ptr++;
1313 }
1314 unicode_oslm_strings(&bcc_ptr, sess_data->nls_cp);
1315 unicode_domain_string(&bcc_ptr, ses, sess_data->nls_cp);
1316 } else {
1317 /* BB: is this right? */
1318 ascii_ssetup_strings(&bcc_ptr, ses, sess_data->nls_cp);
1319 }
1320
1321 sess_data->iov[2].iov_len = (long) bcc_ptr -
1322 (long) sess_data->iov[2].iov_base;
1323
1324 rc = sess_sendreceive(sess_data);
1325 if (rc)
1326 goto out_put_spnego_key;
1327
1328 pSMB = (SESSION_SETUP_ANDX *)sess_data->iov[0].iov_base;
1329 smb_buf = (struct smb_hdr *)sess_data->iov[0].iov_base;
1330
1331 if (smb_buf->WordCount != 4) {
1332 rc = -EIO;
1333 cifs_dbg(VFS, "bad word count %d\n", smb_buf->WordCount);
1334 goto out_put_spnego_key;
1335 }
1336
1337 if (le16_to_cpu(pSMB->resp.Action) & GUEST_LOGIN)
1338 cifs_dbg(FYI, "Guest login\n"); /* BB mark SesInfo struct? */
1339
1340 ses->Suid = smb_buf->Uid; /* UID left in wire format (le) */
1341 cifs_dbg(FYI, "UID = %llu\n", ses->Suid);
1342
1343 bytes_remaining = get_bcc(smb_buf);
1344 bcc_ptr = pByteArea(smb_buf);
1345
1346 blob_len = le16_to_cpu(pSMB->resp.SecurityBlobLength);
1347 if (blob_len > bytes_remaining) {
1348 cifs_dbg(VFS, "bad security blob length %d\n",
1349 blob_len);
1350 rc = -EINVAL;
1351 goto out_put_spnego_key;
1352 }
1353 bcc_ptr += blob_len;
1354 bytes_remaining -= blob_len;
1355
1356 /* BB check if Unicode and decode strings */
1357 if (bytes_remaining == 0) {
1358 /* no string area to decode, do nothing */
1359 } else if (smb_buf->Flags2 & SMBFLG2_UNICODE) {
1360 /* unicode string area must be word-aligned */
1361 if (((unsigned long) bcc_ptr - (unsigned long) smb_buf) % 2) {
1362 ++bcc_ptr;
1363 --bytes_remaining;
1364 }
1365 decode_unicode_ssetup(&bcc_ptr, bytes_remaining, ses,
1366 sess_data->nls_cp);
1367 } else {
1368 decode_ascii_ssetup(&bcc_ptr, bytes_remaining, ses,
1369 sess_data->nls_cp);
1370 }
1371
1372 rc = sess_establish_session(sess_data);
1373out_put_spnego_key:
1374 key_invalidate(spnego_key);
1375 key_put(spnego_key);
1376out:
1377 sess_data->result = rc;
1378 sess_data->func = NULL;
1379 sess_free_buffer(sess_data);
1380 kfree(ses->auth_key.response);
1381 ses->auth_key.response = NULL;
1382}
1383
Sachin Prabhuee03c642014-06-16 15:35:27 +01001384#endif /* ! CONFIG_CIFS_UPCALL */
Sachin Prabhu583cf7a2014-06-16 15:35:26 +01001385
Sachin Prabhucc87c472014-06-16 15:35:28 +01001386/*
1387 * The required kvec buffers have to be allocated before calling this
1388 * function.
1389 */
1390static int
1391_sess_auth_rawntlmssp_assemble_req(struct sess_data *sess_data)
Steve French39798772006-05-31 22:40:51 +00001392{
Steve French39798772006-05-31 22:40:51 +00001393 SESSION_SETUP_ANDX *pSMB;
Sachin Prabhucc87c472014-06-16 15:35:28 +01001394 struct cifs_ses *ses = sess_data->ses;
Steve French39798772006-05-31 22:40:51 +00001395 __u32 capabilities;
Sachin Prabhucc87c472014-06-16 15:35:28 +01001396 char *bcc_ptr;
Steve French254e55e2006-06-04 05:53:15 +00001397
Sachin Prabhucc87c472014-06-16 15:35:28 +01001398 pSMB = (SESSION_SETUP_ANDX *)sess_data->iov[0].iov_base;
Sachin Prabhucc87c472014-06-16 15:35:28 +01001399
1400 capabilities = cifs_ssetup_hdr(ses, pSMB);
1401 if ((pSMB->req.hdr.Flags2 & SMBFLG2_UNICODE) == 0) {
1402 cifs_dbg(VFS, "NTLMSSP requires Unicode support\n");
1403 return -ENOSYS;
Jeff Layton3534b852013-05-24 07:41:01 -04001404 }
Steve French39798772006-05-31 22:40:51 +00001405
Sachin Prabhucc87c472014-06-16 15:35:28 +01001406 pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC;
1407 capabilities |= CAP_EXTENDED_SECURITY;
1408 pSMB->req.Capabilities |= cpu_to_le32(capabilities);
1409
1410 bcc_ptr = sess_data->iov[2].iov_base;
1411 /* unicode strings must be word aligned */
1412 if ((sess_data->iov[0].iov_len + sess_data->iov[1].iov_len) % 2) {
1413 *bcc_ptr = 0;
1414 bcc_ptr++;
1415 }
1416 unicode_oslm_strings(&bcc_ptr, sess_data->nls_cp);
1417
1418 sess_data->iov[2].iov_len = (long) bcc_ptr -
1419 (long) sess_data->iov[2].iov_base;
1420
1421 return 0;
1422}
1423
1424static void
1425sess_auth_rawntlmssp_authenticate(struct sess_data *sess_data);
1426
1427static void
1428sess_auth_rawntlmssp_negotiate(struct sess_data *sess_data)
1429{
1430 int rc;
1431 struct smb_hdr *smb_buf;
1432 SESSION_SETUP_ANDX *pSMB;
1433 struct cifs_ses *ses = sess_data->ses;
1434 __u16 bytes_remaining;
1435 char *bcc_ptr;
1436 u16 blob_len;
1437
1438 cifs_dbg(FYI, "rawntlmssp session setup negotiate phase\n");
1439
1440 /*
1441 * if memory allocation is successful, caller of this function
1442 * frees it.
1443 */
1444 ses->ntlmssp = kmalloc(sizeof(struct ntlmssp_auth), GFP_KERNEL);
1445 if (!ses->ntlmssp) {
1446 rc = -ENOMEM;
1447 goto out;
1448 }
1449 ses->ntlmssp->sesskey_per_smbsess = false;
1450
1451 /* wct = 12 */
1452 rc = sess_alloc_buffer(sess_data, 12);
1453 if (rc)
1454 goto out;
1455
1456 pSMB = (SESSION_SETUP_ANDX *)sess_data->iov[0].iov_base;
1457
1458 /* Build security blob before we assemble the request */
1459 build_ntlmssp_negotiate_blob(pSMB->req.SecurityBlob, ses);
1460 sess_data->iov[1].iov_len = sizeof(NEGOTIATE_MESSAGE);
1461 sess_data->iov[1].iov_base = pSMB->req.SecurityBlob;
1462 pSMB->req.SecurityBlobLength = cpu_to_le16(sizeof(NEGOTIATE_MESSAGE));
1463
1464 rc = _sess_auth_rawntlmssp_assemble_req(sess_data);
1465 if (rc)
1466 goto out;
1467
1468 rc = sess_sendreceive(sess_data);
1469
1470 pSMB = (SESSION_SETUP_ANDX *)sess_data->iov[0].iov_base;
1471 smb_buf = (struct smb_hdr *)sess_data->iov[0].iov_base;
1472
1473 /* If true, rc here is expected and not an error */
1474 if (sess_data->buf0_type != CIFS_NO_BUFFER &&
1475 smb_buf->Status.CifsError ==
1476 cpu_to_le32(NT_STATUS_MORE_PROCESSING_REQUIRED))
1477 rc = 0;
1478
1479 if (rc)
1480 goto out;
1481
1482 cifs_dbg(FYI, "rawntlmssp session setup challenge phase\n");
1483
1484 if (smb_buf->WordCount != 4) {
1485 rc = -EIO;
1486 cifs_dbg(VFS, "bad word count %d\n", smb_buf->WordCount);
1487 goto out;
1488 }
1489
1490 ses->Suid = smb_buf->Uid; /* UID left in wire format (le) */
1491 cifs_dbg(FYI, "UID = %llu\n", ses->Suid);
1492
1493 bytes_remaining = get_bcc(smb_buf);
1494 bcc_ptr = pByteArea(smb_buf);
1495
1496 blob_len = le16_to_cpu(pSMB->resp.SecurityBlobLength);
1497 if (blob_len > bytes_remaining) {
1498 cifs_dbg(VFS, "bad security blob length %d\n",
1499 blob_len);
1500 rc = -EINVAL;
1501 goto out;
1502 }
1503
1504 rc = decode_ntlmssp_challenge(bcc_ptr, blob_len, ses);
1505out:
1506 sess_free_buffer(sess_data);
1507
1508 if (!rc) {
1509 sess_data->func = sess_auth_rawntlmssp_authenticate;
1510 return;
1511 }
1512
1513 /* Else error. Cleanup */
1514 kfree(ses->auth_key.response);
1515 ses->auth_key.response = NULL;
1516 kfree(ses->ntlmssp);
1517 ses->ntlmssp = NULL;
1518
1519 sess_data->func = NULL;
1520 sess_data->result = rc;
1521}
1522
1523static void
1524sess_auth_rawntlmssp_authenticate(struct sess_data *sess_data)
1525{
1526 int rc;
1527 struct smb_hdr *smb_buf;
1528 SESSION_SETUP_ANDX *pSMB;
1529 struct cifs_ses *ses = sess_data->ses;
1530 __u16 bytes_remaining;
1531 char *bcc_ptr;
Jerome Marchandb8da3442016-05-26 11:52:25 +02001532 unsigned char *ntlmsspblob = NULL;
Sachin Prabhucc87c472014-06-16 15:35:28 +01001533 u16 blob_len;
1534
1535 cifs_dbg(FYI, "rawntlmssp session setup authenticate phase\n");
1536
1537 /* wct = 12 */
1538 rc = sess_alloc_buffer(sess_data, 12);
1539 if (rc)
1540 goto out;
1541
1542 /* Build security blob before we assemble the request */
1543 pSMB = (SESSION_SETUP_ANDX *)sess_data->iov[0].iov_base;
1544 smb_buf = (struct smb_hdr *)pSMB;
Jerome Marchandb8da3442016-05-26 11:52:25 +02001545 rc = build_ntlmssp_auth_blob(&ntlmsspblob,
Sachin Prabhucc87c472014-06-16 15:35:28 +01001546 &blob_len, ses, sess_data->nls_cp);
1547 if (rc)
1548 goto out_free_ntlmsspblob;
1549 sess_data->iov[1].iov_len = blob_len;
1550 sess_data->iov[1].iov_base = ntlmsspblob;
1551 pSMB->req.SecurityBlobLength = cpu_to_le16(blob_len);
1552 /*
1553 * Make sure that we tell the server that we are using
1554 * the uid that it just gave us back on the response
1555 * (challenge)
1556 */
1557 smb_buf->Uid = ses->Suid;
1558
1559 rc = _sess_auth_rawntlmssp_assemble_req(sess_data);
1560 if (rc)
1561 goto out_free_ntlmsspblob;
1562
1563 rc = sess_sendreceive(sess_data);
1564 if (rc)
1565 goto out_free_ntlmsspblob;
1566
1567 pSMB = (SESSION_SETUP_ANDX *)sess_data->iov[0].iov_base;
1568 smb_buf = (struct smb_hdr *)sess_data->iov[0].iov_base;
1569 if (smb_buf->WordCount != 4) {
1570 rc = -EIO;
1571 cifs_dbg(VFS, "bad word count %d\n", smb_buf->WordCount);
1572 goto out_free_ntlmsspblob;
1573 }
1574
1575 if (le16_to_cpu(pSMB->resp.Action) & GUEST_LOGIN)
1576 cifs_dbg(FYI, "Guest login\n"); /* BB mark SesInfo struct? */
1577
Sachin Prabhuee9bbf42014-12-03 12:26:36 +00001578 if (ses->Suid != smb_buf->Uid) {
1579 ses->Suid = smb_buf->Uid;
1580 cifs_dbg(FYI, "UID changed! new UID = %llu\n", ses->Suid);
1581 }
1582
Sachin Prabhucc87c472014-06-16 15:35:28 +01001583 bytes_remaining = get_bcc(smb_buf);
1584 bcc_ptr = pByteArea(smb_buf);
1585 blob_len = le16_to_cpu(pSMB->resp.SecurityBlobLength);
1586 if (blob_len > bytes_remaining) {
1587 cifs_dbg(VFS, "bad security blob length %d\n",
1588 blob_len);
1589 rc = -EINVAL;
1590 goto out_free_ntlmsspblob;
1591 }
1592 bcc_ptr += blob_len;
1593 bytes_remaining -= blob_len;
1594
1595
1596 /* BB check if Unicode and decode strings */
1597 if (bytes_remaining == 0) {
1598 /* no string area to decode, do nothing */
1599 } else if (smb_buf->Flags2 & SMBFLG2_UNICODE) {
1600 /* unicode string area must be word-aligned */
1601 if (((unsigned long) bcc_ptr - (unsigned long) smb_buf) % 2) {
1602 ++bcc_ptr;
1603 --bytes_remaining;
1604 }
1605 decode_unicode_ssetup(&bcc_ptr, bytes_remaining, ses,
1606 sess_data->nls_cp);
1607 } else {
1608 decode_ascii_ssetup(&bcc_ptr, bytes_remaining, ses,
1609 sess_data->nls_cp);
1610 }
1611
1612out_free_ntlmsspblob:
1613 kfree(ntlmsspblob);
1614out:
1615 sess_free_buffer(sess_data);
1616
1617 if (!rc)
1618 rc = sess_establish_session(sess_data);
1619
1620 /* Cleanup */
1621 kfree(ses->auth_key.response);
1622 ses->auth_key.response = NULL;
1623 kfree(ses->ntlmssp);
1624 ses->ntlmssp = NULL;
1625
1626 sess_data->func = NULL;
1627 sess_data->result = rc;
1628}
1629
Steve French27924072014-07-11 07:47:01 -05001630static int select_sec(struct cifs_ses *ses, struct sess_data *sess_data)
Sachin Prabhucc87c472014-06-16 15:35:28 +01001631{
1632 int type;
Sachin Prabhu80a0e632014-06-16 15:35:25 +01001633
Sachin Prabhuef65aae2017-01-18 15:35:57 +05301634 type = cifs_select_sectype(ses->server, ses->sectype);
Joe Perchesf96637b2013-05-04 22:12:25 -05001635 cifs_dbg(FYI, "sess setup type %d\n", type);
Jeff Layton3f618222013-06-12 19:52:14 -05001636 if (type == Unspecified) {
Shirish Pargaonkard4e63bd2013-08-29 08:35:09 -05001637 cifs_dbg(VFS,
1638 "Unable to select appropriate authentication method!");
Jeff Layton3f618222013-06-12 19:52:14 -05001639 return -EINVAL;
1640 }
1641
Sachin Prabhu80a0e632014-06-16 15:35:25 +01001642 switch (type) {
1643 case LANMAN:
Sachin Prabhucc87c472014-06-16 15:35:28 +01001644 /* LANMAN and plaintext are less secure and off by default.
1645 * So we make this explicitly be turned on in kconfig (in the
1646 * build) and turned on at runtime (changed from the default)
1647 * in proc/fs/cifs or via mount parm. Unfortunately this is
1648 * needed for old Win (e.g. Win95), some obscure NAS and OS/2 */
1649#ifdef CONFIG_CIFS_WEAK_PW_HASH
1650 sess_data->func = sess_auth_lanman;
1651 break;
1652#else
1653 return -EOPNOTSUPP;
1654#endif
Sachin Prabhu583cf7a2014-06-16 15:35:26 +01001655 case NTLM:
Sachin Prabhucc87c472014-06-16 15:35:28 +01001656 sess_data->func = sess_auth_ntlm;
1657 break;
Sachin Prabhu583cf7a2014-06-16 15:35:26 +01001658 case NTLMv2:
Sachin Prabhucc87c472014-06-16 15:35:28 +01001659 sess_data->func = sess_auth_ntlmv2;
1660 break;
Sachin Prabhuee03c642014-06-16 15:35:27 +01001661 case Kerberos:
Sachin Prabhucc87c472014-06-16 15:35:28 +01001662#ifdef CONFIG_CIFS_UPCALL
1663 sess_data->func = sess_auth_kerberos;
1664 break;
1665#else
1666 cifs_dbg(VFS, "Kerberos negotiated but upcall support disabled!\n");
1667 return -ENOSYS;
1668 break;
1669#endif /* CONFIG_CIFS_UPCALL */
1670 case RawNTLMSSP:
1671 sess_data->func = sess_auth_rawntlmssp_negotiate;
1672 break;
Sachin Prabhu80a0e632014-06-16 15:35:25 +01001673 default:
Joe Perchesf96637b2013-05-04 22:12:25 -05001674 cifs_dbg(VFS, "secType %d not supported!\n", type);
Sachin Prabhucc87c472014-06-16 15:35:28 +01001675 return -ENOSYS;
Steve French39798772006-05-31 22:40:51 +00001676 }
1677
Sachin Prabhucc87c472014-06-16 15:35:28 +01001678 return 0;
1679}
Steve French24424212007-11-16 23:37:35 +00001680
Sachin Prabhucc87c472014-06-16 15:35:28 +01001681int CIFS_SessSetup(const unsigned int xid, struct cifs_ses *ses,
1682 const struct nls_table *nls_cp)
1683{
1684 int rc = 0;
1685 struct sess_data *sess_data;
Steve French39798772006-05-31 22:40:51 +00001686
Sachin Prabhucc87c472014-06-16 15:35:28 +01001687 if (ses == NULL) {
1688 WARN(1, "%s: ses == NULL!", __func__);
1689 return -EINVAL;
Steve French0b3cc8582009-05-04 08:37:12 +00001690 }
Sachin Prabhucc87c472014-06-16 15:35:28 +01001691
1692 sess_data = kzalloc(sizeof(struct sess_data), GFP_KERNEL);
1693 if (!sess_data)
1694 return -ENOMEM;
1695
1696 rc = select_sec(ses, sess_data);
Steve French0b3cc8582009-05-04 08:37:12 +00001697 if (rc)
Sachin Prabhucc87c472014-06-16 15:35:28 +01001698 goto out;
Steve French0b3cc8582009-05-04 08:37:12 +00001699
Sachin Prabhucc87c472014-06-16 15:35:28 +01001700 sess_data->xid = xid;
1701 sess_data->ses = ses;
1702 sess_data->buf0_type = CIFS_NO_BUFFER;
1703 sess_data->nls_cp = (struct nls_table *) nls_cp;
Steve French39798772006-05-31 22:40:51 +00001704
Sachin Prabhucc87c472014-06-16 15:35:28 +01001705 while (sess_data->func)
1706 sess_data->func(sess_data);
Steve French39798772006-05-31 22:40:51 +00001707
Sachin Prabhucc87c472014-06-16 15:35:28 +01001708 /* Store result before we free sess_data */
1709 rc = sess_data->result;
Sachin Prabhu80a0e632014-06-16 15:35:25 +01001710
1711out:
Sachin Prabhu80a0e632014-06-16 15:35:25 +01001712 kfree(sess_data);
1713 return rc;
Steve French39798772006-05-31 22:40:51 +00001714}