GSS-API Programming Guide

Context Establishment

As stated earlier, the two most significant things that the GSS-API does in providing security are to create security contexts and to protect data. After an application has the credential(s) it needs, it's time to establish a security context. To do this, one application (typically a client) initiates the context, and another (usually a server) accepts it. Multiple contexts between peers are allowed.

The communicating applications establish a joint security context by exchanging authentication tokens. The security context is a pair of GSS-API data structures that contain information shared between the two applications. This information describes the state of each application (in terms of security). A security context is required for protection of data.

Context Initiation (Client)

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:

  1. Acquire credentials, if necessary, with gss_acquire_cred(). Commonly, however, the client has received credentials at login, and can skip this step.

  2. 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().

When calling gss_init_sec_context(), the client typically passes the following argument values:

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.

Again, the GSS-API does not send or receive tokens; these must be handled by the application. Examples of token-transferring functions are found in send_token() and recv_token().

Here is a synopsis of gss_init_sec_context(). For more information, see the gss_init_sec_context(3GSS) man page.


Example 1–6 gss_init_sec_context()

     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 )

minor_status

The status code returned by the underlying mechanism.

initiator_cred_handle

The credential handle for the application. This should be initialized to GSS_C_NO_CREDENTIAL to indicate the default credential to use.

context_handle

The context handle to be returned. This should be set to GSS_C_NO_CONTEXT before the loop begins.

target_name

The name of the principal to connect to; for example, “nfs@machinename.”

mech_type

The security mechanism to use. Set this to GSS_C_NO_OID to get the default provided by the GSS-API.

req_flags

Flags indicating additional services or parameters requested for this context. req_flags flags should be logically OR'd to make the desired bit-mask value, as in:


GSS_C_MUTUAL_FLAG | GSS_C_DELEG_FLAG

GSS_C_DELEG_FLAG

Requests that delegation of the initiator's credentials be permitted. See Delegation.

GSS_C_MUTUAL_FLAG

Requests mutual authentication. See Mutual Authentication.

GSS_C_REPLAY_FLAG

Requests detection of repeated messages. See Out-of-Sequence Detection and Replay Detection.

GSS_C_SEQUENCE_FLAG

Requests detection of out-of-sequence messages. See Out-of-Sequence Detection and Replay Detection.

GSS_C_CONF_FLAG

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).

GSS_C_INTEG_FLAG

Requests that the integrity service be applicable to messages; that is, that messages may be stamped with a MIC to ensure their validity.

GSS_C_ANON_FLAG

Requests that the initiator remain anonymous. See Anonymous Authentication.

time_req

The number of seconds for which the context should remain valid. Set this to zero (0) to request the default.

input_chan_bindings

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.

input_token

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).

actual_mech_type

The mechanism actually used in the context. Specify NULL if you don't need to know.

output_token

The token to send to the acceptor.

ret_flags

Flags indicating additional services or parameters requested for this context. ret_flags flags should be logically AND'd to test the returned bit-mask value, as in:


if (ret_flags & GSS_C_CONF_FLAG)
     confidentiality = TRUE;

GSS_C_DELEG_FLAG

If true, indicates that the initiator's credentials can be delegated. See Delegation.

GSS_C_MUTUAL_FLAG

If true, indicates that mutual authentication is allowed. See Mutual Authentication.

GSS_C_REPLAY_FLAG

If true, indicates that detection of repeated messages is in effect. See Out-of-Sequence Detection and Replay Detection.

GSS_C_SEQUENCE_FLAG

If true, indicates that detection of out-of-sequence messages is in effect. See Out-of-Sequence Detection and Replay Detection.

GSS_C_CONF_FLAG

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).

GSS_C_INTEG_FLAG

If true, the integrity service can be applied to messages; that is, that messages can be stamped with a MIC to ensure their validity.

GSS_C_ANON_FLAG

If true, indicates that the context initiator will remain anonymous. See Anonymous Authentication.

GSS_C_PROT_READY_FLAG

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).


Note –

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.


GSS_C_TRANS_FLAG

This flag indicates whether this context can be exported. For more information on importing and exporting contexts, see Context Export and Import.

