diff options
Diffstat (limited to 'fs/cifs/sess.c')
-rw-r--r-- | fs/cifs/sess.c | 95 |
1 files changed, 70 insertions, 25 deletions
diff --git a/fs/cifs/sess.c b/fs/cifs/sess.c index f230571a7ab3..79358e341fd2 100644 --- a/fs/cifs/sess.c +++ b/fs/cifs/sess.c | |||
@@ -138,8 +138,7 @@ static __u32 cifs_ssetup_hdr(struct cifs_ses *ses, SESSION_SETUP_ANDX *pSMB) | |||
138 | capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS | | 138 | capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS | |
139 | CAP_LARGE_WRITE_X | CAP_LARGE_READ_X; | 139 | CAP_LARGE_WRITE_X | CAP_LARGE_READ_X; |
140 | 140 | ||
141 | if (ses->server->sec_mode & | 141 | if (ses->server->sign) |
142 | (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) | ||
143 | pSMB->req.hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE; | 142 | pSMB->req.hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE; |
144 | 143 | ||
145 | if (ses->capabilities & CAP_UNICODE) { | 144 | if (ses->capabilities & CAP_UNICODE) { |
@@ -310,11 +309,10 @@ decode_unicode_ssetup(char **pbcc_area, int bleft, struct cifs_ses *ses, | |||
310 | return; | 309 | return; |
311 | } | 310 | } |
312 | 311 | ||
313 | static int decode_ascii_ssetup(char **pbcc_area, __u16 bleft, | 312 | static void decode_ascii_ssetup(char **pbcc_area, __u16 bleft, |
314 | struct cifs_ses *ses, | 313 | struct cifs_ses *ses, |
315 | const struct nls_table *nls_cp) | 314 | const struct nls_table *nls_cp) |
316 | { | 315 | { |
317 | int rc = 0; | ||
318 | int len; | 316 | int len; |
319 | char *bcc_ptr = *pbcc_area; | 317 | char *bcc_ptr = *pbcc_area; |
320 | 318 | ||
@@ -322,24 +320,22 @@ static int decode_ascii_ssetup(char **pbcc_area, __u16 bleft, | |||
322 | 320 | ||
323 | len = strnlen(bcc_ptr, bleft); | 321 | len = strnlen(bcc_ptr, bleft); |
324 | if (len >= bleft) | 322 | if (len >= bleft) |
325 | return rc; | 323 | return; |
326 | 324 | ||
327 | kfree(ses->serverOS); | 325 | kfree(ses->serverOS); |
328 | 326 | ||
329 | ses->serverOS = kzalloc(len + 1, GFP_KERNEL); | 327 | ses->serverOS = kzalloc(len + 1, GFP_KERNEL); |
330 | if (ses->serverOS) | 328 | if (ses->serverOS) |
331 | strncpy(ses->serverOS, bcc_ptr, len); | 329 | strncpy(ses->serverOS, bcc_ptr, len); |
332 | if (strncmp(ses->serverOS, "OS/2", 4) == 0) { | 330 | if (strncmp(ses->serverOS, "OS/2", 4) == 0) |
333 | cifs_dbg(FYI, "OS/2 server\n"); | 331 | cifs_dbg(FYI, "OS/2 server\n"); |
334 | ses->flags |= CIFS_SES_OS2; | ||
335 | } | ||
336 | 332 | ||
337 | bcc_ptr += len + 1; | 333 | bcc_ptr += len + 1; |
338 | bleft -= len + 1; | 334 | bleft -= len + 1; |
339 | 335 | ||
340 | len = strnlen(bcc_ptr, bleft); | 336 | len = strnlen(bcc_ptr, bleft); |
341 | if (len >= bleft) | 337 | if (len >= bleft) |
342 | return rc; | 338 | return; |
343 | 339 | ||
344 | kfree(ses->serverNOS); | 340 | kfree(ses->serverNOS); |
345 | 341 | ||
@@ -352,7 +348,7 @@ static int decode_ascii_ssetup(char **pbcc_area, __u16 bleft, | |||
352 | 348 | ||
353 | len = strnlen(bcc_ptr, bleft); | 349 | len = strnlen(bcc_ptr, bleft); |
354 | if (len > bleft) | 350 | if (len > bleft) |
355 | return rc; | 351 | return; |
356 | 352 | ||
357 | /* No domain field in LANMAN case. Domain is | 353 | /* No domain field in LANMAN case. Domain is |
358 | returned by old servers in the SMB negprot response */ | 354 | returned by old servers in the SMB negprot response */ |
@@ -360,8 +356,6 @@ static int decode_ascii_ssetup(char **pbcc_area, __u16 bleft, | |||
360 | but thus do return domain here we could add parsing | 356 | but thus do return domain here we could add parsing |
361 | for it later, but it is not very important */ | 357 | for it later, but it is not very important */ |
362 | cifs_dbg(FYI, "ascii: bytes left %d\n", bleft); | 358 | cifs_dbg(FYI, "ascii: bytes left %d\n", bleft); |
363 | |||
364 | return rc; | ||
365 | } | 359 | } |
366 | 360 | ||
367 | int decode_ntlmssp_challenge(char *bcc_ptr, int blob_len, | 361 | int decode_ntlmssp_challenge(char *bcc_ptr, int blob_len, |
@@ -432,8 +426,7 @@ void build_ntlmssp_negotiate_blob(unsigned char *pbuffer, | |||
432 | flags = NTLMSSP_NEGOTIATE_56 | NTLMSSP_REQUEST_TARGET | | 426 | flags = NTLMSSP_NEGOTIATE_56 | NTLMSSP_REQUEST_TARGET | |
433 | NTLMSSP_NEGOTIATE_128 | NTLMSSP_NEGOTIATE_UNICODE | | 427 | NTLMSSP_NEGOTIATE_128 | NTLMSSP_NEGOTIATE_UNICODE | |
434 | NTLMSSP_NEGOTIATE_NTLM | NTLMSSP_NEGOTIATE_EXTENDED_SEC; | 428 | NTLMSSP_NEGOTIATE_NTLM | NTLMSSP_NEGOTIATE_EXTENDED_SEC; |
435 | if (ses->server->sec_mode & | 429 | if (ses->server->sign) { |
436 | (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) { | ||
437 | flags |= NTLMSSP_NEGOTIATE_SIGN; | 430 | flags |= NTLMSSP_NEGOTIATE_SIGN; |
438 | if (!ses->server->session_estab) | 431 | if (!ses->server->session_estab) |
439 | flags |= NTLMSSP_NEGOTIATE_KEY_XCH; | 432 | flags |= NTLMSSP_NEGOTIATE_KEY_XCH; |
@@ -471,8 +464,7 @@ int build_ntlmssp_auth_blob(unsigned char *pbuffer, | |||
471 | NTLMSSP_REQUEST_TARGET | NTLMSSP_NEGOTIATE_TARGET_INFO | | 464 | NTLMSSP_REQUEST_TARGET | NTLMSSP_NEGOTIATE_TARGET_INFO | |
472 | NTLMSSP_NEGOTIATE_128 | NTLMSSP_NEGOTIATE_UNICODE | | 465 | NTLMSSP_NEGOTIATE_128 | NTLMSSP_NEGOTIATE_UNICODE | |
473 | NTLMSSP_NEGOTIATE_NTLM | NTLMSSP_NEGOTIATE_EXTENDED_SEC; | 466 | NTLMSSP_NEGOTIATE_NTLM | NTLMSSP_NEGOTIATE_EXTENDED_SEC; |
474 | if (ses->server->sec_mode & | 467 | if (ses->server->sign) { |
475 | (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) { | ||
476 | flags |= NTLMSSP_NEGOTIATE_SIGN; | 468 | flags |= NTLMSSP_NEGOTIATE_SIGN; |
477 | if (!ses->server->session_estab) | 469 | if (!ses->server->session_estab) |
478 | flags |= NTLMSSP_NEGOTIATE_KEY_XCH; | 470 | flags |= NTLMSSP_NEGOTIATE_KEY_XCH; |
@@ -558,6 +550,56 @@ setup_ntlmv2_ret: | |||
558 | return rc; | 550 | return rc; |
559 | } | 551 | } |
560 | 552 | ||
553 | enum securityEnum | ||
554 | select_sectype(struct TCP_Server_Info *server, enum securityEnum requested) | ||
555 | { | ||
556 | switch (server->negflavor) { | ||
557 | case CIFS_NEGFLAVOR_EXTENDED: | ||
558 | switch (requested) { | ||
559 | case Kerberos: | ||
560 | case RawNTLMSSP: | ||
561 | return requested; | ||
562 | case Unspecified: | ||
563 | if (server->sec_ntlmssp && | ||
564 | (global_secflags & CIFSSEC_MAY_NTLMSSP)) | ||
565 | return RawNTLMSSP; | ||
566 | if ((server->sec_kerberos || server->sec_mskerberos) && | ||
567 | (global_secflags & CIFSSEC_MAY_KRB5)) | ||
568 | return Kerberos; | ||
569 | /* Fallthrough */ | ||
570 | default: | ||
571 | return Unspecified; | ||
572 | } | ||
573 | case CIFS_NEGFLAVOR_UNENCAP: | ||
574 | switch (requested) { | ||
575 | case NTLM: | ||
576 | case NTLMv2: | ||
577 | return requested; | ||
578 | case Unspecified: | ||
579 | if (global_secflags & CIFSSEC_MAY_NTLMV2) | ||
580 | return NTLMv2; | ||
581 | if (global_secflags & CIFSSEC_MAY_NTLM) | ||
582 | return NTLM; | ||
583 | /* Fallthrough */ | ||
584 | default: | ||
585 | return Unspecified; | ||
586 | } | ||
587 | case CIFS_NEGFLAVOR_LANMAN: | ||
588 | switch (requested) { | ||
589 | case LANMAN: | ||
590 | return requested; | ||
591 | case Unspecified: | ||
592 | if (global_secflags & CIFSSEC_MAY_LANMAN) | ||
593 | return LANMAN; | ||
594 | /* Fallthrough */ | ||
595 | default: | ||
596 | return Unspecified; | ||
597 | } | ||
598 | default: | ||
599 | return Unspecified; | ||
600 | } | ||
601 | } | ||
602 | |||
561 | int | 603 | int |
562 | CIFS_SessSetup(const unsigned int xid, struct cifs_ses *ses, | 604 | CIFS_SessSetup(const unsigned int xid, struct cifs_ses *ses, |
563 | const struct nls_table *nls_cp) | 605 | const struct nls_table *nls_cp) |
@@ -579,11 +621,18 @@ CIFS_SessSetup(const unsigned int xid, struct cifs_ses *ses, | |||
579 | u16 blob_len; | 621 | u16 blob_len; |
580 | char *ntlmsspblob = NULL; | 622 | char *ntlmsspblob = NULL; |
581 | 623 | ||
582 | if (ses == NULL) | 624 | if (ses == NULL) { |
625 | WARN(1, "%s: ses == NULL!", __func__); | ||
583 | return -EINVAL; | 626 | return -EINVAL; |
627 | } | ||
584 | 628 | ||
585 | type = ses->server->secType; | 629 | type = select_sectype(ses->server, ses->sectype); |
586 | cifs_dbg(FYI, "sess setup type %d\n", type); | 630 | cifs_dbg(FYI, "sess setup type %d\n", type); |
631 | if (type == Unspecified) { | ||
632 | cifs_dbg(VFS, "Unable to select appropriate authentication method!"); | ||
633 | return -EINVAL; | ||
634 | } | ||
635 | |||
587 | if (type == RawNTLMSSP) { | 636 | if (type == RawNTLMSSP) { |
588 | /* if memory allocation is successful, caller of this function | 637 | /* if memory allocation is successful, caller of this function |
589 | * frees it. | 638 | * frees it. |
@@ -643,8 +692,6 @@ ssetup_ntlmssp_authenticate: | |||
643 | } | 692 | } |
644 | bcc_ptr = str_area; | 693 | bcc_ptr = str_area; |
645 | 694 | ||
646 | ses->flags &= ~CIFS_SES_LANMAN; | ||
647 | |||
648 | iov[1].iov_base = NULL; | 695 | iov[1].iov_base = NULL; |
649 | iov[1].iov_len = 0; | 696 | iov[1].iov_len = 0; |
650 | 697 | ||
@@ -668,7 +715,6 @@ ssetup_ntlmssp_authenticate: | |||
668 | ses->server->sec_mode & SECMODE_PW_ENCRYPT ? | 715 | ses->server->sec_mode & SECMODE_PW_ENCRYPT ? |
669 | true : false, lnm_session_key); | 716 | true : false, lnm_session_key); |
670 | 717 | ||
671 | ses->flags |= CIFS_SES_LANMAN; | ||
672 | memcpy(bcc_ptr, (char *)lnm_session_key, CIFS_AUTH_RESP_SIZE); | 718 | memcpy(bcc_ptr, (char *)lnm_session_key, CIFS_AUTH_RESP_SIZE); |
673 | bcc_ptr += CIFS_AUTH_RESP_SIZE; | 719 | bcc_ptr += CIFS_AUTH_RESP_SIZE; |
674 | 720 | ||
@@ -938,8 +984,7 @@ ssetup_ntlmssp_authenticate: | |||
938 | } | 984 | } |
939 | decode_unicode_ssetup(&bcc_ptr, bytes_remaining, ses, nls_cp); | 985 | decode_unicode_ssetup(&bcc_ptr, bytes_remaining, ses, nls_cp); |
940 | } else { | 986 | } else { |
941 | rc = decode_ascii_ssetup(&bcc_ptr, bytes_remaining, | 987 | decode_ascii_ssetup(&bcc_ptr, bytes_remaining, ses, nls_cp); |
942 | ses, nls_cp); | ||
943 | } | 988 | } |
944 | 989 | ||
945 | ssetup_exit: | 990 | ssetup_exit: |