1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24#include "cifspdu.h"
25#include "cifsglob.h"
26#include "cifsproto.h"
27#include "cifs_unicode.h"
28#include "cifs_debug.h"
29#include "ntlmssp.h"
30#include "nterr.h"
31#include <linux/utsname.h>
32#include <linux/slab.h>
33#include "cifs_spnego.h"
34
35
36
37
38
39
40static bool is_first_ses_reconnect(struct cifs_ses *ses)
41{
42 struct list_head *tmp;
43 struct cifs_ses *tmp_ses;
44
45 list_for_each(tmp, &ses->server->smb_ses_list) {
46 tmp_ses = list_entry(tmp, struct cifs_ses,
47 smb_ses_list);
48 if (tmp_ses->need_reconnect == false)
49 return false;
50 }
51
52
53 return true;
54}
55
56
57
58
59
60
61
62
63
64static __le16 get_next_vcnum(struct cifs_ses *ses)
65{
66 __u16 vcnum = 0;
67 struct list_head *tmp;
68 struct cifs_ses *tmp_ses;
69 __u16 max_vcs = ses->server->max_vcs;
70 __u16 i;
71 int free_vc_found = 0;
72
73
74
75
76
77 if (max_vcs < 2)
78 max_vcs = 0xFFFF;
79
80 spin_lock(&cifs_tcp_ses_lock);
81 if ((ses->need_reconnect) && is_first_ses_reconnect(ses))
82 goto get_vc_num_exit;
83 for (i = ses->server->srv_count - 1; i < max_vcs; i++) {
84 if (i == 0)
85 break;
86
87 free_vc_found = 1;
88
89 list_for_each(tmp, &ses->server->smb_ses_list) {
90 tmp_ses = list_entry(tmp, struct cifs_ses,
91 smb_ses_list);
92 if (tmp_ses->vcnum == i) {
93 free_vc_found = 0;
94 break;
95 }
96 }
97 if (free_vc_found)
98 break;
99 }
100
101 if (i == 0)
102 vcnum = 0;
103
104
105 else if (free_vc_found == 0)
106 vcnum = 1;
107
108 else
109 vcnum = i;
110 ses->vcnum = vcnum;
111get_vc_num_exit:
112 spin_unlock(&cifs_tcp_ses_lock);
113
114 return cpu_to_le16(vcnum);
115}
116
117static __u32 cifs_ssetup_hdr(struct cifs_ses *ses, SESSION_SETUP_ANDX *pSMB)
118{
119 __u32 capabilities = 0;
120
121
122
123
124
125
126 pSMB->req.AndXCommand = 0xFF;
127 pSMB->req.MaxBufferSize = cpu_to_le16(min_t(u32,
128 CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4,
129 USHRT_MAX));
130 pSMB->req.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
131 pSMB->req.VcNumber = get_next_vcnum(ses);
132
133
134
135
136
137
138 capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
139 CAP_LARGE_WRITE_X | CAP_LARGE_READ_X;
140
141 if (ses->server->sec_mode &
142 (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
143 pSMB->req.hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
144
145 if (ses->capabilities & CAP_UNICODE) {
146 pSMB->req.hdr.Flags2 |= SMBFLG2_UNICODE;
147 capabilities |= CAP_UNICODE;
148 }
149 if (ses->capabilities & CAP_STATUS32) {
150 pSMB->req.hdr.Flags2 |= SMBFLG2_ERR_STATUS;
151 capabilities |= CAP_STATUS32;
152 }
153 if (ses->capabilities & CAP_DFS) {
154 pSMB->req.hdr.Flags2 |= SMBFLG2_DFS;
155 capabilities |= CAP_DFS;
156 }
157 if (ses->capabilities & CAP_UNIX)
158 capabilities |= CAP_UNIX;
159
160 return capabilities;
161}
162
163static void
164unicode_oslm_strings(char **pbcc_area, const struct nls_table *nls_cp)
165{
166 char *bcc_ptr = *pbcc_area;
167 int bytes_ret = 0;
168
169
170 bytes_ret = cifs_strtoUTF16((__le16 *)bcc_ptr, "Linux version ", 32,
171 nls_cp);
172 bcc_ptr += 2 * bytes_ret;
173 bytes_ret = cifs_strtoUTF16((__le16 *) bcc_ptr, init_utsname()->release,
174 32, nls_cp);
175 bcc_ptr += 2 * bytes_ret;
176 bcc_ptr += 2;
177
178 bytes_ret = cifs_strtoUTF16((__le16 *) bcc_ptr, CIFS_NETWORK_OPSYS,
179 32, nls_cp);
180 bcc_ptr += 2 * bytes_ret;
181 bcc_ptr += 2;
182
183 *pbcc_area = bcc_ptr;
184}
185
186static void unicode_domain_string(char **pbcc_area, struct cifs_ses *ses,
187 const struct nls_table *nls_cp)
188{
189 char *bcc_ptr = *pbcc_area;
190 int bytes_ret = 0;
191
192
193 if (ses->domainName == NULL) {
194
195
196 *bcc_ptr = 0;
197 *(bcc_ptr+1) = 0;
198 bytes_ret = 0;
199 } else
200 bytes_ret = cifs_strtoUTF16((__le16 *) bcc_ptr, ses->domainName,
201 256, nls_cp);
202 bcc_ptr += 2 * bytes_ret;
203 bcc_ptr += 2;
204
205 *pbcc_area = bcc_ptr;
206}
207
208
209static void unicode_ssetup_strings(char **pbcc_area, struct cifs_ses *ses,
210 const struct nls_table *nls_cp)
211{
212 char *bcc_ptr = *pbcc_area;
213 int bytes_ret = 0;
214
215
216
217
218
219
220
221
222
223
224 if (ses->user_name == NULL) {
225
226 *bcc_ptr = 0;
227 *(bcc_ptr+1) = 0;
228 } else {
229 bytes_ret = cifs_strtoUTF16((__le16 *) bcc_ptr, ses->user_name,
230 MAX_USERNAME_SIZE, nls_cp);
231 }
232 bcc_ptr += 2 * bytes_ret;
233 bcc_ptr += 2;
234
235 unicode_domain_string(&bcc_ptr, ses, nls_cp);
236 unicode_oslm_strings(&bcc_ptr, nls_cp);
237
238 *pbcc_area = bcc_ptr;
239}
240
241static void ascii_ssetup_strings(char **pbcc_area, struct cifs_ses *ses,
242 const struct nls_table *nls_cp)
243{
244 char *bcc_ptr = *pbcc_area;
245
246
247
248
249 if (ses->user_name != NULL) {
250 strncpy(bcc_ptr, ses->user_name, MAX_USERNAME_SIZE);
251 bcc_ptr += strnlen(ses->user_name, MAX_USERNAME_SIZE);
252 }
253
254 *bcc_ptr = 0;
255 bcc_ptr++;
256
257
258 if (ses->domainName != NULL) {
259 strncpy(bcc_ptr, ses->domainName, 256);
260 bcc_ptr += strnlen(ses->domainName, 256);
261 }
262
263 *bcc_ptr = 0;
264 bcc_ptr++;
265
266
267
268 strcpy(bcc_ptr, "Linux version ");
269 bcc_ptr += strlen("Linux version ");
270 strcpy(bcc_ptr, init_utsname()->release);
271 bcc_ptr += strlen(init_utsname()->release) + 1;
272
273 strcpy(bcc_ptr, CIFS_NETWORK_OPSYS);
274 bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1;
275
276 *pbcc_area = bcc_ptr;
277}
278
279static void
280decode_unicode_ssetup(char **pbcc_area, int bleft, struct cifs_ses *ses,
281 const struct nls_table *nls_cp)
282{
283 int len;
284 char *data = *pbcc_area;
285
286 cFYI(1, "bleft %d", bleft);
287
288 kfree(ses->serverOS);
289 ses->serverOS = cifs_strndup_from_utf16(data, bleft, true, nls_cp);
290 cFYI(1, "serverOS=%s", ses->serverOS);
291 len = (UniStrnlen((wchar_t *) data, bleft / 2) * 2) + 2;
292 data += len;
293 bleft -= len;
294 if (bleft <= 0)
295 return;
296
297 kfree(ses->serverNOS);
298 ses->serverNOS = cifs_strndup_from_utf16(data, bleft, true, nls_cp);
299 cFYI(1, "serverNOS=%s", ses->serverNOS);
300 len = (UniStrnlen((wchar_t *) data, bleft / 2) * 2) + 2;
301 data += len;
302 bleft -= len;
303 if (bleft <= 0)
304 return;
305
306 kfree(ses->serverDomain);
307 ses->serverDomain = cifs_strndup_from_utf16(data, bleft, true, nls_cp);
308 cFYI(1, "serverDomain=%s", ses->serverDomain);
309
310 return;
311}
312
313static int decode_ascii_ssetup(char **pbcc_area, __u16 bleft,
314 struct cifs_ses *ses,
315 const struct nls_table *nls_cp)
316{
317 int rc = 0;
318 int len;
319 char *bcc_ptr = *pbcc_area;
320
321 cFYI(1, "decode sessetup ascii. bleft %d", bleft);
322
323 len = strnlen(bcc_ptr, bleft);
324 if (len >= bleft)
325 return rc;
326
327 kfree(ses->serverOS);
328
329 ses->serverOS = kzalloc(len + 1, GFP_KERNEL);
330 if (ses->serverOS)
331 strncpy(ses->serverOS, bcc_ptr, len);
332 if (strncmp(ses->serverOS, "OS/2", 4) == 0) {
333 cFYI(1, "OS/2 server");
334 ses->flags |= CIFS_SES_OS2;
335 }
336
337 bcc_ptr += len + 1;
338 bleft -= len + 1;
339
340 len = strnlen(bcc_ptr, bleft);
341 if (len >= bleft)
342 return rc;
343
344 kfree(ses->serverNOS);
345
346 ses->serverNOS = kzalloc(len + 1, GFP_KERNEL);
347 if (ses->serverNOS)
348 strncpy(ses->serverNOS, bcc_ptr, len);
349
350 bcc_ptr += len + 1;
351 bleft -= len + 1;
352
353 len = strnlen(bcc_ptr, bleft);
354 if (len > bleft)
355 return rc;
356
357
358
359
360
361
362 cFYI(1, "ascii: bytes left %d", bleft);
363
364 return rc;
365}
366
367static int decode_ntlmssp_challenge(char *bcc_ptr, int blob_len,
368 struct cifs_ses *ses)
369{
370 unsigned int tioffset;
371 unsigned int tilen;
372
373 CHALLENGE_MESSAGE *pblob = (CHALLENGE_MESSAGE *)bcc_ptr;
374
375 if (blob_len < sizeof(CHALLENGE_MESSAGE)) {
376 cERROR(1, "challenge blob len %d too small", blob_len);
377 return -EINVAL;
378 }
379
380 if (memcmp(pblob->Signature, "NTLMSSP", 8)) {
381 cERROR(1, "blob signature incorrect %s", pblob->Signature);
382 return -EINVAL;
383 }
384 if (pblob->MessageType != NtLmChallenge) {
385 cERROR(1, "Incorrect message type %d", pblob->MessageType);
386 return -EINVAL;
387 }
388
389 memcpy(ses->ntlmssp->cryptkey, pblob->Challenge, CIFS_CRYPTO_KEY_SIZE);
390
391
392
393
394 ses->ntlmssp->server_flags = le32_to_cpu(pblob->NegotiateFlags);
395 tioffset = le32_to_cpu(pblob->TargetInfoArray.BufferOffset);
396 tilen = le16_to_cpu(pblob->TargetInfoArray.Length);
397 if (tioffset > blob_len || tioffset + tilen > blob_len) {
398 cERROR(1, "tioffset + tilen too high %u + %u", tioffset, tilen);
399 return -EINVAL;
400 }
401 if (tilen) {
402 ses->auth_key.response = kmalloc(tilen, GFP_KERNEL);
403 if (!ses->auth_key.response) {
404 cERROR(1, "Challenge target info allocation failure");
405 return -ENOMEM;
406 }
407 memcpy(ses->auth_key.response, bcc_ptr + tioffset, tilen);
408 ses->auth_key.len = tilen;
409 }
410
411 return 0;
412}
413
414
415
416
417
418static void build_ntlmssp_negotiate_blob(unsigned char *pbuffer,
419 struct cifs_ses *ses)
420{
421 NEGOTIATE_MESSAGE *sec_blob = (NEGOTIATE_MESSAGE *)pbuffer;
422 __u32 flags;
423
424 memset(pbuffer, 0, sizeof(NEGOTIATE_MESSAGE));
425 memcpy(sec_blob->Signature, NTLMSSP_SIGNATURE, 8);
426 sec_blob->MessageType = NtLmNegotiate;
427
428
429 flags = NTLMSSP_NEGOTIATE_56 | NTLMSSP_REQUEST_TARGET |
430 NTLMSSP_NEGOTIATE_128 | NTLMSSP_NEGOTIATE_UNICODE |
431 NTLMSSP_NEGOTIATE_NTLM | NTLMSSP_NEGOTIATE_EXTENDED_SEC;
432 if (ses->server->sec_mode &
433 (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) {
434 flags |= NTLMSSP_NEGOTIATE_SIGN;
435 if (!ses->server->session_estab)
436 flags |= NTLMSSP_NEGOTIATE_KEY_XCH;
437 }
438
439 sec_blob->NegotiateFlags = cpu_to_le32(flags);
440
441 sec_blob->WorkstationName.BufferOffset = 0;
442 sec_blob->WorkstationName.Length = 0;
443 sec_blob->WorkstationName.MaximumLength = 0;
444
445
446 sec_blob->DomainName.BufferOffset = 0;
447 sec_blob->DomainName.Length = 0;
448 sec_blob->DomainName.MaximumLength = 0;
449}
450
451
452
453
454static int build_ntlmssp_auth_blob(unsigned char *pbuffer,
455 u16 *buflen,
456 struct cifs_ses *ses,
457 const struct nls_table *nls_cp)
458{
459 int rc;
460 AUTHENTICATE_MESSAGE *sec_blob = (AUTHENTICATE_MESSAGE *)pbuffer;
461 __u32 flags;
462 unsigned char *tmp;
463
464 memcpy(sec_blob->Signature, NTLMSSP_SIGNATURE, 8);
465 sec_blob->MessageType = NtLmAuthenticate;
466
467 flags = NTLMSSP_NEGOTIATE_56 |
468 NTLMSSP_REQUEST_TARGET | NTLMSSP_NEGOTIATE_TARGET_INFO |
469 NTLMSSP_NEGOTIATE_128 | NTLMSSP_NEGOTIATE_UNICODE |
470 NTLMSSP_NEGOTIATE_NTLM | NTLMSSP_NEGOTIATE_EXTENDED_SEC;
471 if (ses->server->sec_mode &
472 (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) {
473 flags |= NTLMSSP_NEGOTIATE_SIGN;
474 if (!ses->server->session_estab)
475 flags |= NTLMSSP_NEGOTIATE_KEY_XCH;
476 }
477
478 tmp = pbuffer + sizeof(AUTHENTICATE_MESSAGE);
479 sec_blob->NegotiateFlags = cpu_to_le32(flags);
480
481 sec_blob->LmChallengeResponse.BufferOffset =
482 cpu_to_le32(sizeof(AUTHENTICATE_MESSAGE));
483 sec_blob->LmChallengeResponse.Length = 0;
484 sec_blob->LmChallengeResponse.MaximumLength = 0;
485
486 sec_blob->NtChallengeResponse.BufferOffset = cpu_to_le32(tmp - pbuffer);
487 rc = setup_ntlmv2_rsp(ses, nls_cp);
488 if (rc) {
489 cERROR(1, "Error %d during NTLMSSP authentication", rc);
490 goto setup_ntlmv2_ret;
491 }
492 memcpy(tmp, ses->auth_key.response + CIFS_SESS_KEY_SIZE,
493 ses->auth_key.len - CIFS_SESS_KEY_SIZE);
494 tmp += ses->auth_key.len - CIFS_SESS_KEY_SIZE;
495
496 sec_blob->NtChallengeResponse.Length =
497 cpu_to_le16(ses->auth_key.len - CIFS_SESS_KEY_SIZE);
498 sec_blob->NtChallengeResponse.MaximumLength =
499 cpu_to_le16(ses->auth_key.len - CIFS_SESS_KEY_SIZE);
500
501 if (ses->domainName == NULL) {
502 sec_blob->DomainName.BufferOffset = cpu_to_le32(tmp - pbuffer);
503 sec_blob->DomainName.Length = 0;
504 sec_blob->DomainName.MaximumLength = 0;
505 tmp += 2;
506 } else {
507 int len;
508 len = cifs_strtoUTF16((__le16 *)tmp, ses->domainName,
509 MAX_USERNAME_SIZE, nls_cp);
510 len *= 2;
511 sec_blob->DomainName.BufferOffset = cpu_to_le32(tmp - pbuffer);
512 sec_blob->DomainName.Length = cpu_to_le16(len);
513 sec_blob->DomainName.MaximumLength = cpu_to_le16(len);
514 tmp += len;
515 }
516
517 if (ses->user_name == NULL) {
518 sec_blob->UserName.BufferOffset = cpu_to_le32(tmp - pbuffer);
519 sec_blob->UserName.Length = 0;
520 sec_blob->UserName.MaximumLength = 0;
521 tmp += 2;
522 } else {
523 int len;
524 len = cifs_strtoUTF16((__le16 *)tmp, ses->user_name,
525 MAX_USERNAME_SIZE, nls_cp);
526 len *= 2;
527 sec_blob->UserName.BufferOffset = cpu_to_le32(tmp - pbuffer);
528 sec_blob->UserName.Length = cpu_to_le16(len);
529 sec_blob->UserName.MaximumLength = cpu_to_le16(len);
530 tmp += len;
531 }
532
533 sec_blob->WorkstationName.BufferOffset = cpu_to_le32(tmp - pbuffer);
534 sec_blob->WorkstationName.Length = 0;
535 sec_blob->WorkstationName.MaximumLength = 0;
536 tmp += 2;
537
538 if (((ses->ntlmssp->server_flags & NTLMSSP_NEGOTIATE_KEY_XCH) ||
539 (ses->ntlmssp->server_flags & NTLMSSP_NEGOTIATE_EXTENDED_SEC))
540 && !calc_seckey(ses)) {
541 memcpy(tmp, ses->ntlmssp->ciphertext, CIFS_CPHTXT_SIZE);
542 sec_blob->SessionKey.BufferOffset = cpu_to_le32(tmp - pbuffer);
543 sec_blob->SessionKey.Length = cpu_to_le16(CIFS_CPHTXT_SIZE);
544 sec_blob->SessionKey.MaximumLength =
545 cpu_to_le16(CIFS_CPHTXT_SIZE);
546 tmp += CIFS_CPHTXT_SIZE;
547 } else {
548 sec_blob->SessionKey.BufferOffset = cpu_to_le32(tmp - pbuffer);
549 sec_blob->SessionKey.Length = 0;
550 sec_blob->SessionKey.MaximumLength = 0;
551 }
552
553setup_ntlmv2_ret:
554 *buflen = tmp - pbuffer;
555 return rc;
556}
557
558int
559CIFS_SessSetup(unsigned int xid, struct cifs_ses *ses,
560 const struct nls_table *nls_cp)
561{
562 int rc = 0;
563 int wct;
564 struct smb_hdr *smb_buf;
565 char *bcc_ptr;
566 char *str_area;
567 SESSION_SETUP_ANDX *pSMB;
568 __u32 capabilities;
569 __u16 count;
570 int resp_buf_type;
571 struct kvec iov[3];
572 enum securityEnum type;
573 __u16 action, bytes_remaining;
574 struct key *spnego_key = NULL;
575 __le32 phase = NtLmNegotiate;
576 u16 blob_len;
577 char *ntlmsspblob = NULL;
578
579 if (ses == NULL)
580 return -EINVAL;
581
582 type = ses->server->secType;
583 cFYI(1, "sess setup type %d", type);
584 if (type == RawNTLMSSP) {
585
586
587
588 ses->ntlmssp = kmalloc(sizeof(struct ntlmssp_auth), GFP_KERNEL);
589 if (!ses->ntlmssp)
590 return -ENOMEM;
591 }
592
593ssetup_ntlmssp_authenticate:
594 if (phase == NtLmChallenge)
595 phase = NtLmAuthenticate;
596
597 if (type == LANMAN) {
598#ifndef CONFIG_CIFS_WEAK_PW_HASH
599
600
601
602
603
604 return -EOPNOTSUPP;
605#endif
606 wct = 10;
607 } else if ((type == NTLM) || (type == NTLMv2)) {
608
609 wct = 13;
610 } else
611 wct = 12;
612
613 rc = small_smb_init_no_tc(SMB_COM_SESSION_SETUP_ANDX, wct, ses,
614 (void **)&smb_buf);
615 if (rc)
616 return rc;
617
618 pSMB = (SESSION_SETUP_ANDX *)smb_buf;
619
620 capabilities = cifs_ssetup_hdr(ses, pSMB);
621
622
623
624
625
626
627
628 iov[0].iov_base = (char *)pSMB;
629 iov[0].iov_len = be32_to_cpu(smb_buf->smb_buf_length) + 4;
630
631
632
633 resp_buf_type = CIFS_SMALL_BUFFER;
634
635
636 str_area = kmalloc(2000, GFP_KERNEL);
637 if (str_area == NULL) {
638 rc = -ENOMEM;
639 goto ssetup_exit;
640 }
641 bcc_ptr = str_area;
642
643 ses->flags &= ~CIFS_SES_LANMAN;
644
645 iov[1].iov_base = NULL;
646 iov[1].iov_len = 0;
647
648 if (type == LANMAN) {
649#ifdef CONFIG_CIFS_WEAK_PW_HASH
650 char lnm_session_key[CIFS_AUTH_RESP_SIZE];
651
652 pSMB->req.hdr.Flags2 &= ~SMBFLG2_UNICODE;
653
654
655
656 pSMB->old_req.PasswordLength = cpu_to_le16(CIFS_AUTH_RESP_SIZE);
657
658
659
660
661
662
663
664 rc = calc_lanman_hash(ses->password, ses->server->cryptkey,
665 ses->server->sec_mode & SECMODE_PW_ENCRYPT ?
666 true : false, lnm_session_key);
667
668 ses->flags |= CIFS_SES_LANMAN;
669 memcpy(bcc_ptr, (char *)lnm_session_key, CIFS_AUTH_RESP_SIZE);
670 bcc_ptr += CIFS_AUTH_RESP_SIZE;
671
672
673
674
675
676
677 cFYI(1, "Negotiating LANMAN setting up strings");
678
679 ascii_ssetup_strings(&bcc_ptr, ses, nls_cp);
680#endif
681 } else if (type == NTLM) {
682 pSMB->req_no_secext.Capabilities = cpu_to_le32(capabilities);
683 pSMB->req_no_secext.CaseInsensitivePasswordLength =
684 cpu_to_le16(CIFS_AUTH_RESP_SIZE);
685 pSMB->req_no_secext.CaseSensitivePasswordLength =
686 cpu_to_le16(CIFS_AUTH_RESP_SIZE);
687
688
689 rc = setup_ntlm_response(ses, nls_cp);
690 if (rc) {
691 cERROR(1, "Error %d during NTLM authentication", rc);
692 goto ssetup_exit;
693 }
694
695
696 memcpy(bcc_ptr, ses->auth_key.response + CIFS_SESS_KEY_SIZE,
697 CIFS_AUTH_RESP_SIZE);
698 bcc_ptr += CIFS_AUTH_RESP_SIZE;
699 memcpy(bcc_ptr, ses->auth_key.response + CIFS_SESS_KEY_SIZE,
700 CIFS_AUTH_RESP_SIZE);
701 bcc_ptr += CIFS_AUTH_RESP_SIZE;
702
703 if (ses->capabilities & CAP_UNICODE) {
704
705 if (iov[0].iov_len % 2) {
706 *bcc_ptr = 0;
707 bcc_ptr++;
708 }
709 unicode_ssetup_strings(&bcc_ptr, ses, nls_cp);
710 } else
711 ascii_ssetup_strings(&bcc_ptr, ses, nls_cp);
712 } else if (type == NTLMv2) {
713 pSMB->req_no_secext.Capabilities = cpu_to_le32(capabilities);
714
715
716 pSMB->req_no_secext.CaseInsensitivePasswordLength = 0;
717
718
719 rc = setup_ntlmv2_rsp(ses, nls_cp);
720 if (rc) {
721 cERROR(1, "Error %d during NTLMv2 authentication", rc);
722 goto ssetup_exit;
723 }
724 memcpy(bcc_ptr, ses->auth_key.response + CIFS_SESS_KEY_SIZE,
725 ses->auth_key.len - CIFS_SESS_KEY_SIZE);
726 bcc_ptr += ses->auth_key.len - CIFS_SESS_KEY_SIZE;
727
728
729
730
731 pSMB->req_no_secext.CaseSensitivePasswordLength =
732 cpu_to_le16(ses->auth_key.len - CIFS_SESS_KEY_SIZE);
733
734 if (ses->capabilities & CAP_UNICODE) {
735 if (iov[0].iov_len % 2) {
736 *bcc_ptr = 0;
737 bcc_ptr++;
738 }
739 unicode_ssetup_strings(&bcc_ptr, ses, nls_cp);
740 } else
741 ascii_ssetup_strings(&bcc_ptr, ses, nls_cp);
742 } else if (type == Kerberos) {
743#ifdef CONFIG_CIFS_UPCALL
744 struct cifs_spnego_msg *msg;
745
746 spnego_key = cifs_get_spnego_key(ses);
747 if (IS_ERR(spnego_key)) {
748 rc = PTR_ERR(spnego_key);
749 spnego_key = NULL;
750 goto ssetup_exit;
751 }
752
753 msg = spnego_key->payload.data;
754
755
756 if (msg->version != CIFS_SPNEGO_UPCALL_VERSION) {
757 cERROR(1, "incorrect version of cifs.upcall (expected"
758 " %d but got %d)",
759 CIFS_SPNEGO_UPCALL_VERSION, msg->version);
760 rc = -EKEYREJECTED;
761 goto ssetup_exit;
762 }
763
764 ses->auth_key.response = kmalloc(msg->sesskey_len, GFP_KERNEL);
765 if (!ses->auth_key.response) {
766 cERROR(1, "Kerberos can't allocate (%u bytes) memory",
767 msg->sesskey_len);
768 rc = -ENOMEM;
769 goto ssetup_exit;
770 }
771 memcpy(ses->auth_key.response, msg->data, msg->sesskey_len);
772 ses->auth_key.len = msg->sesskey_len;
773
774 pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC;
775 capabilities |= CAP_EXTENDED_SECURITY;
776 pSMB->req.Capabilities = cpu_to_le32(capabilities);
777 iov[1].iov_base = msg->data + msg->sesskey_len;
778 iov[1].iov_len = msg->secblob_len;
779 pSMB->req.SecurityBlobLength = cpu_to_le16(iov[1].iov_len);
780
781 if (ses->capabilities & CAP_UNICODE) {
782
783 if ((iov[0].iov_len + iov[1].iov_len) % 2) {
784 *bcc_ptr = 0;
785 bcc_ptr++;
786 }
787 unicode_oslm_strings(&bcc_ptr, nls_cp);
788 unicode_domain_string(&bcc_ptr, ses, nls_cp);
789 } else
790
791 ascii_ssetup_strings(&bcc_ptr, ses, nls_cp);
792#else
793 cERROR(1, "Kerberos negotiated but upcall support disabled!");
794 rc = -ENOSYS;
795 goto ssetup_exit;
796#endif
797 } else if (type == RawNTLMSSP) {
798 if ((pSMB->req.hdr.Flags2 & SMBFLG2_UNICODE) == 0) {
799 cERROR(1, "NTLMSSP requires Unicode support");
800 rc = -ENOSYS;
801 goto ssetup_exit;
802 }
803
804 cFYI(1, "ntlmssp session setup phase %d", phase);
805 pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC;
806 capabilities |= CAP_EXTENDED_SECURITY;
807 pSMB->req.Capabilities |= cpu_to_le32(capabilities);
808 switch(phase) {
809 case NtLmNegotiate:
810 build_ntlmssp_negotiate_blob(
811 pSMB->req.SecurityBlob, ses);
812 iov[1].iov_len = sizeof(NEGOTIATE_MESSAGE);
813 iov[1].iov_base = pSMB->req.SecurityBlob;
814 pSMB->req.SecurityBlobLength =
815 cpu_to_le16(sizeof(NEGOTIATE_MESSAGE));
816 break;
817 case NtLmAuthenticate:
818
819
820
821
822
823 ntlmsspblob = kzalloc(
824 5*sizeof(struct _AUTHENTICATE_MESSAGE),
825 GFP_KERNEL);
826 if (!ntlmsspblob) {
827 cERROR(1, "Can't allocate NTLMSSP blob");
828 rc = -ENOMEM;
829 goto ssetup_exit;
830 }
831
832 rc = build_ntlmssp_auth_blob(ntlmsspblob,
833 &blob_len, ses, nls_cp);
834 if (rc)
835 goto ssetup_exit;
836 iov[1].iov_len = blob_len;
837 iov[1].iov_base = ntlmsspblob;
838 pSMB->req.SecurityBlobLength = cpu_to_le16(blob_len);
839
840
841
842
843
844 smb_buf->Uid = ses->Suid;
845 break;
846 default:
847 cERROR(1, "invalid phase %d", phase);
848 rc = -ENOSYS;
849 goto ssetup_exit;
850 }
851
852 if ((iov[0].iov_len + iov[1].iov_len) % 2) {
853 *bcc_ptr = 0;
854 bcc_ptr++;
855 }
856 unicode_oslm_strings(&bcc_ptr, nls_cp);
857 } else {
858 cERROR(1, "secType %d not supported!", type);
859 rc = -ENOSYS;
860 goto ssetup_exit;
861 }
862
863 iov[2].iov_base = str_area;
864 iov[2].iov_len = (long) bcc_ptr - (long) str_area;
865
866 count = iov[1].iov_len + iov[2].iov_len;
867 smb_buf->smb_buf_length =
868 cpu_to_be32(be32_to_cpu(smb_buf->smb_buf_length) + count);
869
870 put_bcc(count, smb_buf);
871
872 rc = SendReceive2(xid, ses, iov, 3 , &resp_buf_type,
873 CIFS_LOG_ERROR);
874
875
876 pSMB = (SESSION_SETUP_ANDX *)iov[0].iov_base;
877 smb_buf = (struct smb_hdr *)iov[0].iov_base;
878
879 if ((type == RawNTLMSSP) && (smb_buf->Status.CifsError ==
880 cpu_to_le32(NT_STATUS_MORE_PROCESSING_REQUIRED))) {
881 if (phase != NtLmNegotiate) {
882 cERROR(1, "Unexpected more processing error");
883 goto ssetup_exit;
884 }
885
886 phase = NtLmChallenge;
887 rc = 0;
888 }
889 if (rc)
890 goto ssetup_exit;
891
892 if ((smb_buf->WordCount != 3) && (smb_buf->WordCount != 4)) {
893 rc = -EIO;
894 cERROR(1, "bad word count %d", smb_buf->WordCount);
895 goto ssetup_exit;
896 }
897 action = le16_to_cpu(pSMB->resp.Action);
898 if (action & GUEST_LOGIN)
899 cFYI(1, "Guest login");
900 ses->Suid = smb_buf->Uid;
901 cFYI(1, "UID = %d ", ses->Suid);
902
903
904 bytes_remaining = get_bcc(smb_buf);
905 bcc_ptr = pByteArea(smb_buf);
906
907 if (smb_buf->WordCount == 4) {
908 blob_len = le16_to_cpu(pSMB->resp.SecurityBlobLength);
909 if (blob_len > bytes_remaining) {
910 cERROR(1, "bad security blob length %d", blob_len);
911 rc = -EINVAL;
912 goto ssetup_exit;
913 }
914 if (phase == NtLmChallenge) {
915 rc = decode_ntlmssp_challenge(bcc_ptr, blob_len, ses);
916
917 if (rc)
918 goto ssetup_exit;
919 }
920 bcc_ptr += blob_len;
921 bytes_remaining -= blob_len;
922 }
923
924
925 if (bytes_remaining == 0) {
926
927 } else if (smb_buf->Flags2 & SMBFLG2_UNICODE) {
928
929 if (((unsigned long) bcc_ptr - (unsigned long) smb_buf) % 2) {
930 ++bcc_ptr;
931 --bytes_remaining;
932 }
933 decode_unicode_ssetup(&bcc_ptr, bytes_remaining, ses, nls_cp);
934 } else {
935 rc = decode_ascii_ssetup(&bcc_ptr, bytes_remaining,
936 ses, nls_cp);
937 }
938
939ssetup_exit:
940 if (spnego_key) {
941 key_revoke(spnego_key);
942 key_put(spnego_key);
943 }
944 kfree(str_area);
945 kfree(ntlmsspblob);
946 ntlmsspblob = NULL;
947 if (resp_buf_type == CIFS_SMALL_BUFFER) {
948 cFYI(1, "ssetup freeing small buf %p", iov[0].iov_base);
949 cifs_small_buf_release(iov[0].iov_base);
950 } else if (resp_buf_type == CIFS_LARGE_BUFFER)
951 cifs_buf_release(iov[0].iov_base);
952
953
954 if ((phase == NtLmChallenge) && (rc == 0))
955 goto ssetup_ntlmssp_authenticate;
956
957 return rc;
958}
959