diff options
Diffstat (limited to 'fs/nfs')
| -rw-r--r-- | fs/nfs/super.c | 126 |
1 files changed, 69 insertions, 57 deletions
diff --git a/fs/nfs/super.c b/fs/nfs/super.c index ceb60c78bfc0..8d51101771fc 100644 --- a/fs/nfs/super.c +++ b/fs/nfs/super.c | |||
| @@ -1608,16 +1608,13 @@ out_security_failure: | |||
| 1608 | } | 1608 | } |
| 1609 | 1609 | ||
| 1610 | /* | 1610 | /* |
| 1611 | * Select a security flavor for this mount. The selected flavor | 1611 | * Ensure that the specified authtype in args->auth_flavors[0] is supported by |
| 1612 | * is planted in args->auth_flavors[0]. | 1612 | * the server. Returns 0 if it's ok, and -EACCES if not. |
| 1613 | * | ||
| 1614 | * Returns 0 on success, -EACCES on failure. | ||
| 1615 | */ | 1613 | */ |
| 1616 | static int nfs_select_flavor(struct nfs_parsed_mount_data *args, | 1614 | static int nfs_verify_authflavor(struct nfs_parsed_mount_data *args, |
| 1617 | struct nfs_mount_request *request) | 1615 | rpc_authflavor_t *server_authlist, unsigned int count) |
| 1618 | { | 1616 | { |
| 1619 | unsigned int i, count = *(request->auth_flav_len); | 1617 | unsigned int i; |
| 1620 | rpc_authflavor_t flavor; | ||
| 1621 | 1618 | ||
| 1622 | /* | 1619 | /* |
| 1623 | * If the sec= mount option is used, the specified flavor or AUTH_NULL | 1620 | * If the sec= mount option is used, the specified flavor or AUTH_NULL |
| @@ -1627,60 +1624,19 @@ static int nfs_select_flavor(struct nfs_parsed_mount_data *args, | |||
| 1627 | * means that the server will ignore the rpc creds, so any flavor | 1624 | * means that the server will ignore the rpc creds, so any flavor |
| 1628 | * can be used. | 1625 | * can be used. |
| 1629 | */ | 1626 | */ |
| 1630 | if (args->auth_flavors[0] != RPC_AUTH_MAXFLAVOR) { | ||
| 1631 | for (i = 0; i < count; i++) { | ||
| 1632 | if (args->auth_flavors[0] == request->auth_flavs[i] || | ||
| 1633 | request->auth_flavs[i] == RPC_AUTH_NULL) | ||
| 1634 | goto out; | ||
| 1635 | } | ||
| 1636 | dfprintk(MOUNT, "NFS: auth flavor %d not supported by server\n", | ||
| 1637 | args->auth_flavors[0]); | ||
| 1638 | goto out_err; | ||
| 1639 | } | ||
| 1640 | |||
| 1641 | /* | ||
| 1642 | * RFC 2623, section 2.7 suggests we SHOULD prefer the | ||
| 1643 | * flavor listed first. However, some servers list | ||
| 1644 | * AUTH_NULL first. Avoid ever choosing AUTH_NULL. | ||
| 1645 | */ | ||
| 1646 | for (i = 0; i < count; i++) { | 1627 | for (i = 0; i < count; i++) { |
| 1647 | struct rpcsec_gss_info info; | 1628 | if (args->auth_flavors[0] == server_authlist[i] || |
| 1648 | 1629 | server_authlist[i] == RPC_AUTH_NULL) | |
| 1649 | flavor = request->auth_flavs[i]; | 1630 | goto out; |
| 1650 | switch (flavor) { | ||
| 1651 | case RPC_AUTH_UNIX: | ||
| 1652 | goto out_set; | ||
| 1653 | case RPC_AUTH_NULL: | ||
| 1654 | continue; | ||
| 1655 | default: | ||
| 1656 | if (rpcauth_get_gssinfo(flavor, &info) == 0) | ||
| 1657 | goto out_set; | ||
| 1658 | } | ||
| 1659 | } | 1631 | } |
| 1660 | 1632 | ||
| 1661 | /* | 1633 | dfprintk(MOUNT, "NFS: auth flavor %u not supported by server\n", |
| 1662 | * As a last chance, see if the server list contains AUTH_NULL - | 1634 | args->auth_flavors[0]); |
| 1663 | * if it does, use the default flavor. | 1635 | return -EACCES; |
| 1664 | */ | ||
| 1665 | for (i = 0; i < count; i++) { | ||
| 1666 | if (request->auth_flavs[i] == RPC_AUTH_NULL) | ||
| 1667 | goto out_default; | ||
| 1668 | } | ||
| 1669 | |||
| 1670 | dfprintk(MOUNT, "NFS: no auth flavors in common with server\n"); | ||
| 1671 | goto out_err; | ||
| 1672 | 1636 | ||
| 1673 | out_default: | ||
| 1674 | /* use default if flavor not already set */ | ||
| 1675 | flavor = (args->auth_flavors[0] == RPC_AUTH_MAXFLAVOR) ? | ||
| 1676 | RPC_AUTH_UNIX : args->auth_flavors[0]; | ||
| 1677 | out_set: | ||
| 1678 | args->auth_flavors[0] = flavor; | ||
| 1679 | out: | 1637 | out: |
| 1680 | dfprintk(MOUNT, "NFS: using auth flavor %d\n", args->auth_flavors[0]); | 1638 | dfprintk(MOUNT, "NFS: using auth flavor %u\n", args->auth_flavors[0]); |
| 1681 | return 0; | 1639 | return 0; |
| 1682 | out_err: | ||
| 1683 | return -EACCES; | ||
| 1684 | } | 1640 | } |
| 1685 | 1641 | ||
| 1686 | /* | 1642 | /* |
| @@ -1743,13 +1699,17 @@ static int nfs_request_mount(struct nfs_parsed_mount_data *args, | |||
| 1743 | return status; | 1699 | return status; |
| 1744 | } | 1700 | } |
| 1745 | 1701 | ||
| 1746 | return nfs_select_flavor(args, &request); | 1702 | return 0; |
| 1747 | } | 1703 | } |
| 1748 | 1704 | ||
| 1749 | static struct nfs_server *nfs_try_mount_request(struct nfs_mount_info *mount_info, | 1705 | static struct nfs_server *nfs_try_mount_request(struct nfs_mount_info *mount_info, |
| 1750 | struct nfs_subversion *nfs_mod) | 1706 | struct nfs_subversion *nfs_mod) |
| 1751 | { | 1707 | { |
| 1752 | int status; | 1708 | int status; |
| 1709 | unsigned int i; | ||
| 1710 | bool tried_auth_unix = false; | ||
| 1711 | bool auth_null_in_list = false; | ||
| 1712 | struct nfs_server *server = ERR_PTR(-EACCES); | ||
| 1753 | struct nfs_parsed_mount_data *args = mount_info->parsed; | 1713 | struct nfs_parsed_mount_data *args = mount_info->parsed; |
| 1754 | rpc_authflavor_t authlist[NFS_MAX_SECFLAVORS]; | 1714 | rpc_authflavor_t authlist[NFS_MAX_SECFLAVORS]; |
| 1755 | unsigned int authlist_len = ARRAY_SIZE(authlist); | 1715 | unsigned int authlist_len = ARRAY_SIZE(authlist); |
| @@ -1759,6 +1719,58 @@ static struct nfs_server *nfs_try_mount_request(struct nfs_mount_info *mount_inf | |||
| 1759 | if (status) | 1719 | if (status) |
| 1760 | return ERR_PTR(status); | 1720 | return ERR_PTR(status); |
| 1761 | 1721 | ||
| 1722 | /* | ||
| 1723 | * Was a sec= authflavor specified in the options? First, verify | ||
| 1724 | * whether the server supports it, and then just try to use it if so. | ||
| 1725 | */ | ||
| 1726 | if (args->auth_flavors[0] != RPC_AUTH_MAXFLAVOR) { | ||
| 1727 | status = nfs_verify_authflavor(args, authlist, authlist_len); | ||
| 1728 | dfprintk(MOUNT, "NFS: using auth flavor %u\n", args->auth_flavors[0]); | ||
| 1729 | if (status) | ||
| 1730 | return ERR_PTR(status); | ||
| 1731 | return nfs_mod->rpc_ops->create_server(mount_info, nfs_mod); | ||
| 1732 | } | ||
| 1733 | |||
| 1734 | /* | ||
| 1735 | * No sec= option was provided. RFC 2623, section 2.7 suggests we | ||
| 1736 | * SHOULD prefer the flavor listed first. However, some servers list | ||
| 1737 | * AUTH_NULL first. Avoid ever choosing AUTH_NULL. | ||
| 1738 | */ | ||
| 1739 | for (i = 0; i < authlist_len; ++i) { | ||
| 1740 | rpc_authflavor_t flavor; | ||
| 1741 | struct rpcsec_gss_info info; | ||
| 1742 | |||
| 1743 | flavor = authlist[i]; | ||
| 1744 | switch (flavor) { | ||
| 1745 | case RPC_AUTH_UNIX: | ||
| 1746 | tried_auth_unix = true; | ||
| 1747 | break; | ||
| 1748 | case RPC_AUTH_NULL: | ||
| 1749 | auth_null_in_list = true; | ||
| 1750 | continue; | ||
| 1751 | default: | ||
| 1752 | if (rpcauth_get_gssinfo(flavor, &info) != 0) | ||
| 1753 | continue; | ||
| 1754 | /* Fallthrough */ | ||
| 1755 | } | ||
| 1756 | dfprintk(MOUNT, "NFS: attempting to use auth flavor %u\n", flavor); | ||
| 1757 | args->auth_flavors[0] = flavor; | ||
| 1758 | server = nfs_mod->rpc_ops->create_server(mount_info, nfs_mod); | ||
| 1759 | if (!IS_ERR(server)) | ||
| 1760 | return server; | ||
| 1761 | } | ||
| 1762 | |||
| 1763 | /* | ||
| 1764 | * Nothing we tried so far worked. At this point, give up if we've | ||
| 1765 | * already tried AUTH_UNIX or if the server's list doesn't contain | ||
| 1766 | * AUTH_NULL | ||
| 1767 | */ | ||
| 1768 | if (tried_auth_unix || !auth_null_in_list) | ||
| 1769 | return server; | ||
| 1770 | |||
| 1771 | /* Last chance! Try AUTH_UNIX */ | ||
| 1772 | dfprintk(MOUNT, "NFS: attempting to use auth flavor %u\n", RPC_AUTH_UNIX); | ||
| 1773 | args->auth_flavors[0] = RPC_AUTH_UNIX; | ||
| 1762 | return nfs_mod->rpc_ops->create_server(mount_info, nfs_mod); | 1774 | return nfs_mod->rpc_ops->create_server(mount_info, nfs_mod); |
| 1763 | } | 1775 | } |
| 1764 | 1776 | ||
