blob: dc3b16d1be09aca808286134976e1a4efda7fb6c [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
716 sz += sizeof(__le16) * strnlen(ses->workstation_name, CIFS_MAX_WORKSTATION_LEN);
717
718 return sz;
719}
720
721static inline void cifs_security_buffer_from_str(SECURITY_BUFFER *pbuf,
722 char *str_value,
723 int str_length,
724 unsigned char *pstart,
725 unsigned char **pcur,
726 const struct nls_table *nls_cp)
727{
728 unsigned char *tmp = pstart;
729 int len;
730
731 if (!pbuf)
732 return;
733
734 if (!pcur)
735 pcur = &tmp;
736
737 if (!str_value) {
738 pbuf->BufferOffset = cpu_to_le32(*pcur - pstart);
739 pbuf->Length = 0;
740 pbuf->MaximumLength = 0;
741 *pcur += sizeof(__le16);
742 } else {
743 len = cifs_strtoUTF16((__le16 *)*pcur,
744 str_value,
745 str_length,
746 nls_cp);
747 len *= sizeof(__le16);
748 pbuf->BufferOffset = cpu_to_le32(*pcur - pstart);
749 pbuf->Length = cpu_to_le16(len);
750 pbuf->MaximumLength = cpu_to_le16(len);
751 *pcur += len;
752 }
753}
754
Steve French0b3cc8582009-05-04 08:37:12 +0000755/* BB Move to ntlmssp.c eventually */
756
Shyam Prasad N49bd49f2021-11-05 19:03:57 +0000757int build_ntlmssp_negotiate_blob(unsigned char **pbuffer,
758 u16 *buflen,
759 struct cifs_ses *ses,
Shyam Prasad Nf486ef82021-07-19 13:54:16 +0000760 struct TCP_Server_Info *server,
Shyam Prasad N49bd49f2021-11-05 19:03:57 +0000761 const struct nls_table *nls_cp)
Steve French0b3cc8582009-05-04 08:37:12 +0000762{
Shyam Prasad N49bd49f2021-11-05 19:03:57 +0000763 int rc = 0;
Shyam Prasad N49bd49f2021-11-05 19:03:57 +0000764 NEGOTIATE_MESSAGE *sec_blob;
Steve French0b3cc8582009-05-04 08:37:12 +0000765 __u32 flags;
Shyam Prasad N49bd49f2021-11-05 19:03:57 +0000766 unsigned char *tmp;
767 int len;
Steve French0b3cc8582009-05-04 08:37:12 +0000768
Shyam Prasad N49bd49f2021-11-05 19:03:57 +0000769 len = size_of_ntlmssp_blob(ses, sizeof(NEGOTIATE_MESSAGE));
770 *pbuffer = kmalloc(len, GFP_KERNEL);
771 if (!*pbuffer) {
772 rc = -ENOMEM;
773 cifs_dbg(VFS, "Error %d during NTLMSSP allocation\n", rc);
774 *buflen = 0;
775 goto setup_ntlm_neg_ret;
776 }
777 sec_blob = (NEGOTIATE_MESSAGE *)*pbuffer;
778
779 memset(*pbuffer, 0, sizeof(NEGOTIATE_MESSAGE));
Steve French0b3cc8582009-05-04 08:37:12 +0000780 memcpy(sec_blob->Signature, NTLMSSP_SIGNATURE, 8);
781 sec_blob->MessageType = NtLmNegotiate;
782
783 /* BB is NTLMV2 session security format easier to use here? */
784 flags = NTLMSSP_NEGOTIATE_56 | NTLMSSP_REQUEST_TARGET |
785 NTLMSSP_NEGOTIATE_128 | NTLMSSP_NEGOTIATE_UNICODE |
Pavel Shilovskycabfb362016-11-07 18:20:50 -0800786 NTLMSSP_NEGOTIATE_NTLM | NTLMSSP_NEGOTIATE_EXTENDED_SEC |
Paulo Alcantara9de07372021-12-07 22:51:04 -0300787 NTLMSSP_NEGOTIATE_ALWAYS_SIGN | NTLMSSP_NEGOTIATE_SEAL |
788 NTLMSSP_NEGOTIATE_SIGN;
Aurelien Aptelf6a6bf72019-09-20 06:22:14 +0200789 if (!server->session_estab || ses->ntlmssp->sesskey_per_smbsess)
Pavel Shilovskycabfb362016-11-07 18:20:50 -0800790 flags |= NTLMSSP_NEGOTIATE_KEY_XCH;
Steve French0b3cc8582009-05-04 08:37:12 +0000791
Shyam Prasad N49bd49f2021-11-05 19:03:57 +0000792 tmp = *pbuffer + sizeof(NEGOTIATE_MESSAGE);
Paulo Alcantara9de07372021-12-07 22:51:04 -0300793 ses->ntlmssp->client_flags = flags;
Shirish Pargaonkardf8fbc242010-12-11 14:19:22 -0600794 sec_blob->NegotiateFlags = cpu_to_le32(flags);
Steve French0b3cc8582009-05-04 08:37:12 +0000795
Shyam Prasad N49bd49f2021-11-05 19:03:57 +0000796 /* these fields should be null in negotiate phase MS-NLMP 3.1.5.1.1 */
797 cifs_security_buffer_from_str(&sec_blob->DomainName,
798 NULL,
799 CIFS_MAX_DOMAINNAME_LEN,
800 *pbuffer, &tmp,
801 nls_cp);
Steve French0b3cc8582009-05-04 08:37:12 +0000802
Shyam Prasad N49bd49f2021-11-05 19:03:57 +0000803 cifs_security_buffer_from_str(&sec_blob->WorkstationName,
804 NULL,
805 CIFS_MAX_WORKSTATION_LEN,
806 *pbuffer, &tmp,
807 nls_cp);
Steve French0b3cc8582009-05-04 08:37:12 +0000808
Shyam Prasad N49bd49f2021-11-05 19:03:57 +0000809 *buflen = tmp - *pbuffer;
810setup_ntlm_neg_ret:
811 return rc;
Jerome Marchandb8da3442016-05-26 11:52:25 +0200812}
813
Steve French52d00532022-01-19 22:00:29 -0600814/*
815 * Build ntlmssp blob with additional fields, such as version,
816 * supported by modern servers. For safety limit to SMB3 or later
817 * See notes in MS-NLMP Section 2.2.2.1 e.g.
818 */
819int build_ntlmssp_smb3_negotiate_blob(unsigned char **pbuffer,
820 u16 *buflen,
821 struct cifs_ses *ses,
822 struct TCP_Server_Info *server,
823 const struct nls_table *nls_cp)
824{
825 int rc = 0;
826 struct negotiate_message *sec_blob;
827 __u32 flags;
828 unsigned char *tmp;
829 int len;
830
831 len = size_of_ntlmssp_blob(ses, sizeof(struct negotiate_message));
832 *pbuffer = kmalloc(len, GFP_KERNEL);
833 if (!*pbuffer) {
834 rc = -ENOMEM;
835 cifs_dbg(VFS, "Error %d during NTLMSSP allocation\n", rc);
836 *buflen = 0;
837 goto setup_ntlm_smb3_neg_ret;
838 }
839 sec_blob = (struct negotiate_message *)*pbuffer;
840
841 memset(*pbuffer, 0, sizeof(struct negotiate_message));
842 memcpy(sec_blob->Signature, NTLMSSP_SIGNATURE, 8);
843 sec_blob->MessageType = NtLmNegotiate;
844
845 /* BB is NTLMV2 session security format easier to use here? */
846 flags = NTLMSSP_NEGOTIATE_56 | NTLMSSP_REQUEST_TARGET |
847 NTLMSSP_NEGOTIATE_128 | NTLMSSP_NEGOTIATE_UNICODE |
848 NTLMSSP_NEGOTIATE_NTLM | NTLMSSP_NEGOTIATE_EXTENDED_SEC |
849 NTLMSSP_NEGOTIATE_ALWAYS_SIGN | NTLMSSP_NEGOTIATE_SEAL |
850 NTLMSSP_NEGOTIATE_SIGN | NTLMSSP_NEGOTIATE_VERSION;
851 if (!server->session_estab || ses->ntlmssp->sesskey_per_smbsess)
852 flags |= NTLMSSP_NEGOTIATE_KEY_XCH;
853
854 sec_blob->Version.ProductMajorVersion = LINUX_VERSION_MAJOR;
855 sec_blob->Version.ProductMinorVersion = LINUX_VERSION_PATCHLEVEL;
856 sec_blob->Version.ProductBuild = cpu_to_le16(SMB3_PRODUCT_BUILD);
857 sec_blob->Version.NTLMRevisionCurrent = NTLMSSP_REVISION_W2K3;
858
859 tmp = *pbuffer + sizeof(struct negotiate_message);
860 ses->ntlmssp->client_flags = flags;
861 sec_blob->NegotiateFlags = cpu_to_le32(flags);
862
863 /* these fields should be null in negotiate phase MS-NLMP 3.1.5.1.1 */
864 cifs_security_buffer_from_str(&sec_blob->DomainName,
865 NULL,
866 CIFS_MAX_DOMAINNAME_LEN,
867 *pbuffer, &tmp,
868 nls_cp);
869
870 cifs_security_buffer_from_str(&sec_blob->WorkstationName,
871 NULL,
872 CIFS_MAX_WORKSTATION_LEN,
873 *pbuffer, &tmp,
874 nls_cp);
875
876 *buflen = tmp - *pbuffer;
877setup_ntlm_smb3_neg_ret:
878 return rc;
879}
880
881
Jerome Marchandb8da3442016-05-26 11:52:25 +0200882int build_ntlmssp_auth_blob(unsigned char **pbuffer,
Shirish Pargaonkar89f150f2010-10-19 11:47:52 -0500883 u16 *buflen,
Steve French96daf2b2011-05-27 04:34:02 +0000884 struct cifs_ses *ses,
Shyam Prasad Nf486ef82021-07-19 13:54:16 +0000885 struct TCP_Server_Info *server,
Shirish Pargaonkar2b149f12010-09-18 22:02:18 -0500886 const struct nls_table *nls_cp)
Steve French0b3cc8582009-05-04 08:37:12 +0000887{
Shirish Pargaonkar2b149f12010-09-18 22:02:18 -0500888 int rc;
Jerome Marchandb8da3442016-05-26 11:52:25 +0200889 AUTHENTICATE_MESSAGE *sec_blob;
Steve French0b3cc8582009-05-04 08:37:12 +0000890 __u32 flags;
891 unsigned char *tmp;
Shyam Prasad N49bd49f2021-11-05 19:03:57 +0000892 int len;
Steve French0b3cc8582009-05-04 08:37:12 +0000893
Jerome Marchandb8da3442016-05-26 11:52:25 +0200894 rc = setup_ntlmv2_rsp(ses, nls_cp);
895 if (rc) {
896 cifs_dbg(VFS, "Error %d during NTLMSSP authentication\n", rc);
897 *buflen = 0;
898 goto setup_ntlmv2_ret;
899 }
Shyam Prasad N49bd49f2021-11-05 19:03:57 +0000900
901 len = size_of_ntlmssp_blob(ses, sizeof(AUTHENTICATE_MESSAGE));
902 *pbuffer = kmalloc(len, GFP_KERNEL);
Nicholas Mc Guire126c97f2018-08-23 12:24:02 +0200903 if (!*pbuffer) {
904 rc = -ENOMEM;
905 cifs_dbg(VFS, "Error %d during NTLMSSP allocation\n", rc);
906 *buflen = 0;
907 goto setup_ntlmv2_ret;
908 }
Jerome Marchandb8da3442016-05-26 11:52:25 +0200909 sec_blob = (AUTHENTICATE_MESSAGE *)*pbuffer;
910
Steve French0b3cc8582009-05-04 08:37:12 +0000911 memcpy(sec_blob->Signature, NTLMSSP_SIGNATURE, 8);
912 sec_blob->MessageType = NtLmAuthenticate;
913
Paulo Alcantara9de07372021-12-07 22:51:04 -0300914 flags = ses->ntlmssp->server_flags | NTLMSSP_REQUEST_TARGET |
915 NTLMSSP_NEGOTIATE_TARGET_INFO | NTLMSSP_NEGOTIATE_WORKSTATION_SUPPLIED;
Steve French0b3cc8582009-05-04 08:37:12 +0000916
Jerome Marchandb8da3442016-05-26 11:52:25 +0200917 tmp = *pbuffer + sizeof(AUTHENTICATE_MESSAGE);
Shirish Pargaonkardf8fbc242010-12-11 14:19:22 -0600918 sec_blob->NegotiateFlags = cpu_to_le32(flags);
Steve French0b3cc8582009-05-04 08:37:12 +0000919
920 sec_blob->LmChallengeResponse.BufferOffset =
921 cpu_to_le32(sizeof(AUTHENTICATE_MESSAGE));
922 sec_blob->LmChallengeResponse.Length = 0;
923 sec_blob->LmChallengeResponse.MaximumLength = 0;
924
Jerome Marchandb8da3442016-05-26 11:52:25 +0200925 sec_blob->NtChallengeResponse.BufferOffset =
926 cpu_to_le32(tmp - *pbuffer);
Stefan Metzmachercfda35d2016-05-03 10:52:30 +0200927 if (ses->user_name != NULL) {
Stefan Metzmachercfda35d2016-05-03 10:52:30 +0200928 memcpy(tmp, ses->auth_key.response + CIFS_SESS_KEY_SIZE,
929 ses->auth_key.len - CIFS_SESS_KEY_SIZE);
930 tmp += ses->auth_key.len - CIFS_SESS_KEY_SIZE;
Steve Frenchc8e56f12010-09-08 21:10:58 +0000931
Stefan Metzmachercfda35d2016-05-03 10:52:30 +0200932 sec_blob->NtChallengeResponse.Length =
933 cpu_to_le16(ses->auth_key.len - CIFS_SESS_KEY_SIZE);
934 sec_blob->NtChallengeResponse.MaximumLength =
935 cpu_to_le16(ses->auth_key.len - CIFS_SESS_KEY_SIZE);
936 } else {
937 /*
938 * don't send an NT Response for anonymous access
939 */
940 sec_blob->NtChallengeResponse.Length = 0;
941 sec_blob->NtChallengeResponse.MaximumLength = 0;
942 }
Steve French0b3cc8582009-05-04 08:37:12 +0000943
Shyam Prasad N49bd49f2021-11-05 19:03:57 +0000944 cifs_security_buffer_from_str(&sec_blob->DomainName,
945 ses->domainName,
946 CIFS_MAX_DOMAINNAME_LEN,
947 *pbuffer, &tmp,
948 nls_cp);
Steve French0b3cc8582009-05-04 08:37:12 +0000949
Shyam Prasad N49bd49f2021-11-05 19:03:57 +0000950 cifs_security_buffer_from_str(&sec_blob->UserName,
951 ses->user_name,
952 CIFS_MAX_USERNAME_LEN,
953 *pbuffer, &tmp,
954 nls_cp);
Steve French0b3cc8582009-05-04 08:37:12 +0000955
Shyam Prasad N49bd49f2021-11-05 19:03:57 +0000956 cifs_security_buffer_from_str(&sec_blob->WorkstationName,
957 ses->workstation_name,
958 CIFS_MAX_WORKSTATION_LEN,
959 *pbuffer, &tmp,
960 nls_cp);
Steve French0b3cc8582009-05-04 08:37:12 +0000961
Paulo Alcantara9de07372021-12-07 22:51:04 -0300962 if ((ses->ntlmssp->server_flags & NTLMSSP_NEGOTIATE_KEY_XCH) &&
963 (!ses->server->session_estab || ses->ntlmssp->sesskey_per_smbsess) &&
964 !calc_seckey(ses)) {
Shirish Pargaonkard3686d52010-10-28 09:53:07 -0500965 memcpy(tmp, ses->ntlmssp->ciphertext, CIFS_CPHTXT_SIZE);
Jerome Marchandb8da3442016-05-26 11:52:25 +0200966 sec_blob->SessionKey.BufferOffset = cpu_to_le32(tmp - *pbuffer);
Shirish Pargaonkard2b91522010-10-21 14:25:08 -0500967 sec_blob->SessionKey.Length = cpu_to_le16(CIFS_CPHTXT_SIZE);
968 sec_blob->SessionKey.MaximumLength =
969 cpu_to_le16(CIFS_CPHTXT_SIZE);
970 tmp += CIFS_CPHTXT_SIZE;
971 } else {
Jerome Marchandb8da3442016-05-26 11:52:25 +0200972 sec_blob->SessionKey.BufferOffset = cpu_to_le32(tmp - *pbuffer);
Shirish Pargaonkard2b91522010-10-21 14:25:08 -0500973 sec_blob->SessionKey.Length = 0;
974 sec_blob->SessionKey.MaximumLength = 0;
975 }
Shirish Pargaonkar2b149f12010-09-18 22:02:18 -0500976
Jerome Marchandb8da3442016-05-26 11:52:25 +0200977 *buflen = tmp - *pbuffer;
Shirish Pargaonkar2b149f12010-09-18 22:02:18 -0500978setup_ntlmv2_ret:
Shirish Pargaonkar89f150f2010-10-19 11:47:52 -0500979 return rc;
Steve French0b3cc8582009-05-04 08:37:12 +0000980}
Steve French0b3cc8582009-05-04 08:37:12 +0000981
Jeff Layton3f618222013-06-12 19:52:14 -0500982enum securityEnum
Sachin Prabhuef65aae2017-01-18 15:35:57 +0530983cifs_select_sectype(struct TCP_Server_Info *server, enum securityEnum requested)
Jeff Layton3f618222013-06-12 19:52:14 -0500984{
985 switch (server->negflavor) {
986 case CIFS_NEGFLAVOR_EXTENDED:
987 switch (requested) {
988 case Kerberos:
989 case RawNTLMSSP:
990 return requested;
991 case Unspecified:
992 if (server->sec_ntlmssp &&
993 (global_secflags & CIFSSEC_MAY_NTLMSSP))
994 return RawNTLMSSP;
995 if ((server->sec_kerberos || server->sec_mskerberos) &&
996 (global_secflags & CIFSSEC_MAY_KRB5))
997 return Kerberos;
Gustavo A. R. Silvadf561f662020-08-23 17:36:59 -0500998 fallthrough;
Jeff Layton3f618222013-06-12 19:52:14 -0500999 default:
1000 return Unspecified;
1001 }
1002 case CIFS_NEGFLAVOR_UNENCAP:
1003 switch (requested) {
Jeff Layton3f618222013-06-12 19:52:14 -05001004 case NTLMv2:
1005 return requested;
1006 case Unspecified:
1007 if (global_secflags & CIFSSEC_MAY_NTLMV2)
1008 return NTLMv2;
Gustavo A. R. Silva21ac58f2020-11-20 12:24:14 -06001009 break;
Jeff Layton3f618222013-06-12 19:52:14 -05001010 default:
Sachin Prabhudde23562013-09-27 18:35:42 +01001011 break;
Jeff Layton3f618222013-06-12 19:52:14 -05001012 }
Ronnie Sahlberg76a3c922021-08-19 20:34:58 +10001013 fallthrough;
Jeff Layton3f618222013-06-12 19:52:14 -05001014 default:
1015 return Unspecified;
1016 }
1017}
1018
Sachin Prabhu80a0e632014-06-16 15:35:25 +01001019struct sess_data {
1020 unsigned int xid;
1021 struct cifs_ses *ses;
Shyam Prasad Nf486ef82021-07-19 13:54:16 +00001022 struct TCP_Server_Info *server;
Sachin Prabhu80a0e632014-06-16 15:35:25 +01001023 struct nls_table *nls_cp;
1024 void (*func)(struct sess_data *);
1025 int result;
1026
1027 /* we will send the SMB in three pieces:
1028 * a fixed length beginning part, an optional
1029 * SPNEGO blob (which can be zero length), and a
1030 * last part which will include the strings
1031 * and rest of bcc area. This allows us to avoid
1032 * a large buffer 17K allocation
1033 */
1034 int buf0_type;
1035 struct kvec iov[3];
1036};
1037
1038static int
1039sess_alloc_buffer(struct sess_data *sess_data, int wct)
1040{
1041 int rc;
1042 struct cifs_ses *ses = sess_data->ses;
1043 struct smb_hdr *smb_buf;
1044
1045 rc = small_smb_init_no_tc(SMB_COM_SESSION_SETUP_ANDX, wct, ses,
1046 (void **)&smb_buf);
1047
1048 if (rc)
1049 return rc;
1050
1051 sess_data->iov[0].iov_base = (char *)smb_buf;
1052 sess_data->iov[0].iov_len = be32_to_cpu(smb_buf->smb_buf_length) + 4;
1053 /*
1054 * This variable will be used to clear the buffer
1055 * allocated above in case of any error in the calling function.
1056 */
1057 sess_data->buf0_type = CIFS_SMALL_BUFFER;
1058
1059 /* 2000 big enough to fit max user, domain, NOS name etc. */
1060 sess_data->iov[2].iov_base = kmalloc(2000, GFP_KERNEL);
1061 if (!sess_data->iov[2].iov_base) {
1062 rc = -ENOMEM;
1063 goto out_free_smb_buf;
1064 }
1065
1066 return 0;
1067
1068out_free_smb_buf:
Ding Huid72c7412021-08-17 22:55:10 +08001069 cifs_small_buf_release(smb_buf);
Sachin Prabhu80a0e632014-06-16 15:35:25 +01001070 sess_data->iov[0].iov_base = NULL;
1071 sess_data->iov[0].iov_len = 0;
1072 sess_data->buf0_type = CIFS_NO_BUFFER;
1073 return rc;
1074}
1075
1076static void
1077sess_free_buffer(struct sess_data *sess_data)
1078{
1079
1080 free_rsp_buf(sess_data->buf0_type, sess_data->iov[0].iov_base);
1081 sess_data->buf0_type = CIFS_NO_BUFFER;
1082 kfree(sess_data->iov[2].iov_base);
1083}
1084
1085static int
1086sess_establish_session(struct sess_data *sess_data)
1087{
1088 struct cifs_ses *ses = sess_data->ses;
Shyam Prasad Nf486ef82021-07-19 13:54:16 +00001089 struct TCP_Server_Info *server = sess_data->server;
Sachin Prabhu80a0e632014-06-16 15:35:25 +01001090
Shyam Prasad Nf486ef82021-07-19 13:54:16 +00001091 mutex_lock(&server->srv_mutex);
1092 if (!server->session_estab) {
1093 if (server->sign) {
1094 server->session_key.response =
Sachin Prabhu80a0e632014-06-16 15:35:25 +01001095 kmemdup(ses->auth_key.response,
1096 ses->auth_key.len, GFP_KERNEL);
Shyam Prasad Nf486ef82021-07-19 13:54:16 +00001097 if (!server->session_key.response) {
1098 mutex_unlock(&server->srv_mutex);
Sachin Prabhu80a0e632014-06-16 15:35:25 +01001099 return -ENOMEM;
1100 }
Shyam Prasad Nf486ef82021-07-19 13:54:16 +00001101 server->session_key.len =
Sachin Prabhu80a0e632014-06-16 15:35:25 +01001102 ses->auth_key.len;
1103 }
Shyam Prasad Nf486ef82021-07-19 13:54:16 +00001104 server->sequence_number = 0x2;
1105 server->session_estab = true;
Sachin Prabhu80a0e632014-06-16 15:35:25 +01001106 }
Shyam Prasad Nf486ef82021-07-19 13:54:16 +00001107 mutex_unlock(&server->srv_mutex);
Sachin Prabhu80a0e632014-06-16 15:35:25 +01001108
1109 cifs_dbg(FYI, "CIFS session established successfully\n");
Sachin Prabhu80a0e632014-06-16 15:35:25 +01001110 return 0;
1111}
1112
1113static int
1114sess_sendreceive(struct sess_data *sess_data)
1115{
1116 int rc;
1117 struct smb_hdr *smb_buf = (struct smb_hdr *) sess_data->iov[0].iov_base;
1118 __u16 count;
Pavel Shilovskyda502f72016-10-25 11:38:47 -07001119 struct kvec rsp_iov = { NULL, 0 };
Sachin Prabhu80a0e632014-06-16 15:35:25 +01001120
1121 count = sess_data->iov[1].iov_len + sess_data->iov[2].iov_len;
Qinglang Miao1a0e7f72020-07-25 16:56:01 +08001122 be32_add_cpu(&smb_buf->smb_buf_length, count);
Sachin Prabhu80a0e632014-06-16 15:35:25 +01001123 put_bcc(count, smb_buf);
1124
1125 rc = SendReceive2(sess_data->xid, sess_data->ses,
1126 sess_data->iov, 3 /* num_iovecs */,
1127 &sess_data->buf0_type,
Pavel Shilovskyda502f72016-10-25 11:38:47 -07001128 CIFS_LOG_ERROR, &rsp_iov);
1129 cifs_small_buf_release(sess_data->iov[0].iov_base);
1130 memcpy(&sess_data->iov[0], &rsp_iov, sizeof(struct kvec));
Sachin Prabhu80a0e632014-06-16 15:35:25 +01001131
1132 return rc;
1133}
1134
Sachin Prabhu583cf7a2014-06-16 15:35:26 +01001135static void
1136sess_auth_ntlmv2(struct sess_data *sess_data)
1137{
1138 int rc = 0;
1139 struct smb_hdr *smb_buf;
1140 SESSION_SETUP_ANDX *pSMB;
1141 char *bcc_ptr;
1142 struct cifs_ses *ses = sess_data->ses;
Shyam Prasad Nf486ef82021-07-19 13:54:16 +00001143 struct TCP_Server_Info *server = sess_data->server;
Sachin Prabhu583cf7a2014-06-16 15:35:26 +01001144 __u32 capabilities;
1145 __u16 bytes_remaining;
1146
1147 /* old style NTLM sessionsetup */
1148 /* wct = 13 */
1149 rc = sess_alloc_buffer(sess_data, 13);
1150 if (rc)
1151 goto out;
1152
1153 pSMB = (SESSION_SETUP_ANDX *)sess_data->iov[0].iov_base;
1154 bcc_ptr = sess_data->iov[2].iov_base;
Shyam Prasad Nf486ef82021-07-19 13:54:16 +00001155 capabilities = cifs_ssetup_hdr(ses, server, pSMB);
Sachin Prabhu583cf7a2014-06-16 15:35:26 +01001156
1157 pSMB->req_no_secext.Capabilities = cpu_to_le32(capabilities);
1158
1159 /* LM2 password would be here if we supported it */
1160 pSMB->req_no_secext.CaseInsensitivePasswordLength = 0;
1161
Stefan Metzmacher1a967d62016-05-03 10:52:30 +02001162 if (ses->user_name != NULL) {
1163 /* calculate nlmv2 response and session key */
1164 rc = setup_ntlmv2_rsp(ses, sess_data->nls_cp);
1165 if (rc) {
1166 cifs_dbg(VFS, "Error %d during NTLMv2 authentication\n", rc);
1167 goto out;
1168 }
1169
1170 memcpy(bcc_ptr, ses->auth_key.response + CIFS_SESS_KEY_SIZE,
1171 ses->auth_key.len - CIFS_SESS_KEY_SIZE);
1172 bcc_ptr += ses->auth_key.len - CIFS_SESS_KEY_SIZE;
1173
1174 /* set case sensitive password length after tilen may get
1175 * assigned, tilen is 0 otherwise.
1176 */
1177 pSMB->req_no_secext.CaseSensitivePasswordLength =
1178 cpu_to_le16(ses->auth_key.len - CIFS_SESS_KEY_SIZE);
1179 } else {
1180 pSMB->req_no_secext.CaseSensitivePasswordLength = 0;
Sachin Prabhu583cf7a2014-06-16 15:35:26 +01001181 }
1182
Sachin Prabhu583cf7a2014-06-16 15:35:26 +01001183 if (ses->capabilities & CAP_UNICODE) {
1184 if (sess_data->iov[0].iov_len % 2) {
1185 *bcc_ptr = 0;
1186 bcc_ptr++;
1187 }
1188 unicode_ssetup_strings(&bcc_ptr, ses, sess_data->nls_cp);
1189 } else {
1190 ascii_ssetup_strings(&bcc_ptr, ses, sess_data->nls_cp);
1191 }
1192
1193
1194 sess_data->iov[2].iov_len = (long) bcc_ptr -
1195 (long) sess_data->iov[2].iov_base;
1196
1197 rc = sess_sendreceive(sess_data);
1198 if (rc)
1199 goto out;
1200
1201 pSMB = (SESSION_SETUP_ANDX *)sess_data->iov[0].iov_base;
1202 smb_buf = (struct smb_hdr *)sess_data->iov[0].iov_base;
1203
1204 if (smb_buf->WordCount != 3) {
1205 rc = -EIO;
1206 cifs_dbg(VFS, "bad word count %d\n", smb_buf->WordCount);
1207 goto out;
1208 }
1209
1210 if (le16_to_cpu(pSMB->resp.Action) & GUEST_LOGIN)
1211 cifs_dbg(FYI, "Guest login\n"); /* BB mark SesInfo struct? */
1212
1213 ses->Suid = smb_buf->Uid; /* UID left in wire format (le) */
1214 cifs_dbg(FYI, "UID = %llu\n", ses->Suid);
1215
1216 bytes_remaining = get_bcc(smb_buf);
1217 bcc_ptr = pByteArea(smb_buf);
1218
1219 /* BB check if Unicode and decode strings */
1220 if (bytes_remaining == 0) {
1221 /* no string area to decode, do nothing */
1222 } else if (smb_buf->Flags2 & SMBFLG2_UNICODE) {
1223 /* unicode string area must be word-aligned */
1224 if (((unsigned long) bcc_ptr - (unsigned long) smb_buf) % 2) {
1225 ++bcc_ptr;
1226 --bytes_remaining;
1227 }
1228 decode_unicode_ssetup(&bcc_ptr, bytes_remaining, ses,
1229 sess_data->nls_cp);
1230 } else {
1231 decode_ascii_ssetup(&bcc_ptr, bytes_remaining, ses,
1232 sess_data->nls_cp);
1233 }
1234
1235 rc = sess_establish_session(sess_data);
1236out:
1237 sess_data->result = rc;
1238 sess_data->func = NULL;
1239 sess_free_buffer(sess_data);
1240 kfree(ses->auth_key.response);
1241 ses->auth_key.response = NULL;
1242}
1243
Sachin Prabhuee03c642014-06-16 15:35:27 +01001244#ifdef CONFIG_CIFS_UPCALL
1245static void
1246sess_auth_kerberos(struct sess_data *sess_data)
1247{
1248 int rc = 0;
1249 struct smb_hdr *smb_buf;
1250 SESSION_SETUP_ANDX *pSMB;
1251 char *bcc_ptr;
1252 struct cifs_ses *ses = sess_data->ses;
Shyam Prasad Nf486ef82021-07-19 13:54:16 +00001253 struct TCP_Server_Info *server = sess_data->server;
Sachin Prabhuee03c642014-06-16 15:35:27 +01001254 __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;
Shyam Prasad Nf486ef82021-07-19 13:54:16 +00001268 capabilities = cifs_ssetup_hdr(ses, server, pSMB);
Sachin Prabhuee03c642014-06-16 15:35:27 +01001269
Shyam Prasad Nf486ef82021-07-19 13:54:16 +00001270 spnego_key = cifs_get_spnego_key(ses, server);
Sachin Prabhuee03c642014-06-16 15:35:27 +01001271 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) {
Joe Perchesa0a30362020-04-14 22:42:53 -07001283 cifs_dbg(VFS, "incorrect version of cifs.upcall (expected %d but got %d)\n",
1284 CIFS_SPNEGO_UPCALL_VERSION, msg->version);
Sachin Prabhuee03c642014-06-16 15:35:27 +01001285 rc = -EKEYREJECTED;
1286 goto out_put_spnego_key;
1287 }
1288
1289 ses->auth_key.response = kmemdup(msg->data, msg->sesskey_len,
1290 GFP_KERNEL);
1291 if (!ses->auth_key.response) {
Joe Perchesa0a30362020-04-14 22:42:53 -07001292 cifs_dbg(VFS, "Kerberos can't allocate (%u bytes) memory\n",
1293 msg->sesskey_len);
Sachin Prabhuee03c642014-06-16 15:35:27 +01001294 rc = -ENOMEM;
1295 goto out_put_spnego_key;
1296 }
1297 ses->auth_key.len = msg->sesskey_len;
1298
1299 pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC;
1300 capabilities |= CAP_EXTENDED_SECURITY;
1301 pSMB->req.Capabilities = cpu_to_le32(capabilities);
1302 sess_data->iov[1].iov_base = msg->data + msg->sesskey_len;
1303 sess_data->iov[1].iov_len = msg->secblob_len;
1304 pSMB->req.SecurityBlobLength = cpu_to_le16(sess_data->iov[1].iov_len);
1305
1306 if (ses->capabilities & CAP_UNICODE) {
1307 /* unicode strings must be word aligned */
1308 if ((sess_data->iov[0].iov_len
1309 + sess_data->iov[1].iov_len) % 2) {
1310 *bcc_ptr = 0;
1311 bcc_ptr++;
1312 }
1313 unicode_oslm_strings(&bcc_ptr, sess_data->nls_cp);
1314 unicode_domain_string(&bcc_ptr, ses, sess_data->nls_cp);
1315 } else {
1316 /* BB: is this right? */
1317 ascii_ssetup_strings(&bcc_ptr, ses, sess_data->nls_cp);
1318 }
1319
1320 sess_data->iov[2].iov_len = (long) bcc_ptr -
1321 (long) sess_data->iov[2].iov_base;
1322
1323 rc = sess_sendreceive(sess_data);
1324 if (rc)
1325 goto out_put_spnego_key;
1326
1327 pSMB = (SESSION_SETUP_ANDX *)sess_data->iov[0].iov_base;
1328 smb_buf = (struct smb_hdr *)sess_data->iov[0].iov_base;
1329
1330 if (smb_buf->WordCount != 4) {
1331 rc = -EIO;
1332 cifs_dbg(VFS, "bad word count %d\n", smb_buf->WordCount);
1333 goto out_put_spnego_key;
1334 }
1335
1336 if (le16_to_cpu(pSMB->resp.Action) & GUEST_LOGIN)
1337 cifs_dbg(FYI, "Guest login\n"); /* BB mark SesInfo struct? */
1338
1339 ses->Suid = smb_buf->Uid; /* UID left in wire format (le) */
1340 cifs_dbg(FYI, "UID = %llu\n", ses->Suid);
1341
1342 bytes_remaining = get_bcc(smb_buf);
1343 bcc_ptr = pByteArea(smb_buf);
1344
1345 blob_len = le16_to_cpu(pSMB->resp.SecurityBlobLength);
1346 if (blob_len > bytes_remaining) {
1347 cifs_dbg(VFS, "bad security blob length %d\n",
1348 blob_len);
1349 rc = -EINVAL;
1350 goto out_put_spnego_key;
1351 }
1352 bcc_ptr += blob_len;
1353 bytes_remaining -= blob_len;
1354
1355 /* BB check if Unicode and decode strings */
1356 if (bytes_remaining == 0) {
1357 /* no string area to decode, do nothing */
1358 } else if (smb_buf->Flags2 & SMBFLG2_UNICODE) {
1359 /* unicode string area must be word-aligned */
1360 if (((unsigned long) bcc_ptr - (unsigned long) smb_buf) % 2) {
1361 ++bcc_ptr;
1362 --bytes_remaining;
1363 }
1364 decode_unicode_ssetup(&bcc_ptr, bytes_remaining, ses,
1365 sess_data->nls_cp);
1366 } else {
1367 decode_ascii_ssetup(&bcc_ptr, bytes_remaining, ses,
1368 sess_data->nls_cp);
1369 }
1370
1371 rc = sess_establish_session(sess_data);
1372out_put_spnego_key:
1373 key_invalidate(spnego_key);
1374 key_put(spnego_key);
1375out:
1376 sess_data->result = rc;
1377 sess_data->func = NULL;
1378 sess_free_buffer(sess_data);
1379 kfree(ses->auth_key.response);
1380 ses->auth_key.response = NULL;
1381}
1382
Sachin Prabhuee03c642014-06-16 15:35:27 +01001383#endif /* ! CONFIG_CIFS_UPCALL */
Sachin Prabhu583cf7a2014-06-16 15:35:26 +01001384
Sachin Prabhucc87c472014-06-16 15:35:28 +01001385/*
1386 * The required kvec buffers have to be allocated before calling this
1387 * function.
1388 */
1389static int
1390_sess_auth_rawntlmssp_assemble_req(struct sess_data *sess_data)
Steve French39798772006-05-31 22:40:51 +00001391{
Steve French39798772006-05-31 22:40:51 +00001392 SESSION_SETUP_ANDX *pSMB;
Sachin Prabhucc87c472014-06-16 15:35:28 +01001393 struct cifs_ses *ses = sess_data->ses;
Shyam Prasad Nf486ef82021-07-19 13:54:16 +00001394 struct TCP_Server_Info *server = sess_data->server;
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
Shyam Prasad Nf486ef82021-07-19 13:54:16 +00001400 capabilities = cifs_ssetup_hdr(ses, server, pSMB);
Sachin Prabhucc87c472014-06-16 15:35:28 +01001401 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;
Shyam Prasad Nf486ef82021-07-19 13:54:16 +00001434 struct TCP_Server_Info *server = sess_data->server;
Sachin Prabhucc87c472014-06-16 15:35:28 +01001435 __u16 bytes_remaining;
1436 char *bcc_ptr;
Shyam Prasad N49bd49f2021-11-05 19:03:57 +00001437 unsigned char *ntlmsspblob = NULL;
Sachin Prabhucc87c472014-06-16 15:35:28 +01001438 u16 blob_len;
1439
1440 cifs_dbg(FYI, "rawntlmssp session setup negotiate phase\n");
1441
1442 /*
1443 * if memory allocation is successful, caller of this function
1444 * frees it.
1445 */
1446 ses->ntlmssp = kmalloc(sizeof(struct ntlmssp_auth), GFP_KERNEL);
1447 if (!ses->ntlmssp) {
1448 rc = -ENOMEM;
1449 goto out;
1450 }
1451 ses->ntlmssp->sesskey_per_smbsess = false;
1452
1453 /* wct = 12 */
1454 rc = sess_alloc_buffer(sess_data, 12);
1455 if (rc)
1456 goto out;
1457
1458 pSMB = (SESSION_SETUP_ANDX *)sess_data->iov[0].iov_base;
1459
1460 /* Build security blob before we assemble the request */
Shyam Prasad N49bd49f2021-11-05 19:03:57 +00001461 rc = build_ntlmssp_negotiate_blob(&ntlmsspblob,
Shyam Prasad Nf486ef82021-07-19 13:54:16 +00001462 &blob_len, ses, server,
Shyam Prasad N49bd49f2021-11-05 19:03:57 +00001463 sess_data->nls_cp);
1464 if (rc)
Shyam Prasad Ne3548aa2022-01-17 00:20:47 -06001465 goto out_free_ntlmsspblob;
Shyam Prasad N49bd49f2021-11-05 19:03:57 +00001466
1467 sess_data->iov[1].iov_len = blob_len;
1468 sess_data->iov[1].iov_base = ntlmsspblob;
1469 pSMB->req.SecurityBlobLength = cpu_to_le16(blob_len);
Sachin Prabhucc87c472014-06-16 15:35:28 +01001470
1471 rc = _sess_auth_rawntlmssp_assemble_req(sess_data);
1472 if (rc)
Shyam Prasad Ne3548aa2022-01-17 00:20:47 -06001473 goto out_free_ntlmsspblob;
Sachin Prabhucc87c472014-06-16 15:35:28 +01001474
1475 rc = sess_sendreceive(sess_data);
1476
1477 pSMB = (SESSION_SETUP_ANDX *)sess_data->iov[0].iov_base;
1478 smb_buf = (struct smb_hdr *)sess_data->iov[0].iov_base;
1479
1480 /* If true, rc here is expected and not an error */
1481 if (sess_data->buf0_type != CIFS_NO_BUFFER &&
1482 smb_buf->Status.CifsError ==
1483 cpu_to_le32(NT_STATUS_MORE_PROCESSING_REQUIRED))
1484 rc = 0;
1485
1486 if (rc)
Shyam Prasad Ne3548aa2022-01-17 00:20:47 -06001487 goto out_free_ntlmsspblob;
Sachin Prabhucc87c472014-06-16 15:35:28 +01001488
1489 cifs_dbg(FYI, "rawntlmssp session setup challenge phase\n");
1490
1491 if (smb_buf->WordCount != 4) {
1492 rc = -EIO;
1493 cifs_dbg(VFS, "bad word count %d\n", smb_buf->WordCount);
Shyam Prasad Ne3548aa2022-01-17 00:20:47 -06001494 goto out_free_ntlmsspblob;
Sachin Prabhucc87c472014-06-16 15:35:28 +01001495 }
1496
1497 ses->Suid = smb_buf->Uid; /* UID left in wire format (le) */
1498 cifs_dbg(FYI, "UID = %llu\n", ses->Suid);
1499
1500 bytes_remaining = get_bcc(smb_buf);
1501 bcc_ptr = pByteArea(smb_buf);
1502
1503 blob_len = le16_to_cpu(pSMB->resp.SecurityBlobLength);
1504 if (blob_len > bytes_remaining) {
1505 cifs_dbg(VFS, "bad security blob length %d\n",
1506 blob_len);
1507 rc = -EINVAL;
Shyam Prasad Ne3548aa2022-01-17 00:20:47 -06001508 goto out_free_ntlmsspblob;
Sachin Prabhucc87c472014-06-16 15:35:28 +01001509 }
1510
1511 rc = decode_ntlmssp_challenge(bcc_ptr, blob_len, ses);
Shyam Prasad Ne3548aa2022-01-17 00:20:47 -06001512
1513out_free_ntlmsspblob:
1514 kfree(ntlmsspblob);
Sachin Prabhucc87c472014-06-16 15:35:28 +01001515out:
1516 sess_free_buffer(sess_data);
1517
1518 if (!rc) {
1519 sess_data->func = sess_auth_rawntlmssp_authenticate;
1520 return;
1521 }
1522
1523 /* Else error. Cleanup */
1524 kfree(ses->auth_key.response);
1525 ses->auth_key.response = NULL;
1526 kfree(ses->ntlmssp);
1527 ses->ntlmssp = NULL;
1528
1529 sess_data->func = NULL;
1530 sess_data->result = rc;
1531}
1532
1533static void
1534sess_auth_rawntlmssp_authenticate(struct sess_data *sess_data)
1535{
1536 int rc;
1537 struct smb_hdr *smb_buf;
1538 SESSION_SETUP_ANDX *pSMB;
1539 struct cifs_ses *ses = sess_data->ses;
Shyam Prasad Nf486ef82021-07-19 13:54:16 +00001540 struct TCP_Server_Info *server = sess_data->server;
Sachin Prabhucc87c472014-06-16 15:35:28 +01001541 __u16 bytes_remaining;
1542 char *bcc_ptr;
Jerome Marchandb8da3442016-05-26 11:52:25 +02001543 unsigned char *ntlmsspblob = NULL;
Sachin Prabhucc87c472014-06-16 15:35:28 +01001544 u16 blob_len;
1545
1546 cifs_dbg(FYI, "rawntlmssp session setup authenticate phase\n");
1547
1548 /* wct = 12 */
1549 rc = sess_alloc_buffer(sess_data, 12);
1550 if (rc)
1551 goto out;
1552
1553 /* Build security blob before we assemble the request */
1554 pSMB = (SESSION_SETUP_ANDX *)sess_data->iov[0].iov_base;
1555 smb_buf = (struct smb_hdr *)pSMB;
Jerome Marchandb8da3442016-05-26 11:52:25 +02001556 rc = build_ntlmssp_auth_blob(&ntlmsspblob,
Shyam Prasad Nf486ef82021-07-19 13:54:16 +00001557 &blob_len, ses, server,
1558 sess_data->nls_cp);
Sachin Prabhucc87c472014-06-16 15:35:28 +01001559 if (rc)
1560 goto out_free_ntlmsspblob;
1561 sess_data->iov[1].iov_len = blob_len;
1562 sess_data->iov[1].iov_base = ntlmsspblob;
1563 pSMB->req.SecurityBlobLength = cpu_to_le16(blob_len);
1564 /*
1565 * Make sure that we tell the server that we are using
1566 * the uid that it just gave us back on the response
1567 * (challenge)
1568 */
1569 smb_buf->Uid = ses->Suid;
1570
1571 rc = _sess_auth_rawntlmssp_assemble_req(sess_data);
1572 if (rc)
1573 goto out_free_ntlmsspblob;
1574
1575 rc = sess_sendreceive(sess_data);
1576 if (rc)
1577 goto out_free_ntlmsspblob;
1578
1579 pSMB = (SESSION_SETUP_ANDX *)sess_data->iov[0].iov_base;
1580 smb_buf = (struct smb_hdr *)sess_data->iov[0].iov_base;
1581 if (smb_buf->WordCount != 4) {
1582 rc = -EIO;
1583 cifs_dbg(VFS, "bad word count %d\n", smb_buf->WordCount);
1584 goto out_free_ntlmsspblob;
1585 }
1586
1587 if (le16_to_cpu(pSMB->resp.Action) & GUEST_LOGIN)
1588 cifs_dbg(FYI, "Guest login\n"); /* BB mark SesInfo struct? */
1589
Sachin Prabhuee9bbf42014-12-03 12:26:36 +00001590 if (ses->Suid != smb_buf->Uid) {
1591 ses->Suid = smb_buf->Uid;
1592 cifs_dbg(FYI, "UID changed! new UID = %llu\n", ses->Suid);
1593 }
1594
Sachin Prabhucc87c472014-06-16 15:35:28 +01001595 bytes_remaining = get_bcc(smb_buf);
1596 bcc_ptr = pByteArea(smb_buf);
1597 blob_len = le16_to_cpu(pSMB->resp.SecurityBlobLength);
1598 if (blob_len > bytes_remaining) {
1599 cifs_dbg(VFS, "bad security blob length %d\n",
1600 blob_len);
1601 rc = -EINVAL;
1602 goto out_free_ntlmsspblob;
1603 }
1604 bcc_ptr += blob_len;
1605 bytes_remaining -= blob_len;
1606
1607
1608 /* BB check if Unicode and decode strings */
1609 if (bytes_remaining == 0) {
1610 /* no string area to decode, do nothing */
1611 } else if (smb_buf->Flags2 & SMBFLG2_UNICODE) {
1612 /* unicode string area must be word-aligned */
1613 if (((unsigned long) bcc_ptr - (unsigned long) smb_buf) % 2) {
1614 ++bcc_ptr;
1615 --bytes_remaining;
1616 }
1617 decode_unicode_ssetup(&bcc_ptr, bytes_remaining, ses,
1618 sess_data->nls_cp);
1619 } else {
1620 decode_ascii_ssetup(&bcc_ptr, bytes_remaining, ses,
1621 sess_data->nls_cp);
1622 }
1623
1624out_free_ntlmsspblob:
1625 kfree(ntlmsspblob);
1626out:
1627 sess_free_buffer(sess_data);
1628
Yang Li74ce6132022-01-17 09:11:30 +08001629 if (!rc)
Sachin Prabhucc87c472014-06-16 15:35:28 +01001630 rc = sess_establish_session(sess_data);
1631
1632 /* Cleanup */
1633 kfree(ses->auth_key.response);
1634 ses->auth_key.response = NULL;
1635 kfree(ses->ntlmssp);
1636 ses->ntlmssp = NULL;
1637
1638 sess_data->func = NULL;
1639 sess_data->result = rc;
1640}
1641
Shyam Prasad Nf486ef82021-07-19 13:54:16 +00001642static int select_sec(struct sess_data *sess_data)
Sachin Prabhucc87c472014-06-16 15:35:28 +01001643{
1644 int type;
Shyam Prasad Nf486ef82021-07-19 13:54:16 +00001645 struct cifs_ses *ses = sess_data->ses;
1646 struct TCP_Server_Info *server = sess_data->server;
Sachin Prabhu80a0e632014-06-16 15:35:25 +01001647
Shyam Prasad Nf486ef82021-07-19 13:54:16 +00001648 type = cifs_select_sectype(server, ses->sectype);
Joe Perchesf96637b2013-05-04 22:12:25 -05001649 cifs_dbg(FYI, "sess setup type %d\n", type);
Jeff Layton3f618222013-06-12 19:52:14 -05001650 if (type == Unspecified) {
Joe Perchesa0a30362020-04-14 22:42:53 -07001651 cifs_dbg(VFS, "Unable to select appropriate authentication method!\n");
Jeff Layton3f618222013-06-12 19:52:14 -05001652 return -EINVAL;
1653 }
1654
Sachin Prabhu80a0e632014-06-16 15:35:25 +01001655 switch (type) {
Sachin Prabhu583cf7a2014-06-16 15:35:26 +01001656 case NTLMv2:
Sachin Prabhucc87c472014-06-16 15:35:28 +01001657 sess_data->func = sess_auth_ntlmv2;
1658 break;
Sachin Prabhuee03c642014-06-16 15:35:27 +01001659 case Kerberos:
Sachin Prabhucc87c472014-06-16 15:35:28 +01001660#ifdef CONFIG_CIFS_UPCALL
1661 sess_data->func = sess_auth_kerberos;
1662 break;
1663#else
1664 cifs_dbg(VFS, "Kerberos negotiated but upcall support disabled!\n");
1665 return -ENOSYS;
Sachin Prabhucc87c472014-06-16 15:35:28 +01001666#endif /* CONFIG_CIFS_UPCALL */
1667 case RawNTLMSSP:
1668 sess_data->func = sess_auth_rawntlmssp_negotiate;
1669 break;
Sachin Prabhu80a0e632014-06-16 15:35:25 +01001670 default:
Joe Perchesf96637b2013-05-04 22:12:25 -05001671 cifs_dbg(VFS, "secType %d not supported!\n", type);
Sachin Prabhucc87c472014-06-16 15:35:28 +01001672 return -ENOSYS;
Steve French39798772006-05-31 22:40:51 +00001673 }
1674
Sachin Prabhucc87c472014-06-16 15:35:28 +01001675 return 0;
1676}
Steve French24424212007-11-16 23:37:35 +00001677
Sachin Prabhucc87c472014-06-16 15:35:28 +01001678int CIFS_SessSetup(const unsigned int xid, struct cifs_ses *ses,
Shyam Prasad Nf486ef82021-07-19 13:54:16 +00001679 struct TCP_Server_Info *server,
1680 const struct nls_table *nls_cp)
Sachin Prabhucc87c472014-06-16 15:35:28 +01001681{
1682 int rc = 0;
1683 struct sess_data *sess_data;
Steve French39798772006-05-31 22:40:51 +00001684
Sachin Prabhucc87c472014-06-16 15:35:28 +01001685 if (ses == NULL) {
1686 WARN(1, "%s: ses == NULL!", __func__);
1687 return -EINVAL;
Steve French0b3cc8582009-05-04 08:37:12 +00001688 }
Sachin Prabhucc87c472014-06-16 15:35:28 +01001689
1690 sess_data = kzalloc(sizeof(struct sess_data), GFP_KERNEL);
1691 if (!sess_data)
1692 return -ENOMEM;
1693
Sachin Prabhucc87c472014-06-16 15:35:28 +01001694 sess_data->xid = xid;
1695 sess_data->ses = ses;
Shyam Prasad Nf486ef82021-07-19 13:54:16 +00001696 sess_data->server = server;
Sachin Prabhucc87c472014-06-16 15:35:28 +01001697 sess_data->buf0_type = CIFS_NO_BUFFER;
1698 sess_data->nls_cp = (struct nls_table *) nls_cp;
Steve French39798772006-05-31 22:40:51 +00001699
Shyam Prasad Nf486ef82021-07-19 13:54:16 +00001700 rc = select_sec(sess_data);
1701 if (rc)
1702 goto out;
1703
Sachin Prabhucc87c472014-06-16 15:35:28 +01001704 while (sess_data->func)
1705 sess_data->func(sess_data);
Steve French39798772006-05-31 22:40:51 +00001706
Sachin Prabhucc87c472014-06-16 15:35:28 +01001707 /* Store result before we free sess_data */
1708 rc = sess_data->result;
Sachin Prabhu80a0e632014-06-16 15:35:25 +01001709
1710out:
Sachin Prabhu80a0e632014-06-16 15:35:25 +01001711 kfree(sess_data);
1712 return rc;
Steve French39798772006-05-31 22:40:51 +00001713}