time_rec

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.

Context Acceptance (Server)

The other half of context establishment is context acceptance, which is done through the gss_accept_sec_context() function. In a typical scenario, a server accepts a context initiated (with gss_init_sec_context()) by a client.

gss_accept_sec_context() takes as its main input an input token sent by the initiator. It returns a context handle as well as an output token to be returned to the initiator. Before gss_accept_sec_context() can be called, however, the server should acquire credentials for the service requested by the client. The server acquires these credentials with the gss_acquire_cred() function. Alternatively, the server can bypass acquiring credentials explicitly and instead specify the default credential (indicated by GSS_C_NO_CREDENTIAL) when calling gss_accept_sec_context().

When calling gss_accept_sec_context(), the server passes the following argument values:

The full set of gss_accept_sec_context() arguments is described in the following paragraphs.

Security context establishment may require several “handshakes”; that is, the initiator and acceptor may have to send more than one piece of context information before the context is fully established. Therefore, for portability, context acceptance should always be done as part of a loop that checks whether the context has been fully established. If it hasn't, gss_accept_sec_context() returns a major-status code of GSS_C_CONTINUE_NEEDED. Thus a loop should use the value returned by gss_accept_sec_context() to test whether to continue the acceptance loop.

The context acceptor returns context information to the context initiator in the form of the output token returned by gss_accept_sec_context(). Subsequently, the acceptor can receive further information from the initiator as an input token, which is then passed as an argument to subsequent calls of gss_accept_sec_context(). When gss_accept_sec_context() has no more tokens to send to the initiator, it returns an output token with a length of zero. Therefore, in addition to checking for the return status of gss_accept_sec_context(), the loop should check the output token's length to see if a further token must be sent. Before the loop begins, the output token's length should be initialized to zero, either by setting the output 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 might look like, highly generalized:

context = GSS_C_NO_CONTEXT
output token = GSS_C_NO_BUFFER

do

     receive an input token from the initiator

     call gss_accept_sec_context(context, cred handle, input token,
                                                output token, other args...)

     if (there's an output token to send to the initiator)
          send the output token to the initiator
          release the output token

     if (there's a GSS-API error)
          delete the context

until the context is complete

Naturally, a real loop will be more complete, doing much more extensive error-checking. See Accepting a Context (listing in server_establish_context()) for a real example of such a context-acceptance loop. Additionally, the gss_accept_sec_context() man page gives a somewhat less generic example than this.

Again, the GSS-API does not send or receive tokens; these must be handled by the application. Examples of token-transferring functions are found in send_token() and recv_token().

Here is a synopsis of gss_accept_sec_context(). For more information, see the gss_accept_sec_context(3GSS) man page.


Example 1–7 gss_accept_sec_context()

     OM_uint32 gss_accept_sec_context (
       OM_uint32                    *minor_status,
       gss_ctx_id_t                 *context_handle,
       const gss_cred_id_t          acceptor_cred_handle,
       const gss_buffer_t           input_token_buffer,
       const gss_channel_bindings_t input_chan_bindings,
       const gss_name_t             *src_name,
       gss_OID                      *mech_type,
       gss_buffer_t                 output_token,
       OM_uint32                    *ret_flags,
       OM_uint32                    *time_req,
       gss_cred_id_t                *delegated_cred_handle)

minor_status

The status code returned by the underlying mechanism.

context_handle

The context handle to return to the initiator. This argument should be set to GSS_C_NO_CONTEXT before the loop begins.

acceptor_cred_handle

The handle for the credentials acquired by the acceptor, typically through gss_acquire_cred()). Can be initialized to GSS_C_NO_CREDENTIAL to indicate a default credential to use. If no default credential is defined, the function returns GSS_C_NO_CRED.

(Note: if gss_acquire_cred() was passed GSS_C_NO_NAME as a principal name, it produces a credential that will cause gss_accept_sec_context() to treat it as a default credential.)

input_token_buffer

Token received from the context initiator.

input_chan_bindings

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.

src_name

The name of the initiating principal; for example, nfs@machinename. If you don't care, set to NULL.

mech_type

The security mechanism used. Set to NULL if you don't care which mechanism is used.

output_token

The token to send to the initiator. Should be initialized to GSS_C_NO_BUFFER before the function is called (or its length field set to zero). If the length is zero, no token needs to be sent.

ret_flags

Flags indicating additional services or parameters requested for this context. ret_flags flags should be logically AND'd to test the returned bit-mask value, as in:


if (ret_flags & GSS_C_CONF_FLAG)
     confidentiality = TRUE;

GSS_C_DELEG_FLAG

Indicates the initiator's credentials may be delegated via the delegated_cred_handle argument. See Delegation.

GSS_C_MUTUAL_FLAG

Indicates that mutual authentication is available. See Mutual Authentication.

GSS_C_REPLAY_FLAG

Indicates that detection of repeated messages is available. See Out-of-Sequence Detection and Replay Detection.

GSS_C_SEQUENCE_FLAG

Indicates that detection of out-of-sequence messages is available. See Out-of-Sequence Detection and Replay Detection.

GSS_C_CONF_FLAG

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).

