diff options
Diffstat (limited to 'fs/nfs/super.c')
-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 | ||