nfs4.1: Minimal SP4_MACH_CRED implementation
Subsystems (2)
PATCH 1/1 nfs4.1: Minimal SP4_MACH_CRED implementation
This is a minimal client side implementation of SP4_MACH_CRED. It will attempt to negotiate SP4_MACH_CRED iff the EXCHANGE_ID is using krb5i or krb5p auth. SP4_MACH_CRED will be used if the server supports the minimal operations:
BACKCHANNEL_CTL
BIND_CONN_TO_SESSION
CREATE_SESSION
DESTROY_SESSION
DESTROY_CLIENTID
This implementation only includes the EXCHANGE_ID negotiation code because the client will already use the machine cred for these operations.
This patch also lays the groundwork for adding more SP4_MACH_CRED "features" - instead of just using SP4_MACH_CRED wherever the server says it's ok, we will make sure that appropriate sets of operations are supported in the initial negotiation and then only use these negotiated features. The hope is that this will limit the scope of testing.
--- fs/nfs/nfs4proc.c | 115 +++++++++++++++++++++++++++++++++++++++++++--- fs/nfs/nfs4xdr.c | 73 +++++++++++++++++++++++++---- include/linux/nfs_fs_sb.h | 4 ++ include/linux/nfs_xdr.h | 19 ++++++++ 4 files changed, 194 insertions(+), 17 deletions(-)
fs/nfs/nfs4proc.c +108 -7
@@ -5915,16 +5915,63 @@ out: }/* -* nfs4_proc_exchange_id() +* Minimum set of SP4_MACH_CRED operations from RFC 5661 +*/ +static uint32_t _nfs4_spo_must_enforce[NFS4_OP_MAP_NUM_WORDS ] = { + [1 ] =1 << (OP_BIND_CONN_TO_SESSION -32 ) | +1 << (OP_EXCHANGE_ID -32 ) | +1 << (OP_CREATE_SESSION -32 ) | +1 << (OP_DESTROY_SESSION -32 ) | +1 << (OP_DESTROY_CLIENTID -32 ) +}; + +/* +* Select the state protection mode for client `clp' given the server results +* from exchange_id in `sp'. * -* Returns zero, a negative errno, or a negative NFS4ERR status code. +* Returns 0 on success, negative errno otherwise. +*/ +static int _nfs4_sp4_select_mode (struct nfs_client *clp, +struct nfs41_state_protection *sp) +{ +unsigned int i; + +if (sp->how ==SP4_MACH_CRED ) { +/* Print state protect result */ +dfprintk (MOUNT ,"Server SP4_MACH_CRED support:\n" ); +for (i =0 ; i <=LAST_NFS4_OP ; i++) { +if (test_bit (i, &sp->enforce.u.longs[0 ])) +dfprintk (MOUNT ," enforce op %d\n" , i); +if (test_bit (i, &sp->allow.u.longs[0 ])) +dfprintk (MOUNT ," allow op %d\n" , i); + } + +/* +* Minimal mode - state operations are allowed to use machine +* credential. Note this already happens by default, so the +* client doesn't have to do anything more than the negotiation. +*/ +if (memcmp (sp->enforce.u.words, _nfs4_spo_must_enforce, +sizeof (sp->enforce.u.words)) ==0 ) +set_bit (NFS_SP4_MACH_CRED_MINIMAL , &clp->cl_sp4_flags); + +if (!clp->cl_sp4_flags) { +dfprintk (MOUNT ,"sp4_mach_cred: disabled\n" ); +return -EINVAL ; + }else +dfprintk (MOUNT ,"sp4_mach_cred: enabled\n" ); + } + +return 0 ; +} + +/* +* _nfs4_proc_exchange_id() * -* Since the clientid has expired, all compounds using sessions -* associated with the stale clientid will be returning -* NFS4ERR_BADSESSION in the sequence operation, and will therefore -* be in some phase of session reset. +* Wrapper for EXCHANGE_ID operation. */ -int nfs4_proc_exchange_id (struct nfs_client *clp,struct rpc_cred *cred) +static int _nfs4_proc_exchange_id (struct nfs_client *clp,struct rpc_cred *cred, +u32 sp4_how) {nfs4_verifier verifier;struct nfs41_exchange_id_args args = {
@@ -5971,10 +6018,35 @@ int nfs4_proc_exchange_id(struct nfs_client *clp, struct rpc_cred *cred) goto out_server_scope; } +switch (sp4_how) { +case SP4_NONE : + args.state_protect.how =SP4_NONE ; +break ; + +case SP4_MACH_CRED : + args.state_protect.how =SP4_MACH_CRED ; + +/* request minumum set op operations */ +memcpy (args.state_protect.enforce.u.words, + &_nfs4_spo_must_enforce, +sizeof (uint32_t ) *NFS4_OP_MAP_NUM_WORDS ); + +break ; + +default : +/* unsupportd! */ +WARN_ON_ONCE (1 ); + status = -EINVAL ; + goto out_server_scope; + } + status =rpc_call_sync (clp->cl_rpcclient, &msg,RPC_TASK_TIMEOUT );if (status ==0 ) status =nfs4_check_cl_exchange_flags (res.flags); +if (status ==0 ) + status =_nfs4_sp4_select_mode (clp, &res.state_protect); +if (status ==0 ) { clp->cl_clientid = res.clientid; clp->cl_exchange_flags = (res.flags & ~EXCHGID4_FLAG_CONFIRMED_R );
@@ -6021,6 +6093,35 @@ out:return status; } +/* +* nfs4_proc_exchange_id() +* +* Returns zero, a negative errno, or a negative NFS4ERR status code. +* +* Since the clientid has expired, all compounds using sessions +* associated with the stale clientid will be returning +* NFS4ERR_BADSESSION in the sequence operation, and will therefore +* be in some phase of session reset. +* +* Will attempt to negotiate SP4_MACH_CRED if krb5i / krb5p auth is used. +*/ +int nfs4_proc_exchange_id (struct nfs_client *clp,struct rpc_cred *cred) +{ +rpc_authflavor_t authflavor = clp->cl_rpcclient->cl_auth->au_flavor; +int status; + +/* try SP4_MACH_CRED if krb5i/p */ +if (authflavor ==RPC_AUTH_GSS_KRB5I || + authflavor ==RPC_AUTH_GSS_KRB5P ) { + status =_nfs4_proc_exchange_id (clp, cred,SP4_MACH_CRED ); +if (!status) +return 0 ; + } + +/* try SP4_NONE */ +return _nfs4_proc_exchange_id (clp, cred,SP4_NONE ); +} +static int _nfs4_proc_destroy_clientid (struct nfs_client *clp,struct rpc_cred *cred) {
fs/nfs/nfs4xdr.c +63 -10
122 lines not on this page · raw message
include/linux/nfs_fs_sb.h +4 -0
@@ -87,6 +87,10 @@ struct nfs_client {struct nfs41_server_owner *cl_serverowner;struct nfs41_server_scope *cl_serverscope;struct nfs41_impl_id *cl_implid; +/* nfs 4.1+ state protection modes: */ +unsigned long cl_sp4_flags; +#define NFS_SP4_MACH_CRED_MINIMAL 1/* Minimal sp4_mach_cred - state ops +* must use machine cred */ #endif /* CONFIG_NFS_V4 */ #ifdef CONFIG_NFS_FSCACHE
include/linux/nfs_xdr.h +19 -0
@@ -1107,6 +1107,23 @@ struct pnfs_ds_commit_info {struct pnfs_commit_bucket *buckets; }; +#define NFS4_OP_MAP_NUM_LONGS \ + DIV_ROUND_UP(LAST_NFS4_OP, 8 * sizeof(unsigned long)) +#define NFS4_OP_MAP_NUM_WORDS \ + (NFS4_OP_MAP_NUM_LONGS * sizeof(unsigned long) / sizeof(u32)) +struct nfs4_op_map { +union { +unsigned long longs[NFS4_OP_MAP_NUM_LONGS ]; +u32 words[NFS4_OP_MAP_NUM_WORDS ]; + } u; +}; + +struct nfs41_state_protection { +u32 how; +struct nfs4_op_map enforce; +struct nfs4_op_map allow; +}; +#define NFS4_EXCHANGE_ID_LEN (48)struct nfs41_exchange_id_args {struct nfs_client *client;
@@ -1114,6 +1131,7 @@ struct nfs41_exchange_id_args {unsigned int id_len;char id[NFS4_EXCHANGE_ID_LEN ];u32 flags; +struct nfs41_state_protection state_protect; };struct nfs41_server_owner {
@@ -1146,6 +1164,7 @@ struct nfs41_exchange_id_res {struct nfs41_server_owner *server_owner;struct nfs41_server_scope *server_scope;struct nfs41_impl_id *impl_id; +struct nfs41_state_protection state_protect; };struct nfs41_create_session_args {
Signature · 1 line
1.7.12.4 (Apple Git-37)