GSS_C_INTEG_FLAG

If true, the integrity service can be applied to messages; that is, that messages can be stamped with a MIC to ensure their validity.

GSS_C_ANON_FLAG

Indicates that the context initiator will be anonymous. See Anonymous Authentication.

GSS_C_PROT_READY_FLAG

Sometimes context establishment can take several passes, and sometimes the client can send enough information on the initial passes to allow the acceptor to process context-related data, even though the context is incomplete. In those circumstances the acceptor needs to know in which way, if any, the information has been protected.

If true, GSS_C_PROT_READY_FLAG indicates that the protection services indicated by the GSS_C_CONF_FLAG and GSS_C_INTEG_FLAG flags are available. The acceptor can therefore call the appropriate data–reception functions, gss_unwrap() or gss_verify_mic(), with these services in mind.

(Additionally, as with the context initiator, the acceptor can use these flags in buffering any data it might want to send to the initiator, transmitting it when the context is fully established.)

If GSS_C_PROT_READY_FLAG is false, then the acceptor cannot make any assumptions about data protection, and must wait until the context is complete (that is, when gss_accept_sec_context() returns GSS_S_COMPLETE).


Note –

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.


GSS_C_TRANS_FLAG

If true, this context can be exported. For more information on importing and exporting contexts, see Context Export and Import.

time_rec

Number of seconds for which the context will remain valid. Specify NULL if you're not interested in this value.

delegated_cred_handle

The credential handle for credentials received from the context initiator, that is, the client's credentials. Valid only if the initiator has requested that the acceptor act as a proxy: that is, if the ret_flags argument resolves to GSS_C_DELEG_FLAG. See Delegation for more about delegation.

gss_accept_sec_context() returns GSS_S_COMPLETE if it completes successfully. If the context is not complete, it returns GSS_S_CONTINUE_NEEDED. If there are errors, it returns error codes; for more information, see the gss_accept_sec_context(3GSS) man page.

Additional Context Services

The gss_init_sec_context() function (see Context Initiation (Client)) allows an application to request certain additional data protection services beyond basic context establishment. These services, discussed below, are requested through the req_flags argument to gss_init_sec_context().

Because not all mechanisms offer all these services, gss_init_sec_context()'s ret_flags argument indicates which of them are available in a given context. Similarly, the context acceptor can determine which services are available by looking at the ret_flags value returned by the gss_accept_sec_context() function. The additional services are explained in the following sections.

Delegation

If permitted, a context initiator can request that the context acceptor act as a proxy, in which case the acceptor can initiate further contexts on behalf of the initiator. An example of such delegation would be where someone on Machine A wanted to rlogin to Machine B, and then rlogin from Machine B to Machine C, as shown in Figure 1–8. (Depending on the mechanism, the delegated credential identifies B either as A or “B acting for A.”)

Figure 1–8 Credential Delegation

Graphic

