blob: 5723d50340e5e8df4bfff941fa6d44716c1c3a2c [file] [log] [blame]
Steve French929be902021-06-18 00:31:49 -05001// SPDX-License-Identifier: LGPL-2.1
Steve French39798772006-05-31 22:40:51 +00002/*
Steve French39798772006-05-31 22:40:51 +00003 *
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 *
Steve French39798772006-05-31 22:40:51 +00009 */
10
11#include "cifspdu.h"
12#include "cifsglob.h"
13#include "cifsproto.h"
14#include "cifs_unicode.h"
15#include "cifs_debug.h"
16#include "ntlmssp.h"
17#include "nterr.h"
Steve French9c535882006-06-01 05:09:10 +000018#include <linux/utsname.h>
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090019#include <linux/slab.h>
Steve French52d00532022-01-19 22:00:29 -060020#include <linux/version.h>
21#include "cifsfs.h"
Steve French24424212007-11-16 23:37:35 +000022#include "cifs_spnego.h"
Aurelien Apteld70e9fa2019-09-20 06:31:10 +020023#include "smb2proto.h"
Ronnie Sahlberg3fa1c6d2020-12-09 23:07:12 -060024#include "fs_context.h"
Aurelien Apteld70e9fa2019-09-20 06:31:10 +020025
Ronnie Sahlberg387ec582020-12-14 16:40:20 +100026static int
27cifs_ses_add_channel(struct cifs_sb_info *cifs_sb, struct cifs_ses *ses,
28 struct cifs_server_iface *iface);
29
Aurelien Apteld70e9fa2019-09-20 06:31:10 +020030bool
31is_server_using_iface(struct TCP_Server_Info *server,
32 struct cifs_server_iface *iface)
33{
34 struct sockaddr_in *i4 = (struct sockaddr_in *)&iface->sockaddr;
35 struct sockaddr_in6 *i6 = (struct sockaddr_in6 *)&iface->sockaddr;
36 struct sockaddr_in *s4 = (struct sockaddr_in *)&server->dstaddr;
37 struct sockaddr_in6 *s6 = (struct sockaddr_in6 *)&server->dstaddr;
38
39 if (server->dstaddr.ss_family != iface->sockaddr.ss_family)
40 return false;
41 if (server->dstaddr.ss_family == AF_INET) {
42 if (s4->sin_addr.s_addr != i4->sin_addr.s_addr)
43 return false;
44 } else if (server->dstaddr.ss_family == AF_INET6) {
45 if (memcmp(&s6->sin6_addr, &i6->sin6_addr,
46 sizeof(i6->sin6_addr)) != 0)
47 return false;
48 } else {
49 /* unknown family.. */
50 return false;
51 }
52 return true;
53}
54
55bool is_ses_using_iface(struct cifs_ses *ses, struct cifs_server_iface *iface)
56{
57 int i;
58
Shyam Prasad N724244c2021-07-19 10:54:46 +000059 spin_lock(&ses->chan_lock);
Aurelien Apteld70e9fa2019-09-20 06:31:10 +020060 for (i = 0; i < ses->chan_count; i++) {
Shyam Prasad N724244c2021-07-19 10:54:46 +000061 if (is_server_using_iface(ses->chans[i].server, iface)) {
62 spin_unlock(&ses->chan_lock);
Aurelien Apteld70e9fa2019-09-20 06:31:10 +020063 return true;
Shyam Prasad N724244c2021-07-19 10:54:46 +000064 }
Aurelien Apteld70e9fa2019-09-20 06:31:10 +020065 }
Shyam Prasad N724244c2021-07-19 10:54:46 +000066 spin_unlock(&ses->chan_lock);
Aurelien Apteld70e9fa2019-09-20 06:31:10 +020067 return false;
68}
69
Shyam Prasad N88b024f2021-11-19 14:16:57 +000070/* channel helper functions. assumed that chan_lock is held by caller. */
71
Shyam Prasad Nd1a931c2021-07-19 12:46:53 +000072unsigned int
73cifs_ses_get_chan_index(struct cifs_ses *ses,
74 struct TCP_Server_Info *server)
75{
76 unsigned int i;
77
78 for (i = 0; i < ses->chan_count; i++) {
79 if (ses->chans[i].server == server)
80 return i;
81 }
82
83 /* If we didn't find the channel, it is likely a bug */
84 WARN_ON(1);
85 return 0;
86}
87
88void
89cifs_chan_set_need_reconnect(struct cifs_ses *ses,
90 struct TCP_Server_Info *server)
91{
92 unsigned int chan_index = cifs_ses_get_chan_index(ses, server);
93
94 set_bit(chan_index, &ses->chans_need_reconnect);
95 cifs_dbg(FYI, "Set reconnect bitmask for chan %u; now 0x%lx\n",
96 chan_index, ses->chans_need_reconnect);
97}
98
99void
100cifs_chan_clear_need_reconnect(struct cifs_ses *ses,
101 struct TCP_Server_Info *server)
102{
103 unsigned int chan_index = cifs_ses_get_chan_index(ses, server);
104
105 clear_bit(chan_index, &ses->chans_need_reconnect);
106 cifs_dbg(FYI, "Cleared reconnect bitmask for chan %u; now 0x%lx\n",
107 chan_index, ses->chans_need_reconnect);
108}
109
110bool
111cifs_chan_needs_reconnect(struct cifs_ses *ses,
112 struct TCP_Server_Info *server)
113{
114 unsigned int chan_index = cifs_ses_get_chan_index(ses, server);
115
116 return CIFS_CHAN_NEEDS_RECONNECT(ses, chan_index);
117}
118
Aurelien Apteld70e9fa2019-09-20 06:31:10 +0200119/* returns number of channels added */
Ronnie Sahlberg387ec582020-12-14 16:40:20 +1000120int cifs_try_adding_channels(struct cifs_sb_info *cifs_sb, struct cifs_ses *ses)
Aurelien Apteld70e9fa2019-09-20 06:31:10 +0200121{
Shyam Prasad N724244c2021-07-19 10:54:46 +0000122 int old_chan_count, new_chan_count;
123 int left;
Aurelien Apteld70e9fa2019-09-20 06:31:10 +0200124 int i = 0;
125 int rc = 0;
Aurelien Aptel65a37a32019-11-20 17:15:59 +0100126 int tries = 0;
Aurelien Aptel9a7d5a92019-12-04 16:14:54 +0100127 struct cifs_server_iface *ifaces = NULL;
128 size_t iface_count;
Aurelien Apteld70e9fa2019-09-20 06:31:10 +0200129
Shyam Prasad N724244c2021-07-19 10:54:46 +0000130 if (ses->server->dialect < SMB30_PROT_ID) {
131 cifs_dbg(VFS, "multichannel is not supported on this protocol version, use 3.0 or above\n");
132 return 0;
133 }
134
135 spin_lock(&ses->chan_lock);
136
137 new_chan_count = old_chan_count = ses->chan_count;
138 left = ses->chan_max - ses->chan_count;
139
Aurelien Apteld70e9fa2019-09-20 06:31:10 +0200140 if (left <= 0) {
Shyam Prasad N88b024f2021-11-19 14:16:57 +0000141 spin_unlock(&ses->chan_lock);
Aurelien Apteld70e9fa2019-09-20 06:31:10 +0200142 cifs_dbg(FYI,
143 "ses already at max_channels (%zu), nothing to open\n",
144 ses->chan_max);
Aurelien Apteld70e9fa2019-09-20 06:31:10 +0200145 return 0;
146 }
147
Steve French9c2dc112021-05-07 20:00:41 -0500148 if (!(ses->server->capabilities & SMB2_GLOBAL_CAP_MULTI_CHANNEL)) {
Steve French9c2dc112021-05-07 20:00:41 -0500149 ses->chan_max = 1;
Shyam Prasad N724244c2021-07-19 10:54:46 +0000150 spin_unlock(&ses->chan_lock);
Steve French02264872021-11-15 21:00:08 -0600151 cifs_dbg(VFS, "server %s does not support multichannel\n", ses->server->hostname);
Steve French9c2dc112021-05-07 20:00:41 -0500152 return 0;
153 }
Shyam Prasad N724244c2021-07-19 10:54:46 +0000154 spin_unlock(&ses->chan_lock);
Steve French9c2dc112021-05-07 20:00:41 -0500155
Aurelien Aptel65a37a32019-11-20 17:15:59 +0100156 /*
Aurelien Aptel9a7d5a92019-12-04 16:14:54 +0100157 * Make a copy of the iface list at the time and use that
158 * instead so as to not hold the iface spinlock for opening
159 * channels
160 */
161 spin_lock(&ses->iface_lock);
162 iface_count = ses->iface_count;
163 if (iface_count <= 0) {
164 spin_unlock(&ses->iface_lock);
Aurelien Aptel343a1b72020-02-06 10:19:11 +0100165 cifs_dbg(VFS, "no iface list available to open channels\n");
Aurelien Aptel9a7d5a92019-12-04 16:14:54 +0100166 return 0;
167 }
168 ifaces = kmemdup(ses->iface_list, iface_count*sizeof(*ifaces),
169 GFP_ATOMIC);
170 if (!ifaces) {
171 spin_unlock(&ses->iface_lock);
172 return 0;
173 }
174 spin_unlock(&ses->iface_lock);
175
176 /*
Aurelien Aptel65a37a32019-11-20 17:15:59 +0100177 * Keep connecting to same, fastest, iface for all channels as
178 * long as its RSS. Try next fastest one if not RSS or channel
179 * creation fails.
180 */
181 while (left > 0) {
Aurelien Apteld70e9fa2019-09-20 06:31:10 +0200182 struct cifs_server_iface *iface;
183
Aurelien Aptel65a37a32019-11-20 17:15:59 +0100184 tries++;
185 if (tries > 3*ses->chan_max) {
Steve Frenchbbbf9ea2020-05-30 17:29:50 -0500186 cifs_dbg(FYI, "too many channel open attempts (%d channels left to open)\n",
Aurelien Aptel65a37a32019-11-20 17:15:59 +0100187 left);
188 break;
189 }
Aurelien Apteld70e9fa2019-09-20 06:31:10 +0200190
Aurelien Aptel9a7d5a92019-12-04 16:14:54 +0100191 iface = &ifaces[i];
Aurelien Aptel65a37a32019-11-20 17:15:59 +0100192 if (is_ses_using_iface(ses, iface) && !iface->rss_capable) {
Aurelien Aptel9a7d5a92019-12-04 16:14:54 +0100193 i = (i+1) % iface_count;
Aurelien Apteld70e9fa2019-09-20 06:31:10 +0200194 continue;
195 }
196
Ronnie Sahlberg387ec582020-12-14 16:40:20 +1000197 rc = cifs_ses_add_channel(cifs_sb, ses, iface);
Aurelien Aptel65a37a32019-11-20 17:15:59 +0100198 if (rc) {
199 cifs_dbg(FYI, "failed to open extra channel on iface#%d rc=%d\n",
200 i, rc);
Aurelien Aptel9a7d5a92019-12-04 16:14:54 +0100201 i = (i+1) % iface_count;
Aurelien Aptel65a37a32019-11-20 17:15:59 +0100202 continue;
203 }
204
205 cifs_dbg(FYI, "successfully opened new channel on iface#%d\n",
206 i);
Aurelien Apteld70e9fa2019-09-20 06:31:10 +0200207 left--;
Shyam Prasad N724244c2021-07-19 10:54:46 +0000208 new_chan_count++;
Aurelien Apteld70e9fa2019-09-20 06:31:10 +0200209 }
210
Aurelien Aptel9a7d5a92019-12-04 16:14:54 +0100211 kfree(ifaces);
Shyam Prasad N724244c2021-07-19 10:54:46 +0000212 return new_chan_count - old_chan_count;
Aurelien Apteld70e9fa2019-09-20 06:31:10 +0200213}
214
Aurelien Aptel2f589672020-04-24 16:55:31 +0200215/*
216 * If server is a channel of ses, return the corresponding enclosing
217 * cifs_chan otherwise return NULL.
218 */
219struct cifs_chan *
220cifs_ses_find_chan(struct cifs_ses *ses, struct TCP_Server_Info *server)
221{
222 int i;
223
Shyam Prasad N724244c2021-07-19 10:54:46 +0000224 spin_lock(&ses->chan_lock);
Aurelien Aptel2f589672020-04-24 16:55:31 +0200225 for (i = 0; i < ses->chan_count; i++) {
Shyam Prasad N724244c2021-07-19 10:54:46 +0000226 if (ses->chans[i].server == server) {
227 spin_unlock(&ses->chan_lock);
Aurelien Aptel2f589672020-04-24 16:55:31 +0200228 return &ses->chans[i];
Shyam Prasad N724244c2021-07-19 10:54:46 +0000229 }
Aurelien Aptel2f589672020-04-24 16:55:31 +0200230 }
Shyam Prasad N724244c2021-07-19 10:54:46 +0000231 spin_unlock(&ses->chan_lock);
Aurelien Aptel2f589672020-04-24 16:55:31 +0200232 return NULL;
233}
234
Ronnie Sahlberg387ec582020-12-14 16:40:20 +1000235static int
236cifs_ses_add_channel(struct cifs_sb_info *cifs_sb, struct cifs_ses *ses,
237 struct cifs_server_iface *iface)
Aurelien Apteld70e9fa2019-09-20 06:31:10 +0200238{
Shyam Prasad N724244c2021-07-19 10:54:46 +0000239 struct TCP_Server_Info *chan_server;
Aurelien Apteld70e9fa2019-09-20 06:31:10 +0200240 struct cifs_chan *chan;
Ronnie Sahlberg3fa1c6d2020-12-09 23:07:12 -0600241 struct smb3_fs_context ctx = {NULL};
Aurelien Apteld70e9fa2019-09-20 06:31:10 +0200242 static const char unc_fmt[] = "\\%s\\foo";
243 char unc[sizeof(unc_fmt)+SERVER_NAME_LEN_WITH_NULL] = {0};
244 struct sockaddr_in *ipv4 = (struct sockaddr_in *)&iface->sockaddr;
245 struct sockaddr_in6 *ipv6 = (struct sockaddr_in6 *)&iface->sockaddr;
246 int rc;
247 unsigned int xid = get_xid();
248
Aurelien Apteld70e9fa2019-09-20 06:31:10 +0200249 if (iface->sockaddr.ss_family == AF_INET)
Joe Perchesa0a30362020-04-14 22:42:53 -0700250 cifs_dbg(FYI, "adding channel to ses %p (speed:%zu bps rdma:%s ip:%pI4)\n",
251 ses, iface->speed, iface->rdma_capable ? "yes" : "no",
252 &ipv4->sin_addr);
Aurelien Apteld70e9fa2019-09-20 06:31:10 +0200253 else
Aurelien Aptel5e538952021-05-28 16:32:48 +0200254 cifs_dbg(FYI, "adding channel to ses %p (speed:%zu bps rdma:%s ip:%pI6)\n",
Joe Perchesa0a30362020-04-14 22:42:53 -0700255 ses, iface->speed, iface->rdma_capable ? "yes" : "no",
256 &ipv6->sin6_addr);
Aurelien Apteld70e9fa2019-09-20 06:31:10 +0200257
258 /*
Ronnie Sahlberg3fa1c6d2020-12-09 23:07:12 -0600259 * Setup a ctx with mostly the same info as the existing
Aurelien Apteld70e9fa2019-09-20 06:31:10 +0200260 * session and overwrite it with the requested iface data.
261 *
262 * We need to setup at least the fields used for negprot and
263 * sesssetup.
264 *
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -0600265 * We only need the ctx here, so we can reuse memory from
Aurelien Apteld70e9fa2019-09-20 06:31:10 +0200266 * the session and server without caring about memory
267 * management.
268 */
269
270 /* Always make new connection for now (TODO?) */
Ronnie Sahlberg3fa1c6d2020-12-09 23:07:12 -0600271 ctx.nosharesock = true;
Aurelien Apteld70e9fa2019-09-20 06:31:10 +0200272
273 /* Auth */
Ronnie Sahlberg3fa1c6d2020-12-09 23:07:12 -0600274 ctx.domainauto = ses->domainAuto;
275 ctx.domainname = ses->domainName;
Shyam Prasad N5112d802021-11-19 13:04:11 +0000276 ctx.server_hostname = ses->server->hostname;
Ronnie Sahlberg3fa1c6d2020-12-09 23:07:12 -0600277 ctx.username = ses->user_name;
278 ctx.password = ses->password;
279 ctx.sectype = ses->sectype;
280 ctx.sign = ses->sign;
Aurelien Apteld70e9fa2019-09-20 06:31:10 +0200281
282 /* UNC and paths */
283 /* XXX: Use ses->server->hostname? */
Steve Frenchb438fcf2021-02-20 19:24:11 -0600284 sprintf(unc, unc_fmt, ses->ip_addr);
Ronnie Sahlberg3fa1c6d2020-12-09 23:07:12 -0600285 ctx.UNC = unc;
286 ctx.prepath = "";
Aurelien Apteld70e9fa2019-09-20 06:31:10 +0200287
Steve Frenchbbbf9ea2020-05-30 17:29:50 -0500288 /* Reuse same version as master connection */
Ronnie Sahlberg3fa1c6d2020-12-09 23:07:12 -0600289 ctx.vals = ses->server->vals;
290 ctx.ops = ses->server->ops;
Aurelien Apteld70e9fa2019-09-20 06:31:10 +0200291
Ronnie Sahlberg3fa1c6d2020-12-09 23:07:12 -0600292 ctx.noblocksnd = ses->server->noblocksnd;
293 ctx.noautotune = ses->server->noautotune;
294 ctx.sockopt_tcp_nodelay = ses->server->tcp_nodelay;
295 ctx.echo_interval = ses->server->echo_interval / HZ;
Aurelien Aptela249cc82021-03-04 17:42:21 +0000296 ctx.max_credits = ses->server->max_credits;
Aurelien Apteld70e9fa2019-09-20 06:31:10 +0200297
298 /*
299 * This will be used for encoding/decoding user/domain/pw
300 * during sess setup auth.
Aurelien Apteld70e9fa2019-09-20 06:31:10 +0200301 */
Ronnie Sahlberg387ec582020-12-14 16:40:20 +1000302 ctx.local_nls = cifs_sb->local_nls;
Aurelien Apteld70e9fa2019-09-20 06:31:10 +0200303
304 /* Use RDMA if possible */
Ronnie Sahlberg3fa1c6d2020-12-09 23:07:12 -0600305 ctx.rdma = iface->rdma_capable;
306 memcpy(&ctx.dstaddr, &iface->sockaddr, sizeof(struct sockaddr_storage));
Aurelien Apteld70e9fa2019-09-20 06:31:10 +0200307
308 /* reuse master con client guid */
Ronnie Sahlberg3fa1c6d2020-12-09 23:07:12 -0600309 memcpy(&ctx.client_guid, ses->server->client_guid,
Aurelien Apteld70e9fa2019-09-20 06:31:10 +0200310 SMB2_CLIENT_GUID_SIZE);
Ronnie Sahlberg3fa1c6d2020-12-09 23:07:12 -0600311 ctx.use_client_guid = true;
Aurelien Apteld70e9fa2019-09-20 06:31:10 +0200312
Shyam Prasad N0f2b3052021-07-19 11:26:24 +0000313 chan_server = cifs_get_tcp_session(&ctx, ses->server);
Aurelien Apteld70e9fa2019-09-20 06:31:10 +0200314
Shyam Prasad N724244c2021-07-19 10:54:46 +0000315 spin_lock(&ses->chan_lock);
Shyam Prasad Nf486ef82021-07-19 13:54:16 +0000316 chan = &ses->chans[ses->chan_count];
Shyam Prasad N724244c2021-07-19 10:54:46 +0000317 chan->server = chan_server;
Aurelien Apteld70e9fa2019-09-20 06:31:10 +0200318 if (IS_ERR(chan->server)) {
319 rc = PTR_ERR(chan->server);
320 chan->server = NULL;
Shyam Prasad N724244c2021-07-19 10:54:46 +0000321 spin_unlock(&ses->chan_lock);
Aurelien Apteld70e9fa2019-09-20 06:31:10 +0200322 goto out;
323 }
Shyam Prasad Nf486ef82021-07-19 13:54:16 +0000324 ses->chan_count++;
325 atomic_set(&ses->chan_seq, 0);
326
327 /* Mark this channel as needing connect/setup */
328 cifs_chan_set_need_reconnect(ses, chan->server);
329
Shyam Prasad N724244c2021-07-19 10:54:46 +0000330 spin_unlock(&ses->chan_lock);
331
Shyam Prasad N73f9bfb2021-07-19 17:37:52 +0000332 mutex_lock(&ses->session_mutex);
Aurelien Apteld70e9fa2019-09-20 06:31:10 +0200333 /*
334 * We need to allocate the server crypto now as we will need
335 * to sign packets before we generate the channel signing key
336 * (we sign with the session key)
337 */
338 rc = smb311_crypto_shash_allocate(chan->server);
339 if (rc) {
340 cifs_dbg(VFS, "%s: crypto alloc failed\n", __func__);
Shyam Prasad N73f9bfb2021-07-19 17:37:52 +0000341 mutex_unlock(&ses->session_mutex);
Aurelien Apteld70e9fa2019-09-20 06:31:10 +0200342 goto out;
343 }
344
Shyam Prasad Nf486ef82021-07-19 13:54:16 +0000345 rc = cifs_negotiate_protocol(xid, ses, chan->server);
346 if (!rc)
347 rc = cifs_setup_session(xid, ses, chan->server, cifs_sb->local_nls);
Shyam Prasad N724244c2021-07-19 10:54:46 +0000348
Shyam Prasad N73f9bfb2021-07-19 17:37:52 +0000349 mutex_unlock(&ses->session_mutex);
350
Aurelien Apteld70e9fa2019-09-20 06:31:10 +0200351out:
Shyam Prasad Nd1a931c2021-07-19 12:46:53 +0000352 if (rc && chan->server) {
Shyam Prasad Nf486ef82021-07-19 13:54:16 +0000353 spin_lock(&ses->chan_lock);
Shyam Prasad Nd1a931c2021-07-19 12:46:53 +0000354 /* we rely on all bits beyond chan_count to be clear */
355 cifs_chan_clear_need_reconnect(ses, chan->server);
356 ses->chan_count--;
Shyam Prasad N2e0fa292021-07-19 14:04:11 +0000357 /*
358 * chan_count should never reach 0 as at least the primary
359 * channel is always allocated
360 */
361 WARN_ON(ses->chan_count < 1);
Shyam Prasad Nf486ef82021-07-19 13:54:16 +0000362 spin_unlock(&ses->chan_lock);
Shyam Prasad Nd1a931c2021-07-19 12:46:53 +0000363 }
364
Aurelien Apteld70e9fa2019-09-20 06:31:10 +0200365 if (rc && chan->server)
366 cifs_put_tcp_session(chan->server, 0);
Aurelien Apteld70e9fa2019-09-20 06:31:10 +0200367
368 return rc;
369}
Steve French39798772006-05-31 22:40:51 +0000370
Shyam Prasad Nf486ef82021-07-19 13:54:16 +0000371static __u32 cifs_ssetup_hdr(struct cifs_ses *ses,
372 struct TCP_Server_Info *server,
373 SESSION_SETUP_ANDX *pSMB)
Steve French39798772006-05-31 22:40:51 +0000374{
375 __u32 capabilities = 0;
376
377 /* init fields common to all four types of SessSetup */
Steve Frencheca6acf2009-02-20 05:43:09 +0000378 /* Note that offsets for first seven fields in req struct are same */
379 /* in CIFS Specs so does not matter which of 3 forms of struct */
380 /* that we use in next few lines */
381 /* Note that header is initialized to zero in header_assemble */
Steve French39798772006-05-31 22:40:51 +0000382 pSMB->req.AndXCommand = 0xFF;
Jeff Laytonc974bef2011-10-11 06:41:32 -0400383 pSMB->req.MaxBufferSize = cpu_to_le16(min_t(u32,
384 CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4,
385 USHRT_MAX));
Shyam Prasad Nf486ef82021-07-19 13:54:16 +0000386 pSMB->req.MaxMpxCount = cpu_to_le16(server->maxReq);
Fabian Frederickbc09d142014-12-10 15:41:15 -0800387 pSMB->req.VcNumber = cpu_to_le16(1);
Steve French39798772006-05-31 22:40:51 +0000388
389 /* Now no need to set SMBFLG_CASELESS or obsolete CANONICAL PATH */
390
Steve French790fe572007-07-07 19:25:05 +0000391 /* BB verify whether signing required on neg or just on auth frame
Steve French39798772006-05-31 22:40:51 +0000392 (and NTLM case) */
393
394 capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
395 CAP_LARGE_WRITE_X | CAP_LARGE_READ_X;
396
Shyam Prasad Nf486ef82021-07-19 13:54:16 +0000397 if (server->sign)
Steve French39798772006-05-31 22:40:51 +0000398 pSMB->req.hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
399
400 if (ses->capabilities & CAP_UNICODE) {
401 pSMB->req.hdr.Flags2 |= SMBFLG2_UNICODE;
402 capabilities |= CAP_UNICODE;
403 }
404 if (ses->capabilities & CAP_STATUS32) {
405 pSMB->req.hdr.Flags2 |= SMBFLG2_ERR_STATUS;
406 capabilities |= CAP_STATUS32;
407 }
408 if (ses->capabilities & CAP_DFS) {
409 pSMB->req.hdr.Flags2 |= SMBFLG2_DFS;
410 capabilities |= CAP_DFS;
411 }
Steve French26f57362007-08-30 22:09:15 +0000412 if (ses->capabilities & CAP_UNIX)
Steve French39798772006-05-31 22:40:51 +0000413 capabilities |= CAP_UNIX;
Steve French39798772006-05-31 22:40:51 +0000414
Steve French39798772006-05-31 22:40:51 +0000415 return capabilities;
416}
417
Jeff Layton0d3a01f2007-10-16 17:32:19 +0000418static void
419unicode_oslm_strings(char **pbcc_area, const struct nls_table *nls_cp)
420{
421 char *bcc_ptr = *pbcc_area;
422 int bytes_ret = 0;
423
424 /* Copy OS version */
Steve Frenchacbbb762012-01-18 22:32:33 -0600425 bytes_ret = cifs_strtoUTF16((__le16 *)bcc_ptr, "Linux version ", 32,
426 nls_cp);
Jeff Layton0d3a01f2007-10-16 17:32:19 +0000427 bcc_ptr += 2 * bytes_ret;
Steve Frenchacbbb762012-01-18 22:32:33 -0600428 bytes_ret = cifs_strtoUTF16((__le16 *) bcc_ptr, init_utsname()->release,
429 32, nls_cp);
Jeff Layton0d3a01f2007-10-16 17:32:19 +0000430 bcc_ptr += 2 * bytes_ret;
431 bcc_ptr += 2; /* trailing null */
432
Steve Frenchacbbb762012-01-18 22:32:33 -0600433 bytes_ret = cifs_strtoUTF16((__le16 *) bcc_ptr, CIFS_NETWORK_OPSYS,
434 32, nls_cp);
Jeff Layton0d3a01f2007-10-16 17:32:19 +0000435 bcc_ptr += 2 * bytes_ret;
436 bcc_ptr += 2; /* trailing null */
437
438 *pbcc_area = bcc_ptr;
439}
440
Steve French96daf2b2011-05-27 04:34:02 +0000441static void unicode_domain_string(char **pbcc_area, struct cifs_ses *ses,
Jeff Layton0d3a01f2007-10-16 17:32:19 +0000442 const struct nls_table *nls_cp)
443{
444 char *bcc_ptr = *pbcc_area;
445 int bytes_ret = 0;
446
447 /* copy domain */
448 if (ses->domainName == NULL) {
449 /* Sending null domain better than using a bogus domain name (as
450 we did briefly in 2.6.18) since server will use its default */
451 *bcc_ptr = 0;
452 *(bcc_ptr+1) = 0;
453 bytes_ret = 0;
454 } else
Steve Frenchacbbb762012-01-18 22:32:33 -0600455 bytes_ret = cifs_strtoUTF16((__le16 *) bcc_ptr, ses->domainName,
Chen Gang057d6332013-07-19 09:01:36 +0800456 CIFS_MAX_DOMAINNAME_LEN, nls_cp);
Jeff Layton0d3a01f2007-10-16 17:32:19 +0000457 bcc_ptr += 2 * bytes_ret;
458 bcc_ptr += 2; /* account for null terminator */
459
460 *pbcc_area = bcc_ptr;
461}
462
463
Steve French96daf2b2011-05-27 04:34:02 +0000464static void unicode_ssetup_strings(char **pbcc_area, struct cifs_ses *ses,
Steve French790fe572007-07-07 19:25:05 +0000465 const struct nls_table *nls_cp)
Steve French39798772006-05-31 22:40:51 +0000466{
Steve French790fe572007-07-07 19:25:05 +0000467 char *bcc_ptr = *pbcc_area;
Steve French39798772006-05-31 22:40:51 +0000468 int bytes_ret = 0;
469
470 /* BB FIXME add check that strings total less
471 than 335 or will need to send them as arrays */
472
Steve French0223cf02006-06-27 19:50:57 +0000473 /* unicode strings, must be word aligned before the call */
474/* if ((long) bcc_ptr % 2) {
Steve French39798772006-05-31 22:40:51 +0000475 *bcc_ptr = 0;
476 bcc_ptr++;
Steve French0223cf02006-06-27 19:50:57 +0000477 } */
Steve French39798772006-05-31 22:40:51 +0000478 /* copy user */
Steve French8727c8a2011-02-25 01:11:56 -0600479 if (ses->user_name == NULL) {
Steve French6e659c62006-11-08 23:10:46 +0000480 /* null user mount */
481 *bcc_ptr = 0;
482 *(bcc_ptr+1) = 0;
Steve French301a6a32010-02-06 07:08:53 +0000483 } else {
Steve Frenchacbbb762012-01-18 22:32:33 -0600484 bytes_ret = cifs_strtoUTF16((__le16 *) bcc_ptr, ses->user_name,
Scott Lovenberg8c3a2b42013-08-09 08:47:17 -0400485 CIFS_MAX_USERNAME_LEN, nls_cp);
Steve French39798772006-05-31 22:40:51 +0000486 }
487 bcc_ptr += 2 * bytes_ret;
488 bcc_ptr += 2; /* account for null termination */
Steve French39798772006-05-31 22:40:51 +0000489
Jeff Layton0d3a01f2007-10-16 17:32:19 +0000490 unicode_domain_string(&bcc_ptr, ses, nls_cp);
491 unicode_oslm_strings(&bcc_ptr, nls_cp);
Steve French39798772006-05-31 22:40:51 +0000492
493 *pbcc_area = bcc_ptr;
494}
495
Steve French96daf2b2011-05-27 04:34:02 +0000496static void ascii_ssetup_strings(char **pbcc_area, struct cifs_ses *ses,
Steve French790fe572007-07-07 19:25:05 +0000497 const struct nls_table *nls_cp)
Steve French39798772006-05-31 22:40:51 +0000498{
Steve French790fe572007-07-07 19:25:05 +0000499 char *bcc_ptr = *pbcc_area;
Ronnie Sahlberg340625e2019-08-27 09:30:14 +1000500 int len;
Steve French39798772006-05-31 22:40:51 +0000501
502 /* copy user */
503 /* BB what about null user mounts - check that we do this BB */
Steve French790fe572007-07-07 19:25:05 +0000504 /* copy user */
Shirish Pargaonkarde47a412012-02-02 15:28:28 -0600505 if (ses->user_name != NULL) {
Ronnie Sahlberg340625e2019-08-27 09:30:14 +1000506 len = strscpy(bcc_ptr, ses->user_name, CIFS_MAX_USERNAME_LEN);
507 if (WARN_ON_ONCE(len < 0))
508 len = CIFS_MAX_USERNAME_LEN - 1;
509 bcc_ptr += len;
Shirish Pargaonkarde47a412012-02-02 15:28:28 -0600510 }
Steve French8727c8a2011-02-25 01:11:56 -0600511 /* else null user mount */
Steve French39798772006-05-31 22:40:51 +0000512 *bcc_ptr = 0;
Steve French790fe572007-07-07 19:25:05 +0000513 bcc_ptr++; /* account for null termination */
Steve French39798772006-05-31 22:40:51 +0000514
Steve French790fe572007-07-07 19:25:05 +0000515 /* copy domain */
Steve French790fe572007-07-07 19:25:05 +0000516 if (ses->domainName != NULL) {
Ronnie Sahlberg340625e2019-08-27 09:30:14 +1000517 len = strscpy(bcc_ptr, ses->domainName, CIFS_MAX_DOMAINNAME_LEN);
518 if (WARN_ON_ONCE(len < 0))
519 len = CIFS_MAX_DOMAINNAME_LEN - 1;
520 bcc_ptr += len;
Steve French790fe572007-07-07 19:25:05 +0000521 } /* else we will send a null domain name
Steve French6e659c62006-11-08 23:10:46 +0000522 so the server will default to its own domain */
Steve French39798772006-05-31 22:40:51 +0000523 *bcc_ptr = 0;
524 bcc_ptr++;
525
526 /* BB check for overflow here */
527
528 strcpy(bcc_ptr, "Linux version ");
529 bcc_ptr += strlen("Linux version ");
Serge E. Hallyn96b644b2006-10-02 02:18:13 -0700530 strcpy(bcc_ptr, init_utsname()->release);
531 bcc_ptr += strlen(init_utsname()->release) + 1;
Steve French39798772006-05-31 22:40:51 +0000532
533 strcpy(bcc_ptr, CIFS_NETWORK_OPSYS);
534 bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1;
535
Steve French790fe572007-07-07 19:25:05 +0000536 *pbcc_area = bcc_ptr;
Steve French39798772006-05-31 22:40:51 +0000537}
538
Jeff Layton59140792009-04-30 07:16:21 -0400539static void
Steve French96daf2b2011-05-27 04:34:02 +0000540decode_unicode_ssetup(char **pbcc_area, int bleft, struct cifs_ses *ses,
Jeff Layton59140792009-04-30 07:16:21 -0400541 const struct nls_table *nls_cp)
Steve French39798772006-05-31 22:40:51 +0000542{
Jeff Layton59140792009-04-30 07:16:21 -0400543 int len;
Steve French790fe572007-07-07 19:25:05 +0000544 char *data = *pbcc_area;
Steve French39798772006-05-31 22:40:51 +0000545
Joe Perchesf96637b2013-05-04 22:12:25 -0500546 cifs_dbg(FYI, "bleft %d\n", bleft);
Steve French39798772006-05-31 22:40:51 +0000547
Steve French26f57362007-08-30 22:09:15 +0000548 kfree(ses->serverOS);
Steve Frenchacbbb762012-01-18 22:32:33 -0600549 ses->serverOS = cifs_strndup_from_utf16(data, bleft, true, nls_cp);
Joe Perchesf96637b2013-05-04 22:12:25 -0500550 cifs_dbg(FYI, "serverOS=%s\n", ses->serverOS);
Jeff Layton59140792009-04-30 07:16:21 -0400551 len = (UniStrnlen((wchar_t *) data, bleft / 2) * 2) + 2;
552 data += len;
553 bleft -= len;
554 if (bleft <= 0)
555 return;
Steve French39798772006-05-31 22:40:51 +0000556
Steve French26f57362007-08-30 22:09:15 +0000557 kfree(ses->serverNOS);
Steve Frenchacbbb762012-01-18 22:32:33 -0600558 ses->serverNOS = cifs_strndup_from_utf16(data, bleft, true, nls_cp);
Joe Perchesf96637b2013-05-04 22:12:25 -0500559 cifs_dbg(FYI, "serverNOS=%s\n", ses->serverNOS);
Jeff Layton59140792009-04-30 07:16:21 -0400560 len = (UniStrnlen((wchar_t *) data, bleft / 2) * 2) + 2;
561 data += len;
562 bleft -= len;
563 if (bleft <= 0)
564 return;
Steve French39798772006-05-31 22:40:51 +0000565
Steve French26f57362007-08-30 22:09:15 +0000566 kfree(ses->serverDomain);
Steve Frenchacbbb762012-01-18 22:32:33 -0600567 ses->serverDomain = cifs_strndup_from_utf16(data, bleft, true, nls_cp);
Joe Perchesf96637b2013-05-04 22:12:25 -0500568 cifs_dbg(FYI, "serverDomain=%s\n", ses->serverDomain);
Steve French790fe572007-07-07 19:25:05 +0000569
Jeff Layton59140792009-04-30 07:16:21 -0400570 return;
Steve French39798772006-05-31 22:40:51 +0000571}
572
Jeff Layton7d066452013-05-24 07:41:00 -0400573static void decode_ascii_ssetup(char **pbcc_area, __u16 bleft,
574 struct cifs_ses *ses,
575 const struct nls_table *nls_cp)
Steve French39798772006-05-31 22:40:51 +0000576{
Steve French39798772006-05-31 22:40:51 +0000577 int len;
Steve French790fe572007-07-07 19:25:05 +0000578 char *bcc_ptr = *pbcc_area;
Steve French39798772006-05-31 22:40:51 +0000579
Joe Perchesf96637b2013-05-04 22:12:25 -0500580 cifs_dbg(FYI, "decode sessetup ascii. bleft %d\n", bleft);
Steve French50c2f752007-07-13 00:33:32 +0000581
Steve French39798772006-05-31 22:40:51 +0000582 len = strnlen(bcc_ptr, bleft);
Steve French790fe572007-07-07 19:25:05 +0000583 if (len >= bleft)
Jeff Layton7d066452013-05-24 07:41:00 -0400584 return;
Steve French50c2f752007-07-13 00:33:32 +0000585
Steve French26f57362007-08-30 22:09:15 +0000586 kfree(ses->serverOS);
Steve French39798772006-05-31 22:40:51 +0000587
Ronnie Sahlberg340625e2019-08-27 09:30:14 +1000588 ses->serverOS = kmalloc(len + 1, GFP_KERNEL);
Namjae Jeon27b7edc2014-08-20 19:39:28 +0900589 if (ses->serverOS) {
Ronnie Sahlberg340625e2019-08-27 09:30:14 +1000590 memcpy(ses->serverOS, bcc_ptr, len);
591 ses->serverOS[len] = 0;
Namjae Jeon27b7edc2014-08-20 19:39:28 +0900592 if (strncmp(ses->serverOS, "OS/2", 4) == 0)
593 cifs_dbg(FYI, "OS/2 server\n");
594 }
Steve French39798772006-05-31 22:40:51 +0000595
596 bcc_ptr += len + 1;
597 bleft -= len + 1;
598
599 len = strnlen(bcc_ptr, bleft);
Steve French790fe572007-07-07 19:25:05 +0000600 if (len >= bleft)
Jeff Layton7d066452013-05-24 07:41:00 -0400601 return;
Steve French39798772006-05-31 22:40:51 +0000602
Steve French26f57362007-08-30 22:09:15 +0000603 kfree(ses->serverNOS);
Steve French39798772006-05-31 22:40:51 +0000604
Ronnie Sahlberg340625e2019-08-27 09:30:14 +1000605 ses->serverNOS = kmalloc(len + 1, GFP_KERNEL);
606 if (ses->serverNOS) {
607 memcpy(ses->serverNOS, bcc_ptr, len);
608 ses->serverNOS[len] = 0;
609 }
Steve French39798772006-05-31 22:40:51 +0000610
611 bcc_ptr += len + 1;
612 bleft -= len + 1;
613
Steve French790fe572007-07-07 19:25:05 +0000614 len = strnlen(bcc_ptr, bleft);
615 if (len > bleft)
Jeff Layton7d066452013-05-24 07:41:00 -0400616 return;
Steve French39798772006-05-31 22:40:51 +0000617
Steve French9ac00b72006-09-30 04:13:17 +0000618 /* No domain field in LANMAN case. Domain is
619 returned by old servers in the SMB negprot response */
620 /* BB For newer servers which do not support Unicode,
621 but thus do return domain here we could add parsing
622 for it later, but it is not very important */
Joe Perchesf96637b2013-05-04 22:12:25 -0500623 cifs_dbg(FYI, "ascii: bytes left %d\n", bleft);
Steve French39798772006-05-31 22:40:51 +0000624}
625
Pavel Shilovsky5478f9b2011-12-27 16:22:00 +0400626int decode_ntlmssp_challenge(char *bcc_ptr, int blob_len,
Steve French96daf2b2011-05-27 04:34:02 +0000627 struct cifs_ses *ses)
Steve French0b3cc8582009-05-04 08:37:12 +0000628{
Shirish Pargaonkar2b149f12010-09-18 22:02:18 -0500629 unsigned int tioffset; /* challenge message target info area */
630 unsigned int tilen; /* challenge message target info area length */
Steve French0b3cc8582009-05-04 08:37:12 +0000631 CHALLENGE_MESSAGE *pblob = (CHALLENGE_MESSAGE *)bcc_ptr;
Paulo Alcantara9de07372021-12-07 22:51:04 -0300632 __u32 server_flags;
Steve French0b3cc8582009-05-04 08:37:12 +0000633
634 if (blob_len < sizeof(CHALLENGE_MESSAGE)) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500635 cifs_dbg(VFS, "challenge blob len %d too small\n", blob_len);
Steve French0b3cc8582009-05-04 08:37:12 +0000636 return -EINVAL;
637 }
638
639 if (memcmp(pblob->Signature, "NTLMSSP", 8)) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500640 cifs_dbg(VFS, "blob signature incorrect %s\n",
641 pblob->Signature);
Steve French0b3cc8582009-05-04 08:37:12 +0000642 return -EINVAL;
643 }
644 if (pblob->MessageType != NtLmChallenge) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500645 cifs_dbg(VFS, "Incorrect message type %d\n",
646 pblob->MessageType);
Steve French0b3cc8582009-05-04 08:37:12 +0000647 return -EINVAL;
648 }
649
Paulo Alcantara9de07372021-12-07 22:51:04 -0300650 server_flags = le32_to_cpu(pblob->NegotiateFlags);
651 cifs_dbg(FYI, "%s: negotiate=0x%08x challenge=0x%08x\n", __func__,
652 ses->ntlmssp->client_flags, server_flags);
653
654 if ((ses->ntlmssp->client_flags & (NTLMSSP_NEGOTIATE_SEAL | NTLMSSP_NEGOTIATE_SIGN)) &&
655 (!(server_flags & NTLMSSP_NEGOTIATE_56) && !(server_flags & NTLMSSP_NEGOTIATE_128))) {
656 cifs_dbg(VFS, "%s: requested signing/encryption but server did not return either 56-bit or 128-bit session key size\n",
657 __func__);
658 return -EINVAL;
659 }
660 if (!(server_flags & NTLMSSP_NEGOTIATE_NTLM) && !(server_flags & NTLMSSP_NEGOTIATE_EXTENDED_SEC)) {
661 cifs_dbg(VFS, "%s: server does not seem to support either NTLMv1 or NTLMv2\n", __func__);
662 return -EINVAL;
663 }
664 if (ses->server->sign && !(server_flags & NTLMSSP_NEGOTIATE_SIGN)) {
665 cifs_dbg(VFS, "%s: forced packet signing but server does not seem to support it\n",
666 __func__);
667 return -EOPNOTSUPP;
668 }
669 if ((ses->ntlmssp->client_flags & NTLMSSP_NEGOTIATE_KEY_XCH) &&
670 !(server_flags & NTLMSSP_NEGOTIATE_KEY_XCH))
671 pr_warn_once("%s: authentication has been weakened as server does not support key exchange\n",
672 __func__);
673
674 ses->ntlmssp->server_flags = server_flags;
675
Shirish Pargaonkard3686d52010-10-28 09:53:07 -0500676 memcpy(ses->ntlmssp->cryptkey, pblob->Challenge, CIFS_CRYPTO_KEY_SIZE);
Steve French0b3cc8582009-05-04 08:37:12 +0000677 /* In particular we can examine sign flags */
678 /* BB spec says that if AvId field of MsvAvTimestamp is populated then
679 we must set the MIC field of the AUTHENTICATE_MESSAGE */
Paulo Alcantara9de07372021-12-07 22:51:04 -0300680
Steve French5443d132011-03-13 05:08:25 +0000681 tioffset = le32_to_cpu(pblob->TargetInfoArray.BufferOffset);
682 tilen = le16_to_cpu(pblob->TargetInfoArray.Length);
Dan Carpenter4991a5f2012-01-31 11:52:01 +0300683 if (tioffset > blob_len || tioffset + tilen > blob_len) {
Joe Perchesa0a30362020-04-14 22:42:53 -0700684 cifs_dbg(VFS, "tioffset + tilen too high %u + %u\n",
685 tioffset, tilen);
Dan Carpenter4991a5f2012-01-31 11:52:01 +0300686 return -EINVAL;
687 }
Shirish Pargaonkard3686d52010-10-28 09:53:07 -0500688 if (tilen) {
Silviu-Mihai Popescuf7f7c182013-03-11 18:22:32 +0200689 ses->auth_key.response = kmemdup(bcc_ptr + tioffset, tilen,
690 GFP_KERNEL);
Shirish Pargaonkard3686d52010-10-28 09:53:07 -0500691 if (!ses->auth_key.response) {
Joe Perchesa0a30362020-04-14 22:42:53 -0700692 cifs_dbg(VFS, "Challenge target info alloc failure\n");
Shirish Pargaonkar2b149f12010-09-18 22:02:18 -0500693 return -ENOMEM;
694 }
Shirish Pargaonkard3686d52010-10-28 09:53:07 -0500695 ses->auth_key.len = tilen;
Shirish Pargaonkar2b149f12010-09-18 22:02:18 -0500696 }
697
Steve French0b3cc8582009-05-04 08:37:12 +0000698 return 0;
699}
700
Shyam Prasad N49bd49f2021-11-05 19:03:57 +0000701static int size_of_ntlmssp_blob(struct cifs_ses *ses, int base_size)
702{
703 int sz = base_size + ses->auth_key.len
704 - CIFS_SESS_KEY_SIZE + CIFS_CPHTXT_SIZE + 2;
705
706 if (ses->domainName)
707 sz += sizeof(__le16) * strnlen(ses->domainName, CIFS_MAX_DOMAINNAME_LEN);
708 else
709 sz += sizeof(__le16);
710
711 if (ses->user_name)
712 sz += sizeof(__le16) * strnlen(ses->user_name, CIFS_MAX_USERNAME_LEN);
713 else
714 sz += sizeof(__le16);
715
Ryan Baird3b331f2021-12-22 11:04:05 -0500716 if (ses->workstation_name)
717 sz += sizeof(__le16) * strnlen(ses->workstation_name,
718 CIFS_MAX_WORKSTATION_LEN);
719 else
720 sz += sizeof(__le16);
Shyam Prasad N49bd49f2021-11-05 19:03:57 +0000721
722 return sz;
723}
724
725static inline void cifs_security_buffer_from_str(SECURITY_BUFFER *pbuf,
726 char *str_value,
727 int str_length,
728 unsigned char *pstart,
729 unsigned char **pcur,
730 const struct nls_table *nls_cp)
731{
732 unsigned char *tmp = pstart;
733 int len;
734
735 if (!pbuf)
736 return;
737
738 if (!pcur)
739 pcur = &tmp;
740
741 if (!str_value) {
742 pbuf->BufferOffset = cpu_to_le32(*pcur - pstart);
743 pbuf->Length = 0;
744 pbuf->MaximumLength = 0;
745 *pcur += sizeof(__le16);
746 } else {
747 len = cifs_strtoUTF16((__le16 *)*pcur,
748 str_value,
749 str_length,
750 nls_cp);
751 len *= sizeof(__le16);
752 pbuf->BufferOffset = cpu_to_le32(*pcur - pstart);
753 pbuf->Length = cpu_to_le16(len);
754 pbuf->MaximumLength = cpu_to_le16(len);
755 *pcur += len;
756 }
757}
758
Steve French0b3cc8582009-05-04 08:37:12 +0000759/* BB Move to ntlmssp.c eventually */
760
Shyam Prasad N49bd49f2021-11-05 19:03:57 +0000761int build_ntlmssp_negotiate_blob(unsigned char **pbuffer,
762 u16 *buflen,
763 struct cifs_ses *ses,
Shyam Prasad Nf486ef82021-07-19 13:54:16 +0000764 struct TCP_Server_Info *server,
Shyam Prasad N49bd49f2021-11-05 19:03:57 +0000765 const struct nls_table *nls_cp)
Steve French0b3cc8582009-05-04 08:37:12 +0000766{
Shyam Prasad N49bd49f2021-11-05 19:03:57 +0000767 int rc = 0;
Shyam Prasad N49bd49f2021-11-05 19:03:57 +0000768 NEGOTIATE_MESSAGE *sec_blob;
Steve French0b3cc8582009-05-04 08:37:12 +0000769 __u32 flags;
Shyam Prasad N49bd49f2021-11-05 19:03:57 +0000770 unsigned char *tmp;
771 int len;
Steve French0b3cc8582009-05-04 08:37:12 +0000772
Shyam Prasad N49bd49f2021-11-05 19:03:57 +0000773 len = size_of_ntlmssp_blob(ses, sizeof(NEGOTIATE_MESSAGE));
774 *pbuffer = kmalloc(len, GFP_KERNEL);
775 if (!*pbuffer) {
776 rc = -ENOMEM;
777 cifs_dbg(VFS, "Error %d during NTLMSSP allocation\n", rc);
778 *buflen = 0;
779 goto setup_ntlm_neg_ret;
780 }
781 sec_blob = (NEGOTIATE_MESSAGE *)*pbuffer;
782
783 memset(*pbuffer, 0, sizeof(NEGOTIATE_MESSAGE));
Steve French0b3cc8582009-05-04 08:37:12 +0000784 memcpy(sec_blob->Signature, NTLMSSP_SIGNATURE, 8);
785 sec_blob->MessageType = NtLmNegotiate;
786
787 /* BB is NTLMV2 session security format easier to use here? */
788 flags = NTLMSSP_NEGOTIATE_56 | NTLMSSP_REQUEST_TARGET |
789 NTLMSSP_NEGOTIATE_128 | NTLMSSP_NEGOTIATE_UNICODE |
Pavel Shilovskycabfb362016-11-07 18:20:50 -0800790 NTLMSSP_NEGOTIATE_NTLM | NTLMSSP_NEGOTIATE_EXTENDED_SEC |
Paulo Alcantara9de07372021-12-07 22:51:04 -0300791 NTLMSSP_NEGOTIATE_ALWAYS_SIGN | NTLMSSP_NEGOTIATE_SEAL |
792 NTLMSSP_NEGOTIATE_SIGN;
Aurelien Aptelf6a6bf72019-09-20 06:22:14 +0200793 if (!server->session_estab || ses->ntlmssp->sesskey_per_smbsess)
Pavel Shilovskycabfb362016-11-07 18:20:50 -0800794 flags |= NTLMSSP_NEGOTIATE_KEY_XCH;
Steve French0b3cc8582009-05-04 08:37:12 +0000795
Shyam Prasad N49bd49f2021-11-05 19:03:57 +0000796 tmp = *pbuffer + sizeof(NEGOTIATE_MESSAGE);
Paulo Alcantara9de07372021-12-07 22:51:04 -0300797 ses->ntlmssp->client_flags = flags;
Shirish Pargaonkardf8fbc242010-12-11 14:19:22 -0600798 sec_blob->NegotiateFlags = cpu_to_le32(flags);
Steve French0b3cc8582009-05-04 08:37:12 +0000799
Shyam Prasad N49bd49f2021-11-05 19:03:57 +0000800 /* these fields should be null in negotiate phase MS-NLMP 3.1.5.1.1 */
801 cifs_security_buffer_from_str(&sec_blob->DomainName,
802 NULL,
803 CIFS_MAX_DOMAINNAME_LEN,
804 *pbuffer, &tmp,
805 nls_cp);
Steve French0b3cc8582009-05-04 08:37:12 +0000806
Shyam Prasad N49bd49f2021-11-05 19:03:57 +0000807 cifs_security_buffer_from_str(&sec_blob->WorkstationName,
808 NULL,
809 CIFS_MAX_WORKSTATION_LEN,
810 *pbuffer, &tmp,
811 nls_cp);
Steve French0b3cc8582009-05-04 08:37:12 +0000812
Shyam Prasad N49bd49f2021-11-05 19:03:57 +0000813 *buflen = tmp - *pbuffer;
814setup_ntlm_neg_ret:
815 return rc;
Jerome Marchandb8da3442016-05-26 11:52:25 +0200816}
817
Steve French52d00532022-01-19 22:00:29 -0600818/*
819 * Build ntlmssp blob with additional fields, such as version,
820 * supported by modern servers. For safety limit to SMB3 or later
821 * See notes in MS-NLMP Section 2.2.2.1 e.g.
822 */
823int build_ntlmssp_smb3_negotiate_blob(unsigned char **pbuffer,
824 u16 *buflen,
825 struct cifs_ses *ses,
826 struct TCP_Server_Info *server,
827 const struct nls_table *nls_cp)
828{
829 int rc = 0;
830 struct negotiate_message *sec_blob;
831 __u32 flags;
832 unsigned char *tmp;
833 int len;
834
835 len = size_of_ntlmssp_blob(ses, sizeof(struct negotiate_message));
836 *pbuffer = kmalloc(len, GFP_KERNEL);
837 if (!*pbuffer) {
838 rc = -ENOMEM;
839 cifs_dbg(VFS, "Error %d during NTLMSSP allocation\n", rc);
840 *buflen = 0;
841 goto setup_ntlm_smb3_neg_ret;
842 }
843 sec_blob = (struct negotiate_message *)*pbuffer;
844
845 memset(*pbuffer, 0, sizeof(struct negotiate_message));
846 memcpy(sec_blob->Signature, NTLMSSP_SIGNATURE, 8);
847 sec_blob->MessageType = NtLmNegotiate;
848
849 /* BB is NTLMV2 session security format easier to use here? */
850 flags = NTLMSSP_NEGOTIATE_56 | NTLMSSP_REQUEST_TARGET |
851 NTLMSSP_NEGOTIATE_128 | NTLMSSP_NEGOTIATE_UNICODE |
852 NTLMSSP_NEGOTIATE_NTLM | NTLMSSP_NEGOTIATE_EXTENDED_SEC |
853 NTLMSSP_NEGOTIATE_ALWAYS_SIGN | NTLMSSP_NEGOTIATE_SEAL |
854 NTLMSSP_NEGOTIATE_SIGN | NTLMSSP_NEGOTIATE_VERSION;
855 if (!server->session_estab || ses->ntlmssp->sesskey_per_smbsess)
856 flags |= NTLMSSP_NEGOTIATE_KEY_XCH;
857
858 sec_blob->Version.ProductMajorVersion = LINUX_VERSION_MAJOR;
859 sec_blob->Version.ProductMinorVersion = LINUX_VERSION_PATCHLEVEL;
860 sec_blob->Version.ProductBuild = cpu_to_le16(SMB3_PRODUCT_BUILD);
861 sec_blob->Version.NTLMRevisionCurrent = NTLMSSP_REVISION_W2K3;
862
863 tmp = *pbuffer + sizeof(struct negotiate_message);
864 ses->ntlmssp->client_flags = flags;
865 sec_blob->NegotiateFlags = cpu_to_le32(flags);
866
867 /* these fields should be null in negotiate phase MS-NLMP 3.1.5.1.1 */
868 cifs_security_buffer_from_str(&sec_blob->DomainName,
869 NULL,
870 CIFS_MAX_DOMAINNAME_LEN,
871 *pbuffer, &tmp,
872 nls_cp);
873
874 cifs_security_buffer_from_str(&sec_blob->WorkstationName,
875 NULL,
876 CIFS_MAX_WORKSTATION_LEN,
877 *pbuffer, &tmp,
878 nls_cp);
879
880 *buflen = tmp - *pbuffer;
881setup_ntlm_smb3_neg_ret:
882 return rc;
883}
884
885
Jerome Marchandb8da3442016-05-26 11:52:25 +0200886int build_ntlmssp_auth_blob(unsigned char **pbuffer,
Shirish Pargaonkar89f150f2010-10-19 11:47:52 -0500887 u16 *buflen,
Steve French96daf2b2011-05-27 04:34:02 +0000888 struct cifs_ses *ses,
Shyam Prasad Nf486ef82021-07-19 13:54:16 +0000889 struct TCP_Server_Info *server,
Shirish Pargaonkar2b149f12010-09-18 22:02:18 -0500890 const struct nls_table *nls_cp)
Steve French0b3cc8582009-05-04 08:37:12 +0000891{
Shirish Pargaonkar2b149f12010-09-18 22:02:18 -0500892 int rc;
Jerome Marchandb8da3442016-05-26 11:52:25 +0200893 AUTHENTICATE_MESSAGE *sec_blob;
Steve French0b3cc8582009-05-04 08:37:12 +0000894 __u32 flags;
895 unsigned char *tmp;
Shyam Prasad N49bd49f2021-11-05 19:03:57 +0000896 int len;
Steve French0b3cc8582009-05-04 08:37:12 +0000897
Jerome Marchandb8da3442016-05-26 11:52:25 +0200898 rc = setup_ntlmv2_rsp(ses, nls_cp);
899 if (rc) {
900 cifs_dbg(VFS, "Error %d during NTLMSSP authentication\n", rc);
901 *buflen = 0;
902 goto setup_ntlmv2_ret;
903 }
Shyam Prasad N49bd49f2021-11-05 19:03:57 +0000904
905 len = size_of_ntlmssp_blob(ses, sizeof(AUTHENTICATE_MESSAGE));
906 *pbuffer = kmalloc(len, GFP_KERNEL);
Nicholas Mc Guire126c97f2018-08-23 12:24:02 +0200907 if (!*pbuffer) {
908 rc = -ENOMEM;
909 cifs_dbg(VFS, "Error %d during NTLMSSP allocation\n", rc);
910 *buflen = 0;
911 goto setup_ntlmv2_ret;
912 }
Jerome Marchandb8da3442016-05-26 11:52:25 +0200913 sec_blob = (AUTHENTICATE_MESSAGE *)*pbuffer;
914
Steve French0b3cc8582009-05-04 08:37:12 +0000915 memcpy(sec_blob->Signature, NTLMSSP_SIGNATURE, 8);
916 sec_blob->MessageType = NtLmAuthenticate;
917
Paulo Alcantara9de07372021-12-07 22:51:04 -0300918 flags = ses->ntlmssp->server_flags | NTLMSSP_REQUEST_TARGET |
919 NTLMSSP_NEGOTIATE_TARGET_INFO | NTLMSSP_NEGOTIATE_WORKSTATION_SUPPLIED;
Steve French0b3cc8582009-05-04 08:37:12 +0000920
Jerome Marchandb8da3442016-05-26 11:52:25 +0200921 tmp = *pbuffer + sizeof(AUTHENTICATE_MESSAGE);
Shirish Pargaonkardf8fbc242010-12-11 14:19:22 -0600922 sec_blob->NegotiateFlags = cpu_to_le32(flags);
Steve French0b3cc8582009-05-04 08:37:12 +0000923
924 sec_blob->LmChallengeResponse.BufferOffset =
925 cpu_to_le32(sizeof(AUTHENTICATE_MESSAGE));
926 sec_blob->LmChallengeResponse.Length = 0;
927 sec_blob->LmChallengeResponse.MaximumLength = 0;
928
Jerome Marchandb8da3442016-05-26 11:52:25 +0200929 sec_blob->NtChallengeResponse.BufferOffset =
930 cpu_to_le32(tmp - *pbuffer);
Stefan Metzmachercfda35d2016-05-03 10:52:30 +0200931 if (ses->user_name != NULL) {
Stefan Metzmachercfda35d2016-05-03 10:52:30 +0200932 memcpy(tmp, ses->auth_key.response + CIFS_SESS_KEY_SIZE,
933 ses->auth_key.len - CIFS_SESS_KEY_SIZE);
934 tmp += ses->auth_key.len - CIFS_SESS_KEY_SIZE;
Steve Frenchc8e56f12010-09-08 21:10:58 +0000935
Stefan Metzmachercfda35d2016-05-03 10:52:30 +0200936 sec_blob->NtChallengeResponse.Length =
937 cpu_to_le16(ses->auth_key.len - CIFS_SESS_KEY_SIZE);
938 sec_blob->NtChallengeResponse.MaximumLength =
939 cpu_to_le16(ses->auth_key.len - CIFS_SESS_KEY_SIZE);
940 } else {
941 /*
942 * don't send an NT Response for anonymous access
943 */
944 sec_blob->NtChallengeResponse.Length = 0;
945 sec_blob->NtChallengeResponse.MaximumLength = 0;
946 }
Steve French0b3cc8582009-05-04 08:37:12 +0000947
Shyam Prasad N49bd49f2021-11-05 19:03:57 +0000948 cifs_security_buffer_from_str(&sec_blob->DomainName,
949 ses->domainName,
950 CIFS_MAX_DOMAINNAME_LEN,
951 *pbuffer, &tmp,
952 nls_cp);
Steve French0b3cc8582009-05-04 08:37:12 +0000953
Shyam Prasad N49bd49f2021-11-05 19:03:57 +0000954 cifs_security_buffer_from_str(&sec_blob->UserName,
955 ses->user_name,
956 CIFS_MAX_USERNAME_LEN,
957 *pbuffer, &tmp,
958 nls_cp);
Steve French0b3cc8582009-05-04 08:37:12 +0000959
Shyam Prasad N49bd49f2021-11-05 19:03:57 +0000960 cifs_security_buffer_from_str(&sec_blob->WorkstationName,
961 ses->workstation_name,
962 CIFS_MAX_WORKSTATION_LEN,
963 *pbuffer, &tmp,
964 nls_cp);
Steve French0b3cc8582009-05-04 08:37:12 +0000965
Paulo Alcantara9de07372021-12-07 22:51:04 -0300966 if ((ses->ntlmssp->server_flags & NTLMSSP_NEGOTIATE_KEY_XCH) &&
967 (!ses->server->session_estab || ses->ntlmssp->sesskey_per_smbsess) &&
968 !calc_seckey(ses)) {
Shirish Pargaonkard3686d52010-10-28 09:53:07 -0500969 memcpy(tmp, ses->ntlmssp->ciphertext, CIFS_CPHTXT_SIZE);
Jerome Marchandb8da3442016-05-26 11:52:25 +0200970 sec_blob->SessionKey.BufferOffset = cpu_to_le32(tmp - *pbuffer);
Shirish Pargaonkard2b91522010-10-21 14:25:08 -0500971 sec_blob->SessionKey.Length = cpu_to_le16(CIFS_CPHTXT_SIZE);
972 sec_blob->SessionKey.MaximumLength =
973 cpu_to_le16(CIFS_CPHTXT_SIZE);
974 tmp += CIFS_CPHTXT_SIZE;
975 } else {
Jerome Marchandb8da3442016-05-26 11:52:25 +0200976 sec_blob->SessionKey.BufferOffset = cpu_to_le32(tmp - *pbuffer);
Shirish Pargaonkard2b91522010-10-21 14:25:08 -0500977 sec_blob->SessionKey.Length = 0;
978 sec_blob->SessionKey.MaximumLength = 0;
979 }
Shirish Pargaonkar2b149f12010-09-18 22:02:18 -0500980
Jerome Marchandb8da3442016-05-26 11:52:25 +0200981 *buflen = tmp - *pbuffer;
Shirish Pargaonkar2b149f12010-09-18 22:02:18 -0500982setup_ntlmv2_ret:
Shirish Pargaonkar89f150f2010-10-19 11:47:52 -0500983 return rc;
Steve French0b3cc8582009-05-04 08:37:12 +0000984}
Steve French0b3cc8582009-05-04 08:37:12 +0000985
Jeff Layton3f618222013-06-12 19:52:14 -0500986enum securityEnum
Sachin Prabhuef65aae2017-01-18 15:35:57 +0530987cifs_select_sectype(struct TCP_Server_Info *server, enum securityEnum requested)
Jeff Layton3f618222013-06-12 19:52:14 -0500988{
989 switch (server->negflavor) {
990 case CIFS_NEGFLAVOR_EXTENDED:
991 switch (requested) {
992 case Kerberos:
993 case RawNTLMSSP:
994 return requested;
995 case Unspecified:
996 if (server->sec_ntlmssp &&
997 (global_secflags & CIFSSEC_MAY_NTLMSSP))
998 return RawNTLMSSP;
999 if ((server->sec_kerberos || server->sec_mskerberos) &&
1000 (global_secflags & CIFSSEC_MAY_KRB5))
1001 return Kerberos;
Gustavo A. R. Silvadf561f662020-08-23 17:36:59 -05001002 fallthrough;
Jeff Layton3f618222013-06-12 19:52:14 -05001003 default:
1004 return Unspecified;
1005 }
1006 case CIFS_NEGFLAVOR_UNENCAP:
1007 switch (requested) {
Jeff Layton3f618222013-06-12 19:52:14 -05001008 case NTLMv2:
1009 return requested;
1010 case Unspecified:
1011 if (global_secflags & CIFSSEC_MAY_NTLMV2)
1012 return NTLMv2;
Gustavo A. R. Silva21ac58f2020-11-20 12:24:14 -06001013 break;
Jeff Layton3f618222013-06-12 19:52:14 -05001014 default:
Sachin Prabhudde23562013-09-27 18:35:42 +01001015 break;
Jeff Layton3f618222013-06-12 19:52:14 -05001016 }
Ronnie Sahlberg76a3c922021-08-19 20:34:58 +10001017 fallthrough;
Jeff Layton3f618222013-06-12 19:52:14 -05001018 default:
1019 return Unspecified;
1020 }
1021}
1022
Sachin Prabhu80a0e632014-06-16 15:35:25 +01001023struct sess_data {
1024 unsigned int xid;
1025 struct cifs_ses *ses;
Shyam Prasad Nf486ef82021-07-19 13:54:16 +00001026 struct TCP_Server_Info *server;
Sachin Prabhu80a0e632014-06-16 15:35:25 +01001027 struct nls_table *nls_cp;
1028 void (*func)(struct sess_data *);
1029 int result;
1030
1031 /* we will send the SMB in three pieces:
1032 * a fixed length beginning part, an optional
1033 * SPNEGO blob (which can be zero length), and a
1034 * last part which will include the strings
1035 * and rest of bcc area. This allows us to avoid
1036 * a large buffer 17K allocation
1037 */
1038 int buf0_type;
1039 struct kvec iov[3];
1040};
1041
1042static int
1043sess_alloc_buffer(struct sess_data *sess_data, int wct)
1044{
1045 int rc;
1046 struct cifs_ses *ses = sess_data->ses;
1047 struct smb_hdr *smb_buf;
1048
1049 rc = small_smb_init_no_tc(SMB_COM_SESSION_SETUP_ANDX, wct, ses,
1050 (void **)&smb_buf);
1051
1052 if (rc)
1053 return rc;
1054
1055 sess_data->iov[0].iov_base = (char *)smb_buf;
1056 sess_data->iov[0].iov_len = be32_to_cpu(smb_buf->smb_buf_length) + 4;
1057 /*
1058 * This variable will be used to clear the buffer
1059 * allocated above in case of any error in the calling function.
1060 */
1061 sess_data->buf0_type = CIFS_SMALL_BUFFER;
1062
1063 /* 2000 big enough to fit max user, domain, NOS name etc. */
1064 sess_data->iov[2].iov_base = kmalloc(2000, GFP_KERNEL);
1065 if (!sess_data->iov[2].iov_base) {
1066 rc = -ENOMEM;
1067 goto out_free_smb_buf;
1068 }
1069
1070 return 0;
1071
1072out_free_smb_buf:
Ding Huid72c7412021-08-17 22:55:10 +08001073 cifs_small_buf_release(smb_buf);
Sachin Prabhu80a0e632014-06-16 15:35:25 +01001074 sess_data->iov[0].iov_base = NULL;
1075 sess_data->iov[0].iov_len = 0;
1076 sess_data->buf0_type = CIFS_NO_BUFFER;
1077 return rc;
1078}
1079
1080static void
1081sess_free_buffer(struct sess_data *sess_data)
1082{
1083
1084 free_rsp_buf(sess_data->buf0_type, sess_data->iov[0].iov_base);
1085 sess_data->buf0_type = CIFS_NO_BUFFER;
1086 kfree(sess_data->iov[2].iov_base);
1087}
1088
1089static int
1090sess_establish_session(struct sess_data *sess_data)
1091{
1092 struct cifs_ses *ses = sess_data->ses;
Shyam Prasad Nf486ef82021-07-19 13:54:16 +00001093 struct TCP_Server_Info *server = sess_data->server;
Sachin Prabhu80a0e632014-06-16 15:35:25 +01001094
Shyam Prasad Nf486ef82021-07-19 13:54:16 +00001095 mutex_lock(&server->srv_mutex);
1096 if (!server->session_estab) {
1097 if (server->sign) {
1098 server->session_key.response =
Sachin Prabhu80a0e632014-06-16 15:35:25 +01001099 kmemdup(ses->auth_key.response,
1100 ses->auth_key.len, GFP_KERNEL);
Shyam Prasad Nf486ef82021-07-19 13:54:16 +00001101 if (!server->session_key.response) {
1102 mutex_unlock(&server->srv_mutex);
Sachin Prabhu80a0e632014-06-16 15:35:25 +01001103 return -ENOMEM;
1104 }
Shyam Prasad Nf486ef82021-07-19 13:54:16 +00001105 server->session_key.len =
Sachin Prabhu80a0e632014-06-16 15:35:25 +01001106 ses->auth_key.len;
1107 }
Shyam Prasad Nf486ef82021-07-19 13:54:16 +00001108 server->sequence_number = 0x2;
1109 server->session_estab = true;
Sachin Prabhu80a0e632014-06-16 15:35:25 +01001110 }
Shyam Prasad Nf486ef82021-07-19 13:54:16 +00001111 mutex_unlock(&server->srv_mutex);
Sachin Prabhu80a0e632014-06-16 15:35:25 +01001112
1113 cifs_dbg(FYI, "CIFS session established successfully\n");
Sachin Prabhu80a0e632014-06-16 15:35:25 +01001114 return 0;
1115}
1116
1117static int
1118sess_sendreceive(struct sess_data *sess_data)
1119{
1120 int rc;
1121 struct smb_hdr *smb_buf = (struct smb_hdr *) sess_data->iov[0].iov_base;
1122 __u16 count;
Pavel Shilovskyda502f72016-10-25 11:38:47 -07001123 struct kvec rsp_iov = { NULL, 0 };
Sachin Prabhu80a0e632014-06-16 15:35:25 +01001124
1125 count = sess_data->iov[1].iov_len + sess_data->iov[2].iov_len;
Qinglang Miao1a0e7f72020-07-25 16:56:01 +08001126 be32_add_cpu(&smb_buf->smb_buf_length, count);
Sachin Prabhu80a0e632014-06-16 15:35:25 +01001127 put_bcc(count, smb_buf);
1128
1129 rc = SendReceive2(sess_data->xid, sess_data->ses,
1130 sess_data->iov, 3 /* num_iovecs */,
1131 &sess_data->buf0_type,
Pavel Shilovskyda502f72016-10-25 11:38:47 -07001132 CIFS_LOG_ERROR, &rsp_iov);
1133 cifs_small_buf_release(sess_data->iov[0].iov_base);
1134 memcpy(&sess_data->iov[0], &rsp_iov, sizeof(struct kvec));
Sachin Prabhu80a0e632014-06-16 15:35:25 +01001135
1136 return rc;
1137}
1138
Sachin Prabhu583cf7a2014-06-16 15:35:26 +01001139static void
1140sess_auth_ntlmv2(struct sess_data *sess_data)
1141{
1142 int rc = 0;
1143 struct smb_hdr *smb_buf;
1144 SESSION_SETUP_ANDX *pSMB;
1145 char *bcc_ptr;
1146 struct cifs_ses *ses = sess_data->ses;
Shyam Prasad Nf486ef82021-07-19 13:54:16 +00001147 struct TCP_Server_Info *server = sess_data->server;
Sachin Prabhu583cf7a2014-06-16 15:35:26 +01001148 __u32 capabilities;
1149 __u16 bytes_remaining;
1150
1151 /* old style NTLM sessionsetup */
1152 /* wct = 13 */
1153 rc = sess_alloc_buffer(sess_data, 13);
1154 if (rc)
1155 goto out;
1156
1157 pSMB = (SESSION_SETUP_ANDX *)sess_data->iov[0].iov_base;
1158 bcc_ptr = sess_data->iov[2].iov_base;
Shyam Prasad Nf486ef82021-07-19 13:54:16 +00001159 capabilities = cifs_ssetup_hdr(ses, server, pSMB);
Sachin Prabhu583cf7a2014-06-16 15:35:26 +01001160
1161 pSMB->req_no_secext.Capabilities = cpu_to_le32(capabilities);
1162
1163 /* LM2 password would be here if we supported it */
1164 pSMB->req_no_secext.CaseInsensitivePasswordLength = 0;
1165
Stefan Metzmacher1a967d62016-05-03 10:52:30 +02001166 if (ses->user_name != NULL) {
1167 /* calculate nlmv2 response and session key */
1168 rc = setup_ntlmv2_rsp(ses, sess_data->nls_cp);
1169 if (rc) {
1170 cifs_dbg(VFS, "Error %d during NTLMv2 authentication\n", rc);
1171 goto out;
1172 }
1173
1174 memcpy(bcc_ptr, ses->auth_key.response + CIFS_SESS_KEY_SIZE,
1175 ses->auth_key.len - CIFS_SESS_KEY_SIZE);
1176 bcc_ptr += ses->auth_key.len - CIFS_SESS_KEY_SIZE;
1177
1178 /* set case sensitive password length after tilen may get
1179 * assigned, tilen is 0 otherwise.
1180 */
1181 pSMB->req_no_secext.CaseSensitivePasswordLength =
1182 cpu_to_le16(ses->auth_key.len - CIFS_SESS_KEY_SIZE);
1183 } else {
1184 pSMB->req_no_secext.CaseSensitivePasswordLength = 0;
Sachin Prabhu583cf7a2014-06-16 15:35:26 +01001185 }
1186
Sachin Prabhu583cf7a2014-06-16 15:35:26 +01001187 if (ses->capabilities & CAP_UNICODE) {
1188 if (sess_data->iov[0].iov_len % 2) {
1189 *bcc_ptr = 0;
1190 bcc_ptr++;
1191 }
1192 unicode_ssetup_strings(&bcc_ptr, ses, sess_data->nls_cp);
1193 } else {
1194 ascii_ssetup_strings(&bcc_ptr, ses, sess_data->nls_cp);
1195 }
1196
1197
1198 sess_data->iov[2].iov_len = (long) bcc_ptr -
1199 (long) sess_data->iov[2].iov_base;
1200
1201 rc = sess_sendreceive(sess_data);
1202 if (rc)
1203 goto out;
1204
1205 pSMB = (SESSION_SETUP_ANDX *)sess_data->iov[0].iov_base;
1206 smb_buf = (struct smb_hdr *)sess_data->iov[0].iov_base;
1207
1208 if (smb_buf->WordCount != 3) {
1209 rc = -EIO;
1210 cifs_dbg(VFS, "bad word count %d\n", smb_buf->WordCount);
1211 goto out;
1212 }
1213
1214 if (le16_to_cpu(pSMB->resp.Action) & GUEST_LOGIN)
1215 cifs_dbg(FYI, "Guest login\n"); /* BB mark SesInfo struct? */
1216
1217 ses->Suid = smb_buf->Uid; /* UID left in wire format (le) */
1218 cifs_dbg(FYI, "UID = %llu\n", ses->Suid);
1219
1220 bytes_remaining = get_bcc(smb_buf);
1221 bcc_ptr = pByteArea(smb_buf);
1222
1223 /* BB check if Unicode and decode strings */
1224 if (bytes_remaining == 0) {
1225 /* no string area to decode, do nothing */
1226 } else if (smb_buf->Flags2 & SMBFLG2_UNICODE) {
1227 /* unicode string area must be word-aligned */
1228 if (((unsigned long) bcc_ptr - (unsigned long) smb_buf) % 2) {
1229 ++bcc_ptr;
1230 --bytes_remaining;
1231 }
1232 decode_unicode_ssetup(&bcc_ptr, bytes_remaining, ses,
1233 sess_data->nls_cp);
1234 } else {
1235 decode_ascii_ssetup(&bcc_ptr, bytes_remaining, ses,
1236 sess_data->nls_cp);
1237 }
1238
1239 rc = sess_establish_session(sess_data);
1240out:
1241 sess_data->result = rc;
1242 sess_data->func = NULL;
1243 sess_free_buffer(sess_data);
1244 kfree(ses->auth_key.response);
1245 ses->auth_key.response = NULL;
1246}
1247
Sachin Prabhuee03c642014-06-16 15:35:27 +01001248#ifdef CONFIG_CIFS_UPCALL
1249static void
1250sess_auth_kerberos(struct sess_data *sess_data)
1251{
1252 int rc = 0;
1253 struct smb_hdr *smb_buf;
1254 SESSION_SETUP_ANDX *pSMB;
1255 char *bcc_ptr;
1256 struct cifs_ses *ses = sess_data->ses;
Shyam Prasad Nf486ef82021-07-19 13:54:16 +00001257 struct TCP_Server_Info *server = sess_data->server;
Sachin Prabhuee03c642014-06-16 15:35:27 +01001258 __u32 capabilities;
1259 __u16 bytes_remaining;
1260 struct key *spnego_key = NULL;
1261 struct cifs_spnego_msg *msg;
1262 u16 blob_len;
1263
1264 /* extended security */
1265 /* wct = 12 */
1266 rc = sess_alloc_buffer(sess_data, 12);
1267 if (rc)
1268 goto out;
1269
1270 pSMB = (SESSION_SETUP_ANDX *)sess_data->iov[0].iov_base;
1271 bcc_ptr = sess_data->iov[2].iov_base;
Shyam Prasad Nf486ef82021-07-19 13:54:16 +00001272 capabilities = cifs_ssetup_hdr(ses, server, pSMB);
Sachin Prabhuee03c642014-06-16 15:35:27 +01001273
Shyam Prasad Nf486ef82021-07-19 13:54:16 +00001274 spnego_key = cifs_get_spnego_key(ses, server);
Sachin Prabhuee03c642014-06-16 15:35:27 +01001275 if (IS_ERR(spnego_key)) {
1276 rc = PTR_ERR(spnego_key);
1277 spnego_key = NULL;
1278 goto out;
1279 }
1280
David Howells146aa8b2015-10-21 14:04:48 +01001281 msg = spnego_key->payload.data[0];
Sachin Prabhuee03c642014-06-16 15:35:27 +01001282 /*
1283 * check version field to make sure that cifs.upcall is
1284 * sending us a response in an expected form
1285 */
1286 if (msg->version != CIFS_SPNEGO_UPCALL_VERSION) {
Joe Perchesa0a30362020-04-14 22:42:53 -07001287 cifs_dbg(VFS, "incorrect version of cifs.upcall (expected %d but got %d)\n",
1288 CIFS_SPNEGO_UPCALL_VERSION, msg->version);
Sachin Prabhuee03c642014-06-16 15:35:27 +01001289 rc = -EKEYREJECTED;
1290 goto out_put_spnego_key;
1291 }
1292
1293 ses->auth_key.response = kmemdup(msg->data, msg->sesskey_len,
1294 GFP_KERNEL);
1295 if (!ses->auth_key.response) {
Joe Perchesa0a30362020-04-14 22:42:53 -07001296 cifs_dbg(VFS, "Kerberos can't allocate (%u bytes) memory\n",
1297 msg->sesskey_len);
Sachin Prabhuee03c642014-06-16 15:35:27 +01001298 rc = -ENOMEM;
1299 goto out_put_spnego_key;
1300 }
1301 ses->auth_key.len = msg->sesskey_len;
1302
1303 pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC;
1304 capabilities |= CAP_EXTENDED_SECURITY;
1305 pSMB->req.Capabilities = cpu_to_le32(capabilities);
1306 sess_data->iov[1].iov_base = msg->data + msg->sesskey_len;
1307 sess_data->iov[1].iov_len = msg->secblob_len;
1308 pSMB->req.SecurityBlobLength = cpu_to_le16(sess_data->iov[1].iov_len);
1309
1310 if (ses->capabilities & CAP_UNICODE) {
1311 /* unicode strings must be word aligned */
1312 if ((sess_data->iov[0].iov_len
1313 + sess_data->iov[1].iov_len) % 2) {
1314 *bcc_ptr = 0;
1315 bcc_ptr++;
1316 }
1317 unicode_oslm_strings(&bcc_ptr, sess_data->nls_cp);
1318 unicode_domain_string(&bcc_ptr, ses, sess_data->nls_cp);
1319 } else {
1320 /* BB: is this right? */
1321 ascii_ssetup_strings(&bcc_ptr, ses, sess_data->nls_cp);
1322 }
1323
1324 sess_data->iov[2].iov_len = (long) bcc_ptr -
1325 (long) sess_data->iov[2].iov_base;
1326
1327 rc = sess_sendreceive(sess_data);
1328 if (rc)
1329 goto out_put_spnego_key;
1330
1331 pSMB = (SESSION_SETUP_ANDX *)sess_data->iov[0].iov_base;
1332 smb_buf = (struct smb_hdr *)sess_data->iov[0].iov_base;
1333
1334 if (smb_buf->WordCount != 4) {
1335 rc = -EIO;
1336 cifs_dbg(VFS, "bad word count %d\n", smb_buf->WordCount);
1337 goto out_put_spnego_key;
1338 }
1339
1340 if (le16_to_cpu(pSMB->resp.Action) & GUEST_LOGIN)
1341 cifs_dbg(FYI, "Guest login\n"); /* BB mark SesInfo struct? */
1342
1343 ses->Suid = smb_buf->Uid; /* UID left in wire format (le) */
1344 cifs_dbg(FYI, "UID = %llu\n", ses->Suid);
1345
1346 bytes_remaining = get_bcc(smb_buf);
1347 bcc_ptr = pByteArea(smb_buf);
1348
1349 blob_len = le16_to_cpu(pSMB->resp.SecurityBlobLength);
1350 if (blob_len > bytes_remaining) {
1351 cifs_dbg(VFS, "bad security blob length %d\n",
1352 blob_len);
1353 rc = -EINVAL;
1354 goto out_put_spnego_key;
1355 }
1356 bcc_ptr += blob_len;
1357 bytes_remaining -= blob_len;
1358
1359 /* BB check if Unicode and decode strings */
1360 if (bytes_remaining == 0) {
1361 /* no string area to decode, do nothing */
1362 } else if (smb_buf->Flags2 & SMBFLG2_UNICODE) {
1363 /* unicode string area must be word-aligned */
1364 if (((unsigned long) bcc_ptr - (unsigned long) smb_buf) % 2) {
1365 ++bcc_ptr;
1366 --bytes_remaining;
1367 }
1368 decode_unicode_ssetup(&bcc_ptr, bytes_remaining, ses,
1369 sess_data->nls_cp);
1370 } else {
1371 decode_ascii_ssetup(&bcc_ptr, bytes_remaining, ses,
1372 sess_data->nls_cp);
1373 }
1374
1375 rc = sess_establish_session(sess_data);
1376out_put_spnego_key:
1377 key_invalidate(spnego_key);
1378 key_put(spnego_key);
1379out:
1380 sess_data->result = rc;
1381 sess_data->func = NULL;
1382 sess_free_buffer(sess_data);
1383 kfree(ses->auth_key.response);
1384 ses->auth_key.response = NULL;
1385}
1386
Sachin Prabhuee03c642014-06-16 15:35:27 +01001387#endif /* ! CONFIG_CIFS_UPCALL */
Sachin Prabhu583cf7a2014-06-16 15:35:26 +01001388
Sachin Prabhucc87c472014-06-16 15:35:28 +01001389/*
1390 * The required kvec buffers have to be allocated before calling this
1391 * function.
1392 */
1393static int
1394_sess_auth_rawntlmssp_assemble_req(struct sess_data *sess_data)
Steve French39798772006-05-31 22:40:51 +00001395{
Steve French39798772006-05-31 22:40:51 +00001396 SESSION_SETUP_ANDX *pSMB;
Sachin Prabhucc87c472014-06-16 15:35:28 +01001397 struct cifs_ses *ses = sess_data->ses;
Shyam Prasad Nf486ef82021-07-19 13:54:16 +00001398 struct TCP_Server_Info *server = sess_data->server;
Steve French39798772006-05-31 22:40:51 +00001399 __u32 capabilities;
Sachin Prabhucc87c472014-06-16 15:35:28 +01001400 char *bcc_ptr;
Steve French254e55e2006-06-04 05:53:15 +00001401
Sachin Prabhucc87c472014-06-16 15:35:28 +01001402 pSMB = (SESSION_SETUP_ANDX *)sess_data->iov[0].iov_base;
Sachin Prabhucc87c472014-06-16 15:35:28 +01001403
Shyam Prasad Nf486ef82021-07-19 13:54:16 +00001404 capabilities = cifs_ssetup_hdr(ses, server, pSMB);
Sachin Prabhucc87c472014-06-16 15:35:28 +01001405 if ((pSMB->req.hdr.Flags2 & SMBFLG2_UNICODE) == 0) {
1406 cifs_dbg(VFS, "NTLMSSP requires Unicode support\n");
1407 return -ENOSYS;
Jeff Layton3534b852013-05-24 07:41:01 -04001408 }
Steve French39798772006-05-31 22:40:51 +00001409
Sachin Prabhucc87c472014-06-16 15:35:28 +01001410 pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC;
1411 capabilities |= CAP_EXTENDED_SECURITY;
1412 pSMB->req.Capabilities |= cpu_to_le32(capabilities);
1413
1414 bcc_ptr = sess_data->iov[2].iov_base;
1415 /* unicode strings must be word aligned */
1416 if ((sess_data->iov[0].iov_len + sess_data->iov[1].iov_len) % 2) {
1417 *bcc_ptr = 0;
1418 bcc_ptr++;
1419 }
1420 unicode_oslm_strings(&bcc_ptr, sess_data->nls_cp);
1421
1422 sess_data->iov[2].iov_len = (long) bcc_ptr -
1423 (long) sess_data->iov[2].iov_base;
1424
1425 return 0;
1426}
1427
1428static void
1429sess_auth_rawntlmssp_authenticate(struct sess_data *sess_data);
1430
1431static void
1432sess_auth_rawntlmssp_negotiate(struct sess_data *sess_data)
1433{
1434 int rc;
1435 struct smb_hdr *smb_buf;
1436 SESSION_SETUP_ANDX *pSMB;
1437 struct cifs_ses *ses = sess_data->ses;
Shyam Prasad Nf486ef82021-07-19 13:54:16 +00001438 struct TCP_Server_Info *server = sess_data->server;
Sachin Prabhucc87c472014-06-16 15:35:28 +01001439 __u16 bytes_remaining;
1440 char *bcc_ptr;
Shyam Prasad N49bd49f2021-11-05 19:03:57 +00001441 unsigned char *ntlmsspblob = NULL;
Sachin Prabhucc87c472014-06-16 15:35:28 +01001442 u16 blob_len;
1443
1444 cifs_dbg(FYI, "rawntlmssp session setup negotiate phase\n");
1445
1446 /*
1447 * if memory allocation is successful, caller of this function
1448 * frees it.
1449 */
1450 ses->ntlmssp = kmalloc(sizeof(struct ntlmssp_auth), GFP_KERNEL);
1451 if (!ses->ntlmssp) {
1452 rc = -ENOMEM;
1453 goto out;
1454 }
1455 ses->ntlmssp->sesskey_per_smbsess = false;
1456
1457 /* wct = 12 */
1458 rc = sess_alloc_buffer(sess_data, 12);
1459 if (rc)
1460 goto out;
1461
1462 pSMB = (SESSION_SETUP_ANDX *)sess_data->iov[0].iov_base;
1463
1464 /* Build security blob before we assemble the request */
Shyam Prasad N49bd49f2021-11-05 19:03:57 +00001465 rc = build_ntlmssp_negotiate_blob(&ntlmsspblob,
Shyam Prasad Nf486ef82021-07-19 13:54:16 +00001466 &blob_len, ses, server,
Shyam Prasad N49bd49f2021-11-05 19:03:57 +00001467 sess_data->nls_cp);
1468 if (rc)
Shyam Prasad Ne3548aa2022-01-17 00:20:47 -06001469 goto out_free_ntlmsspblob;
Shyam Prasad N49bd49f2021-11-05 19:03:57 +00001470
1471 sess_data->iov[1].iov_len = blob_len;
1472 sess_data->iov[1].iov_base = ntlmsspblob;
1473 pSMB->req.SecurityBlobLength = cpu_to_le16(blob_len);
Sachin Prabhucc87c472014-06-16 15:35:28 +01001474
1475 rc = _sess_auth_rawntlmssp_assemble_req(sess_data);
1476 if (rc)
Shyam Prasad Ne3548aa2022-01-17 00:20:47 -06001477 goto out_free_ntlmsspblob;
Sachin Prabhucc87c472014-06-16 15:35:28 +01001478
1479 rc = sess_sendreceive(sess_data);
1480
1481 pSMB = (SESSION_SETUP_ANDX *)sess_data->iov[0].iov_base;
1482 smb_buf = (struct smb_hdr *)sess_data->iov[0].iov_base;
1483
1484 /* If true, rc here is expected and not an error */
1485 if (sess_data->buf0_type != CIFS_NO_BUFFER &&
1486 smb_buf->Status.CifsError ==
1487 cpu_to_le32(NT_STATUS_MORE_PROCESSING_REQUIRED))
1488 rc = 0;
1489
1490 if (rc)
Shyam Prasad Ne3548aa2022-01-17 00:20:47 -06001491 goto out_free_ntlmsspblob;
Sachin Prabhucc87c472014-06-16 15:35:28 +01001492
1493 cifs_dbg(FYI, "rawntlmssp session setup challenge phase\n");
1494
1495 if (smb_buf->WordCount != 4) {
1496 rc = -EIO;
1497 cifs_dbg(VFS, "bad word count %d\n", smb_buf->WordCount);
Shyam Prasad Ne3548aa2022-01-17 00:20:47 -06001498 goto out_free_ntlmsspblob;
Sachin Prabhucc87c472014-06-16 15:35:28 +01001499 }
1500
1501 ses->Suid = smb_buf->Uid; /* UID left in wire format (le) */
1502 cifs_dbg(FYI, "UID = %llu\n", ses->Suid);
1503
1504 bytes_remaining = get_bcc(smb_buf);
1505 bcc_ptr = pByteArea(smb_buf);
1506
1507 blob_len = le16_to_cpu(pSMB->resp.SecurityBlobLength);
1508 if (blob_len > bytes_remaining) {
1509 cifs_dbg(VFS, "bad security blob length %d\n",
1510 blob_len);
1511 rc = -EINVAL;
Shyam Prasad Ne3548aa2022-01-17 00:20:47 -06001512 goto out_free_ntlmsspblob;
Sachin Prabhucc87c472014-06-16 15:35:28 +01001513 }
1514
1515 rc = decode_ntlmssp_challenge(bcc_ptr, blob_len, ses);
Shyam Prasad Ne3548aa2022-01-17 00:20:47 -06001516
1517out_free_ntlmsspblob:
1518 kfree(ntlmsspblob);
Sachin Prabhucc87c472014-06-16 15:35:28 +01001519out:
1520 sess_free_buffer(sess_data);
1521
1522 if (!rc) {
1523 sess_data->func = sess_auth_rawntlmssp_authenticate;
1524 return;
1525 }
1526
1527 /* Else error. Cleanup */
1528 kfree(ses->auth_key.response);
1529 ses->auth_key.response = NULL;
1530 kfree(ses->ntlmssp);
1531 ses->ntlmssp = NULL;
1532
1533 sess_data->func = NULL;
1534 sess_data->result = rc;
1535}
1536
1537static void
1538sess_auth_rawntlmssp_authenticate(struct sess_data *sess_data)
1539{
1540 int rc;
1541 struct smb_hdr *smb_buf;
1542 SESSION_SETUP_ANDX *pSMB;
1543 struct cifs_ses *ses = sess_data->ses;
Shyam Prasad Nf486ef82021-07-19 13:54:16 +00001544 struct TCP_Server_Info *server = sess_data->server;
Sachin Prabhucc87c472014-06-16 15:35:28 +01001545 __u16 bytes_remaining;
1546 char *bcc_ptr;
Jerome Marchandb8da3442016-05-26 11:52:25 +02001547 unsigned char *ntlmsspblob = NULL;
Sachin Prabhucc87c472014-06-16 15:35:28 +01001548 u16 blob_len;
1549
1550 cifs_dbg(FYI, "rawntlmssp session setup authenticate phase\n");
1551
1552 /* wct = 12 */
1553 rc = sess_alloc_buffer(sess_data, 12);
1554 if (rc)
1555 goto out;
1556
1557 /* Build security blob before we assemble the request */
1558 pSMB = (SESSION_SETUP_ANDX *)sess_data->iov[0].iov_base;
1559 smb_buf = (struct smb_hdr *)pSMB;
Jerome Marchandb8da3442016-05-26 11:52:25 +02001560 rc = build_ntlmssp_auth_blob(&ntlmsspblob,
Shyam Prasad Nf486ef82021-07-19 13:54:16 +00001561 &blob_len, ses, server,
1562 sess_data->nls_cp);
Sachin Prabhucc87c472014-06-16 15:35:28 +01001563 if (rc)
1564 goto out_free_ntlmsspblob;
1565 sess_data->iov[1].iov_len = blob_len;
1566 sess_data->iov[1].iov_base = ntlmsspblob;
1567 pSMB->req.SecurityBlobLength = cpu_to_le16(blob_len);
1568 /*
1569 * Make sure that we tell the server that we are using
1570 * the uid that it just gave us back on the response
1571 * (challenge)
1572 */
1573 smb_buf->Uid = ses->Suid;
1574
1575 rc = _sess_auth_rawntlmssp_assemble_req(sess_data);
1576 if (rc)
1577 goto out_free_ntlmsspblob;
1578
1579 rc = sess_sendreceive(sess_data);
1580 if (rc)
1581 goto out_free_ntlmsspblob;
1582
1583 pSMB = (SESSION_SETUP_ANDX *)sess_data->iov[0].iov_base;
1584 smb_buf = (struct smb_hdr *)sess_data->iov[0].iov_base;
1585 if (smb_buf->WordCount != 4) {
1586 rc = -EIO;
1587 cifs_dbg(VFS, "bad word count %d\n", smb_buf->WordCount);
1588 goto out_free_ntlmsspblob;
1589 }
1590
1591 if (le16_to_cpu(pSMB->resp.Action) & GUEST_LOGIN)
1592 cifs_dbg(FYI, "Guest login\n"); /* BB mark SesInfo struct? */
1593
Sachin Prabhuee9bbf42014-12-03 12:26:36 +00001594 if (ses->Suid != smb_buf->Uid) {
1595 ses->Suid = smb_buf->Uid;
1596 cifs_dbg(FYI, "UID changed! new UID = %llu\n", ses->Suid);
1597 }
1598
Sachin Prabhucc87c472014-06-16 15:35:28 +01001599 bytes_remaining = get_bcc(smb_buf);
1600 bcc_ptr = pByteArea(smb_buf);
1601 blob_len = le16_to_cpu(pSMB->resp.SecurityBlobLength);
1602 if (blob_len > bytes_remaining) {
1603 cifs_dbg(VFS, "bad security blob length %d\n",
1604 blob_len);
1605 rc = -EINVAL;
1606 goto out_free_ntlmsspblob;
1607 }
1608 bcc_ptr += blob_len;
1609 bytes_remaining -= blob_len;
1610
1611
1612 /* BB check if Unicode and decode strings */
1613 if (bytes_remaining == 0) {
1614 /* no string area to decode, do nothing */
1615 } else if (smb_buf->Flags2 & SMBFLG2_UNICODE) {
1616 /* unicode string area must be word-aligned */
1617 if (((unsigned long) bcc_ptr - (unsigned long) smb_buf) % 2) {
1618 ++bcc_ptr;
1619 --bytes_remaining;
1620 }
1621 decode_unicode_ssetup(&bcc_ptr, bytes_remaining, ses,
1622 sess_data->nls_cp);
1623 } else {
1624 decode_ascii_ssetup(&bcc_ptr, bytes_remaining, ses,
1625 sess_data->nls_cp);
1626 }
1627
1628out_free_ntlmsspblob:
1629 kfree(ntlmsspblob);
1630out:
1631 sess_free_buffer(sess_data);
1632
Yang Li74ce6132022-01-17 09:11:30 +08001633 if (!rc)
Sachin Prabhucc87c472014-06-16 15:35:28 +01001634 rc = sess_establish_session(sess_data);
1635
1636 /* Cleanup */
1637 kfree(ses->auth_key.response);
1638 ses->auth_key.response = NULL;
1639 kfree(ses->ntlmssp);
1640 ses->ntlmssp = NULL;
1641
1642 sess_data->func = NULL;
1643 sess_data->result = rc;
1644}
1645
Shyam Prasad Nf486ef82021-07-19 13:54:16 +00001646static int select_sec(struct sess_data *sess_data)
Sachin Prabhucc87c472014-06-16 15:35:28 +01001647{
1648 int type;
Shyam Prasad Nf486ef82021-07-19 13:54:16 +00001649 struct cifs_ses *ses = sess_data->ses;
1650 struct TCP_Server_Info *server = sess_data->server;
Sachin Prabhu80a0e632014-06-16 15:35:25 +01001651
Shyam Prasad Nf486ef82021-07-19 13:54:16 +00001652 type = cifs_select_sectype(server, ses->sectype);
Joe Perchesf96637b2013-05-04 22:12:25 -05001653 cifs_dbg(FYI, "sess setup type %d\n", type);
Jeff Layton3f618222013-06-12 19:52:14 -05001654 if (type == Unspecified) {
Joe Perchesa0a30362020-04-14 22:42:53 -07001655 cifs_dbg(VFS, "Unable to select appropriate authentication method!\n");
Jeff Layton3f618222013-06-12 19:52:14 -05001656 return -EINVAL;
1657 }
1658
Sachin Prabhu80a0e632014-06-16 15:35:25 +01001659 switch (type) {
Sachin Prabhu583cf7a2014-06-16 15:35:26 +01001660 case NTLMv2:
Sachin Prabhucc87c472014-06-16 15:35:28 +01001661 sess_data->func = sess_auth_ntlmv2;
1662 break;
Sachin Prabhuee03c642014-06-16 15:35:27 +01001663 case Kerberos:
Sachin Prabhucc87c472014-06-16 15:35:28 +01001664#ifdef CONFIG_CIFS_UPCALL
1665 sess_data->func = sess_auth_kerberos;
1666 break;
1667#else
1668 cifs_dbg(VFS, "Kerberos negotiated but upcall support disabled!\n");
1669 return -ENOSYS;
Sachin Prabhucc87c472014-06-16 15:35:28 +01001670#endif /* CONFIG_CIFS_UPCALL */
1671 case RawNTLMSSP:
1672 sess_data->func = sess_auth_rawntlmssp_negotiate;
1673 break;
Sachin Prabhu80a0e632014-06-16 15:35:25 +01001674 default:
Joe Perchesf96637b2013-05-04 22:12:25 -05001675 cifs_dbg(VFS, "secType %d not supported!\n", type);
Sachin Prabhucc87c472014-06-16 15:35:28 +01001676 return -ENOSYS;
Steve French39798772006-05-31 22:40:51 +00001677 }
1678
Sachin Prabhucc87c472014-06-16 15:35:28 +01001679 return 0;
1680}
Steve French24424212007-11-16 23:37:35 +00001681
Sachin Prabhucc87c472014-06-16 15:35:28 +01001682int CIFS_SessSetup(const unsigned int xid, struct cifs_ses *ses,
Shyam Prasad Nf486ef82021-07-19 13:54:16 +00001683 struct TCP_Server_Info *server,
1684 const struct nls_table *nls_cp)
Sachin Prabhucc87c472014-06-16 15:35:28 +01001685{
1686 int rc = 0;
1687 struct sess_data *sess_data;
Steve French39798772006-05-31 22:40:51 +00001688
Sachin Prabhucc87c472014-06-16 15:35:28 +01001689 if (ses == NULL) {
1690 WARN(1, "%s: ses == NULL!", __func__);
1691 return -EINVAL;
Steve French0b3cc8582009-05-04 08:37:12 +00001692 }
Sachin Prabhucc87c472014-06-16 15:35:28 +01001693
1694 sess_data = kzalloc(sizeof(struct sess_data), GFP_KERNEL);
1695 if (!sess_data)
1696 return -ENOMEM;
1697
Sachin Prabhucc87c472014-06-16 15:35:28 +01001698 sess_data->xid = xid;
1699 sess_data->ses = ses;
Shyam Prasad Nf486ef82021-07-19 13:54:16 +00001700 sess_data->server = server;
Sachin Prabhucc87c472014-06-16 15:35:28 +01001701 sess_data->buf0_type = CIFS_NO_BUFFER;
1702 sess_data->nls_cp = (struct nls_table *) nls_cp;
Steve French39798772006-05-31 22:40:51 +00001703
Shyam Prasad Nf486ef82021-07-19 13:54:16 +00001704 rc = select_sec(sess_data);
1705 if (rc)
1706 goto out;
1707
Sachin Prabhucc87c472014-06-16 15:35:28 +01001708 while (sess_data->func)
1709 sess_data->func(sess_data);
Steve French39798772006-05-31 22:40:51 +00001710
Sachin Prabhucc87c472014-06-16 15:35:28 +01001711 /* Store result before we free sess_data */
1712 rc = sess_data->result;
Sachin Prabhu80a0e632014-06-16 15:35:25 +01001713
1714out:
Sachin Prabhu80a0e632014-06-16 15:35:25 +01001715 kfree(sess_data);
1716 return rc;
Steve French39798772006-05-31 22:40:51 +00001717}