aboutsummaryrefslogtreecommitdiffstats
path: root/roms/edk2/CryptoPkg/Library/OpensslLib/openssl/krb5/doc/appdev/gssapi.rst
diff options
context:
space:
mode:
Diffstat (limited to 'roms/edk2/CryptoPkg/Library/OpensslLib/openssl/krb5/doc/appdev/gssapi.rst')
-rw-r--r--roms/edk2/CryptoPkg/Library/OpensslLib/openssl/krb5/doc/appdev/gssapi.rst641
1 files changed, 641 insertions, 0 deletions
diff --git a/roms/edk2/CryptoPkg/Library/OpensslLib/openssl/krb5/doc/appdev/gssapi.rst b/roms/edk2/CryptoPkg/Library/OpensslLib/openssl/krb5/doc/appdev/gssapi.rst
new file mode 100644
index 000000000..f574b608b
--- /dev/null
+++ b/roms/edk2/CryptoPkg/Library/OpensslLib/openssl/krb5/doc/appdev/gssapi.rst
@@ -0,0 +1,641 @@
+Developing with GSSAPI
+======================
+
+The GSSAPI (Generic Security Services API) allows applications to
+communicate securely using Kerberos 5 or other security mechanisms.
+We recommend using the GSSAPI (or a higher-level framework which
+encompasses GSSAPI, such as SASL) for secure network communication
+over using the libkrb5 API directly.
+
+GSSAPIv2 is specified in :rfc:`2743` and :rfc:`2744`. Also see
+:rfc:`7546` for a description of how to use the GSSAPI in a client or
+server program.
+
+This documentation will describe how various ways of using the
+GSSAPI will behave with the krb5 mechanism as implemented in MIT krb5,
+as well as krb5-specific extensions to the GSSAPI.
+
+
+Name types
+----------
+
+A GSSAPI application can name a local or remote entity by calling
+gss_import_name_, specifying a name type and a value. The following
+name types are supported by the krb5 mechanism:
+
+* **GSS_C_NT_HOSTBASED_SERVICE**: The value should be a string of the
+ form ``service`` or ``service@hostname``. This is the most common
+ way to name target services when initiating a security context, and
+ is the most likely name type to work across multiple mechanisms.
+
+* **GSS_KRB5_NT_PRINCIPAL_NAME**: The value should be a principal name
+ string. This name type only works with the krb5 mechanism, and is
+ defined in the ``<gssapi/gssapi_krb5.h>`` header.
+
+* **GSS_C_NT_USER_NAME** or **GSS_C_NULL_OID**: The value is treated
+ as an unparsed principal name string, as above. These name types
+ may work with mechanisms other than krb5, but will have different
+ interpretations in those mechanisms. **GSS_C_NT_USER_NAME** is
+ intended to be used with a local username, which will parse into a
+ single-component principal in the default realm.
+
+* **GSS_C_NT_ANONYMOUS**: The value is ignored. The anonymous
+ principal is used, allowing a client to authenticate to a server
+ without asserting a particular identity (which may or may not be
+ allowed by a particular server or Kerberos realm).
+
+* **GSS_C_NT_MACHINE_UID_NAME**: The value is uid_t object. On
+ Unix-like systems, the username of the uid is looked up in the
+ system user database and the resulting username is parsed as a
+ principal name.
+
+* **GSS_C_NT_STRING_UID_NAME**: As above, but the value is a decimal
+ string representation of the uid.
+
+* **GSS_C_NT_EXPORT_NAME**: The value must be the result of a
+ gss_export_name_ call.
+
+* **GSS_KRB5_NT_ENTERPRISE_NAME**: The value should be a krb5
+ enterprise name string (see :rfc:`6806` section 5), in the form
+ ``user@suffix``. This name type is used to convey alias names, and
+ is defined in the ``<gssapi/gssapi_krb5.h>`` header. (New in
+ release 1.17.)
+
+
+Initiator credentials
+---------------------
+
+A GSSAPI client application uses gss_init_sec_context_ to establish a
+security context. The *initiator_cred_handle* parameter determines
+what tickets are used to establish the connection. An application can
+either pass **GSS_C_NO_CREDENTIAL** to use the default client
+credential, or it can use gss_acquire_cred_ beforehand to acquire an
+initiator credential. The call to gss_acquire_cred_ may include a
+*desired_name* parameter, or it may pass **GSS_C_NO_NAME** if it does
+not have a specific name preference.
+
+If the desired name for a krb5 initiator credential is a host-based
+name, it is converted to a principal name of the form
+``service/hostname`` in the local realm, where *hostname* is the local
+hostname if not specified. The hostname will be canonicalized using
+forward name resolution, and possibly also using reverse name
+resolution depending on the value of the **rdns** variable in
+:ref:`libdefaults`.
+
+If a desired name is specified in the call to gss_acquire_cred_, the
+krb5 mechanism will attempt to find existing tickets for that client
+principal name in the default credential cache or collection. If the
+default cache type does not support a collection, and the default
+cache contains credentials for a different principal than the desired
+name, a **GSS_S_CRED_UNAVAIL** error will be returned with a minor
+code indicating a mismatch.
+
+If no existing tickets are available for the desired name, but the
+name has an entry in the default client :ref:`keytab_definition`, the
+krb5 mechanism will acquire initial tickets for the name using the
+default client keytab.
+
+If no desired name is specified, credential acquisition will be
+deferred until the credential is used in a call to
+gss_init_sec_context_ or gss_inquire_cred_. If the call is to
+gss_init_sec_context_, the target name will be used to choose a client
+principal name using the credential cache selection facility. (This
+facility might, for instance, try to choose existing tickets for a
+client principal in the same realm as the target service). If there
+are no existing tickets for the chosen principal, but it is present in
+the default client keytab, the krb5 mechanism will acquire initial
+tickets using the keytab.
+
+If the target name cannot be used to select a client principal
+(because the credentials are used in a call to gss_inquire_cred_), or
+if the credential cache selection facility cannot choose a principal
+for it, the default credential cache will be selected if it exists and
+contains tickets.
+
+If the default credential cache does not exist, but the default client
+keytab does, the krb5 mechanism will try to acquire initial tickets
+for the first principal in the default client keytab.
+
+If the krb5 mechanism acquires initial tickets using the default
+client keytab, the resulting tickets will be stored in the default
+cache or collection, and will be refreshed by future calls to
+gss_acquire_cred_ as they approach their expire time.
+
+
+Acceptor names
+--------------
+
+A GSSAPI server application uses gss_accept_sec_context_ to establish
+a security context based on tokens provided by the client. The
+*acceptor_cred_handle* parameter determines what
+:ref:`keytab_definition` entries may be authenticated to by the
+client, if the krb5 mechanism is used.
+
+The simplest choice is to pass **GSS_C_NO_CREDENTIAL** as the acceptor
+credential. In this case, clients may authenticate to any service
+principal in the default keytab (typically |keytab|, or the value of
+the **KRB5_KTNAME** environment variable). This is the recommended
+approach if the server application has no specific requirements to the
+contrary.
+
+A server may acquire an acceptor credential with gss_acquire_cred_ and
+a *cred_usage* of **GSS_C_ACCEPT** or **GSS_C_BOTH**. If the
+*desired_name* parameter is **GSS_C_NO_NAME**, then clients will be
+allowed to authenticate to any service principal in the default
+keytab, just as if no acceptor credential was supplied.
+
+If a server wishes to specify a *desired_name* to gss_acquire_cred_,
+the most common choice is a host-based name. If the host-based
+*desired_name* contains just a *service*, then clients will be allowed
+to authenticate to any host-based service principal (that is, a
+principal of the form ``service/hostname@REALM``) for the named
+service, regardless of hostname or realm, as long as it is present in
+the default keytab. If the input name contains both a *service* and a
+*hostname*, clients will be allowed to authenticate to any host-based
+principal for the named service and hostname, regardless of realm.
+
+.. note::
+
+ If a *hostname* is specified, it will be canonicalized
+ using forward name resolution, and possibly also using
+ reverse name resolution depending on the value of the
+ **rdns** variable in :ref:`libdefaults`.
+
+.. note::
+
+ If the **ignore_acceptor_hostname** variable in
+ :ref:`libdefaults` is enabled, then *hostname* will be
+ ignored even if one is specified in the input name.
+
+.. note::
+
+ In MIT krb5 versions prior to 1.10, and in Heimdal's
+ implementation of the krb5 mechanism, an input name with
+ just a *service* is treated like an input name of
+ ``service@localhostname``, where *localhostname* is the
+ string returned by gethostname().
+
+If the *desired_name* is a krb5 principal name or a local system name
+type which is mapped to a krb5 principal name, clients will only be
+allowed to authenticate to that principal in the default keytab.
+
+
+Name Attributes
+---------------
+
+In release 1.8 or later, the gss_inquire_name_ and
+gss_get_name_attribute_ functions, specified in :rfc:`6680`, can be
+used to retrieve name attributes from the *src_name* returned by
+gss_accept_sec_context_. The following attributes are defined when
+the krb5 mechanism is used:
+
+.. _gssapi_authind_attr:
+
+* "auth-indicators" attribute:
+
+This attribute will be included in the gss_inquire_name_ output if the
+ticket contains :ref:`authentication indicators <auth_indicator>`.
+One indicator is returned per invocation of gss_get_name_attribute_,
+so multiple invocations may be necessary to retrieve all of the
+indicators from the ticket. (New in release 1.15.)
+
+
+Importing and exporting credentials
+-----------------------------------
+
+The following GSSAPI extensions can be used to import and export
+credentials (declared in ``<gssapi/gssapi_ext.h>``)::
+
+ OM_uint32 gss_export_cred(OM_uint32 *minor_status,
+ gss_cred_id_t cred_handle,
+ gss_buffer_t token);
+
+ OM_uint32 gss_import_cred(OM_uint32 *minor_status,
+ gss_buffer_t token,
+ gss_cred_id_t *cred_handle);
+
+The first function serializes a GSSAPI credential handle into a
+buffer; the second unseralizes a buffer into a GSSAPI credential
+handle. Serializing a credential does not destroy it. If any of the
+mechanisms used in *cred_handle* do not support serialization,
+gss_export_cred will return **GSS_S_UNAVAILABLE**. As with other
+GSSAPI serialization functions, these extensions are only intended to
+work with a matching implementation on the other side; they do not
+serialize credentials in a standardized format.
+
+A serialized credential may contain secret information such as ticket
+session keys. The serialization format does not protect this
+information from eavesdropping or tampering. The calling application
+must take care to protect the serialized credential when communicating
+it over an insecure channel or to an untrusted party.
+
+A krb5 GSSAPI credential may contain references to a credential cache,
+a client keytab, an acceptor keytab, and a replay cache. These
+resources are normally serialized as references to their external
+locations (such as the filename of the credential cache). Because of
+this, a serialized krb5 credential can only be imported by a process
+with similar privileges to the exporter. A serialized credential
+should not be trusted if it originates from a source with lower
+privileges than the importer, as it may contain references to external
+credential cache, keytab, or replay cache resources not accessible to
+the originator.
+
+An exception to the above rule applies when a krb5 GSSAPI credential
+refers to a memory credential cache, as is normally the case for
+delegated credentials received by gss_accept_sec_context_. In this
+case, the contents of the credential cache are serialized, so that the
+resulting token may be imported even if the original memory credential
+cache no longer exists.
+
+
+Constrained delegation (S4U)
+----------------------------
+
+The Microsoft S4U2Self and S4U2Proxy Kerberos protocol extensions
+allow an intermediate service to acquire credentials from a client to
+a target service without requiring the client to delegate a
+ticket-granting ticket, if the KDC is configured to allow it.
+
+To perform a constrained delegation operation, the intermediate
+service must submit to the KDC an "evidence ticket" from the client to
+the intermediate service with the forwardable bit set. An evidence
+ticket can be acquired when the client authenticates to the
+intermediate service with Kerberos, or with an S4U2Self request if the
+KDC allows it. The MIT krb5 GSSAPI library represents an evidence
+ticket using a "proxy credential", which is a special kind of
+gss_cred_id_t object whose underlying credential cache contains the
+evidence ticket and a krbtgt ticket for the intermediate service.
+
+To acquire a proxy credential during client authentication, the
+service should first create an acceptor credential using the
+**GSS_C_BOTH** usage. The application should then pass this
+credential as the *acceptor_cred_handle* to gss_accept_sec_context_,
+and also pass a *delegated_cred_handle* output parameter to receive a
+proxy credential containing the evidence ticket. The output value of
+*delegated_cred_handle* may be a delegated ticket-granting ticket if
+the client sent one, or a proxy credential if the client authenticated
+with a forwardable service ticket, or **GSS_C_NO_CREDENTIAL** if
+neither is the case.
+
+To acquire a proxy credential using an S4U2Self request, the service
+can use the following GSSAPI extension::
+
+ OM_uint32 gss_acquire_cred_impersonate_name(OM_uint32 *minor_status,
+ gss_cred_id_t icred,
+ gss_name_t desired_name,
+ OM_uint32 time_req,
+ gss_OID_set desired_mechs,
+ gss_cred_usage_t cred_usage,
+ gss_cred_id_t *output_cred,
+ gss_OID_set *actual_mechs,
+ OM_uint32 *time_rec);
+
+The parameters to this function are similar to those of
+gss_acquire_cred_, except that *icred* is used to make an S4U2Self
+request to the KDC for a ticket from *desired_name* to the
+intermediate service. Both *icred* and *desired_name* are required
+for this function; passing **GSS_C_NO_CREDENTIAL** or
+**GSS_C_NO_NAME** will cause the call to fail. *icred* must contain a
+krbtgt ticket for the intermediate service. If the KDC returns a
+forwardable ticket, the result of this operation is a proxy
+credential; if it is not forwardable, the result is a regular
+credential for *desired_name*.
+
+A recent KDC will usually allow any service to acquire a ticket from a
+client to itself with an S4U2Self request, but the ticket will only be
+forwardable if the service has a specific privilege. In the MIT krb5
+KDC, this privilege is determined by the **ok_to_auth_as_delegate**
+bit on the intermediate service's principal entry, which can be
+configured with :ref:`kadmin(1)`.
+
+Once the intermediate service has a proxy credential, it can simply
+pass it to gss_init_sec_context_ as the *initiator_cred_handle*
+parameter, and the desired service as the *target_name* parameter.
+The GSSAPI library will present the krbtgt ticket and evidence ticket
+in the proxy credential to the KDC in an S4U2Proxy request; if the
+intermediate service has the appropriate permissions, the KDC will
+issue a ticket from the client to the target service. The GSSAPI
+library will then use this ticket to authenticate to the target
+service.
+
+If an application needs to find out whether a credential it holds is a
+proxy credential and the name of the intermediate service, it can
+query the credential with the **GSS_KRB5_GET_CRED_IMPERSONATOR** OID
+(new in release 1.16, declared in ``<gssapi/gssapi_krb5.h>``) using
+the gss_inquire_cred_by_oid extension (declared in
+``<gssapi/gssapi_ext.h>``)::
+
+ OM_uint32 gss_inquire_cred_by_oid(OM_uint32 *minor_status,
+ const gss_cred_id_t cred_handle,
+ gss_OID desired_object,
+ gss_buffer_set_t *data_set);
+
+If the call succeeds and *cred_handle* is a proxy credential,
+*data_set* will be set to a single-element buffer set containing the
+unparsed principal name of the intermediate service. If *cred_handle*
+is not a proxy credential, *data_set* will be set to an empty buffer
+set. If the library does not support the query,
+gss_inquire_cred_by_oid will return **GSS_S_UNAVAILABLE**.
+
+
+AEAD message wrapping
+---------------------
+
+The following GSSAPI extensions (declared in
+``<gssapi/gssapi_ext.h>``) can be used to wrap and unwrap messages
+with additional "associated data" which is integrity-checked but is
+not included in the output buffer::
+
+ OM_uint32 gss_wrap_aead(OM_uint32 *minor_status,
+ gss_ctx_id_t context_handle,
+ int conf_req_flag, gss_qop_t qop_req,
+ gss_buffer_t input_assoc_buffer,
+ gss_buffer_t input_payload_buffer,
+ int *conf_state,
+ gss_buffer_t output_message_buffer);
+
+ OM_uint32 gss_unwrap_aead(OM_uint32 *minor_status,
+ gss_ctx_id_t context_handle,
+ gss_buffer_t input_message_buffer,
+ gss_buffer_t input_assoc_buffer,
+ gss_buffer_t output_payload_buffer,
+ int *conf_state,
+ gss_qop_t *qop_state);
+
+Wrap tokens created with gss_wrap_aead will successfully unwrap only
+if the same *input_assoc_buffer* contents are presented to
+gss_unwrap_aead.
+
+
+IOV message wrapping
+--------------------
+
+The following extensions (declared in ``<gssapi/gssapi_ext.h>``) can
+be used for in-place encryption, fine-grained control over wrap token
+layout, and for constructing wrap tokens compatible with Microsoft DCE
+RPC::
+
+ typedef struct gss_iov_buffer_desc_struct {
+ OM_uint32 type;
+ gss_buffer_desc buffer;
+ } gss_iov_buffer_desc, *gss_iov_buffer_t;
+
+ OM_uint32 gss_wrap_iov(OM_uint32 *minor_status,
+ gss_ctx_id_t context_handle,
+ int conf_req_flag, gss_qop_t qop_req,
+ int *conf_state,
+ gss_iov_buffer_desc *iov, int iov_count);
+
+ OM_uint32 gss_unwrap_iov(OM_uint32 *minor_status,
+ gss_ctx_id_t context_handle,
+ int *conf_state, gss_qop_t *qop_state,
+ gss_iov_buffer_desc *iov, int iov_count);
+
+ OM_uint32 gss_wrap_iov_length(OM_uint32 *minor_status,
+ gss_ctx_id_t context_handle,
+ int conf_req_flag,
+ gss_qop_t qop_req, int *conf_state,
+ gss_iov_buffer_desc *iov,
+ int iov_count);
+
+ OM_uint32 gss_release_iov_buffer(OM_uint32 *minor_status,
+ gss_iov_buffer_desc *iov,
+ int iov_count);
+
+The caller of gss_wrap_iov provides an array of gss_iov_buffer_desc
+structures, each containing a type and a gss_buffer_desc structure.
+Valid types include:
+
+* **GSS_C_BUFFER_TYPE_DATA**: A data buffer to be included in the
+ token, and to be encrypted or decrypted in-place if the token is
+ confidentiality-protected.
+
+* **GSS_C_BUFFER_TYPE_HEADER**: The GSSAPI wrap token header and
+ underlying cryptographic header.
+
+* **GSS_C_BUFFER_TYPE_TRAILER**: The cryptographic trailer, if one is
+ required.
+
+* **GSS_C_BUFFER_TYPE_PADDING**: Padding to be combined with the data
+ during encryption and decryption. (The implementation may choose to
+ place padding in the trailer buffer, in which case it will set the
+ padding buffer length to 0.)
+
+* **GSS_C_BUFFER_TYPE_STREAM**: For unwrapping only, a buffer
+ containing a complete wrap token in standard format to be unwrapped.
+
+* **GSS_C_BUFFER_TYPE_SIGN_ONLY**: A buffer to be included in the
+ token's integrity protection checksum, but not to be encrypted or
+ included in the token itself.
+
+For gss_wrap_iov, the IOV list should contain one HEADER buffer,
+followed by zero or more SIGN_ONLY buffers, followed by one or more
+DATA buffers, followed by a TRAILER buffer. The memory pointed to by
+the buffers is not required to be contiguous or in any particular
+order. If *conf_req_flag* is true, DATA buffers will be encrypted
+in-place, while SIGN_ONLY buffers will not be modified.
+
+The type of an output buffer may be combined with
+**GSS_C_BUFFER_FLAG_ALLOCATE** to request that gss_wrap_iov allocate
+the buffer contents. If gss_wrap_iov allocates a buffer, it sets the
+**GSS_C_BUFFER_FLAG_ALLOCATED** flag on the buffer type.
+gss_release_iov_buffer can be used to release all allocated buffers
+within an iov list and unset their allocated flags. Here is an
+example of how gss_wrap_iov can be used with allocation requested
+(*ctx* is assumed to be a previously established gss_ctx_id_t)::
+
+ OM_uint32 major, minor;
+ gss_iov_buffer_desc iov[4];
+ char str[] = "message";
+
+ iov[0].type = GSS_IOV_BUFFER_TYPE_HEADER | GSS_IOV_BUFFER_FLAG_ALLOCATE;
+ iov[1].type = GSS_IOV_BUFFER_TYPE_DATA;
+ iov[1].buffer.value = str;
+ iov[1].buffer.length = strlen(str);
+ iov[2].type = GSS_IOV_BUFFER_TYPE_PADDING | GSS_IOV_BUFFER_FLAG_ALLOCATE;
+ iov[3].type = GSS_IOV_BUFFER_TYPE_TRAILER | GSS_IOV_BUFFER_FLAG_ALLOCATE;
+
+ major = gss_wrap_iov(&minor, ctx, 1, GSS_C_QOP_DEFAULT, NULL,
+ iov, 4);
+ if (GSS_ERROR(major))
+ handle_error(major, minor);
+
+ /* Transmit or otherwise use resulting buffers. */
+
+ (void)gss_release_iov_buffer(&minor, iov, 4);
+
+If the caller does not choose to request buffer allocation by
+gss_wrap_iov, it should first call gss_wrap_iov_length to query the
+lengths of the HEADER, PADDING, and TRAILER buffers. DATA buffers
+must be provided in the iov list so that padding length can be
+computed correctly, but the output buffers need not be initialized.
+Here is an example of using gss_wrap_iov_length and gss_wrap_iov::
+
+ OM_uint32 major, minor;
+ gss_iov_buffer_desc iov[4];
+ char str[1024] = "message", *ptr;
+
+ iov[0].type = GSS_IOV_BUFFER_TYPE_HEADER;
+ iov[1].type = GSS_IOV_BUFFER_TYPE_DATA;
+ iov[1].buffer.value = str;
+ iov[1].buffer.length = strlen(str);
+
+ iov[2].type = GSS_IOV_BUFFER_TYPE_PADDING;
+ iov[3].type = GSS_IOV_BUFFER_TYPE_TRAILER;
+
+ major = gss_wrap_iov_length(&minor, ctx, 1, GSS_C_QOP_DEFAULT,
+ NULL, iov, 4);
+ if (GSS_ERROR(major))
+ handle_error(major, minor);
+ if (strlen(str) + iov[0].buffer.length + iov[2].buffer.length +
+ iov[3].buffer.length > sizeof(str))
+ handle_out_of_space_error();
+ ptr = str + strlen(str);
+ iov[0].buffer.value = ptr;
+ ptr += iov[0].buffer.length;
+ iov[2].buffer.value = ptr;
+ ptr += iov[2].buffer.length;
+ iov[3].buffer.value = ptr;
+
+ major = gss_wrap_iov(&minor, ctx, 1, GSS_C_QOP_DEFAULT, NULL,
+ iov, 4);
+ if (GSS_ERROR(major))
+ handle_error(major, minor);
+
+If the context was established using the **GSS_C_DCE_STYLE** flag
+(described in :rfc:`4757`), wrap tokens compatible with Microsoft DCE
+RPC can be constructed. In this case, the IOV list must include a
+SIGN_ONLY buffer, a DATA buffer, a second SIGN_ONLY buffer, and a
+HEADER buffer in that order (the order of the buffer contents remains
+arbitrary). The application must pad the DATA buffer to a multiple of
+16 bytes as no padding or trailer buffer is used.
+
+gss_unwrap_iov may be called with an IOV list just like one which
+would be provided to gss_wrap_iov. DATA buffers will be decrypted
+in-place if they were encrypted, and SIGN_ONLY buffers will not be
+modified.
+
+Alternatively, gss_unwrap_iov may be called with a single STREAM
+buffer, zero or more SIGN_ONLY buffers, and a single DATA buffer. The
+STREAM buffer is interpreted as a complete wrap token. The STREAM
+buffer will be modified in-place to decrypt its contents. The DATA
+buffer will be initialized to point to the decrypted data within the
+STREAM buffer, unless it has the **GSS_C_BUFFER_FLAG_ALLOCATE** flag
+set, in which case it will be initialized with a copy of the decrypted
+data. Here is an example (*token* and *token_len* are assumed to be a
+pre-existing pointer and length for a modifiable region of data)::
+
+ OM_uint32 major, minor;
+ gss_iov_buffer_desc iov[2];
+
+ iov[0].type = GSS_IOV_BUFFER_TYPE_STREAM;
+ iov[0].buffer.value = token;
+ iov[0].buffer.length = token_len;
+ iov[1].type = GSS_IOV_BUFFER_TYPE_DATA;
+ major = gss_unwrap_iov(&minor, ctx, NULL, NULL, iov, 2);
+ if (GSS_ERROR(major))
+ handle_error(major, minor);
+
+ /* Decrypted data is in iov[1].buffer, pointing to a subregion of
+ * token. */
+
+.. _gssapi_mic_token:
+
+IOV MIC tokens
+--------------
+
+The following extensions (declared in ``<gssapi/gssapi_ext.h>``) can
+be used in release 1.12 or later to construct and verify MIC tokens
+using an IOV list::
+
+ OM_uint32 gss_get_mic_iov(OM_uint32 *minor_status,
+ gss_ctx_id_t context_handle,
+ gss_qop_t qop_req,
+ gss_iov_buffer_desc *iov,
+ int iov_count);
+
+ OM_uint32 gss_get_mic_iov_length(OM_uint32 *minor_status,
+ gss_ctx_id_t context_handle,
+ gss_qop_t qop_req,
+ gss_iov_buffer_desc *iov,
+ iov_count);
+
+ OM_uint32 gss_verify_mic_iov(OM_uint32 *minor_status,
+ gss_ctx_id_t context_handle,
+ gss_qop_t *qop_state,
+ gss_iov_buffer_desc *iov,
+ int iov_count);
+
+The caller of gss_get_mic_iov provides an array of gss_iov_buffer_desc
+structures, each containing a type and a gss_buffer_desc structure.
+Valid types include:
+
+* **GSS_C_BUFFER_TYPE_DATA** and **GSS_C_BUFFER_TYPE_SIGN_ONLY**: The
+ corresponding buffer for each of these types will be signed for the
+ MIC token, in the order provided.
+
+* **GSS_C_BUFFER_TYPE_MIC_TOKEN**: The GSSAPI MIC token.
+
+The type of the MIC_TOKEN buffer may be combined with
+**GSS_C_BUFFER_FLAG_ALLOCATE** to request that gss_get_mic_iov
+allocate the buffer contents. If gss_get_mic_iov allocates the
+buffer, it sets the **GSS_C_BUFFER_FLAG_ALLOCATED** flag on the buffer
+type. gss_release_iov_buffer can be used to release all allocated
+buffers within an iov list and unset their allocated flags. Here is
+an example of how gss_get_mic_iov can be used with allocation
+requested (*ctx* is assumed to be a previously established
+gss_ctx_id_t)::
+
+ OM_uint32 major, minor;
+ gss_iov_buffer_desc iov[3];
+
+ iov[0].type = GSS_IOV_BUFFER_TYPE_DATA;
+ iov[0].buffer.value = "sign1";
+ iov[0].buffer.length = 5;
+ iov[1].type = GSS_IOV_BUFFER_TYPE_SIGN_ONLY;
+ iov[1].buffer.value = "sign2";
+ iov[1].buffer.length = 5;
+ iov[2].type = GSS_IOV_BUFFER_TYPE_MIC_TOKEN | GSS_IOV_BUFFER_FLAG_ALLOCATE;
+
+ major = gss_get_mic_iov(&minor, ctx, GSS_C_QOP_DEFAULT, iov, 3);
+ if (GSS_ERROR(major))
+ handle_error(major, minor);
+
+ /* Transmit or otherwise use iov[2].buffer. */
+
+ (void)gss_release_iov_buffer(&minor, iov, 3);
+
+If the caller does not choose to request buffer allocation by
+gss_get_mic_iov, it should first call gss_get_mic_iov_length to query
+the length of the MIC_TOKEN buffer. Here is an example of using
+gss_get_mic_iov_length and gss_get_mic_iov::
+
+ OM_uint32 major, minor;
+ gss_iov_buffer_desc iov[2];
+ char data[1024];
+
+ iov[0].type = GSS_IOV_BUFFER_TYPE_MIC_TOKEN;
+ iov[1].type = GSS_IOV_BUFFER_TYPE_DATA;
+ iov[1].buffer.value = "message";
+ iov[1].buffer.length = 7;
+
+ major = gss_get_mic_iov_length(&minor, ctx, GSS_C_QOP_DEFAULT, iov, 2);
+ if (GSS_ERROR(major))
+ handle_error(major, minor);
+ if (iov[0].buffer.length > sizeof(data))
+ handle_out_of_space_error();
+ iov[0].buffer.value = data;
+
+ major = gss_get_mic_iov(&minor, ctx, GSS_C_QOP_DEFAULT, iov, 2);
+ if (GSS_ERROR(major))
+ handle_error(major, minor);
+
+
+.. _gss_accept_sec_context: https://tools.ietf.org/html/rfc2744.html#section-5.1
+.. _gss_acquire_cred: https://tools.ietf.org/html/rfc2744.html#section-5.2
+.. _gss_export_name: https://tools.ietf.org/html/rfc2744.html#section-5.13
+.. _gss_get_name_attribute: https://tools.ietf.org/html/6680.html#section-7.5
+.. _gss_import_name: https://tools.ietf.org/html/rfc2744.html#section-5.16
+.. _gss_init_sec_context: https://tools.ietf.org/html/rfc2744.html#section-5.19
+.. _gss_inquire_name: https://tools.ietf.org/html/rfc6680.txt#section-7.4
+.. _gss_inquire_cred: https://tools.ietf.org/html/rfc2744.html#section-5.21