If delegation is permitted, ret_flags will be set to GSS_C_DELEG_FLAG; the acceptor receives a delegated credential as the delegated_cred_handle argument of gss_accept_sec_context(). Delegating a credential is not the same as exporting a context (see Context Export and Import). One difference is that an application can delegate its credentials multiple times simultaneously, while a context can only be held by one process at a time.

Mutual Authentication

If you are using ftpto download files into a public ftp site, you probably don't require that the site prove its identity, even if it requires proof of your own. On the other hand, if you are providing a password or credit card number to an application, you probably want to be sure of the receiver's bona fides. In these cases, mutual authentication is required — that is, both the context initiator and the acceptor must prove their identities.

A context initiator can request mutual authentication by setting gss_init_sec_context()'s req_flags argument to the value GSS_C_MUTUAL_FLAG. If mutual authentication has been authorized, the function indicates authorization by setting the ret_flags argument to this value. If mutual authentication is requested but not available, it is the initiating application's responsibility to respond accordingly — the GSS-API will not terminate a context for this reason. Some mechanisms will perform mutual authentication regardless of whether it has been requested.

Out-of-Sequence Detection and Replay Detection

In the common case where a context initiator is transmitting several sequential data packets to the acceptor, some mechanisms allow the context acceptor to check whether or not the packets are arriving as they should: in the right order, and with no unwanted duplication of packets (shown in Figure 1–9). The acceptor checks for these two conditions when it verifies a packet's validity or when it unwraps a packet; see Unwrapping and Verification for more information.

Figure 1–9 Message Replay and Message Out-of-Sequence

Graphic

To request that these two conditions be looked for, the initiator should logically OR the req_flags argument with the values GSS_C_REPLAY_FLAG or GSS_C_SEQUENCE_FLAG when initiating the context with gss_init_sec_context().

Anonymous Authentication

In normal use of the GSS-API, the initiator's identity is made available to the acceptor as a result of the context establishment process. However, context initiators can request that their identity not be revealed to the context acceptor.

As an example, consider an application providing access to a database containing medical information, and offering unrestricted access to the service. A client of such a service might want to authenticate the service (in order to establish trust in any information retrieved from it), but might not want the service to be able to obtain the client's identity (perhaps due to privacy concerns about the specific inquiries, or perhaps to avoid being placed on mailing lists).

To request anonymity, set the req_flags argument of gss_init_sec_context() to GSS_C_ANON_FLAG; to check if anonymity is available, check the ret_flags argument to gss_init_sec_context() or gss_accept_sec_context() to see if this same value is returned.

If anonymity is in effect and gss_display_name() is called on a client name returned by gss_accept_sec_context() or gss_inquire_context(), gss_display_name() will produce a generic anonymous name.


Note –

It is the application's responsibility to take appropriate action if anonymity is requested but not permitted — the GSS-API will not terminate a context on these grounds.


Channel Bindings

For many applications, basic context establishment is sufficient to assure proper authentication of a context initiator. In cases where additional security is desired, the GSS-API offers the use of channel bindings. Channel bindings are tags that identify the particular data channel being used — that is, the origin and endpoint (initiator and acceptor) of the context. Because these tags are specific to the originator and recipient applications, they offer more proof of a valid identity.

Channel bindings are pointed to by the gss_channel_bindings_t data type, which is a pointer to a gss_channel_bindings_struct structure as shown in Example 1–8:


Example 1–8 gss_channel_bindings_t

typedef struct gss_channel_bindings_struct {
OM_uint32       initiator_addrtype;
gss_buffer_desc initiator_address;
OM_uint32       acceptor_addrtype;
gss_buffer_desc acceptor_address;
gss_buffer_desc application_data;
} *gss_channel_bindings_t;

The first two fields are the address of the initiator along with an address type that identifies the format in which the initiator's address is being sent. For example, the inititiator_addrtype might be sent to GSS_C_AF_INET to indicate that the initiator_address is in the form of an Internet address — that is, an IP address. Similarly, the third and fourth fields indicate the address and address type of the acceptor. The final field, application_data, can be used by the application as it wants (it's good programming practice to set it to GSS_C_NO_BUFFER if you're not going to use it). If an application does not want to specify an address, it should set its address type field to GSS_C_AF_NULLADDR. Address Types for Channel Bindings has a list of valid address type values.

