18.33. Operation 40: BACKCHANNEL_CTL - Backchannel Control
18.33.1. ARGUMENT
typedef opaque gsshandle4_t<>; struct gss_cb_handles4 { rpc_gss_svc_t gcbp_service; /* RFC 2203 */ gsshandle4_t gcbp_handle_from_server; gsshandle4_t gcbp_handle_from_client; }; union callback_sec_parms4 switch (uint32_t cb_secflavor) { case AUTH_NONE: void; case AUTH_SYS: authsys_parms cbsp_sys_cred; /* RFC 1831 */ case RPCSEC_GSS: gss_cb_handles4 cbsp_gss_handles; }; struct BACKCHANNEL_CTL4args { uint32_t bca_cb_program; callback_sec_parms4 bca_sec_parms<>; };18.33.2. RESULT
struct BACKCHANNEL_CTL4res { nfsstat4 bcr_status; };
18.33.3. DESCRIPTION
The BACKCHANNEL_CTL operation replaces the backchannel's callback program number and adds (not replaces) RPCSEC_GSS handles for use by the backchannel. The arguments of the BACKCHANNEL_CTL call are a subset of the CREATE_SESSION parameters. In the arguments of BACKCHANNEL_CTL, the bca_cb_program field and bca_sec_parms fields correspond respectively to the csa_cb_program and csa_sec_parms fields of the arguments of CREATE_SESSION (Section 18.36). BACKCHANNEL_CTL MUST appear in a COMPOUND that starts with SEQUENCE. If the RPCSEC_GSS handle identified by gcbp_handle_from_server does not exist on the server, the server MUST return NFS4ERR_NOENT. If an RPCSEC_GSS handle is using the SSV context (see Section 2.10.9), then because each SSV RPCSEC_GSS handle shares a common SSV GSS context, there are security considerations specific to this situation discussed in Section 2.10.10.18.34. Operation 41: BIND_CONN_TO_SESSION - Associate Connection with Session
18.34.1. ARGUMENT
enum channel_dir_from_client4 { CDFC4_FORE = 0x1, CDFC4_BACK = 0x2, CDFC4_FORE_OR_BOTH = 0x3, CDFC4_BACK_OR_BOTH = 0x7 }; struct BIND_CONN_TO_SESSION4args { sessionid4 bctsa_sessid; channel_dir_from_client4 bctsa_dir; bool bctsa_use_conn_in_rdma_mode; };
18.34.2. RESULT
enum channel_dir_from_server4 { CDFS4_FORE = 0x1, CDFS4_BACK = 0x2, CDFS4_BOTH = 0x3 }; struct BIND_CONN_TO_SESSION4resok { sessionid4 bctsr_sessid; channel_dir_from_server4 bctsr_dir; bool bctsr_use_conn_in_rdma_mode; }; union BIND_CONN_TO_SESSION4res switch (nfsstat4 bctsr_status) { case NFS4_OK: BIND_CONN_TO_SESSION4resok bctsr_resok4; default: void; };18.34.3. DESCRIPTION
BIND_CONN_TO_SESSION is used to associate additional connections with a session. It MUST be used on the connection being associated with the session. It MUST be the only operation in the COMPOUND procedure. If SP4_NONE (Section 18.35) state protection is used, any principal, security flavor, or RPCSEC_GSS context MAY be used to invoke the operation. If SP4_MACH_CRED is used, RPCSEC_GSS MUST be used with the integrity or privacy services, using the principal that created the client ID. If SP4_SSV is used, RPCSEC_GSS with the SSV GSS mechanism (Section 2.10.9) and integrity or privacy MUST be used. If, when the client ID was created, the client opted for SP4_NONE state protection, the client is not required to use BIND_CONN_TO_SESSION to associate the connection with the session, unless the client wishes to associate the connection with the backchannel. When SP4_NONE protection is used, simply sending a COMPOUND request with a SEQUENCE operation is sufficient to associate the connection with the session specified in SEQUENCE.
The field bctsa_dir indicates whether the client wants to associate the connection with the fore channel or the backchannel or both channels. The value CDFC4_FORE_OR_BOTH indicates that the client wants to associate the connection with both the fore channel and backchannel, but will accept the connection being associated to just the fore channel. The value CDFC4_BACK_OR_BOTH indicates that the client wants to associate with both the fore channel and backchannel, but will accept the connection being associated with just the backchannel. The server replies in bctsr_dir which channel(s) the connection is associated with. If the client specified CDFC4_FORE, the server MUST return CDFS4_FORE. If the client specified CDFC4_BACK, the server MUST return CDFS4_BACK. If the client specified CDFC4_FORE_OR_BOTH, the server MUST return CDFS4_FORE or CDFS4_BOTH. If the client specified CDFC4_BACK_OR_BOTH, the server MUST return CDFS4_BACK or CDFS4_BOTH. See the CREATE_SESSION operation (Section 18.36), and the description of the argument csa_use_conn_in_rdma_mode to understand bctsa_use_conn_in_rdma_mode, and the description of csr_use_conn_in_rdma_mode to understand bctsr_use_conn_in_rdma_mode. Invoking BIND_CONN_TO_SESSION on a connection already associated with the specified session has no effect, and the server MUST respond with NFS4_OK, unless the client is demanding changes to the set of channels the connection is associated with. If so, the server MUST return NFS4ERR_INVAL.18.34.4. IMPLEMENTATION
If a session's channel loses all connections, depending on the client ID's state protection and type of channel, the client might need to use BIND_CONN_TO_SESSION to associate a new connection. If the server restarted and does not keep the reply cache in stable storage, the server will not recognize the session ID. The client will ultimately have to invoke EXCHANGE_ID to create a new client ID and session. Suppose SP4_SSV state protection is being used, and BIND_CONN_TO_SESSION is among the operations included in the spo_must_enforce set when the client ID was created (Section 18.35). If so, there is an issue if SET_SSV is sent, no response is returned, and the last connection associated with the client ID drops. The client, per the sessions model, MUST retry the SET_SSV. But it needs a new connection to do so, and MUST associate that connection with the session via a BIND_CONN_TO_SESSION authenticated with the SSV GSS mechanism. The problem is that the RPCSEC_GSS message integrity
codes use a subkey derived from the SSV as the key and the SSV may
have changed. While there are multiple recovery strategies, a
single, general strategy is described here.
o The client reconnects.
o The client assumes that the SET_SSV was executed, and so sends
BIND_CONN_TO_SESSION with the subkey (derived from the new SSV,
i.e., what SET_SSV would have set the SSV to) used as the key for
the RPCSEC_GSS credential message integrity codes.
o If the request succeeds, this means that the original attempted
SET_SSV did execute successfully. The client re-sends the
original SET_SSV, which the server will reply to via the reply
cache.
o If the server returns an RPC authentication error, this means that
the server's current SSV was not changed (and the SET_SSV was
likely not executed). The client then tries BIND_CONN_TO_SESSION
with the subkey derived from the old SSV as the key for the
RPCSEC_GSS message integrity codes.
o The attempted BIND_CONN_TO_SESSION with the old SSV should
succeed. If so, the client re-sends the original SET_SSV. If the
original SET_SSV was not executed, then the server executes it.
If the original SET_SSV was executed but failed, the server will
return the SET_SSV from the reply cache.
18.35. Operation 42: EXCHANGE_ID - Instantiate Client ID
The EXCHANGE_ID exchanges long-hand client and server identifiers
(owners), and creates a client ID.
18.35.1. ARGUMENT
const EXCHGID4_FLAG_SUPP_MOVED_REFER = 0x00000001;
const EXCHGID4_FLAG_SUPP_MOVED_MIGR = 0x00000002;
const EXCHGID4_FLAG_BIND_PRINC_STATEID = 0x00000100;
const EXCHGID4_FLAG_USE_NON_PNFS = 0x00010000;
const EXCHGID4_FLAG_USE_PNFS_MDS = 0x00020000;
const EXCHGID4_FLAG_USE_PNFS_DS = 0x00040000;
const EXCHGID4_FLAG_MASK_PNFS = 0x00070000;
const EXCHGID4_FLAG_UPD_CONFIRMED_REC_A = 0x40000000;
const EXCHGID4_FLAG_CONFIRMED_R = 0x80000000;
struct state_protect_ops4 {
bitmap4 spo_must_enforce;
bitmap4 spo_must_allow;
};
struct ssv_sp_parms4 {
state_protect_ops4 ssp_ops;
sec_oid4 ssp_hash_algs<>;
sec_oid4 ssp_encr_algs<>;
uint32_t ssp_window;
uint32_t ssp_num_gss_handles;
};
enum state_protect_how4 {
SP4_NONE = 0,
SP4_MACH_CRED = 1,
SP4_SSV = 2
};
union state_protect4_a switch(state_protect_how4 spa_how) {
case SP4_NONE:
void;
case SP4_MACH_CRED:
state_protect_ops4 spa_mach_ops;
case SP4_SSV:
ssv_sp_parms4 spa_ssv_parms;
};
struct EXCHANGE_ID4args {
client_owner4 eia_clientowner;
uint32_t eia_flags;
state_protect4_a eia_state_protect;
nfs_impl_id4 eia_client_impl_id<1>;
};
18.35.2. RESULT
struct ssv_prot_info4 {
state_protect_ops4 spi_ops;
uint32_t spi_hash_alg;
uint32_t spi_encr_alg;
uint32_t spi_ssv_len;
uint32_t spi_window;
gsshandle4_t spi_handles<>;
};
union state_protect4_r switch(state_protect_how4 spr_how) {
case SP4_NONE:
void;
case SP4_MACH_CRED:
state_protect_ops4 spr_mach_ops;
case SP4_SSV:
ssv_prot_info4 spr_ssv_info;
};
struct EXCHANGE_ID4resok {
clientid4 eir_clientid;
sequenceid4 eir_sequenceid;
uint32_t eir_flags;
state_protect4_r eir_state_protect;
server_owner4 eir_server_owner;
opaque eir_server_scope<NFS4_OPAQUE_LIMIT>;
nfs_impl_id4 eir_server_impl_id<1>;
};
union EXCHANGE_ID4res switch (nfsstat4 eir_status) {
case NFS4_OK:
EXCHANGE_ID4resok eir_resok4;
default:
void;
};
18.35.3. DESCRIPTION
The client uses the EXCHANGE_ID operation to register a particular
client owner with the server. The client ID returned from this
operation will be necessary for requests that create state on the
server and will serve as a parent object to sessions created by the
client. In order to confirm the client ID it must first be used,
along with the returned eir_sequenceid, as arguments to
CREATE_SESSION. If the flag EXCHGID4_FLAG_CONFIRMED_R is set in the
result, eir_flags, then eir_sequenceid MUST be ignored, as it has no
relevancy.
EXCHANGE_ID MAY be sent in a COMPOUND procedure that starts with
SEQUENCE. However, when a client communicates with a server for the
first time, it will not have a session, so using SEQUENCE will not be
possible. If EXCHANGE_ID is sent without a preceding SEQUENCE, then
it MUST be the only operation in the COMPOUND procedure's request.
If it is not, the server MUST return NFS4ERR_NOT_ONLY_OP.
The eia_clientowner field is composed of a co_verifier field and a co_ownerid string. As noted in Section 2.4, the co_ownerid describes the client, and the co_verifier is the incarnation of the client. An EXCHANGE_ID sent with a new incarnation of the client will lead to the server removing lock state of the old incarnation. Whereas an EXCHANGE_ID sent with the current incarnation and co_ownerid will result in an error or an update of the client ID's properties, depending on the arguments to EXCHANGE_ID. A server MUST NOT use the same client ID for two different incarnations of an eir_clientowner. In addition to the client ID and sequence ID, the server returns a server owner (eir_server_owner) and server scope (eir_server_scope). The former field is used for network trunking as described in Section 2.10.5. The latter field is used to allow clients to determine when client IDs sent by one server may be recognized by another in the event of file system migration (see Section 11.7.7). The client ID returned by EXCHANGE_ID is only unique relative to the combination of eir_server_owner.so_major_id and eir_server_scope. Thus, if two servers return the same client ID, the onus is on the client to distinguish the client IDs on the basis of eir_server_owner.so_major_id and eir_server_scope. In the event two different servers claim matching server_owner.so_major_id and eir_server_scope, the client can use the verification techniques discussed in Section 2.10.5 to determine if the servers are distinct. If they are distinct, then the client will need to note the destination network addresses of the connections used with each server, and use the network address as the final discriminator. The server, as defined by the unique identity expressed in the so_major_id of the server owner and the server scope, needs to track several properties of each client ID it hands out. The properties apply to the client ID and all sessions associated with the client ID. The properties are derived from the arguments and results of EXCHANGE_ID. The client ID properties include: o The capabilities expressed by the following bits, which come from the results of EXCHANGE_ID: * EXCHGID4_FLAG_SUPP_MOVED_REFER * EXCHGID4_FLAG_SUPP_MOVED_MIGR * EXCHGID4_FLAG_BIND_PRINC_STATEID * EXCHGID4_FLAG_USE_NON_PNFS
* EXCHGID4_FLAG_USE_PNFS_MDS
* EXCHGID4_FLAG_USE_PNFS_DS
These properties may be updated by subsequent EXCHANGE_ID requests
on confirmed client IDs though the server MAY refuse to change
them.
o The state protection method used, one of SP4_NONE, SP4_MACH_CRED,
or SP4_SSV, as set by the spa_how field of the arguments to
EXCHANGE_ID. Once the client ID is confirmed, this property
cannot be updated by subsequent EXCHANGE_ID requests.
o For SP4_MACH_CRED or SP4_SSV state protection:
* The list of operations (spo_must_enforce) that MUST use the
specified state protection. This list comes from the results
of EXCHANGE_ID.
* The list of operations (spo_must_allow) that MAY use the
specified state protection. This list comes from the results
of EXCHANGE_ID.
Once the client ID is confirmed, these properties cannot be
updated by subsequent EXCHANGE_ID requests.
o For SP4_SSV protection:
* The OID of the hash algorithm. This property is represented by
one of the algorithms in the ssp_hash_algs field of the
EXCHANGE_ID arguments. Once the client ID is confirmed, this
property cannot be updated by subsequent EXCHANGE_ID requests.
* The OID of the encryption algorithm. This property is
represented by one of the algorithms in the ssp_encr_algs field
of the EXCHANGE_ID arguments. Once the client ID is confirmed,
this property cannot be updated by subsequent EXCHANGE_ID
requests.
* The length of the SSV. This property is represented by the
spi_ssv_len field in the EXCHANGE_ID results. Once the client
ID is confirmed, this property cannot be updated by subsequent
EXCHANGE_ID requests.
There are REQUIRED and RECOMMENDED relationships among the
length of the key of the encryption algorithm ("key length"),
the length of the output of hash algorithm ("hash length"), and
the length of the SSV ("SSV length").
+ key length MUST be <= hash length. This is because the keys
used for the encryption algorithm are actually subkeys
derived from the SSV, and the derivation is via the hash
algorithm. The selection of an encryption algorithm with a
key length that exceeded the length of the output of the
hash algorithm would require padding, and thus weaken the
use of the encryption algorithm.
+ hash length SHOULD be <= SSV length. This is because the
SSV is a key used to derive subkeys via an HMAC, and it is
recommended that the key used as input to an HMAC be at
least as long as the length of the HMAC's hash algorithm's
output (see Section 3 of RFC2104 [11]).
+ key length SHOULD be <= SSV length. This is a transitive
result of the above two invariants.
+ key length SHOULD be >= hash length / 2. This is because
the subkey derivation is via an HMAC and it is recommended
that if the HMAC has to be truncated, it should not be
truncated to less than half the hash length (see Section 4
of RFC2104 [11]).
* Number of concurrent versions of the SSV the client and server
will support (Section 2.10.9). This property is represented by
spi_window in the EXCHANGE_ID results. The property may be
updated by subsequent EXCHANGE_ID requests.
o The client's implementation ID as represented by the
eia_client_impl_id field of the arguments. The property may be
updated by subsequent EXCHANGE_ID requests.
o The server's implementation ID as represented by the
eir_server_impl_id field of the reply. The property may be
updated by replies to subsequent EXCHANGE_ID requests.
The eia_flags passed as part of the arguments and the eir_flags
results allow the client and server to inform each other of their
capabilities as well as indicate how the client ID will be used.
Whether a bit is set or cleared on the arguments' flags does not
force the server to set or clear the same bit on the results' side.
Bits not defined above cannot be set in the eia_flags field. If they
are, the server MUST reject the operation with NFS4ERR_INVAL.
The EXCHGID4_FLAG_UPD_CONFIRMED_REC_A bit can only be set in
eia_flags; it is always off in eir_flags. The
EXCHGID4_FLAG_CONFIRMED_R bit can only be set in eir_flags; it is
always off in eia_flags. If the server recognizes the co_ownerid and
co_verifier as mapping to a confirmed client ID, it sets EXCHGID4_FLAG_CONFIRMED_R in eir_flags. The EXCHGID4_FLAG_CONFIRMED_R flag allows a client to tell if the client ID it is trying to create already exists and is confirmed. If EXCHGID4_FLAG_UPD_CONFIRMED_REC_A is set in eia_flags, this means that the client is attempting to update properties of an existing confirmed client ID (if the client wants to update properties of an unconfirmed client ID, it MUST NOT set EXCHGID4_FLAG_UPD_CONFIRMED_REC_A). If so, it is RECOMMENDED that the client send the update EXCHANGE_ID operation in the same COMPOUND as a SEQUENCE so that the EXCHANGE_ID is executed exactly once. Whether the client can update the properties of client ID depends on the state protection it selected when the client ID was created, and the principal and security flavor it uses when sending the EXCHANGE_ID request. The situations described in items 6, 7, 8, or 9 of the second numbered list of Section 18.35.4 will apply. Note that if the operation succeeds and returns a client ID that is already confirmed, the server MUST set the EXCHGID4_FLAG_CONFIRMED_R bit in eir_flags. If EXCHGID4_FLAG_UPD_CONFIRMED_REC_A is not set in eia_flags, this means that the client is trying to establish a new client ID; it is attempting to trunk data communication to the server (Section 2.10.5); or it is attempting to update properties of an unconfirmed client ID. The situations described in items 1, 2, 3, 4, or 5 of the second numbered list of Section 18.35.4 will apply. Note that if the operation succeeds and returns a client ID that was previously confirmed, the server MUST set the EXCHGID4_FLAG_CONFIRMED_R bit in eir_flags. When the EXCHGID4_FLAG_SUPP_MOVED_REFER flag bit is set, the client indicates that it is capable of dealing with an NFS4ERR_MOVED error as part of a referral sequence. When this bit is not set, it is still legal for the server to perform a referral sequence. However, a server may use the fact that the client is incapable of correctly responding to a referral, by avoiding it for that particular client. It may, for instance, act as a proxy for that particular file system, at some cost in performance, although it is not obligated to do so. If the server will potentially perform a referral, it MUST set EXCHGID4_FLAG_SUPP_MOVED_REFER in eir_flags. When the EXCHGID4_FLAG_SUPP_MOVED_MIGR is set, the client indicates that it is capable of dealing with an NFS4ERR_MOVED error as part of a file system migration sequence. When this bit is not set, it is still legal for the server to indicate that a file system has moved, when this in fact happens. However, a server may use the fact that the client is incapable of correctly responding to a migration in its
scheduling of file systems to migrate so as to avoid migration of file systems being actively used. It may also hide actual migrations from clients unable to deal with them by acting as a proxy for a migrated file system for particular clients, at some cost in performance, although it is not obligated to do so. If the server will potentially perform a migration, it MUST set EXCHGID4_FLAG_SUPP_MOVED_MIGR in eir_flags. When EXCHGID4_FLAG_BIND_PRINC_STATEID is set, the client indicates that it wants the server to bind the stateid to the principal. This means that when a principal creates a stateid, it has to be the one to use the stateid. If the server will perform binding, it will return EXCHGID4_FLAG_BIND_PRINC_STATEID. The server MAY return EXCHGID4_FLAG_BIND_PRINC_STATEID even if the client does not request it. If an update to the client ID changes the value of EXCHGID4_FLAG_BIND_PRINC_STATEID's client ID property, the effect applies only to new stateids. Existing stateids (and all stateids with the same "other" field) that were created with stateid to principal binding in force will continue to have binding in force. Existing stateids (and all stateids with the same "other" field) that were created with stateid to principal not in force will continue to have binding not in force. The EXCHGID4_FLAG_USE_NON_PNFS, EXCHGID4_FLAG_USE_PNFS_MDS, and EXCHGID4_FLAG_USE_PNFS_DS bits are described in Section 13.1 and convey roles the client ID is to be used for in a pNFS environment. The server MUST set one of the acceptable combinations of these bits (roles) in eir_flags, as specified in Section 13.1. Note that the same client owner/server owner pair can have multiple roles. Multiple roles can be associated with the same client ID or with different client IDs. Thus, if a client sends EXCHANGE_ID from the same client owner to the same server owner multiple times, but specifies different pNFS roles each time, the server might return different client IDs. Given that different pNFS roles might have different client IDs, the client may ask for different properties for each role/client ID. The spa_how field of the eia_state_protect field specifies how the client wants to protect its client, locking, and session states from unauthorized changes (Section 2.10.8.3): o SP4_NONE. The client does not request the NFSv4.1 server to enforce state protection. The NFSv4.1 server MUST NOT enforce state protection for the returned client ID. o SP4_MACH_CRED. If spa_how is SP4_MACH_CRED, then the client MUST send the EXCHANGE_ID request with RPCSEC_GSS as the security flavor, and with a service of RPC_GSS_SVC_INTEGRITY or
RPC_GSS_SVC_PRIVACY. If SP4_MACH_CRED is specified, then the
client wants to use an RPCSEC_GSS-based machine credential to
protect its state. The server MUST note the principal the
EXCHANGE_ID operation was sent with, and the GSS mechanism used.
These notes collectively comprise the machine credential.
After the client ID is confirmed, as long as the lease associated
with the client ID is unexpired, a subsequent EXCHANGE_ID
operation that uses the same eia_clientowner.co_owner as the first
EXCHANGE_ID MUST also use the same machine credential as the first
EXCHANGE_ID. The server returns the same client ID for the
subsequent EXCHANGE_ID as that returned from the first
EXCHANGE_ID.
o SP4_SSV. If spa_how is SP4_SSV, then the client MUST send the
EXCHANGE_ID request with RPCSEC_GSS as the security flavor, and
with a service of RPC_GSS_SVC_INTEGRITY or RPC_GSS_SVC_PRIVACY.
If SP4_SSV is specified, then the client wants to use the SSV to
protect its state. The server records the credential used in the
request as the machine credential (as defined above) for the
eia_clientowner.co_owner. The CREATE_SESSION operation that
confirms the client ID MUST use the same machine credential.
When a client specifies SP4_MACH_CRED or SP4_SSV, it also provides
two lists of operations (each expressed as a bitmap). The first list
is spo_must_enforce and consists of those operations the client MUST
send (subject to the server confirming the list of operations in the
result of EXCHANGE_ID) with the machine credential (if SP4_MACH_CRED
protection is specified) or the SSV-based credential (if SP4_SSV
protection is used). The client MUST send the operations with
RPCSEC_GSS credentials that specify the RPC_GSS_SVC_INTEGRITY or
RPC_GSS_SVC_PRIVACY security service. Typically, the first list of
operations includes EXCHANGE_ID, CREATE_SESSION, DELEGPURGE,
DESTROY_SESSION, BIND_CONN_TO_SESSION, and DESTROY_CLIENTID. The
client SHOULD NOT specify in this list any operations that require a
filehandle because the server's access policies MAY conflict with the
client's choice, and thus the client would then be unable to access a
subset of the server's namespace.
Note that if SP4_SSV protection is specified, and the client
indicates that CREATE_SESSION must be protected with SP4_SSV, because
the SSV cannot exist without a confirmed client ID, the first
CREATE_SESSION MUST instead be sent using the machine credential, and
the server MUST accept the machine credential.
There is a corresponding result, also called spo_must_enforce, of the
operations for which the server will require SP4_MACH_CRED or SP4_SSV
protection. Normally, the server's result equals the client's
argument, but the result MAY be different. If the client requests
one or more operations in the set { EXCHANGE_ID, CREATE_SESSION,
DELEGPURGE, DESTROY_SESSION, BIND_CONN_TO_SESSION, DESTROY_CLIENTID
}, then the result spo_must_enforce MUST include the operations the
client requested from that set.
If spo_must_enforce in the results has BIND_CONN_TO_SESSION set, then
connection binding enforcement is enabled, and the client MUST use
the machine (if SP4_MACH_CRED protection is used) or SSV (if SP4_SSV
protection is used) credential on calls to BIND_CONN_TO_SESSION.
The second list is spo_must_allow and consists of those operations
the client wants to have the option of sending with the machine
credential or the SSV-based credential, even if the object the
operations are performed on is not owned by the machine or SSV
credential.
The corresponding result, also called spo_must_allow, consists of the
operations the server will allow the client to use SP4_SSV or
SP4_MACH_CRED credentials with. Normally, the server's result equals
the client's argument, but the result MAY be different.
The purpose of spo_must_allow is to allow clients to solve the
following conundrum. Suppose the client ID is confirmed with
EXCHGID4_FLAG_BIND_PRINC_STATEID, and it calls OPEN with the
RPCSEC_GSS credentials of a normal user. Now suppose the user's
credentials expire, and cannot be renewed (e.g., a Kerberos ticket
granting ticket expires, and the user has logged off and will not be
acquiring a new ticket granting ticket). The client will be unable
to send CLOSE without the user's credentials, which is to say the
client has to either leave the state on the server or re-send
EXCHANGE_ID with a new verifier to clear all state, that is, unless
the client includes CLOSE on the list of operations in spo_must_allow
and the server agrees.
The SP4_SSV protection parameters also have:
ssp_hash_algs:
This is the set of algorithms the client supports for the purpose
of computing the digests needed for the internal SSV GSS mechanism
and for the SET_SSV operation. Each algorithm is specified as an
object identifier (OID). The REQUIRED algorithms for a server are
id-sha1, id-sha224, id-sha256, id-sha384, and id-sha512 [28]. The
algorithm the server selects among the set is indicated in
spi_hash_alg, a field of spr_ssv_prot_info. The field
spi_hash_alg is an index into the array ssp_hash_algs. If the
server does not support any of the offered algorithms, it returns
NFS4ERR_HASH_ALG_UNSUPP. If ssp_hash_algs is empty, the server
MUST return NFS4ERR_INVAL.
ssp_encr_algs:
This is the set of algorithms the client supports for the purpose
of providing privacy protection for the internal SSV GSS
mechanism. Each algorithm is specified as an OID. The REQUIRED
algorithm for a server is id-aes256-CBC. The RECOMMENDED
algorithms are id-aes192-CBC and id-aes128-CBC [29]. The selected
algorithm is returned in spi_encr_alg, an index into
ssp_encr_algs. If the server does not support any of the offered
algorithms, it returns NFS4ERR_ENCR_ALG_UNSUPP. If ssp_encr_algs
is empty, the server MUST return NFS4ERR_INVAL. Note that due to
previously stated requirements and recommendations on the
relationships between key length and hash length, some
combinations of RECOMMENDED and REQUIRED encryption algorithm and
hash algorithm either SHOULD NOT or MUST NOT be used. Table 12
summarizes the illegal and discouraged combinations.
ssp_window:
This is the number of SSV versions the client wants the server to
maintain (i.e., each successful call to SET_SSV produces a new
version of the SSV). If ssp_window is zero, the server MUST
return NFS4ERR_INVAL. The server responds with spi_window, which
MUST NOT exceed ssp_window, and MUST be at least one. Any
requests on the backchannel or fore channel that are using a
version of the SSV that is outside the window will fail with an
ONC RPC authentication error, and the requester will have to retry
them with the same slot ID and sequence ID.
ssp_num_gss_handles:
This is the number of RPCSEC_GSS handles the server should create
that are based on the GSS SSV mechanism (Section 2.10.9). It is
not the total number of RPCSEC_GSS handles for the client ID.
Indeed, subsequent calls to EXCHANGE_ID will add RPCSEC_GSS
handles. The server responds with a list of handles in
spi_handles. If the client asks for at least one handle and the
server cannot create it, the server MUST return an error. The
handles in spi_handles are not available for use until the client
ID is confirmed, which could be immediately if EXCHANGE_ID returns
EXCHGID4_FLAG_CONFIRMED_R, or upon successful confirmation from
CREATE_SESSION.
While a client ID can span all the connections that are connected
to a server sharing the same eir_server_owner.so_major_id, the
RPCSEC_GSS handles returned in spi_handles can only be used on
connections connected to a server that returns the same the
eir_server_owner.so_major_id and eir_server_owner.so_minor_id on
each connection. It is permissible for the client to set
ssp_num_gss_handles to zero; the client can create more handles
with another EXCHANGE_ID call.
Because each SSV RPCSEC_GSS handle shares a common SSV GSS
context, there are security considerations specific to this
situation discussed in Section 2.10.10.
The seq_window (see Section 5.2.3.1 of RFC2203 [4]) of each
RPCSEC_GSS handle in spi_handle MUST be the same as the seq_window
of the RPCSEC_GSS handle used for the credential of the RPC
request that the EXCHANGE_ID request was sent with.
+-------------------+----------------------+------------------------+
| Encryption | MUST NOT be combined | SHOULD NOT be combined |
| Algorithm | with | with |
+-------------------+----------------------+------------------------+
| id-aes128-CBC | | id-sha384, id-sha512 |
| id-aes192-CBC | id-sha1 | id-sha512 |
| id-aes256-CBC | id-sha1, id-sha224 | |
+-------------------+----------------------+------------------------+
Table 12
The arguments include an array of up to one element in length called
eia_client_impl_id. If eia_client_impl_id is present, it contains
the information identifying the implementation of the client.
Similarly, the results include an array of up to one element in
length called eir_server_impl_id that identifies the implementation
of the server. Servers MUST accept a zero-length eia_client_impl_id
array, and clients MUST accept a zero-length eir_server_impl_id
array.
An example use for implementation identifiers would be diagnostic
software that extracts this information in an attempt to identify
interoperability problems, performance workload behaviors, or general
usage statistics. Since the intent of having access to this
information is for planning or general diagnosis only, the client and
server MUST NOT interpret this implementation identity information in
a way that affects interoperational behavior of the implementation.
The reason is that if clients and servers did such a thing, they
might use fewer capabilities of the protocol than the peer can
support, or the client and server might refuse to interoperate.
Because it is possible that some implementations will violate the protocol specification and interpret the identity information, implementations MUST allow the users of the NFSv4 client and server to set the contents of the sent nfs_impl_id structure to any value.18.35.4. IMPLEMENTATION
A server's client record is a 5-tuple: 1. co_ownerid The client identifier string, from the eia_clientowner structure of the EXCHANGE_ID4args structure. 2. co_verifier: A client-specific value used to indicate incarnations (where a client restart represents a new incarnation), from the eia_clientowner structure of the EXCHANGE_ID4args structure. 3. principal: The principal that was defined in the RPC header's credential and/or verifier at the time the client record was established. 4. client ID: The shorthand client identifier, generated by the server and returned via the eir_clientid field in the EXCHANGE_ID4resok structure. 5. confirmed: A private field on the server indicating whether or not a client record has been confirmed. A client record is confirmed if there has been a successful CREATE_SESSION operation to confirm it. Otherwise, it is unconfirmed. An unconfirmed record is established by an EXCHANGE_ID call. Any unconfirmed record that is not confirmed within a lease period SHOULD be removed. The following identifiers represent special values for the fields in the records. ownerid_arg: The value of the eia_clientowner.co_ownerid subfield of the EXCHANGE_ID4args structure of the current request.
verifier_arg:
The value of the eia_clientowner.co_verifier subfield of the
EXCHANGE_ID4args structure of the current request.
old_verifier_arg:
A value of the eia_clientowner.co_verifier field of a client
record received in a previous request; this is distinct from
verifier_arg.
principal_arg:
The value of the RPCSEC_GSS principal for the current request.
old_principal_arg:
A value of the principal of a client record as defined by the RPC
header's credential or verifier of a previous request. This is
distinct from principal_arg.
clientid_ret:
The value of the eir_clientid field the server will return in the
EXCHANGE_ID4resok structure for the current request.
old_clientid_ret:
The value of the eir_clientid field the server returned in the
EXCHANGE_ID4resok structure for a previous request. This is
distinct from clientid_ret.
confirmed:
The client ID has been confirmed.
unconfirmed:
The client ID has not been confirmed.
Since EXCHANGE_ID is a non-idempotent operation, we must consider the
possibility that retries occur as a result of a client restart,
network partition, malfunctioning router, etc. Retries are
identified by the value of the eia_clientowner field of
EXCHANGE_ID4args, and the method for dealing with them is outlined in
the scenarios below.
The scenarios are described in terms of the client record(s) a server
has for a given co_ownerid. Note that if the client ID was created
specifying SP4_SSV state protection and EXCHANGE_ID as the one of the
operations in spo_must_allow, then the server MUST authorize
EXCHANGE_IDs with the SSV principal in addition to the principal that
created the client ID.
1. New Owner ID
If the server has no client records with
eia_clientowner.co_ownerid matching ownerid_arg, and
EXCHGID4_FLAG_UPD_CONFIRMED_REC_A is not set in the
EXCHANGE_ID, then a new shorthand client ID (let us call it
clientid_ret) is generated, and the following unconfirmed
record is added to the server's state.
{ ownerid_arg, verifier_arg, principal_arg, clientid_ret,
unconfirmed }
Subsequently, the server returns clientid_ret.
2. Non-Update on Existing Client ID
If the server has the following confirmed record, and the
request does not have EXCHGID4_FLAG_UPD_CONFIRMED_REC_A set,
then the request is the result of a retried request due to a
faulty router or lost connection, or the client is trying to
determine if it can perform trunking.
{ ownerid_arg, verifier_arg, principal_arg, clientid_ret,
confirmed }
Since the record has been confirmed, the client must have
received the server's reply from the initial EXCHANGE_ID
request. Since the server has a confirmed record, and since
EXCHGID4_FLAG_UPD_CONFIRMED_REC_A is not set, with the
possible exception of eir_server_owner.so_minor_id, the server
returns the same result it did when the client ID's properties
were last updated (or if never updated, the result when the
client ID was created). The confirmed record is unchanged.
3. Client Collision
If EXCHGID4_FLAG_UPD_CONFIRMED_REC_A is not set, and if the
server has the following confirmed record, then this request
is likely the result of a chance collision between the values
of the eia_clientowner.co_ownerid subfield of EXCHANGE_ID4args
for two different clients.
{ ownerid_arg, *, old_principal_arg, old_clientid_ret,
confirmed }
If there is currently no state associated with
old_clientid_ret, or if there is state but the lease has
expired, then this case is effectively equivalent to the New
Owner ID case of Paragraph 1. The confirmed record is
deleted, the old_clientid_ret and its lock state are deleted,
a new shorthand client ID is generated, and the following
unconfirmed record is added to the server's state.
{ ownerid_arg, verifier_arg, principal_arg, clientid_ret,
unconfirmed }
Subsequently, the server returns clientid_ret.
If old_clientid_ret has an unexpired lease with state, then no
state of old_clientid_ret is changed or deleted. The server
returns NFS4ERR_CLID_INUSE to indicate that the client should
retry with a different value for the
eia_clientowner.co_ownerid subfield of EXCHANGE_ID4args. The
client record is not changed.
4. Replacement of Unconfirmed Record
If the EXCHGID4_FLAG_UPD_CONFIRMED_REC_A flag is not set, and
the server has the following unconfirmed record, then the
client is attempting EXCHANGE_ID again on an unconfirmed
client ID, perhaps due to a retry, a client restart before
client ID confirmation (i.e., before CREATE_SESSION was
called), or some other reason.
{ ownerid_arg, *, *, old_clientid_ret, unconfirmed }
It is possible that the properties of old_clientid_ret are
different than those specified in the current EXCHANGE_ID.
Whether or not the properties are being updated, to eliminate
ambiguity, the server deletes the unconfirmed record,
generates a new client ID (clientid_ret), and establishes the
following unconfirmed record:
{ ownerid_arg, verifier_arg, principal_arg, clientid_ret,
unconfirmed }
5. Client Restart
If EXCHGID4_FLAG_UPD_CONFIRMED_REC_A is not set, and if the
server has the following confirmed client record, then this
request is likely from a previously confirmed client that has
restarted.
{ ownerid_arg, old_verifier_arg, principal_arg,
old_clientid_ret, confirmed }
Since the previous incarnation of the same client will no
longer be making requests, once the new client ID is confirmed
by CREATE_SESSION, byte-range locks and share reservations
should be released immediately rather than forcing the new
incarnation to wait for the lease time on the previous
incarnation to expire. Furthermore, session state should be
removed since if the client had maintained that information
across restart, this request would not have been sent. If the
server supports neither the CLAIM_DELEGATE_PREV nor
CLAIM_DELEG_PREV_FH claim types, associated delegations should
be purged as well; otherwise, delegations are retained and
recovery proceeds according to Section 10.2.1.
After processing, clientid_ret is returned to the client and
this client record is added:
{ ownerid_arg, verifier_arg, principal_arg, clientid_ret,
unconfirmed }
The previously described confirmed record continues to exist,
and thus the same ownerid_arg exists in both a confirmed and
unconfirmed state at the same time. The number of states can
collapse to one once the server receives an applicable
CREATE_SESSION or EXCHANGE_ID.
+ If the server subsequently receives a successful
CREATE_SESSION that confirms clientid_ret, then the server
atomically destroys the confirmed record and makes the
unconfirmed record confirmed as described in
Section 18.36.4.
+ If the server instead subsequently receives an EXCHANGE_ID
with the client owner equal to ownerid_arg, one strategy is
to simply delete the unconfirmed record, and process the
EXCHANGE_ID as described in the entirety of
Section 18.35.4.
6. Update
If EXCHGID4_FLAG_UPD_CONFIRMED_REC_A is set, and the server
has the following confirmed record, then this request is an
attempt at an update.
{ ownerid_arg, verifier_arg, principal_arg, clientid_ret,
confirmed }
Since the record has been confirmed, the client must have
received the server's reply from the initial EXCHANGE_ID
request. The server allows the update, and the client record
is left intact.
7. Update but No Confirmed Record
If EXCHGID4_FLAG_UPD_CONFIRMED_REC_A is set, and the server
has no confirmed record corresponding ownerid_arg, then the
server returns NFS4ERR_NOENT and leaves any unconfirmed record
intact.
8. Update but Wrong Verifier
If EXCHGID4_FLAG_UPD_CONFIRMED_REC_A is set, and the server
has the following confirmed record, then this request is an
illegal attempt at an update, perhaps because of a retry from
a previous client incarnation.
{ ownerid_arg, old_verifier_arg, *, clientid_ret, confirmed }
The server returns NFS4ERR_NOT_SAME and leaves the client
record intact.
9. Update but Wrong Principal
If EXCHGID4_FLAG_UPD_CONFIRMED_REC_A is set, and the server
has the following confirmed record, then this request is an
illegal attempt at an update by an unauthorized principal.
{ ownerid_arg, verifier_arg, old_principal_arg, clientid_ret,
confirmed }
The server returns NFS4ERR_PERM and leaves the client record
intact.
18.36. Operation 43: CREATE_SESSION - Create New Session and Confirm Client ID
18.36.1. ARGUMENT
struct channel_attrs4 { count4 ca_headerpadsize; count4 ca_maxrequestsize; count4 ca_maxresponsesize; count4 ca_maxresponsesize_cached; count4 ca_maxoperations; count4 ca_maxrequests; uint32_t ca_rdma_ird<1>; }; const CREATE_SESSION4_FLAG_PERSIST = 0x00000001; const CREATE_SESSION4_FLAG_CONN_BACK_CHAN = 0x00000002; const CREATE_SESSION4_FLAG_CONN_RDMA = 0x00000004; struct CREATE_SESSION4args { clientid4 csa_clientid; sequenceid4 csa_sequence; uint32_t csa_flags; channel_attrs4 csa_fore_chan_attrs; channel_attrs4 csa_back_chan_attrs; uint32_t csa_cb_program; callback_sec_parms4 csa_sec_parms<>; };18.36.2. RESULT
struct CREATE_SESSION4resok { sessionid4 csr_sessionid; sequenceid4 csr_sequence; uint32_t csr_flags; channel_attrs4 csr_fore_chan_attrs; channel_attrs4 csr_back_chan_attrs; };
union CREATE_SESSION4res switch (nfsstat4 csr_status) {
case NFS4_OK:
CREATE_SESSION4resok csr_resok4;
default:
void;
};
18.36.3. DESCRIPTION
This operation is used by the client to create new session objects on
the server.
CREATE_SESSION can be sent with or without a preceding SEQUENCE
operation in the same COMPOUND procedure. If CREATE_SESSION is sent
with a preceding SEQUENCE operation, any session created by
CREATE_SESSION has no direct relation to the session specified in the
SEQUENCE operation, although the two sessions might be associated
with the same client ID. If CREATE_SESSION is sent without a
preceding SEQUENCE, then it MUST be the only operation in the
COMPOUND procedure's request. If it is not, the server MUST return
NFS4ERR_NOT_ONLY_OP.
In addition to creating a session, CREATE_SESSION has the following
effects:
o The first session created with a new client ID serves to confirm
the creation of that client's state on the server. The server
returns the parameter values for the new session.
o The connection CREATE_SESSION that is sent over is associated with
the session's fore channel.
The arguments and results of CREATE_SESSION are described as follows:
csa_clientid:
This is the client ID with which the new session will be
associated. The corresponding result is csr_sessionid, the
session ID of the new session.
csa_sequence:
Each client ID serializes CREATE_SESSION via a per-client ID
sequence number (see Section 18.36.4). The corresponding result
is csr_sequence, which MUST be equal to csa_sequence.
In the next three arguments, the client offers a value that is to be
a property of the session. Except where stated otherwise, it is
RECOMMENDED that the server accept the value. If it is not
acceptable, the server MAY use a different value. Regardless, the
server MUST return the value the session will use (which will be
either what the client offered, or what the server is insisting on)
to the client.
csa_flags:
The csa_flags field contains a list of the following flag bits:
CREATE_SESSION4_FLAG_PERSIST:
If CREATE_SESSION4_FLAG_PERSIST is set, the client wants the
server to provide a persistent reply cache. For sessions in
which only idempotent operations will be used (e.g., a read-
only session), clients SHOULD NOT set
CREATE_SESSION4_FLAG_PERSIST. If the server does not or cannot
provide a persistent reply cache, the server MUST NOT set
CREATE_SESSION4_FLAG_PERSIST in the field csr_flags.
If the server is a pNFS metadata server, for reasons described
in Section 12.5.2 it SHOULD support
CREATE_SESSION4_FLAG_PERSIST if it supports the layout_hint
(Section 5.12.4) attribute.
CREATE_SESSION4_FLAG_CONN_BACK_CHAN:
If CREATE_SESSION4_FLAG_CONN_BACK_CHAN is set in csa_flags, the
client is requesting that the connection over which the
CREATE_SESSION operation arrived be associated with the
session's backchannel in addition to its fore channel. If the
server agrees, it sets CREATE_SESSION4_FLAG_CONN_BACK_CHAN in
the result field csr_flags. If
CREATE_SESSION4_FLAG_CONN_BACK_CHAN is not set in csa_flags,
then CREATE_SESSION4_FLAG_CONN_BACK_CHAN MUST NOT be set in
csr_flags.
CREATE_SESSION4_FLAG_CONN_RDMA:
If CREATE_SESSION4_FLAG_CONN_RDMA is set in csa_flags, and if
the connection over which the CREATE_SESSION operation arrived
is currently in non-RDMA mode but has the capability to operate
in RDMA mode, then the client is requesting that the server
"step up" to RDMA mode on the connection. If the server
agrees, it sets CREATE_SESSION4_FLAG_CONN_RDMA in the result
field csr_flags. If CREATE_SESSION4_FLAG_CONN_RDMA is not set
in csa_flags, then CREATE_SESSION4_FLAG_CONN_RDMA MUST NOT be
set in csr_flags. Note that once the server agrees to step up,
it and the client MUST exchange all future traffic on the
connection with RPC RDMA framing and not Record Marking ([8]).
csa_fore_chan_attrs, csa_fore_chan_attrs:
The csa_fore_chan_attrs and csa_back_chan_attrs fields apply to
attributes of the fore channel (which conveys requests originating
from the client to the server), and the backchannel (the channel
that conveys callback requests originating from the server to the
client), respectively. The results are in corresponding
structures called csr_fore_chan_attrs and csr_back_chan_attrs.
The results establish attributes for each channel, and on all
subsequent use of each channel of the session. Each structure has
the following fields:
ca_headerpadsize:
The maximum amount of padding the requester is willing to apply
to ensure that write payloads are aligned on some boundary at
the replier. For each channel, the server
+ will reply in ca_headerpadsize with its preferred value, or
zero if padding is not in use, and
+ MAY decrease this value but MUST NOT increase it.
ca_maxrequestsize:
The maximum size of a COMPOUND or CB_COMPOUND request that will
be sent. This size represents the XDR encoded size of the
request, including the RPC headers (including security flavor
credentials and verifiers) but excludes any RPC transport
framing headers. Imagine a request coming over a non-RDMA
TCP/IP connection, and that it has a single Record Marking
header preceding it. The maximum allowable count encoded in
the header will be ca_maxrequestsize. If a requester sends a
request that exceeds ca_maxrequestsize, the error
NFS4ERR_REQ_TOO_BIG will be returned per the description in
Section 2.10.6.4. For each channel, the server MAY decrease
this value but MUST NOT increase it.
ca_maxresponsesize:
The maximum size of a COMPOUND or CB_COMPOUND reply that the
requester will accept from the replier including RPC headers
(see the ca_maxrequestsize definition). For each channel, the
server MAY decrease this value, but MUST NOT increase it.
However, if the client selects a value for ca_maxresponsesize
such that a replier on a channel could never send a response,
the server SHOULD return NFS4ERR_TOOSMALL in the CREATE_SESSION
reply. After the session is created, if a requester sends a
request for which the size of the reply would exceed this
value, the replier will return NFS4ERR_REP_TOO_BIG, per the
description in Section 2.10.6.4.
ca_maxresponsesize_cached:
Like ca_maxresponsesize, but the maximum size of a reply that
will be stored in the reply cache (Section 2.10.6.1). For each
channel, the server MAY decrease this value, but MUST NOT
increase it. If, in the reply to CREATE_SESSION, the value of
ca_maxresponsesize_cached of a channel is less than the value
of ca_maxresponsesize of the same channel, then this is an
indication to the requester that it needs to be selective about
which replies it directs the replier to cache; for example,
large replies from nonidempotent operations (e.g., COMPOUND
requests with a READ operation) should not be cached. The
requester decides which replies to cache via an argument to the
SEQUENCE (the sa_cachethis field, see Section 18.46) or
CB_SEQUENCE (the csa_cachethis field, see Section 20.9)
operations. After the session is created, if a requester sends
a request for which the size of the reply would exceed
ca_maxresponsesize_cached, the replier will return
NFS4ERR_REP_TOO_BIG_TO_CACHE, per the description in
Section 2.10.6.4.
ca_maxoperations:
The maximum number of operations the replier will accept in a
COMPOUND or CB_COMPOUND. For the backchannel, the server MUST
NOT change the value the client offers. For the fore channel,
the server MAY change the requested value. After the session
is created, if a requester sends a COMPOUND or CB_COMPOUND with
more operations than ca_maxoperations, the replier MUST return
NFS4ERR_TOO_MANY_OPS.
ca_maxrequests:
The maximum number of concurrent COMPOUND or CB_COMPOUND
requests the requester will send on the session. Subsequent
requests will each be assigned a slot identifier by the
requester within the range zero to ca_maxrequests - 1
inclusive. For the backchannel, the server MUST NOT change the
value the client offers. For the fore channel, the server MAY
change the requested value.
ca_rdma_ird:
This array has a maximum of one element. If this array has one
element, then the element contains the inbound RDMA read queue
depth (IRD). For each channel, the server MAY decrease this
value, but MUST NOT increase it.
csa_cb_program
This is the ONC RPC program number the server MUST use in any
callbacks sent through the backchannel to the client. The server
MUST specify an ONC RPC program number equal to csa_cb_program and
an ONC RPC version number equal to 4 in callbacks sent to the
client. If a CB_COMPOUND is sent to the client, the server MUST
use a minor version number of 1. There is no corresponding
result.
csa_sec_parms
The field csa_sec_parms is an array of acceptable security
credentials the server can use on the session's backchannel.
Three security flavors are supported: AUTH_NONE, AUTH_SYS, and
RPCSEC_GSS. If AUTH_NONE is specified for a credential, then this
says the client is authorizing the server to use AUTH_NONE on all
callbacks for the session. If AUTH_SYS is specified, then the
client is authorizing the server to use AUTH_SYS on all callbacks,
using the credential specified cbsp_sys_cred. If RPCSEC_GSS is
specified, then the server is allowed to use the RPCSEC_GSS
context specified in cbsp_gss_parms as the RPCSEC_GSS context in
the credential of the RPC header of callbacks to the client.
There is no corresponding result.
The RPCSEC_GSS context for the backchannel is specified via a pair
of values of data type gsshandle4_t. The data type gsshandle4_t
represents an RPCSEC_GSS handle, and is precisely the same as the
data type of the "handle" field of the rpc_gss_init_res data type
defined in Section 5.2.3.1, "Context Creation Response -
Successful Acceptance", of [4].
The first RPCSEC_GSS handle, gcbp_handle_from_server, is the fore
handle the server returned to the client (either in the handle
field of data type rpc_gss_init_res or as one of the elements of
the spi_handles field returned in the reply to EXCHANGE_ID) when
the RPCSEC_GSS context was created on the server. The second
handle, gcbp_handle_from_client, is the back handle to which the
client will map the RPCSEC_GSS context. The server can
immediately use the value of gcbp_handle_from_client in the
RPCSEC_GSS credential in callback RPCs. That is, the value in
gcbp_handle_from_client can be used as the value of the field
"handle" in data type rpc_gss_cred_t (see Section 5, "Elements of
the RPCSEC_GSS Security Protocol", of [4]) in callback RPCs. The
server MUST use the RPCSEC_GSS security service specified in
gcbp_service, i.e., it MUST set the "service" field of the
rpc_gss_cred_t data type in RPCSEC_GSS credential to the value of
gcbp_service (see Section 5.3.1, "RPC Request Header", of [4]).
If the RPCSEC_GSS handle identified by gcbp_handle_from_server
does not exist on the server, the server will return
NFS4ERR_NOENT.
Within each element of csa_sec_parms, the fore and back RPCSEC_GSS
contexts MUST share the same GSS context and MUST have the same
seq_window (see Section 5.2.3.1 of RFC2203 [4]). The fore and
back RPCSEC_GSS context state are independent of each other as far
as the RPCSEC_GSS sequence number (see the seq_num field in the
rpc_gss_cred_t data type of Sections 5 and 5.3.1 of [4]).
If an RPCSEC_GSS handle is using the SSV context (see
Section 2.10.9), then because each SSV RPCSEC_GSS handle shares a
common SSV GSS context, there are security considerations specific
to this situation discussed in Section 2.10.10.
Once the session is created, the first SEQUENCE or CB_SEQUENCE
received on a slot MUST have a sequence ID equal to 1; if not, the
replier MUST return NFS4ERR_SEQ_MISORDERED.
18.36.4. IMPLEMENTATION
To describe a possible implementation, the same notation for client
records introduced in the description of EXCHANGE_ID is used with the
following addition:
clientid_arg: The value of the csa_clientid field of the
CREATE_SESSION4args structure of the current request.
Since CREATE_SESSION is a non-idempotent operation, we need to
consider the possibility that retries may occur as a result of a
client restart, network partition, malfunctioning router, etc. For
each client ID created by EXCHANGE_ID, the server maintains a
separate reply cache (called the CREATE_SESSION reply cache) similar
to the session reply cache used for SEQUENCE operations, with two
distinctions.
o First, this is a reply cache just for detecting and processing
CREATE_SESSION requests for a given client ID.
o Second, the size of the client ID reply cache is of one slot (and
as a result, the CREATE_SESSION request does not carry a slot
number). This means that at most one CREATE_SESSION request for a
given client ID can be outstanding.
As previously stated, CREATE_SESSION can be sent with or without a
preceding SEQUENCE operation. Even if a SEQUENCE precedes
CREATE_SESSION, the server MUST maintain the CREATE_SESSION reply
cache, which is separate from the reply cache for the session
associated with a SEQUENCE. If CREATE_SESSION was originally sent by
itself, the client MAY send a retry of the CREATE_SESSION operation
within a COMPOUND preceded by a SEQUENCE. If CREATE_SESSION was
originally sent in a COMPOUND that started with a SEQUENCE, then the
client SHOULD send a retry in a COMPOUND that starts with a SEQUENCE
that has the same session ID as the SEQUENCE of the original request.
However, the client MAY send a retry in a COMPOUND that either has no
preceding SEQUENCE, or has a preceding SEQUENCE that refers to a
different session than the original CREATE_SESSION. This might be
necessary if the client sends a CREATE_SESSION in a COMPOUND preceded
by a SEQUENCE with session ID X, and session X no longer exists.
Regardless, any retry of CREATE_SESSION, with or without a preceding
SEQUENCE, MUST use the same value of csa_sequence as the original.
After the client received a reply to an EXCHANGE_ID operation that
contains a new, unconfirmed client ID, the server expects the client
to follow with a CREATE_SESSION operation to confirm the client ID.
The server expects value of csa_sequenceid in the arguments to that
CREATE_SESSION to be to equal the value of the field eir_sequenceid
that was returned in results of the EXCHANGE_ID that returned the
unconfirmed client ID. Before the server replies to that EXCHANGE_ID
operation, it initializes the client ID slot to be equal to
eir_sequenceid - 1 (accounting for underflow), and records a
contrived CREATE_SESSION result with a "cached" result of
NFS4ERR_SEQ_MISORDERED. With the client ID slot thus initialized,
the processing of the CREATE_SESSION operation is divided into four
phases:
1. Client record look up. The server looks up the client ID in its
client record table. If the server contains no records with
client ID equal to clientid_arg, then most likely the client's
state has been purged during a period of inactivity, possibly due
to a loss of connectivity. NFS4ERR_STALE_CLIENTID is returned,
and no changes are made to any client records on the server.
Otherwise, the server goes to phase 2.
2. Sequence ID processing. If csa_sequenceid is equal to the
sequence ID in the client ID's slot, then this is a replay of the
previous CREATE_SESSION request, and the server returns the
cached result. If csa_sequenceid is not equal to the sequence ID
in the slot, and is more than one greater (accounting for
wraparound), then the server returns the error
NFS4ERR_SEQ_MISORDERED, and does not change the slot. If
csa_sequenceid is equal to the slot's sequence ID + 1 (accounting
for wraparound), then the slot's sequence ID is set to
csa_sequenceid, and the CREATE_SESSION processing goes to the
next phase. A subsequent new CREATE_SESSION call over the same
client ID MUST use a csa_sequenceid that is one greater than the
sequence ID in the slot.
3. Client ID confirmation. If this would be the first session for
the client ID, the CREATE_SESSION operation serves to confirm the
client ID. Otherwise, the client ID confirmation phase is
skipped and only the session creation phase occurs. Any case in
which there is more than one record with identical values for
client ID represents a server implementation error. Operation in
the potential valid cases is summarized as follows.
* Successful Confirmation
If the server has the following unconfirmed record, then
this is the expected confirmation of an unconfirmed record.
{ ownerid, verifier, principal_arg, clientid_arg,
unconfirmed }
As noted in Section 18.35.4, the server might also have the
following confirmed record.
{ ownerid, old_verifier, principal_arg, old_clientid,
confirmed }
The server schedules the replacement of both records with:
{ ownerid, verifier, principal_arg, clientid_arg, confirmed
}
The processing of CREATE_SESSION continues on to session
creation. Once the session is successfully created, the
scheduled client record replacement is committed. If the
session is not successfully created, then no changes are
made to any client records on the server.
* Unsuccessful Confirmation
If the server has the following record, then the client has
changed principals after the previous EXCHANGE_ID request,
or there has been a chance collision between shorthand
client identifiers.
{ *, *, old_principal_arg, clientid_arg, * }
Neither of these cases is permissible. Processing stops
and NFS4ERR_CLID_INUSE is returned to the client. No
changes are made to any client records on the server.
4. Session creation. The server confirmed the client ID, either in
this CREATE_SESSION operation, or a previous CREATE_SESSION
operation. The server examines the remaining fields of the
arguments.
The server creates the session by recording the parameter values
used (including whether the CREATE_SESSION4_FLAG_PERSIST flag is
set and has been accepted by the server) and allocating space for
the session reply cache (if there is not enough space, the server
returns NFS4ERR_NOSPC). For each slot in the reply cache, the
server sets the sequence ID to zero, and records an entry
containing a COMPOUND reply with zero operations and the error
NFS4ERR_SEQ_MISORDERED. This way, if the first SEQUENCE request
sent has a sequence ID equal to zero, the server can simply
return what is in the reply cache: NFS4ERR_SEQ_MISORDERED. The
client initializes its reply cache for receiving callbacks in the
same way, and similarly, the first CB_SEQUENCE operation on a
slot after session creation MUST have a sequence ID of one.
If the session state is created successfully, the server
associates the session with the client ID provided by the client.
When a request that had CREATE_SESSION4_FLAG_CONN_RDMA set needs
to be retried, the retry MUST be done on a new connection that is
in non-RDMA mode. If properties of the new connection are
different enough that the arguments to CREATE_SESSION need to
change, then a non-retry MUST be sent. The server will
eventually dispose of any session that was created on the
original connection.
On the backchannel, the client and server might wish to have many
slots, in some cases perhaps more that the fore channel, in order to
deal with the situations where the network link has high latency and
is the primary bottleneck for response to recalls. If so, and if the
client provides too few slots to the backchannel, the server might
limit the number of recallable objects it gives to the client.
Implementing RPCSEC_GSS callback support requires changes to both the
client and server implementations of RPCSEC_GSS. One possible set of
changes includes:
o Adding a data structure that wraps the GSS-API context with a
reference count.
o New functions to increment and decrement the reference count. If
the reference count is decremented to zero, the wrapper data
structure and the GSS-API context it refers to would be freed.
o Change RPCSEC_GSS to create the wrapper data structure upon
receiving GSS-API context from gss_accept_sec_context() and
gss_init_sec_context(). The reference count would be initialized
to 1.
o Adding a function to map an existing RPCSEC_GSS handle to a
pointer to the wrapper data structure. The reference count would
be incremented.
o Adding a function to create a new RPCSEC_GSS handle from a pointer
to the wrapper data structure. The reference count would be
incremented.
o Replacing calls from RPCSEC_GSS that free GSS-API contexts, with
calls to decrement the reference count on the wrapper data
structure.
18.37. Operation 44: DESTROY_SESSION - Destroy a Session
18.37.1. ARGUMENT
struct DESTROY_SESSION4args {
sessionid4 dsa_sessionid;
};
18.37.2. RESULT
struct DESTROY_SESSION4res {
nfsstat4 dsr_status;
};
18.37.3. DESCRIPTION
The DESTROY_SESSION operation closes the session and discards the session's reply cache, if any. Any remaining connections associated with the session are immediately disassociated. If the connection has no remaining associated sessions, the connection MAY be closed by the server. Locks, delegations, layouts, wants, and the lease, which are all tied to the client ID, are not affected by DESTROY_SESSION. DESTROY_SESSION MUST be invoked on a connection that is associated with the session being destroyed. In addition, if SP4_MACH_CRED state protection was specified when the client ID was created, the RPCSEC_GSS principal that created the session MUST be the one that destroys the session, using RPCSEC_GSS privacy or integrity. If SP4_SSV state protection was specified when the client ID was created, RPCSEC_GSS using the SSV mechanism (Section 2.10.9) MUST be used, with integrity or privacy. If the COMPOUND request starts with SEQUENCE, and if the sessionids specified in SEQUENCE and DESTROY_SESSION are the same, then o DESTROY_SESSION MUST be the final operation in the COMPOUND request. o It is advisable to avoid placing DESTROY_SESSION in a COMPOUND request with other state-modifying operations, because the DESTROY_SESSION will destroy the reply cache. o Because the session and its reply cache are destroyed, a client that retries the request may receive an error in reply to the retry, even though the original request was successful. If the COMPOUND request starts with SEQUENCE, and if the sessionids specified in SEQUENCE and DESTROY_SESSION are different, then DESTROY_SESSION can appear in any position of the COMPOUND request (except for the first position). The two sessionids can belong to different client IDs. If the COMPOUND request does not start with SEQUENCE, and if DESTROY_SESSION is not the sole operation, then server MUST return NFS4ERR_NOT_ONLY_OP. If there is a backchannel on the session and the server has outstanding CB_COMPOUND operations for the session which have not been replied to, then the server MAY refuse to destroy the session and return an error. If so, then in the event the backchannel is down, the server SHOULD return NFS4ERR_CB_PATH_DOWN to inform the client that the backchannel needs to be repaired before the server
will allow the session to be destroyed. Otherwise, the error CB_BACK_CHAN_BUSY SHOULD be returned to indicate that there are CB_COMPOUNDs that need to be replied to. The client SHOULD reply to all outstanding CB_COMPOUNDs before re-sending DESTROY_SESSION.18.38. Operation 45: FREE_STATEID - Free Stateid with No Locks
18.38.1. ARGUMENT
struct FREE_STATEID4args { stateid4 fsa_stateid; };18.38.2. RESULT
struct FREE_STATEID4res { nfsstat4 fsr_status; };18.38.3. DESCRIPTION
The FREE_STATEID operation is used to free a stateid that no longer has any associated locks (including opens, byte-range locks, delegations, and layouts). This may be because of client LOCKU operations or because of server revocation. If there are valid locks (of any kind) associated with the stateid in question, the error NFS4ERR_LOCKS_HELD will be returned, and the associated stateid will not be freed. When a stateid is freed that had been associated with revoked locks, by sending the FREE_STATEID operation, the client acknowledges the loss of those locks. This allows the server, once all such revoked state is acknowledged, to allow that client again to reclaim locks, without encountering the edge conditions discussed in Section 8.4.2. Once a successful FREE_STATEID is done for a given stateid, any subsequent use of that stateid will result in an NFS4ERR_BAD_STATEID error.