sess.c 21.0 KB
Newer Older
1 2 3 4 5
/*
 *   fs/cifs/sess.c
 *
 *   SMB/CIFS session setup handling routines
 *
S
Steve French 已提交
6
 *   Copyright (c) International Business Machines  Corp., 2006, 2007
7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
 *   Author(s): Steve French (sfrench@us.ibm.com)
 *
 *   This library is free software; you can redistribute it and/or modify
 *   it under the terms of the GNU Lesser General Public License as published
 *   by the Free Software Foundation; either version 2.1 of the License, or
 *   (at your option) any later version.
 *
 *   This library is distributed in the hope that it will be useful,
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
 *   the GNU Lesser General Public License for more details.
 *
 *   You should have received a copy of the GNU Lesser General Public License
 *   along with this library; if not, write to the Free Software
 *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 */

#include "cifspdu.h"
#include "cifsglob.h"
#include "cifsproto.h"
#include "cifs_unicode.h"
#include "cifs_debug.h"
#include "ntlmssp.h"
#include "nterr.h"
31
#include <linux/utsname.h>
32
#include "cifs_spnego.h"
33 34

extern void SMBNTencrypt(unsigned char *passwd, unsigned char *c8,
S
Steve French 已提交
35
			 unsigned char *p24);
36

37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116
/* Checks if this is the first smb session to be reconnected after
   the socket has been reestablished (so we know whether to use vc 0).
   Called while holding the cifs_tcp_ses_lock, so do not block */
static bool is_first_ses_reconnect(struct cifsSesInfo *ses)
{
	struct list_head *tmp;
	struct cifsSesInfo *tmp_ses;

	list_for_each(tmp, &ses->server->smb_ses_list) {
		tmp_ses = list_entry(tmp, struct cifsSesInfo,
				     smb_ses_list);
		if (tmp_ses->need_reconnect == false)
			return false;
	}
	/* could not find a session that was already connected,
	   this must be the first one we are reconnecting */
	return true;
}

/*
 *	vc number 0 is treated specially by some servers, and should be the
 *      first one we request.  After that we can use vcnumbers up to maxvcs,
 *	one for each smb session (some Windows versions set maxvcs incorrectly
 *	so maxvc=1 can be ignored).  If we have too many vcs, we can reuse
 *	any vc but zero (some servers reset the connection on vcnum zero)
 *
 */
static __le16 get_next_vcnum(struct cifsSesInfo *ses)
{
	__u16 vcnum = 0;
	struct list_head *tmp;
	struct cifsSesInfo *tmp_ses;
	__u16 max_vcs = ses->server->max_vcs;
	__u16 i;
	int free_vc_found = 0;

	/* Quoting the MS-SMB specification: "Windows-based SMB servers set this
	field to one but do not enforce this limit, which allows an SMB client
	to establish more virtual circuits than allowed by this value ... but
	other server implementations can enforce this limit." */
	if (max_vcs < 2)
		max_vcs = 0xFFFF;

	write_lock(&cifs_tcp_ses_lock);
	if ((ses->need_reconnect) && is_first_ses_reconnect(ses))
			goto get_vc_num_exit;  /* vcnum will be zero */
	for (i = ses->server->srv_count - 1; i < max_vcs; i++) {
		if (i == 0) /* this is the only connection, use vc 0 */
			break;

		free_vc_found = 1;

		list_for_each(tmp, &ses->server->smb_ses_list) {
			tmp_ses = list_entry(tmp, struct cifsSesInfo,
					     smb_ses_list);
			if (tmp_ses->vcnum == i) {
				free_vc_found = 0;
				break; /* found duplicate, try next vcnum */
			}
		}
		if (free_vc_found)
			break; /* we found a vcnumber that will work - use it */
	}

	if (i == 0)
		vcnum = 0; /* for most common case, ie if one smb session, use
			      vc zero.  Also for case when no free vcnum, zero
			      is safest to send (some clients only send zero) */
	else if (free_vc_found == 0)
		vcnum = 1;  /* we can not reuse vc=0 safely, since some servers
				reset all uids on that, but 1 is ok. */
	else
		vcnum = i;
	ses->vcnum = vcnum;
get_vc_num_exit:
	write_unlock(&cifs_tcp_ses_lock);

	return le16_to_cpu(vcnum);
}