These address types indicate address families, rather than specific addressing formats. For address families that contain several alternative address forms, the initiator_address and acceptor_address fields must contain sufficient information to determine which address form is used. When not otherwise specified, addresses should be specified in network byte-order (that is, native byte-ordering for the address family).

To establish a context using channel bindings, the input_chan_bindings argument for gss_init_sec_context() should point to an allocated channel bindings structure. The function concatenates the structure's fields into an octet string, calculates a MIC over this string, and binds the MIC to the output token produced by gss_init_sec_context(). The application then sends the token to the context acceptor, which receives it and calls gss_accept_sec_context(). (See Context Acceptance (Server).) gss_accept_sec_context() calculates a MIC on the received channel bindings and returns GSS_C_BAD_BINDINGS if the MIC does not match.

Because gss_accept_sec_context() returns the transmitted channel bindings, an acceptor can do its own security checking based on the received channel binding values. For example, it might check the value of application_data against code words kept in a secure database. However, in many cases this is “overkill.”


Note –

An underlying mechanism might or might not provide confidentiality for channel binding information. Therefore, an application should not include sensitive information as part of channel bindings unless it knows that confidentiality is ensured. The application might check the ret_flags argument of gss_init_sec_context() or gss_accept_sec_context(), especially for the values GSS_C_CONF_FLAG and GSS_C_PROT_READY_FLAG in order to determine if confidentiality is available. See Context Initiation (Client) or Context Acceptance (Server) for information on ret_flags.


Individual mechanisms can impose additional constraints on addresses and address types that can appear in channel bindings. For example, a mechanism can verify that the initiator_address field of the channel bindings presented to gss_init_sec_context() contains the correct network address of the host system. Portable applications should therefore ensure that they either provide correct information for the address fields or omit addressing information, specifying GSS_C_AF_NULLADDR as the address types.

Context Export and Import

The GSS-API provides a means for exporting and importing a context. The primary reason for this ability is to allow a multiprocess application (usually the context acceptor) to transfer a context from one process to another. For example, an acceptor might have one process that listens for context initiators and another that processes data sent in a context. (test_import_export_context() shows how a context can be saved and restored with these functions.)

The function gss_export_sec_context() creates an interprocess token that contains information about the exported context. (See Interprocess Tokens. This buffer to receive the token should be set to GSS_C_NO_BUFFER before gss_export_sec_context() is called.)

The application then passes the token on to the other process, which accepts it and passes it to gss_import_sec_context(). The same functions used to pass tokens between applications can often be used to pass them between processes as well.

Only one instantiation of a security process can exist at a time. gss_export_sec_context() deactivates the exported context and sets its context handle to GSS_C_NO_CONTEXT. It also deallocates any and all process-wide resources associated with that context. In the event that context exportation cannot be completed, gss_export_sec_context() does not return an interprocess token, but leaves the existing security context unchanged.

Not all mechanisms permit contexts to be exported. An application can determine whether a context can be exported by checking the ret_flags argument to gss_accept_sec_context() or gss_init_sec_context(). If this flag is set to GSS_C_TRANS_FLAG, then the context can be exported. (See Context Acceptance (Server) and Context Initiation (Client).)

Figure 1–10 shows how a multiprocess acceptor might use context exporting to multitask. In this case, Process 1 receives and processes tokens, separating the context-level tokens from the data tokens, and passes the tokens on to Process 2, which deals with data in an application-specific way. In this illustration, the clients have already gotten export tokens from gss_init_sec_context(); they pass them to a user-defined function, send_a_token(), which indicates whether the token it's transmitting is a context-level token or a message token. send_a_token() transmits the tokens to the server. Although not shown here, send_a_token() would presumably be used to pass tokens between threads as well.

Figure 1–10 Exporting Contexts: Multithreaded Acceptor Example

Graphic

Context Information

The GSS-API provides a function, gss_inquire_context(), that obtains information about a given security context (even an incomplete one). Given a context handle, gss_inquire_context() provides the following information about it:

For more information, see the gss_inquire_context(3GSS) man page.