Security context initiation between an application and a remote peer is done using the gss_init_sec_context() function. If successful, this function returns a context handle for the context being established and a context-level token to send to the acceptor. Before calling gss_init_sec_context(), however, the client should:
Acquire credentials, if necessary, with gss_acquire_cred(). Commonly, however, the client has received credentials at login, and can skip this step.
Import the name of the server into GSS-API internal format with gss_import_name(). See Names for more about names and gss_import_name().
GSS_C_NO_CREDENTIAL for the cred_handle argument, to indicate the default credential.
GSS_C_NULL_OID for the mech_type argument, to indicate the default mechanism.
GSS_C_NO_CONTEXT for the context_handle argument, to indicate an initial null context. Because gss_init_sec_context() is usually called in a loop, subsequent calls should pass the context handle returned by previous calls.
GSS_C_NO_BUFFER for the input_token argument, to indicate an initially empty token. Alternatively, the application can pass a pointer to a gss_buffer_desc object whose length field has been set to zero.
The name of the server, imported into internal GSS-API format with gss_import_name().
Applications are not bound to use these default values. Additionally, the client will specify its requirements for other security parameters with the req_flags argument. The full set of gss_init_sec_context() arguments is described below.
The context acceptor can require several “handshakes” in order to establish a context; that is, it can require the initiator to send more than one piece of context information before it considers the context fully established. Therefore, for portability, context initiation should always be done as part of a loop that checks whether the context has been fully established.
If the context isn't complete, gss_init_sec_context() returns a major-status code of GSS_C_CONTINUE_NEEDED. Thus a loop should use gss_init_sec_context()'s return value to test whether to continue the initiation loop.
The client passes context information to the server in the form of the output token returned by gss_init_sec_context(). The client receives information back from the server as an input token, which can then be passed as an argument to subsequent calls of gss_init_sec_context(). If the received input token has a length of zero, however, then no more output tokens are required by the server.
Therefore, in addition to checking for the return status of gss_init_sec_context(), the loop should check the input token's length to see if a further token needs to be sent to the server. (Before the loop begins, the input token's length should be initialized to zero, either by setting the input token to
GSS_C_NO_BUFFER or by setting the structure's length field to a value of zero.)
This is what such a loop can look like, highly generalized:
context = GSS_C_NO_CONTEXT input token = GSS_C_NO_BUFFER do call gss_init_sec_context(credential, context, name, input token, output token, other args...) if (there's an output token to send to the acceptor) send the output token to the acceptor release the output token if (the context is not complete) receive an input token from the acceptor if (there's a GSS-API error) delete the context until the context is complete
Naturally, a real loop will be more complete, with, for example, much more extensive error-checking. See Establishing a Context (program listing in client_establish_context()) for a real example of such a context-initiation loop. Additionally, the gss_init_sec_context(3GSS) man page gives a less generic example than this.
Here is a synopsis of gss_init_sec_context(). For more information, see the gss_init_sec_context(3GSS) man page.
OM_uint32 gss_init_sec_context ( OM_uint32 *minor_status, const gss_cred_id_t initiator_cred_handle, gss_ctx_id_t *context_handle, const gss_name_t target_name, const gss_OID mech_type, OM_uint32 req_flags, OM_uint32 time_req, const gss_channel_bindings_t input_chan_bindings, const gss_buffer_t input_token gss_OID *actual_mech_type, gss_buffer_t output_token, OM_uint32 *ret_flags, OM_uint32 *time_rec )
The status code returned by the underlying mechanism.
The credential handle for the application. This should be initialized to
GSS_C_NO_CREDENTIAL to indicate the default credential to use.
The context handle to be returned. This should be set to
GSS_C_NO_CONTEXT before the loop begins.
The name of the principal to connect to; for example, “nfs@machinename.”
The security mechanism to use. Set this to
GSS_C_NO_OID to get the default provided by the GSS-API.
GSS_C_MUTUAL_FLAG | GSS_C_DELEG_FLAG
Requests that delegation of the initiator's credentials be permitted. See Delegation.
Requests mutual authentication. See Mutual Authentication.
Requests detection of repeated messages. See Out-of-Sequence Detection and Replay Detection.
Requests detection of out-of-sequence messages. See Out-of-Sequence Detection and Replay Detection.
Requests that the confidentiality service be allowed for transferred messages; that is, that messages be encrypted. If confidentiality is not allowed, then only data-origin authentication and integrity services can be applied (this last only if
GSS_C_INTEG_FLAG is not false).
Requests that the integrity service be applicable to messages; that is, that messages may be stamped with a MIC to ensure their validity.
Requests that the initiator remain anonymous. See Anonymous Authentication.
The number of seconds for which the context should remain valid. Set this to zero (0) to request the default.
Specific peer-to-peer channel identification information connected with the security context. See Channel Bindings for more information about channel bindings. Set to
GSS_C_NO_CHANNEL_BINDINGS if you don't want to use channel bindings.
Token received from the context acceptor, if any. Should be initialized to
GSS_C_NO_BUFFER before the function is called (or its length field set to zero).
The mechanism actually used in the context. Specify NULL if you don't need to know.
The token to send to the acceptor.
if (ret_flags & GSS_C_CONF_FLAG) confidentiality = TRUE;
If true, indicates that the initiator's credentials can be delegated. See Delegation.
If true, indicates that mutual authentication is allowed. See Mutual Authentication.
If true, indicates that detection of repeated messages is in effect. See Out-of-Sequence Detection and Replay Detection.
If true, indicates that detection of out-of-sequence messages is in effect. See Out-of-Sequence Detection and Replay Detection.
If true, confidentiality service is allowed for transferred messages; that is, that messages can be encrypted. If confidentiality is not allowed, then only data-origin authentication, and integrity services can be applied (this last only if GSS_C_INTEG_FLAG is not returned as false).
If true, the integrity service can be applied to messages; that is, that messages can be stamped with a MIC to ensure their validity.
If true, indicates that the context initiator will remain anonymous. See Anonymous Authentication.
Sometimes context establishment can take several passes, and sometimes the client might have to wait before it's complete. Even though a context is not fully established, gss_init_sec_context() can indicate what protection services, if any, will be available after the context is complete. An application can therefore buffer its data, sending it when the context is eventually fully established.
If ret_flags indicates GSS_C_PROT_READY_FLAG, the protection services indicated by the GSS_C_CONF_FLAG and GSS_C_INTEG_FLAG flags are available even if the context has not been fully established (that is, if gss_init_sec_context() returns GSS_S_CONTINUE_NEEDED). An application can then call the appropriate wrapping functions, gss_wrap() or gss_get_mic(), with the preferred protection services, and buffer the output for transfer when the context is complete.
If GSS_C_PROT_READY_FLAG is false, then the application cannot make any assumptions about data protection, and must wait until the context is complete (that is, when gss_init_sec_context() returns GSS_S_COMPLETE).
Earlier versions of the GSS-API did not support the GSS_C_PROT_READY_FLAG argument, so developers wanting to maximize portability should determine which per-message services are available by looking at the GSS_C_CONF_FLAG and GSS_C_INTEG_FLAG flags after a context has been successfully established.
This flag indicates whether this context can be exported. For more information on importing and exporting contexts, see Context Export and Import.
Number of seconds for which the context will remain valid. Specify NULL if you're not interested in this value.
In general, the parameter values returned when a context is not fully established are those that would be returned when the context is complete. See the gss_init_sec_context() man page for more information.
gss_init_sec_context() returns GSS_S_COMPLETE if it completes successfully. If a context-establishment token is required from the peer application, it returns GSS_S_CONTINUE_NEEDED. If there are errors, it returns error codes, which can be found on the gss_init_sec_context(3GSS) man page.
If context initiation fails, the client should disconnect from the server.