diff options
Diffstat (limited to 'fs/cifs/connect.c')
-rw-r--r-- | fs/cifs/connect.c | 89 |
1 files changed, 76 insertions, 13 deletions
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index c467de857610..88f60aa52058 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c | |||
@@ -76,12 +76,19 @@ struct smb_vol { | |||
76 | unsigned setuids:1; | 76 | unsigned setuids:1; |
77 | unsigned noperm:1; | 77 | unsigned noperm:1; |
78 | unsigned no_psx_acl:1; /* set if posix acl support should be disabled */ | 78 | unsigned no_psx_acl:1; /* set if posix acl support should be disabled */ |
79 | unsigned cifs_acl:1; | ||
79 | unsigned no_xattr:1; /* set if xattr (EA) support should be disabled*/ | 80 | unsigned no_xattr:1; /* set if xattr (EA) support should be disabled*/ |
80 | unsigned server_ino:1; /* use inode numbers from server ie UniqueId */ | 81 | unsigned server_ino:1; /* use inode numbers from server ie UniqueId */ |
81 | unsigned direct_io:1; | 82 | unsigned direct_io:1; |
82 | unsigned remap:1; /* set to remap seven reserved chars in filenames */ | 83 | unsigned remap:1; /* set to remap seven reserved chars in filenames */ |
83 | unsigned posix_paths:1; /* unset to not ask for posix pathnames. */ | 84 | unsigned posix_paths:1; /* unset to not ask for posix pathnames. */ |
84 | unsigned sfu_emul:1; | 85 | unsigned sfu_emul:1; |
86 | unsigned krb5:1; | ||
87 | unsigned ntlm:1; | ||
88 | unsigned ntlmv2:1; | ||
89 | unsigned nullauth:1; /* attempt to authenticate with null user */ | ||
90 | unsigned sign:1; | ||
91 | unsigned seal:1; /* encrypt */ | ||
85 | unsigned nocase; /* request case insensitive filenames */ | 92 | unsigned nocase; /* request case insensitive filenames */ |
86 | unsigned nobrl; /* disable sending byte range locks to srv */ | 93 | unsigned nobrl; /* disable sending byte range locks to srv */ |
87 | unsigned int rsize; | 94 | unsigned int rsize; |
@@ -508,7 +515,7 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server) | |||
508 | /* else length ok */ | 515 | /* else length ok */ |
509 | reconnect = 0; | 516 | reconnect = 0; |
510 | 517 | ||
511 | if(pdu_length > MAX_CIFS_HDR_SIZE - 4) { | 518 | if(pdu_length > MAX_CIFS_SMALL_BUFFER_SIZE - 4) { |
512 | isLargeBuf = TRUE; | 519 | isLargeBuf = TRUE; |
513 | memcpy(bigbuf, smallbuf, 4); | 520 | memcpy(bigbuf, smallbuf, 4); |
514 | smb_buffer = bigbuf; | 521 | smb_buffer = bigbuf; |
@@ -777,7 +784,7 @@ cifs_parse_mount_options(char *options, const char *devname,struct smb_vol *vol) | |||
777 | 784 | ||
778 | /* vol->retry default is 0 (i.e. "soft" limited retry not hard retry) */ | 785 | /* vol->retry default is 0 (i.e. "soft" limited retry not hard retry) */ |
779 | vol->rw = TRUE; | 786 | vol->rw = TRUE; |
780 | 787 | vol->ntlm = TRUE; | |
781 | /* default is always to request posix paths. */ | 788 | /* default is always to request posix paths. */ |
782 | vol->posix_paths = 1; | 789 | vol->posix_paths = 1; |
783 | 790 | ||
@@ -903,6 +910,39 @@ cifs_parse_mount_options(char *options, const char *devname,struct smb_vol *vol) | |||
903 | printk(KERN_WARNING "CIFS: ip address too long\n"); | 910 | printk(KERN_WARNING "CIFS: ip address too long\n"); |
904 | return 1; | 911 | return 1; |
905 | } | 912 | } |
913 | } else if (strnicmp(data, "sec", 3) == 0) { | ||
914 | if (!value || !*value) { | ||
915 | cERROR(1,("no security value specified")); | ||
916 | continue; | ||
917 | } else if (strnicmp(value, "krb5i", 5) == 0) { | ||
918 | vol->sign = 1; | ||
919 | vol->krb5 = 1; | ||
920 | } else if (strnicmp(value, "krb5p", 5) == 0) { | ||
921 | /* vol->seal = 1; | ||
922 | vol->krb5 = 1; */ | ||
923 | cERROR(1,("Krb5 cifs privacy not supported")); | ||
924 | return 1; | ||
925 | } else if (strnicmp(value, "krb5", 4) == 0) { | ||
926 | vol->krb5 = 1; | ||
927 | } else if (strnicmp(value, "ntlmv2i", 7) == 0) { | ||
928 | vol->ntlmv2 = 1; | ||
929 | vol->sign = 1; | ||
930 | } else if (strnicmp(value, "ntlmv2", 6) == 0) { | ||
931 | vol->ntlmv2 = 1; | ||
932 | } else if (strnicmp(value, "ntlmi", 5) == 0) { | ||
933 | vol->ntlm = 1; | ||
934 | vol->sign = 1; | ||
935 | } else if (strnicmp(value, "ntlm", 4) == 0) { | ||
936 | /* ntlm is default so can be turned off too */ | ||
937 | vol->ntlm = 1; | ||
938 | } else if (strnicmp(value, "nontlm", 6) == 0) { | ||
939 | vol->ntlm = 0; | ||
940 | } else if (strnicmp(value, "none", 4) == 0) { | ||
941 | vol->nullauth = 1; | ||
942 | } else { | ||
943 | cERROR(1,("bad security option: %s", value)); | ||
944 | return 1; | ||
945 | } | ||
906 | } else if ((strnicmp(data, "unc", 3) == 0) | 946 | } else if ((strnicmp(data, "unc", 3) == 0) |
907 | || (strnicmp(data, "target", 6) == 0) | 947 | || (strnicmp(data, "target", 6) == 0) |
908 | || (strnicmp(data, "path", 4) == 0)) { | 948 | || (strnicmp(data, "path", 4) == 0)) { |
@@ -1120,6 +1160,10 @@ cifs_parse_mount_options(char *options, const char *devname,struct smb_vol *vol) | |||
1120 | vol->server_ino = 1; | 1160 | vol->server_ino = 1; |
1121 | } else if (strnicmp(data, "noserverino",9) == 0) { | 1161 | } else if (strnicmp(data, "noserverino",9) == 0) { |
1122 | vol->server_ino = 0; | 1162 | vol->server_ino = 0; |
1163 | } else if (strnicmp(data, "cifsacl",7) == 0) { | ||
1164 | vol->cifs_acl = 1; | ||
1165 | } else if (strnicmp(data, "nocifsacl", 9) == 0) { | ||
1166 | vol->cifs_acl = 0; | ||
1123 | } else if (strnicmp(data, "acl",3) == 0) { | 1167 | } else if (strnicmp(data, "acl",3) == 0) { |
1124 | vol->no_psx_acl = 0; | 1168 | vol->no_psx_acl = 0; |
1125 | } else if (strnicmp(data, "noacl",5) == 0) { | 1169 | } else if (strnicmp(data, "noacl",5) == 0) { |
@@ -1546,7 +1590,7 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, | |||
1546 | cFYI(1, ("Username: %s ", volume_info.username)); | 1590 | cFYI(1, ("Username: %s ", volume_info.username)); |
1547 | 1591 | ||
1548 | } else { | 1592 | } else { |
1549 | cifserror("No username specified "); | 1593 | cifserror("No username specified"); |
1550 | /* In userspace mount helper we can get user name from alternate | 1594 | /* In userspace mount helper we can get user name from alternate |
1551 | locations such as env variables and files on disk */ | 1595 | locations such as env variables and files on disk */ |
1552 | kfree(volume_info.UNC); | 1596 | kfree(volume_info.UNC); |
@@ -1587,7 +1631,7 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, | |||
1587 | return -EINVAL; | 1631 | return -EINVAL; |
1588 | } else /* which servers DFS root would we conect to */ { | 1632 | } else /* which servers DFS root would we conect to */ { |
1589 | cERROR(1, | 1633 | cERROR(1, |
1590 | ("CIFS mount error: No UNC path (e.g. -o unc=//192.168.1.100/public) specified ")); | 1634 | ("CIFS mount error: No UNC path (e.g. -o unc=//192.168.1.100/public) specified")); |
1591 | kfree(volume_info.UNC); | 1635 | kfree(volume_info.UNC); |
1592 | kfree(volume_info.password); | 1636 | kfree(volume_info.password); |
1593 | FreeXid(xid); | 1637 | FreeXid(xid); |
@@ -1626,7 +1670,7 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, | |||
1626 | 1670 | ||
1627 | 1671 | ||
1628 | if (srvTcp) { | 1672 | if (srvTcp) { |
1629 | cFYI(1, ("Existing tcp session with server found ")); | 1673 | cFYI(1, ("Existing tcp session with server found")); |
1630 | } else { /* create socket */ | 1674 | } else { /* create socket */ |
1631 | if(volume_info.port) | 1675 | if(volume_info.port) |
1632 | sin_server.sin_port = htons(volume_info.port); | 1676 | sin_server.sin_port = htons(volume_info.port); |
@@ -1689,11 +1733,11 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, | |||
1689 | 1733 | ||
1690 | if (existingCifsSes) { | 1734 | if (existingCifsSes) { |
1691 | pSesInfo = existingCifsSes; | 1735 | pSesInfo = existingCifsSes; |
1692 | cFYI(1, ("Existing smb sess found ")); | 1736 | cFYI(1, ("Existing smb sess found")); |
1693 | kfree(volume_info.password); | 1737 | kfree(volume_info.password); |
1694 | /* volume_info.UNC freed at end of function */ | 1738 | /* volume_info.UNC freed at end of function */ |
1695 | } else if (!rc) { | 1739 | } else if (!rc) { |
1696 | cFYI(1, ("Existing smb sess not found ")); | 1740 | cFYI(1, ("Existing smb sess not found")); |
1697 | pSesInfo = sesInfoAlloc(); | 1741 | pSesInfo = sesInfoAlloc(); |
1698 | if (pSesInfo == NULL) | 1742 | if (pSesInfo == NULL) |
1699 | rc = -ENOMEM; | 1743 | rc = -ENOMEM; |
@@ -1751,7 +1795,8 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, | |||
1751 | cifs_sb->mnt_gid = volume_info.linux_gid; | 1795 | cifs_sb->mnt_gid = volume_info.linux_gid; |
1752 | cifs_sb->mnt_file_mode = volume_info.file_mode; | 1796 | cifs_sb->mnt_file_mode = volume_info.file_mode; |
1753 | cifs_sb->mnt_dir_mode = volume_info.dir_mode; | 1797 | cifs_sb->mnt_dir_mode = volume_info.dir_mode; |
1754 | cFYI(1,("file mode: 0x%x dir mode: 0x%x",cifs_sb->mnt_file_mode,cifs_sb->mnt_dir_mode)); | 1798 | cFYI(1,("file mode: 0x%x dir mode: 0x%x", |
1799 | cifs_sb->mnt_file_mode,cifs_sb->mnt_dir_mode)); | ||
1755 | 1800 | ||
1756 | if(volume_info.noperm) | 1801 | if(volume_info.noperm) |
1757 | cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_PERM; | 1802 | cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_PERM; |
@@ -1767,6 +1812,8 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, | |||
1767 | cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_UNX_EMUL; | 1812 | cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_UNX_EMUL; |
1768 | if(volume_info.nobrl) | 1813 | if(volume_info.nobrl) |
1769 | cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_BRL; | 1814 | cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_BRL; |
1815 | if(volume_info.cifs_acl) | ||
1816 | cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_CIFS_ACL; | ||
1770 | 1817 | ||
1771 | if(volume_info.direct_io) { | 1818 | if(volume_info.direct_io) { |
1772 | cFYI(1,("mounting share using direct i/o")); | 1819 | cFYI(1,("mounting share using direct i/o")); |
@@ -1777,7 +1824,7 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, | |||
1777 | find_unc(sin_server.sin_addr.s_addr, volume_info.UNC, | 1824 | find_unc(sin_server.sin_addr.s_addr, volume_info.UNC, |
1778 | volume_info.username); | 1825 | volume_info.username); |
1779 | if (tcon) { | 1826 | if (tcon) { |
1780 | cFYI(1, ("Found match on UNC path ")); | 1827 | cFYI(1, ("Found match on UNC path")); |
1781 | /* we can have only one retry value for a connection | 1828 | /* we can have only one retry value for a connection |
1782 | to a share so for resources mounted more than once | 1829 | to a share so for resources mounted more than once |
1783 | to the same server share the last value passed in | 1830 | to the same server share the last value passed in |
@@ -1926,7 +1973,7 @@ CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses, | |||
1926 | __u32 capabilities; | 1973 | __u32 capabilities; |
1927 | __u16 count; | 1974 | __u16 count; |
1928 | 1975 | ||
1929 | cFYI(1, ("In sesssetup ")); | 1976 | cFYI(1, ("In sesssetup")); |
1930 | if(ses == NULL) | 1977 | if(ses == NULL) |
1931 | return -EINVAL; | 1978 | return -EINVAL; |
1932 | user = ses->userName; | 1979 | user = ses->userName; |
@@ -3202,9 +3249,26 @@ CIFSTCon(unsigned int xid, struct cifsSesInfo *ses, | |||
3202 | 3249 | ||
3203 | pSMB->AndXCommand = 0xFF; | 3250 | pSMB->AndXCommand = 0xFF; |
3204 | pSMB->Flags = cpu_to_le16(TCON_EXTENDED_SECINFO); | 3251 | pSMB->Flags = cpu_to_le16(TCON_EXTENDED_SECINFO); |
3205 | pSMB->PasswordLength = cpu_to_le16(1); /* minimum */ | ||
3206 | bcc_ptr = &pSMB->Password[0]; | 3252 | bcc_ptr = &pSMB->Password[0]; |
3207 | bcc_ptr++; /* skip password */ | 3253 | if((ses->server->secMode) & SECMODE_USER) { |
3254 | pSMB->PasswordLength = cpu_to_le16(1); /* minimum */ | ||
3255 | bcc_ptr++; /* skip password */ | ||
3256 | } else { | ||
3257 | pSMB->PasswordLength = cpu_to_le16(CIFS_SESSION_KEY_SIZE); | ||
3258 | /* BB FIXME add code to fail this if NTLMv2 or Kerberos | ||
3259 | specified as required (when that support is added to | ||
3260 | the vfs in the future) as only NTLM or the much | ||
3261 | weaker LANMAN (which we do not send) is accepted | ||
3262 | by Samba (not sure whether other servers allow | ||
3263 | NTLMv2 password here) */ | ||
3264 | SMBNTencrypt(ses->password, | ||
3265 | ses->server->cryptKey, | ||
3266 | bcc_ptr); | ||
3267 | |||
3268 | bcc_ptr += CIFS_SESSION_KEY_SIZE; | ||
3269 | *bcc_ptr = 0; | ||
3270 | bcc_ptr++; /* align */ | ||
3271 | } | ||
3208 | 3272 | ||
3209 | if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) | 3273 | if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) |
3210 | smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE; | 3274 | smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE; |
@@ -3222,7 +3286,6 @@ CIFSTCon(unsigned int xid, struct cifsSesInfo *ses, | |||
3222 | bcc_ptr += 2 * length; /* convert num of 16 bit words to bytes */ | 3286 | bcc_ptr += 2 * length; /* convert num of 16 bit words to bytes */ |
3223 | bcc_ptr += 2; /* skip trailing null */ | 3287 | bcc_ptr += 2; /* skip trailing null */ |
3224 | } else { /* ASCII */ | 3288 | } else { /* ASCII */ |
3225 | |||
3226 | strcpy(bcc_ptr, tree); | 3289 | strcpy(bcc_ptr, tree); |
3227 | bcc_ptr += strlen(tree) + 1; | 3290 | bcc_ptr += strlen(tree) + 1; |
3228 | } | 3291 | } |