117 118 119 120 121
static __u32 cifs_ssetup_hdr(struct cifsSesInfo *ses, SESSION_SETUP_ANDX *pSMB)
{
	__u32 capabilities = 0;

	/* init fields common to all four types of SessSetup */
122 123 124 125
	/* Note that offsets for first seven fields in req struct are same  */
	/*	in CIFS Specs so does not matter which of 3 forms of struct */
	/*	that we use in next few lines                               */
	/* Note that header is initialized to zero in header_assemble */
126 127 128
	pSMB->req.AndXCommand = 0xFF;
	pSMB->req.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
	pSMB->req.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
129
	pSMB->req.VcNumber = get_next_vcnum(ses);
130 131 132

	/* Now no need to set SMBFLG_CASELESS or obsolete CANONICAL PATH */

S
Steve French 已提交
133
	/* BB verify whether signing required on neg or just on auth frame
134 135 136 137 138
	   (and NTLM case) */

	capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
			CAP_LARGE_WRITE_X | CAP_LARGE_READ_X;

S
Steve French 已提交
139 140
	if (ses->server->secMode &
	    (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
141 142 143 144 145 146 147 148 149 150 151 152 153 154
		pSMB->req.hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;

	if (ses->capabilities & CAP_UNICODE) {
		pSMB->req.hdr.Flags2 |= SMBFLG2_UNICODE;
		capabilities |= CAP_UNICODE;
	}
	if (ses->capabilities & CAP_STATUS32) {
		pSMB->req.hdr.Flags2 |= SMBFLG2_ERR_STATUS;
		capabilities |= CAP_STATUS32;
	}
	if (ses->capabilities & CAP_DFS) {
		pSMB->req.hdr.Flags2 |= SMBFLG2_DFS;
		capabilities |= CAP_DFS;
	}
155
	if (ses->capabilities & CAP_UNIX)
156 157 158 159 160
		capabilities |= CAP_UNIX;

	return capabilities;
}

161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206
static void
unicode_oslm_strings(char **pbcc_area, const struct nls_table *nls_cp)
{
	char *bcc_ptr = *pbcc_area;
	int bytes_ret = 0;

	/* Copy OS version */
	bytes_ret = cifs_strtoUCS((__le16 *)bcc_ptr, "Linux version ", 32,
				  nls_cp);
	bcc_ptr += 2 * bytes_ret;
	bytes_ret = cifs_strtoUCS((__le16 *) bcc_ptr, init_utsname()->release,
				  32, nls_cp);
	bcc_ptr += 2 * bytes_ret;
	bcc_ptr += 2; /* trailing null */

	bytes_ret = cifs_strtoUCS((__le16 *) bcc_ptr, CIFS_NETWORK_OPSYS,
				  32, nls_cp);
	bcc_ptr += 2 * bytes_ret;
	bcc_ptr += 2; /* trailing null */

	*pbcc_area = bcc_ptr;
}

static void unicode_domain_string(char **pbcc_area, struct cifsSesInfo *ses,
				   const struct nls_table *nls_cp)
{
	char *bcc_ptr = *pbcc_area;
	int bytes_ret = 0;

	/* copy domain */
	if (ses->domainName == NULL) {
		/* Sending null domain better than using a bogus domain name (as
		we did briefly in 2.6.18) since server will use its default */
		*bcc_ptr = 0;
		*(bcc_ptr+1) = 0;
		bytes_ret = 0;
	} else
		bytes_ret = cifs_strtoUCS((__le16 *) bcc_ptr, ses->domainName,
					  256, nls_cp);
	bcc_ptr += 2 * bytes_ret;
	bcc_ptr += 2;  /* account for null terminator */

	*pbcc_area = bcc_ptr;
}


S
Steve French 已提交
207
static void unicode_ssetup_strings(char **pbcc_area, struct cifsSesInfo *ses,
S
Steve French 已提交
208
				   const struct nls_table *nls_cp)
209
{
S
Steve French 已提交
210
	char *bcc_ptr = *pbcc_area;
211 212 213 214 215
	int bytes_ret = 0;

	/* BB FIXME add check that strings total less
	than 335 or will need to send them as arrays */

216 217
	/* unicode strings, must be word aligned before the call */
/*	if ((long) bcc_ptr % 2)	{
218 219
		*bcc_ptr = 0;
		bcc_ptr++;
220
	} */
221
	/* copy user */
S
Steve French 已提交
222
	if (ses->userName == NULL) {
223 224 225
		/* null user mount */
		*bcc_ptr = 0;
		*(bcc_ptr+1) = 0;
226 227 228 229 230 231 232
	} else { /* 300 should be long enough for any conceivable user name */
		bytes_ret = cifs_strtoUCS((__le16 *) bcc_ptr, ses->userName,
					  300, nls_cp);
	}
	bcc_ptr += 2 * bytes_ret;
	bcc_ptr += 2; /* account for null termination */

233 234
	unicode_domain_string(&bcc_ptr, ses, nls_cp);
	unicode_oslm_strings(&bcc_ptr, nls_cp);
235 236 237 238

	*pbcc_area = bcc_ptr;
}

S
Steve French 已提交
239
static void ascii_ssetup_strings(char **pbcc_area, struct cifsSesInfo *ses,
S
Steve French 已提交
240
				 const struct nls_table *nls_cp)
241
{
S
Steve French 已提交
242
	char *bcc_ptr = *pbcc_area;
243 244 245

	/* copy user */
	/* BB what about null user mounts - check that we do this BB */
S
Steve French 已提交
246 247 248 249 250 251
	/* copy user */
	if (ses->userName == NULL) {
		/* BB what about null user mounts - check that we do this BB */
	} else { /* 300 should be long enough for any conceivable user name */
		strncpy(bcc_ptr, ses->userName, 300);
	}
252
	/* BB improve check for overflow */
S
Steve French 已提交
253
	bcc_ptr += strnlen(ses->userName, 300);
254
	*bcc_ptr = 0;
S
Steve French 已提交
255
	bcc_ptr++; /* account for null termination */
256

S
Steve French 已提交
257 258 259 260
	/* copy domain */

	if (ses->domainName != NULL) {
		strncpy(bcc_ptr, ses->domainName, 256);
261
		bcc_ptr += strnlen(ses->domainName, 256);
S
Steve French 已提交
262
	} /* else we will send a null domain name
263
	     so the server will default to its own domain */
264 265 266 267 268 269 270
	*bcc_ptr = 0;
	bcc_ptr++;

	/* BB check for overflow here */

	strcpy(bcc_ptr, "Linux version ");
	bcc_ptr += strlen("Linux version ");
271 272
	strcpy(bcc_ptr, init_utsname()->release);
	bcc_ptr += strlen(init_utsname()->release) + 1;
273 274 275 276

	strcpy(bcc_ptr, CIFS_NETWORK_OPSYS);
	bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1;

S
Steve French 已提交
277
	*pbcc_area = bcc_ptr;
278 279
}

S
Steve French 已提交
280 281 282
static int decode_unicode_ssetup(char **pbcc_area, int bleft,
				 struct cifsSesInfo *ses,
				 const struct nls_table *nls_cp)
283 284 285
{
	int rc = 0;
	int words_left, len;
S
Steve French 已提交
286
	char *data = *pbcc_area;
287 288 289



S
Steve French 已提交
290
	cFYI(1, ("bleft %d", bleft));
291 292


293 294 295 296 297 298 299
	/* SMB header is unaligned, so cifs servers word align start of
	   Unicode strings */
	data++;
	bleft--; /* Windows servers do not always double null terminate
		    their final Unicode string - in which case we
		    now will not attempt to decode the byte of junk
		    which follows it */
300

301 302 303 304 305 306 307 308
	words_left = bleft / 2;

	/* save off server operating system */
	len = UniStrnlen((wchar_t *) data, words_left);

/* We look for obvious messed up bcc or strings in response so we do not go off
   the end since (at least) WIN2K and Windows XP have a major bug in not null
   terminating last Unicode string in response  */
S
Steve French 已提交
309
	if (len >= words_left)
310 311
		return rc;

312
	kfree(ses->serverOS);
313
	/* UTF-8 string will not grow more than four times as big as UCS-16 */
314
	ses->serverOS = kzalloc((4 * len) + 2 /* trailing null */, GFP_KERNEL);
315 316
	if (ses->serverOS != NULL)
		cifs_strfromUCS_le(ses->serverOS, (__le16 *)data, len, nls_cp);
317 318 319 320 321 322
	data += 2 * (len + 1);
	words_left -= len + 1;

	/* save off server network operating system */
	len = UniStrnlen((wchar_t *) data, words_left);

S
Steve French 已提交
323
	if (len >= words_left)
324 325
		return rc;

326
	kfree(ses->serverNOS);
327
	ses->serverNOS = kzalloc((4 * len) + 2 /* trailing null */, GFP_KERNEL);
S
Steve French 已提交
328
	if (ses->serverNOS != NULL) {
329 330
		cifs_strfromUCS_le(ses->serverNOS, (__le16 *)data, len,
				   nls_cp);
S
Steve French 已提交
331 332
		if (strncmp(ses->serverNOS, "NT LAN Manager 4", 16) == 0) {
			cFYI(1, ("NT4 server"));
333 334 335 336 337 338
			ses->flags |= CIFS_SES_NT4;
		}
	}
	data += 2 * (len + 1);
	words_left -= len + 1;

S
Steve French 已提交
339 340 341 342 343 344
	/* save off server domain */
	len = UniStrnlen((wchar_t *) data, words_left);

	if (len > words_left)
		return rc;

345
	kfree(ses->serverDomain);
S
Steve French 已提交
346 347 348 349 350 351 352 353 354 355 356
	ses->serverDomain = kzalloc(2 * (len + 1), GFP_KERNEL); /* BB FIXME wrong length */
	if (ses->serverDomain != NULL) {
		cifs_strfromUCS_le(ses->serverDomain, (__le16 *)data, len,
				   nls_cp);
		ses->serverDomain[2*len] = 0;
		ses->serverDomain[(2*len) + 1] = 0;
	}
	data += 2 * (len + 1);
	words_left -= len + 1;

	cFYI(1, ("words left: %d", words_left));
357 358 359 360

	return rc;
}

S
Steve French 已提交
361 362 363
static int decode_ascii_ssetup(char **pbcc_area, int bleft,
			       struct cifsSesInfo *ses,
			       const struct nls_table *nls_cp)
364 365 366
{
	int rc = 0;
	int len;
S
Steve French 已提交
367
	char *bcc_ptr = *pbcc_area;
368

S
Steve French 已提交
369
	cFYI(1, ("decode sessetup ascii. bleft %d", bleft));
370

371
	len = strnlen(bcc_ptr, bleft);
S
Steve French 已提交
372
	if (len >= bleft)
373
		return rc;
374

375
	kfree(ses->serverOS);
376 377

	ses->serverOS = kzalloc(len + 1, GFP_KERNEL);
S
Steve French 已提交
378
	if (ses->serverOS)
379
		strncpy(ses->serverOS, bcc_ptr, len);
S
Steve French 已提交
380 381
	if (strncmp(ses->serverOS, "OS/2", 4) == 0) {
			cFYI(1, ("OS/2 server"));
382 383
			ses->flags |= CIFS_SES_OS2;
	}
384 385 386 387 388

	bcc_ptr += len + 1;
	bleft -= len + 1;

	len = strnlen(bcc_ptr, bleft);
S
Steve French 已提交
389
	if (len >= bleft)
390 391
		return rc;

392
	kfree(ses->serverNOS);
393 394

	ses->serverNOS = kzalloc(len + 1, GFP_KERNEL);
S
Steve French 已提交
395
	if (ses->serverNOS)
396 397 398 399 400
		strncpy(ses->serverNOS, bcc_ptr, len);

	bcc_ptr += len + 1;
	bleft -= len + 1;

S
Steve French 已提交
401 402 403
	len = strnlen(bcc_ptr, bleft);
	if (len > bleft)
		return rc;
404

405 406 407 408 409
	/* No domain field in LANMAN case. Domain is
	   returned by old servers in the SMB negprot response */
	/* BB For newer servers which do not support Unicode,
	   but thus do return domain here we could add parsing
	   for it later, but it is not very important */
S
Steve French 已提交
410
	cFYI(1, ("ascii: bytes left %d", bleft));
411 412 413 414

	return rc;
}

S
Steve French 已提交
415
int
416 417 418 419 420 421 422
CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, int first_time,
		const struct nls_table *nls_cp)
{
	int rc = 0;
	int wct;
	struct smb_hdr *smb_buf;
	char *bcc_ptr;
423
	char *str_area;
424 425 426
	SESSION_SETUP_ANDX *pSMB;
	__u32 capabilities;
	int count;
427 428
	int resp_buf_type;
	struct kvec iov[3];
429 430 431
	enum securityEnum type;
	__u16 action;
	int bytes_remaining;
432
	struct key *spnego_key = NULL;
433

S
Steve French 已提交
434
	if (ses == NULL)
435 436 437
		return -EINVAL;

	type = ses->server->secType;
438

S
Steve French 已提交
439 440
	cFYI(1, ("sess setup type %d", type));
	if (type == LANMAN) {
441 442 443 444 445 446 447 448 449
#ifndef CONFIG_CIFS_WEAK_PW_HASH
		/* LANMAN and plaintext are less secure and off by default.
		So we make this explicitly be turned on in kconfig (in the
		build) and turned on at runtime (changed from the default)
		in proc/fs/cifs or via mount parm.  Unfortunately this is
		needed for old Win (e.g. Win95), some obscure NAS and OS/2 */
		return -EOPNOTSUPP;
#endif
		wct = 10; /* lanman 2 style sessionsetup */
S
Steve French 已提交
450
	} else if ((type == NTLM) || (type == NTLMv2)) {
451
		/* For NTLMv2 failures eventually may need to retry NTLM */
452
		wct = 13; /* old style NTLM sessionsetup */
S
Steve French 已提交
453
	} else /* same size: negotiate or auth, NTLMSSP or extended security */
454 455 456 457
		wct = 12;

	rc = small_smb_init_no_tc(SMB_COM_SESSION_SETUP_ANDX, wct, ses,
			    (void **)&smb_buf);
S
Steve French 已提交
458
	if (rc)
459 460 461 462 463
		return rc;

	pSMB = (SESSION_SETUP_ANDX *)smb_buf;

	capabilities = cifs_ssetup_hdr(ses, pSMB);
464

465 466 467 468 469 470
	/* we will send the SMB in three pieces:
	a fixed length beginning part, an optional
	SPNEGO blob (which can be zero length), and a
	last part which will include the strings
	and rest of bcc area. This allows us to avoid
	a large buffer 17K allocation */
S
Steve French 已提交
471 472
	iov[0].iov_base = (char *)pSMB;
	iov[0].iov_len = smb_buf->smb_buf_length + 4;
473

474 475 476 477
	/* setting this here allows the code at the end of the function
	   to free the request buffer if there's an error */
	resp_buf_type = CIFS_SMALL_BUFFER;

478 479
	/* 2000 big enough to fit max user, domain, NOS name etc. */
	str_area = kmalloc(2000, GFP_KERNEL);
480
	if (str_area == NULL) {
481 482
		rc = -ENOMEM;
		goto ssetup_exit;
483
	}
484
	bcc_ptr = str_area;
485

486 487
	ses->flags &= ~CIFS_SES_LANMAN;

488 489 490
	iov[1].iov_base = NULL;
	iov[1].iov_len = 0;

S
Steve French 已提交
491
	if (type == LANMAN) {
492
#ifdef CONFIG_CIFS_WEAK_PW_HASH
493
		char lnm_session_key[CIFS_SESS_KEY_SIZE];
494

495 496
		pSMB->req.hdr.Flags2 &= ~SMBFLG2_UNICODE;

497 498
		/* no capabilities flags in old lanman negotiation */

S
Steve French 已提交
499
		pSMB->old_req.PasswordLength = cpu_to_le16(CIFS_SESS_KEY_SIZE);
500 501 502
		/* BB calculate hash with password */
		/* and copy into bcc */

503 504 505 506
		calc_lanman_hash(ses->password, ses->server->cryptKey,
				 ses->server->secMode & SECMODE_PW_ENCRYPT ?
					true : false, lnm_session_key);

S
Steve French 已提交
507
		ses->flags |= CIFS_SES_LANMAN;
508 509
		memcpy(bcc_ptr, (char *)lnm_session_key, CIFS_SESS_KEY_SIZE);
		bcc_ptr += CIFS_SESS_KEY_SIZE;
510 511 512 513 514 515

		/* can not sign if LANMAN negotiated so no need
		to calculate signing key? but what if server
		changed to do higher than lanman dialect and
		we reconnected would we ever calc signing_key? */

S
Steve French 已提交
516
		cFYI(1, ("Negotiating LANMAN setting up strings"));
517 518
		/* Unicode not allowed for LANMAN dialects */
		ascii_ssetup_strings(&bcc_ptr, ses, nls_cp);
S
Steve French 已提交
519
#endif
520
	} else if (type == NTLM) {
521
		char ntlm_session_key[CIFS_SESS_KEY_SIZE];
522 523 524

		pSMB->req_no_secext.Capabilities = cpu_to_le32(capabilities);
		pSMB->req_no_secext.CaseInsensitivePasswordLength =
525
			cpu_to_le16(CIFS_SESS_KEY_SIZE);
526
		pSMB->req_no_secext.CaseSensitivePasswordLength =
527
			cpu_to_le16(CIFS_SESS_KEY_SIZE);
528

529 530 531 532
		/* calculate session key */
		SMBNTencrypt(ses->password, ses->server->cryptKey,
			     ntlm_session_key);

S
Steve French 已提交
533
		if (first_time) /* should this be moved into common code
534
				  with similar ntlmv2 path? */
535
			cifs_calculate_mac_key(&ses->server->mac_signing_key,
536 537 538
				ntlm_session_key, ses->password);
		/* copy session key */

S
Steve French 已提交
539
		memcpy(bcc_ptr, (char *)ntlm_session_key, CIFS_SESS_KEY_SIZE);
540
		bcc_ptr += CIFS_SESS_KEY_SIZE;
S
Steve French 已提交
541
		memcpy(bcc_ptr, (char *)ntlm_session_key, CIFS_SESS_KEY_SIZE);
542
		bcc_ptr += CIFS_SESS_KEY_SIZE;
S
Steve French 已提交
543
		if (ses->capabilities & CAP_UNICODE) {
544 545 546
			/* unicode strings must be word aligned */
			if (iov[0].iov_len % 2) {
				*bcc_ptr = 0;
S
Steve French 已提交
547 548
				bcc_ptr++;
			}
549
			unicode_ssetup_strings(&bcc_ptr, ses, nls_cp);
550
		} else
551 552
			ascii_ssetup_strings(&bcc_ptr, ses, nls_cp);
	} else if (type == NTLMv2) {
S
Steve French 已提交
553
		char *v2_sess_key =
S
Steve French 已提交
554
			kmalloc(sizeof(struct ntlmv2_resp), GFP_KERNEL);
S
Steve French 已提交
555 556 557

		/* BB FIXME change all users of v2_sess_key to
		   struct ntlmv2_resp */
558

S
Steve French 已提交
559
		if (v2_sess_key == NULL) {
560 561
			rc = -ENOMEM;
			goto ssetup_exit;
562 563 564 565 566 567 568 569 570
		}

		pSMB->req_no_secext.Capabilities = cpu_to_le32(capabilities);

		/* LM2 password would be here if we supported it */
		pSMB->req_no_secext.CaseInsensitivePasswordLength = 0;
		/*	cpu_to_le16(LM2_SESS_KEY_SIZE); */

		pSMB->req_no_secext.CaseSensitivePasswordLength =
S
Steve French 已提交
571
			cpu_to_le16(sizeof(struct ntlmv2_resp));
572 573

		/* calculate session key */
S
Steve French 已提交
574
		setup_ntlmv2_rsp(ses, v2_sess_key, nls_cp);
S
Steve French 已提交
575 576
		if (first_time) /* should this be moved into common code
				   with similar ntlmv2 path? */
577 578 579 580 581 582 583
		/*   cifs_calculate_ntlmv2_mac_key(ses->server->mac_signing_key,
				response BB FIXME, v2_sess_key); */

		/* copy session key */

	/*	memcpy(bcc_ptr, (char *)ntlm_session_key,LM2_SESS_KEY_SIZE);
		bcc_ptr += LM2_SESS_KEY_SIZE; */
S
Steve French 已提交
584 585
		memcpy(bcc_ptr, (char *)v2_sess_key,
		       sizeof(struct ntlmv2_resp));
S
Steve French 已提交
586 587
		bcc_ptr += sizeof(struct ntlmv2_resp);
		kfree(v2_sess_key);
S
Steve French 已提交
588 589
		if (ses->capabilities & CAP_UNICODE) {
			if (iov[0].iov_len % 2) {
590
				*bcc_ptr = 0;
591 592
				bcc_ptr++;
			}
593
			unicode_ssetup_strings(&bcc_ptr, ses, nls_cp);
594
		} else
595
			ascii_ssetup_strings(&bcc_ptr, ses, nls_cp);
596
	} else if (type == Kerberos || type == MSKerberos) {
597 598 599 600 601 602 603 604 605 606
#ifdef CONFIG_CIFS_UPCALL
		struct cifs_spnego_msg *msg;
		spnego_key = cifs_get_spnego_key(ses);
		if (IS_ERR(spnego_key)) {
			rc = PTR_ERR(spnego_key);
			spnego_key = NULL;
			goto ssetup_exit;
		}

		msg = spnego_key->payload.data;
607 608 609 610 611 612 613 614 615
		/* check version field to make sure that cifs.upcall is
		   sending us a response in an expected form */
		if (msg->version != CIFS_SPNEGO_UPCALL_VERSION) {
			cERROR(1, ("incorrect version of cifs.upcall (expected"
				   " %d but got %d)",
				   CIFS_SPNEGO_UPCALL_VERSION, msg->version));
			rc = -EKEYREJECTED;
			goto ssetup_exit;
		}
616 617 618 619 620 621 622 623
		/* bail out if key is too long */
		if (msg->sesskey_len >
		    sizeof(ses->server->mac_signing_key.data.krb5)) {
			cERROR(1, ("Kerberos signing key too long (%u bytes)",
				msg->sesskey_len));
			rc = -EOVERFLOW;
			goto ssetup_exit;
		}
624 625 626 627 628
		if (first_time) {
			ses->server->mac_signing_key.len = msg->sesskey_len;
			memcpy(ses->server->mac_signing_key.data.krb5,
				msg->data, msg->sesskey_len);
		}
629 630 631
		pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC;
		capabilities |= CAP_EXTENDED_SECURITY;
		pSMB->req.Capabilities = cpu_to_le32(capabilities);
632 633 634 635 636 637
		iov[1].iov_base = msg->data + msg->sesskey_len;
		iov[1].iov_len = msg->secblob_len;
		pSMB->req.SecurityBlobLength = cpu_to_le16(iov[1].iov_len);

		if (ses->capabilities & CAP_UNICODE) {
			/* unicode strings must be word aligned */
638
			if ((iov[0].iov_len + iov[1].iov_len) % 2) {
639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655
				*bcc_ptr = 0;
				bcc_ptr++;
			}
			unicode_oslm_strings(&bcc_ptr, nls_cp);
			unicode_domain_string(&bcc_ptr, ses, nls_cp);
		} else
		/* BB: is this right? */
			ascii_ssetup_strings(&bcc_ptr, ses, nls_cp);
#else /* ! CONFIG_CIFS_UPCALL */
		cERROR(1, ("Kerberos negotiated but upcall support disabled!"));
		rc = -ENOSYS;
		goto ssetup_exit;
#endif /* CONFIG_CIFS_UPCALL */
	} else {
		cERROR(1, ("secType %d not supported!", type));
		rc = -ENOSYS;
		goto ssetup_exit;
656 657
	}

658 659 660 661
	iov[2].iov_base = str_area;
	iov[2].iov_len = (long) bcc_ptr - (long) str_area;

	count = iov[1].iov_len + iov[2].iov_len;
662 663 664 665
	smb_buf->smb_buf_length += count;

	BCC_LE(smb_buf) = cpu_to_le16(count);

666
	rc = SendReceive2(xid, ses, iov, 3 /* num_iovecs */, &resp_buf_type,
667
			  CIFS_STD_OP /* not long */ | CIFS_LOG_ERROR);
668 669
	/* SMB request buf freed in SendReceive2 */

S
Steve French 已提交
670 671
	cFYI(1, ("ssetup rc from sendrecv2 is %d", rc));
	if (rc)
672 673 674 675 676
		goto ssetup_exit;

	pSMB = (SESSION_SETUP_ANDX *)iov[0].iov_base;
	smb_buf = (struct smb_hdr *)iov[0].iov_base;

S
Steve French 已提交
677
	if ((smb_buf->WordCount != 3) && (smb_buf->WordCount != 4)) {
678
		rc = -EIO;
S
Steve French 已提交
679
		cERROR(1, ("bad word count %d", smb_buf->WordCount));
680 681 682 683
		goto ssetup_exit;
	}
	action = le16_to_cpu(pSMB->resp.Action);
	if (action & GUEST_LOGIN)
684
		cFYI(1, ("Guest login")); /* BB mark SesInfo struct? */
685 686 687 688 689 690 691
	ses->Suid = smb_buf->Uid;   /* UID left in wire format (le) */
	cFYI(1, ("UID = %d ", ses->Suid));
	/* response can have either 3 or 4 word count - Samba sends 3 */
	/* and lanman response is 3 */
	bytes_remaining = BCC(smb_buf);
	bcc_ptr = pByteArea(smb_buf);

S
Steve French 已提交
692
	if (smb_buf->WordCount == 4) {
693 694 695
		__u16 blob_len;
		blob_len = le16_to_cpu(pSMB->resp.SecurityBlobLength);
		bcc_ptr += blob_len;
S
Steve French 已提交
696 697
		if (blob_len > bytes_remaining) {
			cERROR(1, ("bad security blob length %d", blob_len));
698 699 700 701
			rc = -EINVAL;
			goto ssetup_exit;
		}
		bytes_remaining -= blob_len;
S
Steve French 已提交
702
	}
703 704

	/* BB check if Unicode and decode strings */
S
Steve French 已提交
705
	if (smb_buf->Flags2 & SMBFLG2_UNICODE)
706 707 708
		rc = decode_unicode_ssetup(&bcc_ptr, bytes_remaining,
						   ses, nls_cp);
	else
709 710
		rc = decode_ascii_ssetup(&bcc_ptr, bytes_remaining,
					 ses, nls_cp);
711

712
ssetup_exit:
713 714
	if (spnego_key) {
		key_revoke(spnego_key);
715
		key_put(spnego_key);
716
	}
717
	kfree(str_area);
S
Steve French 已提交
718 719
	if (resp_buf_type == CIFS_SMALL_BUFFER) {
		cFYI(1, ("ssetup freeing small buf %p", iov[0].iov_base));
720
		cifs_small_buf_release(iov[0].iov_base);
S
Steve French 已提交
721
	} else if (resp_buf_type == CIFS_LARGE_BUFFER)
722 723 724 725
		cifs_buf_release(iov[0].iov_base);

	return rc;
}