aboutsummaryrefslogtreecommitdiffstats
path: root/fs/cifs/connect.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/cifs/connect.c')
-rw-r--r--fs/cifs/connect.c181
1 files changed, 131 insertions, 50 deletions
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index 2208f06e4c45..95c2ea67edfb 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -48,6 +48,7 @@
48#include "nterr.h" 48#include "nterr.h"
49#include "rfc1002pdu.h" 49#include "rfc1002pdu.h"
50#include "cn_cifs.h" 50#include "cn_cifs.h"
51#include "fscache.h"
51 52
52#define CIFS_PORT 445 53#define CIFS_PORT 445
53#define RFC1001_PORT 139 54#define RFC1001_PORT 139
@@ -66,6 +67,7 @@ struct smb_vol {
66 char *iocharset; /* local code page for mapping to and from Unicode */ 67 char *iocharset; /* local code page for mapping to and from Unicode */
67 char source_rfc1001_name[16]; /* netbios name of client */ 68 char source_rfc1001_name[16]; /* netbios name of client */
68 char target_rfc1001_name[16]; /* netbios name of server for Win9x/ME */ 69 char target_rfc1001_name[16]; /* netbios name of server for Win9x/ME */
70 uid_t cred_uid;
69 uid_t linux_uid; 71 uid_t linux_uid;
70 gid_t linux_gid; 72 gid_t linux_gid;
71 mode_t file_mode; 73 mode_t file_mode;
@@ -97,6 +99,7 @@ struct smb_vol {
97 bool noblocksnd:1; 99 bool noblocksnd:1;
98 bool noautotune:1; 100 bool noautotune:1;
99 bool nostrictsync:1; /* do not force expensive SMBflush on every sync */ 101 bool nostrictsync:1; /* do not force expensive SMBflush on every sync */
102 bool fsc:1; /* enable fscache */
100 unsigned int rsize; 103 unsigned int rsize;
101 unsigned int wsize; 104 unsigned int wsize;
102 bool sockopt_tcp_nodelay:1; 105 bool sockopt_tcp_nodelay:1;
@@ -830,7 +833,8 @@ cifs_parse_mount_options(char *options, const char *devname,
830 /* null target name indicates to use *SMBSERVR default called name 833 /* null target name indicates to use *SMBSERVR default called name
831 if we end up sending RFC1001 session initialize */ 834 if we end up sending RFC1001 session initialize */
832 vol->target_rfc1001_name[0] = 0; 835 vol->target_rfc1001_name[0] = 0;
833 vol->linux_uid = current_uid(); /* use current_euid() instead? */ 836 vol->cred_uid = current_uid();
837 vol->linux_uid = current_uid();
834 vol->linux_gid = current_gid(); 838 vol->linux_gid = current_gid();
835 839
836 /* default to only allowing write access to owner of the mount */ 840 /* default to only allowing write access to owner of the mount */
@@ -1257,6 +1261,12 @@ cifs_parse_mount_options(char *options, const char *devname,
1257 } else if ((strnicmp(data, "nocase", 6) == 0) || 1261 } else if ((strnicmp(data, "nocase", 6) == 0) ||
1258 (strnicmp(data, "ignorecase", 10) == 0)) { 1262 (strnicmp(data, "ignorecase", 10) == 0)) {
1259 vol->nocase = 1; 1263 vol->nocase = 1;
1264 } else if (strnicmp(data, "mand", 4) == 0) {
1265 /* ignore */
1266 } else if (strnicmp(data, "nomand", 6) == 0) {
1267 /* ignore */
1268 } else if (strnicmp(data, "_netdev", 7) == 0) {
1269 /* ignore */
1260 } else if (strnicmp(data, "brl", 3) == 0) { 1270 } else if (strnicmp(data, "brl", 3) == 0) {
1261 vol->nobrl = 0; 1271 vol->nobrl = 0;
1262 } else if ((strnicmp(data, "nobrl", 5) == 0) || 1272 } else if ((strnicmp(data, "nobrl", 5) == 0) ||
@@ -1331,6 +1341,8 @@ cifs_parse_mount_options(char *options, const char *devname,
1331 printk(KERN_WARNING "CIFS: Mount option noac not " 1341 printk(KERN_WARNING "CIFS: Mount option noac not "
1332 "supported. Instead set " 1342 "supported. Instead set "
1333 "/proc/fs/cifs/LookupCacheEnabled to 0\n"); 1343 "/proc/fs/cifs/LookupCacheEnabled to 0\n");
1344 } else if (strnicmp(data, "fsc", 3) == 0) {
1345 vol->fsc = true;
1334 } else 1346 } else
1335 printk(KERN_WARNING "CIFS: Unknown mount option %s\n", 1347 printk(KERN_WARNING "CIFS: Unknown mount option %s\n",
1336 data); 1348 data);
@@ -1380,18 +1392,92 @@ cifs_parse_mount_options(char *options, const char *devname,
1380 return 0; 1392 return 0;
1381} 1393}
1382 1394
1395static bool
1396match_address(struct TCP_Server_Info *server, struct sockaddr *addr)
1397{
1398 struct sockaddr_in *addr4 = (struct sockaddr_in *)addr;
1399 struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)addr;
1400
1401 switch (addr->sa_family) {
1402 case AF_INET:
1403 if (addr4->sin_addr.s_addr !=
1404 server->addr.sockAddr.sin_addr.s_addr)
1405 return false;
1406 if (addr4->sin_port &&
1407 addr4->sin_port != server->addr.sockAddr.sin_port)
1408 return false;
1409 break;
1410 case AF_INET6:
1411 if (!ipv6_addr_equal(&addr6->sin6_addr,
1412 &server->addr.sockAddr6.sin6_addr))
1413 return false;
1414 if (addr6->sin6_scope_id !=
1415 server->addr.sockAddr6.sin6_scope_id)
1416 return false;
1417 if (addr6->sin6_port &&
1418 addr6->sin6_port != server->addr.sockAddr6.sin6_port)
1419 return false;
1420 break;
1421 }
1422
1423 return true;
1424}
1425
1426static bool
1427match_security(struct TCP_Server_Info *server, struct smb_vol *vol)
1428{
1429 unsigned int secFlags;
1430
1431 if (vol->secFlg & (~(CIFSSEC_MUST_SIGN | CIFSSEC_MUST_SEAL)))
1432 secFlags = vol->secFlg;
1433 else
1434 secFlags = global_secflags | vol->secFlg;
1435
1436 switch (server->secType) {
1437 case LANMAN:
1438 if (!(secFlags & (CIFSSEC_MAY_LANMAN|CIFSSEC_MAY_PLNTXT)))
1439 return false;
1440 break;
1441 case NTLMv2:
1442 if (!(secFlags & CIFSSEC_MAY_NTLMV2))
1443 return false;
1444 break;
1445 case NTLM:
1446 if (!(secFlags & CIFSSEC_MAY_NTLM))
1447 return false;
1448 break;
1449 case Kerberos:
1450 if (!(secFlags & CIFSSEC_MAY_KRB5))
1451 return false;
1452 break;
1453 case RawNTLMSSP:
1454 if (!(secFlags & CIFSSEC_MAY_NTLMSSP))
1455 return false;
1456 break;
1457 default:
1458 /* shouldn't happen */
1459 return false;
1460 }
1461
1462 /* now check if signing mode is acceptible */
1463 if ((secFlags & CIFSSEC_MAY_SIGN) == 0 &&
1464 (server->secMode & SECMODE_SIGN_REQUIRED))
1465 return false;
1466 else if (((secFlags & CIFSSEC_MUST_SIGN) == CIFSSEC_MUST_SIGN) &&
1467 (server->secMode &
1468 (SECMODE_SIGN_ENABLED|SECMODE_SIGN_REQUIRED)) == 0)
1469 return false;
1470
1471 return true;
1472}
1473
1383static struct TCP_Server_Info * 1474static struct TCP_Server_Info *
1384cifs_find_tcp_session(struct sockaddr_storage *addr, unsigned short int port) 1475cifs_find_tcp_session(struct sockaddr *addr, struct smb_vol *vol)
1385{ 1476{
1386 struct list_head *tmp;
1387 struct TCP_Server_Info *server; 1477 struct TCP_Server_Info *server;
1388 struct sockaddr_in *addr4 = (struct sockaddr_in *) addr;
1389 struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *) addr;
1390 1478
1391 write_lock(&cifs_tcp_ses_lock); 1479 write_lock(&cifs_tcp_ses_lock);
1392 list_for_each(tmp, &cifs_tcp_ses_list) { 1480 list_for_each_entry(server, &cifs_tcp_ses_list, tcp_ses_list) {
1393 server = list_entry(tmp, struct TCP_Server_Info,
1394 tcp_ses_list);
1395 /* 1481 /*
1396 * the demux thread can exit on its own while still in CifsNew 1482 * the demux thread can exit on its own while still in CifsNew
1397 * so don't accept any sockets in that state. Since the 1483 * so don't accept any sockets in that state. Since the
@@ -1401,37 +1487,11 @@ cifs_find_tcp_session(struct sockaddr_storage *addr, unsigned short int port)
1401 if (server->tcpStatus == CifsNew) 1487 if (server->tcpStatus == CifsNew)
1402 continue; 1488 continue;
1403 1489
1404 switch (addr->ss_family) { 1490 if (!match_address(server, addr))
1405 case AF_INET: 1491 continue;
1406 if (addr4->sin_addr.s_addr ==
1407 server->addr.sockAddr.sin_addr.s_addr) {
1408 addr4->sin_port = htons(port);
1409 /* user overrode default port? */
1410 if (addr4->sin_port) {
1411 if (addr4->sin_port !=
1412 server->addr.sockAddr.sin_port)
1413 continue;
1414 }
1415 break;
1416 } else
1417 continue;
1418 1492
1419 case AF_INET6: 1493 if (!match_security(server, vol))
1420 if (ipv6_addr_equal(&addr6->sin6_addr, 1494 continue;
1421 &server->addr.sockAddr6.sin6_addr) &&
1422 (addr6->sin6_scope_id ==
1423 server->addr.sockAddr6.sin6_scope_id)) {
1424 addr6->sin6_port = htons(port);
1425 /* user overrode default port? */
1426 if (addr6->sin6_port) {
1427 if (addr6->sin6_port !=
1428 server->addr.sockAddr6.sin6_port)
1429 continue;
1430 }
1431 break;
1432 } else
1433 continue;
1434 }
1435 1495
1436 ++server->srv_count; 1496 ++server->srv_count;
1437 write_unlock(&cifs_tcp_ses_lock); 1497 write_unlock(&cifs_tcp_ses_lock);
@@ -1460,6 +1520,8 @@ cifs_put_tcp_session(struct TCP_Server_Info *server)
1460 server->tcpStatus = CifsExiting; 1520 server->tcpStatus = CifsExiting;
1461 spin_unlock(&GlobalMid_Lock); 1521 spin_unlock(&GlobalMid_Lock);
1462 1522
1523 cifs_fscache_release_client_cookie(server);
1524
1463 task = xchg(&server->tsk, NULL); 1525 task = xchg(&server->tsk, NULL);
1464 if (task) 1526 if (task)
1465 force_sig(SIGKILL, task); 1527 force_sig(SIGKILL, task);
@@ -1479,7 +1541,10 @@ cifs_get_tcp_session(struct smb_vol *volume_info)
1479 cFYI(1, "UNC: %s ip: %s", volume_info->UNC, volume_info->UNCip); 1541 cFYI(1, "UNC: %s ip: %s", volume_info->UNC, volume_info->UNCip);
1480 1542
1481 if (volume_info->UNCip && volume_info->UNC) { 1543 if (volume_info->UNCip && volume_info->UNC) {
1482 rc = cifs_convert_address(volume_info->UNCip, &addr); 1544 rc = cifs_fill_sockaddr((struct sockaddr *)&addr,
1545 volume_info->UNCip,
1546 strlen(volume_info->UNCip),
1547 volume_info->port);
1483 if (!rc) { 1548 if (!rc) {
1484 /* we failed translating address */ 1549 /* we failed translating address */
1485 rc = -EINVAL; 1550 rc = -EINVAL;
@@ -1499,7 +1564,7 @@ cifs_get_tcp_session(struct smb_vol *volume_info)
1499 } 1564 }
1500 1565
1501 /* see if we already have a matching tcp_ses */ 1566 /* see if we already have a matching tcp_ses */
1502 tcp_ses = cifs_find_tcp_session(&addr, volume_info->port); 1567 tcp_ses = cifs_find_tcp_session((struct sockaddr *)&addr, volume_info);
1503 if (tcp_ses) 1568 if (tcp_ses)
1504 return tcp_ses; 1569 return tcp_ses;
1505 1570
@@ -1543,12 +1608,10 @@ cifs_get_tcp_session(struct smb_vol *volume_info)
1543 cFYI(1, "attempting ipv6 connect"); 1608 cFYI(1, "attempting ipv6 connect");
1544 /* BB should we allow ipv6 on port 139? */ 1609 /* BB should we allow ipv6 on port 139? */
1545 /* other OS never observed in Wild doing 139 with v6 */ 1610 /* other OS never observed in Wild doing 139 with v6 */
1546 sin_server6->sin6_port = htons(volume_info->port);
1547 memcpy(&tcp_ses->addr.sockAddr6, sin_server6, 1611 memcpy(&tcp_ses->addr.sockAddr6, sin_server6,
1548 sizeof(struct sockaddr_in6)); 1612 sizeof(struct sockaddr_in6));
1549 rc = ipv6_connect(tcp_ses); 1613 rc = ipv6_connect(tcp_ses);
1550 } else { 1614 } else {
1551 sin_server->sin_port = htons(volume_info->port);
1552 memcpy(&tcp_ses->addr.sockAddr, sin_server, 1615 memcpy(&tcp_ses->addr.sockAddr, sin_server,
1553 sizeof(struct sockaddr_in)); 1616 sizeof(struct sockaddr_in));
1554 rc = ipv4_connect(tcp_ses); 1617 rc = ipv4_connect(tcp_ses);
@@ -1577,6 +1640,8 @@ cifs_get_tcp_session(struct smb_vol *volume_info)
1577 list_add(&tcp_ses->tcp_ses_list, &cifs_tcp_ses_list); 1640 list_add(&tcp_ses->tcp_ses_list, &cifs_tcp_ses_list);
1578 write_unlock(&cifs_tcp_ses_lock); 1641 write_unlock(&cifs_tcp_ses_lock);
1579 1642
1643 cifs_fscache_get_client_cookie(tcp_ses);
1644
1580 return tcp_ses; 1645 return tcp_ses;
1581 1646
1582out_err: 1647out_err:
@@ -1591,17 +1656,27 @@ out_err:
1591} 1656}
1592 1657
1593static struct cifsSesInfo * 1658static struct cifsSesInfo *
1594cifs_find_smb_ses(struct TCP_Server_Info *server, char *username) 1659cifs_find_smb_ses(struct TCP_Server_Info *server, struct smb_vol *vol)
1595{ 1660{
1596 struct list_head *tmp;
1597 struct cifsSesInfo *ses; 1661 struct cifsSesInfo *ses;
1598 1662
1599 write_lock(&cifs_tcp_ses_lock); 1663 write_lock(&cifs_tcp_ses_lock);
1600 list_for_each(tmp, &server->smb_ses_list) { 1664 list_for_each_entry(ses, &server->smb_ses_list, smb_ses_list) {
1601 ses = list_entry(tmp, struct cifsSesInfo, smb_ses_list); 1665 switch (server->secType) {
1602 if (strncmp(ses->userName, username, MAX_USERNAME_SIZE)) 1666 case Kerberos:
1603 continue; 1667 if (vol->cred_uid != ses->cred_uid)
1604 1668 continue;
1669 break;
1670 default:
1671 /* anything else takes username/password */
1672 if (strncmp(ses->userName, vol->username,
1673 MAX_USERNAME_SIZE))
1674 continue;
1675 if (strlen(vol->username) != 0 &&
1676 strncmp(ses->password, vol->password,
1677 MAX_PASSWORD_SIZE))
1678 continue;
1679 }
1605 ++ses->ses_count; 1680 ++ses->ses_count;
1606 write_unlock(&cifs_tcp_ses_lock); 1681 write_unlock(&cifs_tcp_ses_lock);
1607 return ses; 1682 return ses;
@@ -1643,7 +1718,7 @@ cifs_get_smb_ses(struct TCP_Server_Info *server, struct smb_vol *volume_info)
1643 1718
1644 xid = GetXid(); 1719 xid = GetXid();
1645 1720
1646 ses = cifs_find_smb_ses(server, volume_info->username); 1721 ses = cifs_find_smb_ses(server, volume_info);
1647 if (ses) { 1722 if (ses) {
1648 cFYI(1, "Existing smb sess found (status=%d)", ses->status); 1723 cFYI(1, "Existing smb sess found (status=%d)", ses->status);
1649 1724
@@ -1706,6 +1781,7 @@ cifs_get_smb_ses(struct TCP_Server_Info *server, struct smb_vol *volume_info)
1706 if (ses->domainName) 1781 if (ses->domainName)
1707 strcpy(ses->domainName, volume_info->domainname); 1782 strcpy(ses->domainName, volume_info->domainname);
1708 } 1783 }
1784 ses->cred_uid = volume_info->cred_uid;
1709 ses->linux_uid = volume_info->linux_uid; 1785 ses->linux_uid = volume_info->linux_uid;
1710 ses->overrideSecFlg = volume_info->secFlg; 1786 ses->overrideSecFlg = volume_info->secFlg;
1711 1787
@@ -1773,6 +1849,7 @@ cifs_put_tcon(struct cifsTconInfo *tcon)
1773 CIFSSMBTDis(xid, tcon); 1849 CIFSSMBTDis(xid, tcon);
1774 _FreeXid(xid); 1850 _FreeXid(xid);
1775 1851
1852 cifs_fscache_release_super_cookie(tcon);
1776 tconInfoFree(tcon); 1853 tconInfoFree(tcon);
1777 cifs_put_smb_ses(ses); 1854 cifs_put_smb_ses(ses);
1778} 1855}
@@ -1843,6 +1920,8 @@ cifs_get_tcon(struct cifsSesInfo *ses, struct smb_vol *volume_info)
1843 list_add(&tcon->tcon_list, &ses->tcon_list); 1920 list_add(&tcon->tcon_list, &ses->tcon_list);
1844 write_unlock(&cifs_tcp_ses_lock); 1921 write_unlock(&cifs_tcp_ses_lock);
1845 1922
1923 cifs_fscache_get_super_cookie(tcon);
1924
1846 return tcon; 1925 return tcon;
1847 1926
1848out_fail: 1927out_fail:
@@ -2397,6 +2476,8 @@ static void setup_cifs_sb(struct smb_vol *pvolume_info,
2397 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_OVERR_GID; 2476 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_OVERR_GID;
2398 if (pvolume_info->dynperm) 2477 if (pvolume_info->dynperm)
2399 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DYNPERM; 2478 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DYNPERM;
2479 if (pvolume_info->fsc)
2480 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_FSCACHE;
2400 if (pvolume_info->direct_io) { 2481 if (pvolume_info->direct_io) {
2401 cFYI(1, "mounting share using direct i/o"); 2482 cFYI(1, "mounting share using direct i/o");
2402 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DIRECT_IO; 2483 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DIRECT_IO;