xref: /freebsd/crypto/krb5/doc/html/_sources/appdev/gssapi.rst.txt (revision 7f2fe78b9dd5f51c821d771b63d2e096f6fd49e9)
1*7f2fe78bSCy SchubertDeveloping with GSSAPI
2*7f2fe78bSCy Schubert======================
3*7f2fe78bSCy Schubert
4*7f2fe78bSCy SchubertThe GSSAPI (Generic Security Services API) allows applications to
5*7f2fe78bSCy Schubertcommunicate securely using Kerberos 5 or other security mechanisms.
6*7f2fe78bSCy SchubertWe recommend using the GSSAPI (or a higher-level framework which
7*7f2fe78bSCy Schubertencompasses GSSAPI, such as SASL) for secure network communication
8*7f2fe78bSCy Schubertover using the libkrb5 API directly.
9*7f2fe78bSCy Schubert
10*7f2fe78bSCy SchubertGSSAPIv2 is specified in :rfc:`2743` and :rfc:`2744`.  Also see
11*7f2fe78bSCy Schubert:rfc:`7546` for a description of how to use the GSSAPI in a client or
12*7f2fe78bSCy Schubertserver program.
13*7f2fe78bSCy Schubert
14*7f2fe78bSCy SchubertThis documentation will describe how various ways of using the
15*7f2fe78bSCy SchubertGSSAPI will behave with the krb5 mechanism as implemented in MIT krb5,
16*7f2fe78bSCy Schubertas well as krb5-specific extensions to the GSSAPI.
17*7f2fe78bSCy Schubert
18*7f2fe78bSCy Schubert
19*7f2fe78bSCy SchubertName types
20*7f2fe78bSCy Schubert----------
21*7f2fe78bSCy Schubert
22*7f2fe78bSCy SchubertA GSSAPI application can name a local or remote entity by calling
23*7f2fe78bSCy Schubertgss_import_name_, specifying a name type and a value.  The following
24*7f2fe78bSCy Schubertname types are supported by the krb5 mechanism:
25*7f2fe78bSCy Schubert
26*7f2fe78bSCy Schubert* **GSS_C_NT_HOSTBASED_SERVICE**: The value should be a string of the
27*7f2fe78bSCy Schubert  form ``service`` or ``service@hostname``.  This is the most common
28*7f2fe78bSCy Schubert  way to name target services when initiating a security context, and
29*7f2fe78bSCy Schubert  is the most likely name type to work across multiple mechanisms.
30*7f2fe78bSCy Schubert
31*7f2fe78bSCy Schubert* **GSS_KRB5_NT_PRINCIPAL_NAME**: The value should be a principal name
32*7f2fe78bSCy Schubert  string.  This name type only works with the krb5 mechanism, and is
33*7f2fe78bSCy Schubert  defined in the ``<gssapi/gssapi_krb5.h>`` header.
34*7f2fe78bSCy Schubert
35*7f2fe78bSCy Schubert* **GSS_C_NT_USER_NAME** or **GSS_C_NULL_OID**: The value is treated
36*7f2fe78bSCy Schubert  as an unparsed principal name string, as above.  These name types
37*7f2fe78bSCy Schubert  may work with mechanisms other than krb5, but will have different
38*7f2fe78bSCy Schubert  interpretations in those mechanisms.  **GSS_C_NT_USER_NAME** is
39*7f2fe78bSCy Schubert  intended to be used with a local username, which will parse into a
40*7f2fe78bSCy Schubert  single-component principal in the default realm.
41*7f2fe78bSCy Schubert
42*7f2fe78bSCy Schubert* **GSS_C_NT_ANONYMOUS**: The value is ignored.  The anonymous
43*7f2fe78bSCy Schubert  principal is used, allowing a client to authenticate to a server
44*7f2fe78bSCy Schubert  without asserting a particular identity (which may or may not be
45*7f2fe78bSCy Schubert  allowed by a particular server or Kerberos realm).
46*7f2fe78bSCy Schubert
47*7f2fe78bSCy Schubert* **GSS_C_NT_MACHINE_UID_NAME**: The value is uid_t object.  On
48*7f2fe78bSCy Schubert  Unix-like systems, the username of the uid is looked up in the
49*7f2fe78bSCy Schubert  system user database and the resulting username is parsed as a
50*7f2fe78bSCy Schubert  principal name.
51*7f2fe78bSCy Schubert
52*7f2fe78bSCy Schubert* **GSS_C_NT_STRING_UID_NAME**: As above, but the value is a decimal
53*7f2fe78bSCy Schubert  string representation of the uid.
54*7f2fe78bSCy Schubert
55*7f2fe78bSCy Schubert* **GSS_C_NT_EXPORT_NAME**: The value must be the result of a
56*7f2fe78bSCy Schubert  gss_export_name_ call.
57*7f2fe78bSCy Schubert
58*7f2fe78bSCy Schubert* **GSS_KRB5_NT_ENTERPRISE_NAME**: The value should be a krb5
59*7f2fe78bSCy Schubert  enterprise name string (see :rfc:`6806` section 5), in the form
60*7f2fe78bSCy Schubert  ``user@suffix``.  This name type is used to convey alias names, and
61*7f2fe78bSCy Schubert  is defined in the ``<gssapi/gssapi_krb5.h>`` header.  (New in
62*7f2fe78bSCy Schubert  release 1.17.)
63*7f2fe78bSCy Schubert
64*7f2fe78bSCy Schubert* **GSS_KRB5_NT_X509_CERT**: The value should be an X.509 certificate
65*7f2fe78bSCy Schubert  encoded according to :rfc:`5280`.  This name form can be used for
66*7f2fe78bSCy Schubert  the desired_name parameter of gss_acquire_cred_impersonate_name(),
67*7f2fe78bSCy Schubert  to identify the S4U2Self user by certificate.  (New in release
68*7f2fe78bSCy Schubert  1.19.)
69*7f2fe78bSCy Schubert
70*7f2fe78bSCy Schubert
71*7f2fe78bSCy SchubertInitiator credentials
72*7f2fe78bSCy Schubert---------------------
73*7f2fe78bSCy Schubert
74*7f2fe78bSCy SchubertA GSSAPI client application uses gss_init_sec_context_ to establish a
75*7f2fe78bSCy Schubertsecurity context.  The *initiator_cred_handle* parameter determines
76*7f2fe78bSCy Schubertwhat tickets are used to establish the connection.  An application can
77*7f2fe78bSCy Schuberteither pass **GSS_C_NO_CREDENTIAL** to use the default client
78*7f2fe78bSCy Schubertcredential, or it can use gss_acquire_cred_ beforehand to acquire an
79*7f2fe78bSCy Schubertinitiator credential.  The call to gss_acquire_cred_ may include a
80*7f2fe78bSCy Schubert*desired_name* parameter, or it may pass **GSS_C_NO_NAME** if it does
81*7f2fe78bSCy Schubertnot have a specific name preference.
82*7f2fe78bSCy Schubert
83*7f2fe78bSCy SchubertIf the desired name for a krb5 initiator credential is a host-based
84*7f2fe78bSCy Schubertname, it is converted to a principal name of the form
85*7f2fe78bSCy Schubert``service/hostname`` in the local realm, where *hostname* is the local
86*7f2fe78bSCy Schuberthostname if not specified.  The hostname will be canonicalized using
87*7f2fe78bSCy Schubertforward name resolution, and possibly also using reverse name
88*7f2fe78bSCy Schubertresolution depending on the value of the **rdns** variable in
89*7f2fe78bSCy Schubert:ref:`libdefaults`.
90*7f2fe78bSCy Schubert
91*7f2fe78bSCy SchubertIf a desired name is specified in the call to gss_acquire_cred_, the
92*7f2fe78bSCy Schubertkrb5 mechanism will attempt to find existing tickets for that client
93*7f2fe78bSCy Schubertprincipal name in the default credential cache or collection.  If the
94*7f2fe78bSCy Schubertdefault cache type does not support a collection, and the default
95*7f2fe78bSCy Schubertcache contains credentials for a different principal than the desired
96*7f2fe78bSCy Schubertname, a **GSS_S_CRED_UNAVAIL** error will be returned with a minor
97*7f2fe78bSCy Schubertcode indicating a mismatch.
98*7f2fe78bSCy Schubert
99*7f2fe78bSCy SchubertIf no existing tickets are available for the desired name, but the
100*7f2fe78bSCy Schubertname has an entry in the default client :ref:`keytab_definition`, the
101*7f2fe78bSCy Schubertkrb5 mechanism will acquire initial tickets for the name using the
102*7f2fe78bSCy Schubertdefault client keytab.
103*7f2fe78bSCy Schubert
104*7f2fe78bSCy SchubertIf no desired name is specified, credential acquisition will be
105*7f2fe78bSCy Schubertdeferred until the credential is used in a call to
106*7f2fe78bSCy Schubertgss_init_sec_context_ or gss_inquire_cred_.  If the call is to
107*7f2fe78bSCy Schubertgss_init_sec_context_, the target name will be used to choose a client
108*7f2fe78bSCy Schubertprincipal name using the credential cache selection facility.  (This
109*7f2fe78bSCy Schubertfacility might, for instance, try to choose existing tickets for a
110*7f2fe78bSCy Schubertclient principal in the same realm as the target service).  If there
111*7f2fe78bSCy Schubertare no existing tickets for the chosen principal, but it is present in
112*7f2fe78bSCy Schubertthe default client keytab, the krb5 mechanism will acquire initial
113*7f2fe78bSCy Schuberttickets using the keytab.
114*7f2fe78bSCy Schubert
115*7f2fe78bSCy SchubertIf the target name cannot be used to select a client principal
116*7f2fe78bSCy Schubert(because the credentials are used in a call to gss_inquire_cred_), or
117*7f2fe78bSCy Schubertif the credential cache selection facility cannot choose a principal
118*7f2fe78bSCy Schubertfor it, the default credential cache will be selected if it exists and
119*7f2fe78bSCy Schubertcontains tickets.
120*7f2fe78bSCy Schubert
121*7f2fe78bSCy SchubertIf the default credential cache does not exist, but the default client
122*7f2fe78bSCy Schubertkeytab does, the krb5 mechanism will try to acquire initial tickets
123*7f2fe78bSCy Schubertfor the first principal in the default client keytab.
124*7f2fe78bSCy Schubert
125*7f2fe78bSCy SchubertIf the krb5 mechanism acquires initial tickets using the default
126*7f2fe78bSCy Schubertclient keytab, the resulting tickets will be stored in the default
127*7f2fe78bSCy Schubertcache or collection, and will be refreshed by future calls to
128*7f2fe78bSCy Schubertgss_acquire_cred_ as they approach their expire time.
129*7f2fe78bSCy Schubert
130*7f2fe78bSCy Schubert
131*7f2fe78bSCy SchubertAcceptor names
132*7f2fe78bSCy Schubert--------------
133*7f2fe78bSCy Schubert
134*7f2fe78bSCy SchubertA GSSAPI server application uses gss_accept_sec_context_ to establish
135*7f2fe78bSCy Schuberta security context based on tokens provided by the client.  The
136*7f2fe78bSCy Schubert*acceptor_cred_handle* parameter determines what
137*7f2fe78bSCy Schubert:ref:`keytab_definition` entries may be authenticated to by the
138*7f2fe78bSCy Schubertclient, if the krb5 mechanism is used.
139*7f2fe78bSCy Schubert
140*7f2fe78bSCy SchubertThe simplest choice is to pass **GSS_C_NO_CREDENTIAL** as the acceptor
141*7f2fe78bSCy Schubertcredential.  In this case, clients may authenticate to any service
142*7f2fe78bSCy Schubertprincipal in the default keytab (typically |keytab|, or the value of
143*7f2fe78bSCy Schubertthe **KRB5_KTNAME** environment variable).  This is the recommended
144*7f2fe78bSCy Schubertapproach if the server application has no specific requirements to the
145*7f2fe78bSCy Schubertcontrary.
146*7f2fe78bSCy Schubert
147*7f2fe78bSCy SchubertA server may acquire an acceptor credential with gss_acquire_cred_ and
148*7f2fe78bSCy Schuberta *cred_usage* of **GSS_C_ACCEPT** or **GSS_C_BOTH**.  If the
149*7f2fe78bSCy Schubert*desired_name* parameter is **GSS_C_NO_NAME**, then clients will be
150*7f2fe78bSCy Schubertallowed to authenticate to any service principal in the default
151*7f2fe78bSCy Schubertkeytab, just as if no acceptor credential was supplied.
152*7f2fe78bSCy Schubert
153*7f2fe78bSCy SchubertIf a server wishes to specify a *desired_name* to gss_acquire_cred_,
154*7f2fe78bSCy Schubertthe most common choice is a host-based name.  If the host-based
155*7f2fe78bSCy Schubert*desired_name* contains just a *service*, then clients will be allowed
156*7f2fe78bSCy Schubertto authenticate to any host-based service principal (that is, a
157*7f2fe78bSCy Schubertprincipal of the form ``service/hostname@REALM``) for the named
158*7f2fe78bSCy Schubertservice, regardless of hostname or realm, as long as it is present in
159*7f2fe78bSCy Schubertthe default keytab.  If the input name contains both a *service* and a
160*7f2fe78bSCy Schubert*hostname*, clients will be allowed to authenticate to any host-based
161*7f2fe78bSCy Schubertprincipal for the named service and hostname, regardless of realm.
162*7f2fe78bSCy Schubert
163*7f2fe78bSCy Schubert.. note::
164*7f2fe78bSCy Schubert
165*7f2fe78bSCy Schubert          If a *hostname* is specified, it will be canonicalized
166*7f2fe78bSCy Schubert          using forward name resolution, and possibly also using
167*7f2fe78bSCy Schubert          reverse name resolution depending on the value of the
168*7f2fe78bSCy Schubert          **rdns** variable in :ref:`libdefaults`.
169*7f2fe78bSCy Schubert
170*7f2fe78bSCy Schubert.. note::
171*7f2fe78bSCy Schubert
172*7f2fe78bSCy Schubert          If the **ignore_acceptor_hostname** variable in
173*7f2fe78bSCy Schubert          :ref:`libdefaults` is enabled, then *hostname* will be
174*7f2fe78bSCy Schubert          ignored even if one is specified in the input name.
175*7f2fe78bSCy Schubert
176*7f2fe78bSCy Schubert.. note::
177*7f2fe78bSCy Schubert
178*7f2fe78bSCy Schubert          In MIT krb5 versions prior to 1.10, and in Heimdal's
179*7f2fe78bSCy Schubert          implementation of the krb5 mechanism, an input name with
180*7f2fe78bSCy Schubert          just a *service* is treated like an input name of
181*7f2fe78bSCy Schubert          ``service@localhostname``, where *localhostname* is the
182*7f2fe78bSCy Schubert          string returned by gethostname().
183*7f2fe78bSCy Schubert
184*7f2fe78bSCy SchubertIf the *desired_name* is a krb5 principal name or a local system name
185*7f2fe78bSCy Schuberttype which is mapped to a krb5 principal name, clients will only be
186*7f2fe78bSCy Schubertallowed to authenticate to that principal in the default keytab.
187*7f2fe78bSCy Schubert
188*7f2fe78bSCy Schubert
189*7f2fe78bSCy SchubertName Attributes
190*7f2fe78bSCy Schubert---------------
191*7f2fe78bSCy Schubert
192*7f2fe78bSCy SchubertIn release 1.8 or later, the gss_inquire_name_ and
193*7f2fe78bSCy Schubertgss_get_name_attribute_ functions, specified in :rfc:`6680`, can be
194*7f2fe78bSCy Schubertused to retrieve name attributes from the *src_name* returned by
195*7f2fe78bSCy Schubertgss_accept_sec_context_.  The following attributes are defined when
196*7f2fe78bSCy Schubertthe krb5 mechanism is used:
197*7f2fe78bSCy Schubert
198*7f2fe78bSCy Schubert.. _gssapi_authind_attr:
199*7f2fe78bSCy Schubert
200*7f2fe78bSCy Schubert* "auth-indicators" attribute:
201*7f2fe78bSCy Schubert
202*7f2fe78bSCy SchubertThis attribute will be included in the gss_inquire_name_ output if the
203*7f2fe78bSCy Schubertticket contains :ref:`authentication indicators <auth_indicator>`.
204*7f2fe78bSCy SchubertOne indicator is returned per invocation of gss_get_name_attribute_,
205*7f2fe78bSCy Schubertso multiple invocations may be necessary to retrieve all of the
206*7f2fe78bSCy Schubertindicators from the ticket.  (New in release 1.15.)
207*7f2fe78bSCy Schubert
208*7f2fe78bSCy Schubert
209*7f2fe78bSCy SchubertCredential store extensions
210*7f2fe78bSCy Schubert---------------------------
211*7f2fe78bSCy Schubert
212*7f2fe78bSCy SchubertBeginning with release 1.11, the following GSSAPI extensions declared
213*7f2fe78bSCy Schubertin ``<gssapi/gssapi_ext.h>`` can be used to specify how credentials
214*7f2fe78bSCy Schubertare acquired or stored::
215*7f2fe78bSCy Schubert
216*7f2fe78bSCy Schubert    struct gss_key_value_element_struct {
217*7f2fe78bSCy Schubert        const char *key;
218*7f2fe78bSCy Schubert        const char *value;
219*7f2fe78bSCy Schubert    };
220*7f2fe78bSCy Schubert    typedef struct gss_key_value_element_struct gss_key_value_element_desc;
221*7f2fe78bSCy Schubert
222*7f2fe78bSCy Schubert    struct gss_key_value_set_struct {
223*7f2fe78bSCy Schubert        OM_uint32 count;
224*7f2fe78bSCy Schubert        gss_key_value_element_desc *elements;
225*7f2fe78bSCy Schubert    };
226*7f2fe78bSCy Schubert    typedef const struct gss_key_value_set_struct gss_key_value_set_desc;
227*7f2fe78bSCy Schubert    typedef const gss_key_value_set_desc *gss_const_key_value_set_t;
228*7f2fe78bSCy Schubert
229*7f2fe78bSCy Schubert    OM_uint32 gss_acquire_cred_from(OM_uint32 *minor_status,
230*7f2fe78bSCy Schubert                                    const gss_name_t desired_name,
231*7f2fe78bSCy Schubert                                    OM_uint32 time_req,
232*7f2fe78bSCy Schubert                                    const gss_OID_set desired_mechs,
233*7f2fe78bSCy Schubert                                    gss_cred_usage_t cred_usage,
234*7f2fe78bSCy Schubert                                    gss_const_key_value_set_t cred_store,
235*7f2fe78bSCy Schubert                                    gss_cred_id_t *output_cred_handle,
236*7f2fe78bSCy Schubert                                    gss_OID_set *actual_mechs,
237*7f2fe78bSCy Schubert                                    OM_uint32 *time_rec);
238*7f2fe78bSCy Schubert
239*7f2fe78bSCy Schubert    OM_uint32 gss_store_cred_into(OM_uint32 *minor_status,
240*7f2fe78bSCy Schubert                                  gss_cred_id_t input_cred_handle,
241*7f2fe78bSCy Schubert                                  gss_cred_usage_t cred_usage,
242*7f2fe78bSCy Schubert                                  const gss_OID desired_mech,
243*7f2fe78bSCy Schubert                                  OM_uint32 overwrite_cred,
244*7f2fe78bSCy Schubert                                  OM_uint32 default_cred,
245*7f2fe78bSCy Schubert                                  gss_const_key_value_set_t cred_store,
246*7f2fe78bSCy Schubert                                  gss_OID_set *elements_stored,
247*7f2fe78bSCy Schubert                                  gss_cred_usage_t *cred_usage_stored);
248*7f2fe78bSCy Schubert
249*7f2fe78bSCy SchubertThe additional *cred_store* parameter allows the caller to specify
250*7f2fe78bSCy Schubertinformation about how the credentials should be obtained and stored.
251*7f2fe78bSCy SchubertThe following options are supported by the krb5 mechanism:
252*7f2fe78bSCy Schubert
253*7f2fe78bSCy Schubert* **ccache**: For acquiring initiator credentials, the name of the
254*7f2fe78bSCy Schubert  :ref:`credential cache <ccache_definition>` to which the handle will
255*7f2fe78bSCy Schubert  refer.  For storing credentials, the name of the cache or collection
256*7f2fe78bSCy Schubert  where the credentials will be stored (see below).
257*7f2fe78bSCy Schubert
258*7f2fe78bSCy Schubert* **client_keytab**: For acquiring initiator credentials, the name of
259*7f2fe78bSCy Schubert  the :ref:`keytab <keytab_definition>` which will be used, if
260*7f2fe78bSCy Schubert  necessary, to refresh the credentials in the cache.
261*7f2fe78bSCy Schubert
262*7f2fe78bSCy Schubert* **keytab**: For acquiring acceptor credentials, the name of the
263*7f2fe78bSCy Schubert  :ref:`keytab <keytab_definition>` to which the handle will refer.
264*7f2fe78bSCy Schubert  In release 1.19 and later, this option also determines the keytab to
265*7f2fe78bSCy Schubert  be used for verification when initiator credentials are acquired
266*7f2fe78bSCy Schubert  using a password and verified.
267*7f2fe78bSCy Schubert
268*7f2fe78bSCy Schubert* **password**: For acquiring initiator credentials, this option
269*7f2fe78bSCy Schubert  instructs the mechanism to acquire fresh credentials into a unique
270*7f2fe78bSCy Schubert  memory credential cache.  This option may not be used with the
271*7f2fe78bSCy Schubert  **ccache** or **client_keytab** options, and a *desired_name* must
272*7f2fe78bSCy Schubert  be specified.  (New in release 1.19.)
273*7f2fe78bSCy Schubert
274*7f2fe78bSCy Schubert* **rcache**: For acquiring acceptor credentials, the name of the
275*7f2fe78bSCy Schubert  :ref:`replay cache <rcache_definition>` to be used when processing
276*7f2fe78bSCy Schubert  the initiator tokens.  (New in release 1.13.)
277*7f2fe78bSCy Schubert
278*7f2fe78bSCy Schubert* **verify**: For acquiring initiator credentials, this option
279*7f2fe78bSCy Schubert  instructs the mechanism to verify the credentials by obtaining a
280*7f2fe78bSCy Schubert  ticket to a service with a known key.  The service key is obtained
281*7f2fe78bSCy Schubert  from the keytab specified with the **keytab** option or the default
282*7f2fe78bSCy Schubert  keytab.  The value may be the name of a principal in the keytab, or
283*7f2fe78bSCy Schubert  the empty string.  If the empty string is given, any ``host``
284*7f2fe78bSCy Schubert  service principal in the keytab may be used.  (New in release 1.19.)
285*7f2fe78bSCy Schubert
286*7f2fe78bSCy SchubertIn release 1.20 or later, if a collection name is specified for
287*7f2fe78bSCy Schubert**cache** in a call to gss_store_cred_into(), an existing cache for
288*7f2fe78bSCy Schubertthe client principal within the collection will be selected, or a new
289*7f2fe78bSCy Schubertcache will be created within the collection.  If *overwrite_cred* is
290*7f2fe78bSCy Schubertfalse and the selected credential cache already exists, a
291*7f2fe78bSCy Schubert**GSS_S_DUPLICATE_ELEMENT** error will be returned.  If *default_cred*
292*7f2fe78bSCy Schubertis true, the primary cache of the collection will be switched to the
293*7f2fe78bSCy Schubertselected cache.
294*7f2fe78bSCy Schubert
295*7f2fe78bSCy Schubert
296*7f2fe78bSCy SchubertImporting and exporting credentials
297*7f2fe78bSCy Schubert-----------------------------------
298*7f2fe78bSCy Schubert
299*7f2fe78bSCy SchubertThe following GSSAPI extensions can be used to import and export
300*7f2fe78bSCy Schubertcredentials (declared in ``<gssapi/gssapi_ext.h>``)::
301*7f2fe78bSCy Schubert
302*7f2fe78bSCy Schubert    OM_uint32 gss_export_cred(OM_uint32 *minor_status,
303*7f2fe78bSCy Schubert                              gss_cred_id_t cred_handle,
304*7f2fe78bSCy Schubert                              gss_buffer_t token);
305*7f2fe78bSCy Schubert
306*7f2fe78bSCy Schubert    OM_uint32 gss_import_cred(OM_uint32 *minor_status,
307*7f2fe78bSCy Schubert                              gss_buffer_t token,
308*7f2fe78bSCy Schubert                              gss_cred_id_t *cred_handle);
309*7f2fe78bSCy Schubert
310*7f2fe78bSCy SchubertThe first function serializes a GSSAPI credential handle into a
311*7f2fe78bSCy Schubertbuffer; the second unseralizes a buffer into a GSSAPI credential
312*7f2fe78bSCy Schuberthandle.  Serializing a credential does not destroy it.  If any of the
313*7f2fe78bSCy Schubertmechanisms used in *cred_handle* do not support serialization,
314*7f2fe78bSCy Schubertgss_export_cred will return **GSS_S_UNAVAILABLE**.  As with other
315*7f2fe78bSCy SchubertGSSAPI serialization functions, these extensions are only intended to
316*7f2fe78bSCy Schubertwork with a matching implementation on the other side; they do not
317*7f2fe78bSCy Schubertserialize credentials in a standardized format.
318*7f2fe78bSCy Schubert
319*7f2fe78bSCy SchubertA serialized credential may contain secret information such as ticket
320*7f2fe78bSCy Schubertsession keys.  The serialization format does not protect this
321*7f2fe78bSCy Schubertinformation from eavesdropping or tampering.  The calling application
322*7f2fe78bSCy Schubertmust take care to protect the serialized credential when communicating
323*7f2fe78bSCy Schubertit over an insecure channel or to an untrusted party.
324*7f2fe78bSCy Schubert
325*7f2fe78bSCy SchubertA krb5 GSSAPI credential may contain references to a credential cache,
326*7f2fe78bSCy Schuberta client keytab, an acceptor keytab, and a replay cache.  These
327*7f2fe78bSCy Schubertresources are normally serialized as references to their external
328*7f2fe78bSCy Schubertlocations (such as the filename of the credential cache).  Because of
329*7f2fe78bSCy Schubertthis, a serialized krb5 credential can only be imported by a process
330*7f2fe78bSCy Schubertwith similar privileges to the exporter.  A serialized credential
331*7f2fe78bSCy Schubertshould not be trusted if it originates from a source with lower
332*7f2fe78bSCy Schubertprivileges than the importer, as it may contain references to external
333*7f2fe78bSCy Schubertcredential cache, keytab, or replay cache resources not accessible to
334*7f2fe78bSCy Schubertthe originator.
335*7f2fe78bSCy Schubert
336*7f2fe78bSCy SchubertAn exception to the above rule applies when a krb5 GSSAPI credential
337*7f2fe78bSCy Schubertrefers to a memory credential cache, as is normally the case for
338*7f2fe78bSCy Schubertdelegated credentials received by gss_accept_sec_context_.  In this
339*7f2fe78bSCy Schubertcase, the contents of the credential cache are serialized, so that the
340*7f2fe78bSCy Schubertresulting token may be imported even if the original memory credential
341*7f2fe78bSCy Schubertcache no longer exists.
342*7f2fe78bSCy Schubert
343*7f2fe78bSCy Schubert
344*7f2fe78bSCy SchubertConstrained delegation (S4U)
345*7f2fe78bSCy Schubert----------------------------
346*7f2fe78bSCy Schubert
347*7f2fe78bSCy SchubertThe Microsoft S4U2Self and S4U2Proxy Kerberos protocol extensions
348*7f2fe78bSCy Schubertallow an intermediate service to acquire credentials from a client to
349*7f2fe78bSCy Schuberta target service without requiring the client to delegate a
350*7f2fe78bSCy Schubertticket-granting ticket, if the KDC is configured to allow it.
351*7f2fe78bSCy Schubert
352*7f2fe78bSCy SchubertTo perform a constrained delegation operation, the intermediate
353*7f2fe78bSCy Schubertservice must submit to the KDC an "evidence ticket" from the client to
354*7f2fe78bSCy Schubertthe intermediate service.  An evidence ticket can be acquired when the
355*7f2fe78bSCy Schubertclient authenticates to the intermediate service with Kerberos, or
356*7f2fe78bSCy Schubertwith an S4U2Self request if the KDC allows it.  The MIT krb5 GSSAPI
357*7f2fe78bSCy Schubertlibrary represents an evidence ticket using a "proxy credential",
358*7f2fe78bSCy Schubertwhich is a special kind of gss_cred_id_t object whose underlying
359*7f2fe78bSCy Schubertcredential cache contains the evidence ticket and a krbtgt ticket for
360*7f2fe78bSCy Schubertthe intermediate service.
361*7f2fe78bSCy Schubert
362*7f2fe78bSCy SchubertTo acquire a proxy credential during client authentication, the
363*7f2fe78bSCy Schubertservice should first create an acceptor credential using the
364*7f2fe78bSCy Schubert**GSS_C_BOTH** usage.  The application should then pass this
365*7f2fe78bSCy Schubertcredential as the *acceptor_cred_handle* to gss_accept_sec_context_,
366*7f2fe78bSCy Schubertand also pass a *delegated_cred_handle* output parameter to receive a
367*7f2fe78bSCy Schubertproxy credential containing the evidence ticket.  The output value of
368*7f2fe78bSCy Schubert*delegated_cred_handle* may be a delegated ticket-granting ticket if
369*7f2fe78bSCy Schubertthe client sent one, or a proxy credential if not.  If the library can
370*7f2fe78bSCy Schubertdetermine that the client's ticket is not a valid evidence ticket, it
371*7f2fe78bSCy Schubertwill place **GSS_C_NO_CREDENTIAL** in *delegated_cred_handle*.
372*7f2fe78bSCy Schubert
373*7f2fe78bSCy SchubertTo acquire a proxy credential using an S4U2Self request, the service
374*7f2fe78bSCy Schubertcan use the following GSSAPI extension::
375*7f2fe78bSCy Schubert
376*7f2fe78bSCy Schubert    OM_uint32 gss_acquire_cred_impersonate_name(OM_uint32 *minor_status,
377*7f2fe78bSCy Schubert                                                gss_cred_id_t icred,
378*7f2fe78bSCy Schubert                                                gss_name_t desired_name,
379*7f2fe78bSCy Schubert                                                OM_uint32 time_req,
380*7f2fe78bSCy Schubert                                                gss_OID_set desired_mechs,
381*7f2fe78bSCy Schubert                                                gss_cred_usage_t cred_usage,
382*7f2fe78bSCy Schubert                                                gss_cred_id_t *output_cred,
383*7f2fe78bSCy Schubert                                                gss_OID_set *actual_mechs,
384*7f2fe78bSCy Schubert                                                OM_uint32 *time_rec);
385*7f2fe78bSCy Schubert
386*7f2fe78bSCy SchubertThe parameters to this function are similar to those of
387*7f2fe78bSCy Schubertgss_acquire_cred_, except that *icred* is used to make an S4U2Self
388*7f2fe78bSCy Schubertrequest to the KDC for a ticket from *desired_name* to the
389*7f2fe78bSCy Schubertintermediate service.  Both *icred* and *desired_name* are required
390*7f2fe78bSCy Schubertfor this function; passing **GSS_C_NO_CREDENTIAL** or
391*7f2fe78bSCy Schubert**GSS_C_NO_NAME** will cause the call to fail.  *icred* must contain a
392*7f2fe78bSCy Schubertkrbtgt ticket for the intermediate service.  The result of this
393*7f2fe78bSCy Schubertoperation is a proxy credential.  (Prior to release 1.18, the result
394*7f2fe78bSCy Schubertof this operation may be a regular credential for *desired_name*, if
395*7f2fe78bSCy Schubertthe KDC issues a non-forwardable ticket.)
396*7f2fe78bSCy Schubert
397*7f2fe78bSCy SchubertOnce the intermediate service has a proxy credential, it can simply
398*7f2fe78bSCy Schubertpass it to gss_init_sec_context_ as the *initiator_cred_handle*
399*7f2fe78bSCy Schubertparameter, and the desired service as the *target_name* parameter.
400*7f2fe78bSCy SchubertThe GSSAPI library will present the krbtgt ticket and evidence ticket
401*7f2fe78bSCy Schubertin the proxy credential to the KDC in an S4U2Proxy request; if the
402*7f2fe78bSCy Schubertintermediate service has the appropriate permissions, the KDC will
403*7f2fe78bSCy Schubertissue a ticket from the client to the target service.  The GSSAPI
404*7f2fe78bSCy Schubertlibrary will then use this ticket to authenticate to the target
405*7f2fe78bSCy Schubertservice.
406*7f2fe78bSCy Schubert
407*7f2fe78bSCy SchubertIf an application needs to find out whether a credential it holds is a
408*7f2fe78bSCy Schubertproxy credential and the name of the intermediate service, it can
409*7f2fe78bSCy Schubertquery the credential with the **GSS_KRB5_GET_CRED_IMPERSONATOR** OID
410*7f2fe78bSCy Schubert(new in release 1.16, declared in ``<gssapi/gssapi_krb5.h>``) using
411*7f2fe78bSCy Schubertthe gss_inquire_cred_by_oid extension (declared in
412*7f2fe78bSCy Schubert``<gssapi/gssapi_ext.h>``)::
413*7f2fe78bSCy Schubert
414*7f2fe78bSCy Schubert    OM_uint32 gss_inquire_cred_by_oid(OM_uint32 *minor_status,
415*7f2fe78bSCy Schubert                                      const gss_cred_id_t cred_handle,
416*7f2fe78bSCy Schubert                                      gss_OID desired_object,
417*7f2fe78bSCy Schubert                                      gss_buffer_set_t *data_set);
418*7f2fe78bSCy Schubert
419*7f2fe78bSCy SchubertIf the call succeeds and *cred_handle* is a proxy credential,
420*7f2fe78bSCy Schubert*data_set* will be set to a single-element buffer set containing the
421*7f2fe78bSCy Schubertunparsed principal name of the intermediate service.  If *cred_handle*
422*7f2fe78bSCy Schubertis not a proxy credential, *data_set* will be set to an empty buffer
423*7f2fe78bSCy Schubertset.  If the library does not support the query,
424*7f2fe78bSCy Schubertgss_inquire_cred_by_oid will return **GSS_S_UNAVAILABLE**.
425*7f2fe78bSCy Schubert
426*7f2fe78bSCy Schubert
427*7f2fe78bSCy SchubertAEAD message wrapping
428*7f2fe78bSCy Schubert---------------------
429*7f2fe78bSCy Schubert
430*7f2fe78bSCy SchubertThe following GSSAPI extensions (declared in
431*7f2fe78bSCy Schubert``<gssapi/gssapi_ext.h>``) can be used to wrap and unwrap messages
432*7f2fe78bSCy Schubertwith additional "associated data" which is integrity-checked but is
433*7f2fe78bSCy Schubertnot included in the output buffer::
434*7f2fe78bSCy Schubert
435*7f2fe78bSCy Schubert    OM_uint32 gss_wrap_aead(OM_uint32 *minor_status,
436*7f2fe78bSCy Schubert                            gss_ctx_id_t context_handle,
437*7f2fe78bSCy Schubert                            int conf_req_flag, gss_qop_t qop_req,
438*7f2fe78bSCy Schubert                            gss_buffer_t input_assoc_buffer,
439*7f2fe78bSCy Schubert                            gss_buffer_t input_payload_buffer,
440*7f2fe78bSCy Schubert                            int *conf_state,
441*7f2fe78bSCy Schubert                            gss_buffer_t output_message_buffer);
442*7f2fe78bSCy Schubert
443*7f2fe78bSCy Schubert    OM_uint32 gss_unwrap_aead(OM_uint32 *minor_status,
444*7f2fe78bSCy Schubert                              gss_ctx_id_t context_handle,
445*7f2fe78bSCy Schubert                              gss_buffer_t input_message_buffer,
446*7f2fe78bSCy Schubert                              gss_buffer_t input_assoc_buffer,
447*7f2fe78bSCy Schubert                              gss_buffer_t output_payload_buffer,
448*7f2fe78bSCy Schubert                              int *conf_state,
449*7f2fe78bSCy Schubert                              gss_qop_t *qop_state);
450*7f2fe78bSCy Schubert
451*7f2fe78bSCy SchubertWrap tokens created with gss_wrap_aead will successfully unwrap only
452*7f2fe78bSCy Schubertif the same *input_assoc_buffer* contents are presented to
453*7f2fe78bSCy Schubertgss_unwrap_aead.
454*7f2fe78bSCy Schubert
455*7f2fe78bSCy Schubert
456*7f2fe78bSCy SchubertIOV message wrapping
457*7f2fe78bSCy Schubert--------------------
458*7f2fe78bSCy Schubert
459*7f2fe78bSCy SchubertThe following extensions (declared in ``<gssapi/gssapi_ext.h>``) can
460*7f2fe78bSCy Schubertbe used for in-place encryption, fine-grained control over wrap token
461*7f2fe78bSCy Schubertlayout, and for constructing wrap tokens compatible with Microsoft DCE
462*7f2fe78bSCy SchubertRPC::
463*7f2fe78bSCy Schubert
464*7f2fe78bSCy Schubert    typedef struct gss_iov_buffer_desc_struct {
465*7f2fe78bSCy Schubert        OM_uint32 type;
466*7f2fe78bSCy Schubert        gss_buffer_desc buffer;
467*7f2fe78bSCy Schubert    } gss_iov_buffer_desc, *gss_iov_buffer_t;
468*7f2fe78bSCy Schubert
469*7f2fe78bSCy Schubert    OM_uint32 gss_wrap_iov(OM_uint32 *minor_status,
470*7f2fe78bSCy Schubert                           gss_ctx_id_t context_handle,
471*7f2fe78bSCy Schubert                           int conf_req_flag, gss_qop_t qop_req,
472*7f2fe78bSCy Schubert                           int *conf_state,
473*7f2fe78bSCy Schubert                           gss_iov_buffer_desc *iov, int iov_count);
474*7f2fe78bSCy Schubert
475*7f2fe78bSCy Schubert    OM_uint32 gss_unwrap_iov(OM_uint32 *minor_status,
476*7f2fe78bSCy Schubert                             gss_ctx_id_t context_handle,
477*7f2fe78bSCy Schubert                             int *conf_state, gss_qop_t *qop_state,
478*7f2fe78bSCy Schubert                             gss_iov_buffer_desc *iov, int iov_count);
479*7f2fe78bSCy Schubert
480*7f2fe78bSCy Schubert    OM_uint32 gss_wrap_iov_length(OM_uint32 *minor_status,
481*7f2fe78bSCy Schubert                                  gss_ctx_id_t context_handle,
482*7f2fe78bSCy Schubert                                  int conf_req_flag,
483*7f2fe78bSCy Schubert                                  gss_qop_t qop_req, int *conf_state,
484*7f2fe78bSCy Schubert                                  gss_iov_buffer_desc *iov,
485*7f2fe78bSCy Schubert                                  int iov_count);
486*7f2fe78bSCy Schubert
487*7f2fe78bSCy Schubert    OM_uint32 gss_release_iov_buffer(OM_uint32 *minor_status,
488*7f2fe78bSCy Schubert                                     gss_iov_buffer_desc *iov,
489*7f2fe78bSCy Schubert                                     int iov_count);
490*7f2fe78bSCy Schubert
491*7f2fe78bSCy SchubertThe caller of gss_wrap_iov provides an array of gss_iov_buffer_desc
492*7f2fe78bSCy Schubertstructures, each containing a type and a gss_buffer_desc structure.
493*7f2fe78bSCy SchubertValid types include:
494*7f2fe78bSCy Schubert
495*7f2fe78bSCy Schubert* **GSS_C_BUFFER_TYPE_DATA**: A data buffer to be included in the
496*7f2fe78bSCy Schubert  token, and to be encrypted or decrypted in-place if the token is
497*7f2fe78bSCy Schubert  confidentiality-protected.
498*7f2fe78bSCy Schubert
499*7f2fe78bSCy Schubert* **GSS_C_BUFFER_TYPE_HEADER**: The GSSAPI wrap token header and
500*7f2fe78bSCy Schubert  underlying cryptographic header.
501*7f2fe78bSCy Schubert
502*7f2fe78bSCy Schubert* **GSS_C_BUFFER_TYPE_TRAILER**: The cryptographic trailer, if one is
503*7f2fe78bSCy Schubert  required.
504*7f2fe78bSCy Schubert
505*7f2fe78bSCy Schubert* **GSS_C_BUFFER_TYPE_PADDING**: Padding to be combined with the data
506*7f2fe78bSCy Schubert  during encryption and decryption.  (The implementation may choose to
507*7f2fe78bSCy Schubert  place padding in the trailer buffer, in which case it will set the
508*7f2fe78bSCy Schubert  padding buffer length to 0.)
509*7f2fe78bSCy Schubert
510*7f2fe78bSCy Schubert* **GSS_C_BUFFER_TYPE_STREAM**: For unwrapping only, a buffer
511*7f2fe78bSCy Schubert  containing a complete wrap token in standard format to be unwrapped.
512*7f2fe78bSCy Schubert
513*7f2fe78bSCy Schubert* **GSS_C_BUFFER_TYPE_SIGN_ONLY**: A buffer to be included in the
514*7f2fe78bSCy Schubert  token's integrity protection checksum, but not to be encrypted or
515*7f2fe78bSCy Schubert  included in the token itself.
516*7f2fe78bSCy Schubert
517*7f2fe78bSCy SchubertFor gss_wrap_iov, the IOV list should contain one HEADER buffer,
518*7f2fe78bSCy Schubertfollowed by zero or more SIGN_ONLY buffers, followed by one or more
519*7f2fe78bSCy SchubertDATA buffers, followed by a TRAILER buffer.  The memory pointed to by
520*7f2fe78bSCy Schubertthe buffers is not required to be contiguous or in any particular
521*7f2fe78bSCy Schubertorder.  If *conf_req_flag* is true, DATA buffers will be encrypted
522*7f2fe78bSCy Schubertin-place, while SIGN_ONLY buffers will not be modified.
523*7f2fe78bSCy Schubert
524*7f2fe78bSCy SchubertThe type of an output buffer may be combined with
525*7f2fe78bSCy Schubert**GSS_C_BUFFER_FLAG_ALLOCATE** to request that gss_wrap_iov allocate
526*7f2fe78bSCy Schubertthe buffer contents.  If gss_wrap_iov allocates a buffer, it sets the
527*7f2fe78bSCy Schubert**GSS_C_BUFFER_FLAG_ALLOCATED** flag on the buffer type.
528*7f2fe78bSCy Schubertgss_release_iov_buffer can be used to release all allocated buffers
529*7f2fe78bSCy Schubertwithin an iov list and unset their allocated flags.  Here is an
530*7f2fe78bSCy Schubertexample of how gss_wrap_iov can be used with allocation requested
531*7f2fe78bSCy Schubert(*ctx* is assumed to be a previously established gss_ctx_id_t)::
532*7f2fe78bSCy Schubert
533*7f2fe78bSCy Schubert    OM_uint32 major, minor;
534*7f2fe78bSCy Schubert    gss_iov_buffer_desc iov[4];
535*7f2fe78bSCy Schubert    char str[] = "message";
536*7f2fe78bSCy Schubert
537*7f2fe78bSCy Schubert    iov[0].type = GSS_IOV_BUFFER_TYPE_HEADER | GSS_IOV_BUFFER_FLAG_ALLOCATE;
538*7f2fe78bSCy Schubert    iov[1].type = GSS_IOV_BUFFER_TYPE_DATA;
539*7f2fe78bSCy Schubert    iov[1].buffer.value = str;
540*7f2fe78bSCy Schubert    iov[1].buffer.length = strlen(str);
541*7f2fe78bSCy Schubert    iov[2].type = GSS_IOV_BUFFER_TYPE_PADDING | GSS_IOV_BUFFER_FLAG_ALLOCATE;
542*7f2fe78bSCy Schubert    iov[3].type = GSS_IOV_BUFFER_TYPE_TRAILER | GSS_IOV_BUFFER_FLAG_ALLOCATE;
543*7f2fe78bSCy Schubert
544*7f2fe78bSCy Schubert    major = gss_wrap_iov(&minor, ctx, 1, GSS_C_QOP_DEFAULT, NULL,
545*7f2fe78bSCy Schubert                         iov, 4);
546*7f2fe78bSCy Schubert    if (GSS_ERROR(major))
547*7f2fe78bSCy Schubert        handle_error(major, minor);
548*7f2fe78bSCy Schubert
549*7f2fe78bSCy Schubert    /* Transmit or otherwise use resulting buffers. */
550*7f2fe78bSCy Schubert
551*7f2fe78bSCy Schubert    (void)gss_release_iov_buffer(&minor, iov, 4);
552*7f2fe78bSCy Schubert
553*7f2fe78bSCy SchubertIf the caller does not choose to request buffer allocation by
554*7f2fe78bSCy Schubertgss_wrap_iov, it should first call gss_wrap_iov_length to query the
555*7f2fe78bSCy Schubertlengths of the HEADER, PADDING, and TRAILER buffers.  DATA buffers
556*7f2fe78bSCy Schubertmust be provided in the iov list so that padding length can be
557*7f2fe78bSCy Schubertcomputed correctly, but the output buffers need not be initialized.
558*7f2fe78bSCy SchubertHere is an example of using gss_wrap_iov_length and gss_wrap_iov::
559*7f2fe78bSCy Schubert
560*7f2fe78bSCy Schubert    OM_uint32 major, minor;
561*7f2fe78bSCy Schubert    gss_iov_buffer_desc iov[4];
562*7f2fe78bSCy Schubert    char str[1024] = "message", *ptr;
563*7f2fe78bSCy Schubert
564*7f2fe78bSCy Schubert    iov[0].type = GSS_IOV_BUFFER_TYPE_HEADER;
565*7f2fe78bSCy Schubert    iov[1].type = GSS_IOV_BUFFER_TYPE_DATA;
566*7f2fe78bSCy Schubert    iov[1].buffer.value = str;
567*7f2fe78bSCy Schubert    iov[1].buffer.length = strlen(str);
568*7f2fe78bSCy Schubert
569*7f2fe78bSCy Schubert    iov[2].type = GSS_IOV_BUFFER_TYPE_PADDING;
570*7f2fe78bSCy Schubert    iov[3].type = GSS_IOV_BUFFER_TYPE_TRAILER;
571*7f2fe78bSCy Schubert
572*7f2fe78bSCy Schubert    major = gss_wrap_iov_length(&minor, ctx, 1, GSS_C_QOP_DEFAULT,
573*7f2fe78bSCy Schubert                                NULL, iov, 4);
574*7f2fe78bSCy Schubert    if (GSS_ERROR(major))
575*7f2fe78bSCy Schubert        handle_error(major, minor);
576*7f2fe78bSCy Schubert    if (strlen(str) + iov[0].buffer.length + iov[2].buffer.length +
577*7f2fe78bSCy Schubert        iov[3].buffer.length > sizeof(str))
578*7f2fe78bSCy Schubert        handle_out_of_space_error();
579*7f2fe78bSCy Schubert    ptr = str + strlen(str);
580*7f2fe78bSCy Schubert    iov[0].buffer.value = ptr;
581*7f2fe78bSCy Schubert    ptr += iov[0].buffer.length;
582*7f2fe78bSCy Schubert    iov[2].buffer.value = ptr;
583*7f2fe78bSCy Schubert    ptr += iov[2].buffer.length;
584*7f2fe78bSCy Schubert    iov[3].buffer.value = ptr;
585*7f2fe78bSCy Schubert
586*7f2fe78bSCy Schubert    major = gss_wrap_iov(&minor, ctx, 1, GSS_C_QOP_DEFAULT, NULL,
587*7f2fe78bSCy Schubert                         iov, 4);
588*7f2fe78bSCy Schubert    if (GSS_ERROR(major))
589*7f2fe78bSCy Schubert        handle_error(major, minor);
590*7f2fe78bSCy Schubert
591*7f2fe78bSCy SchubertIf the context was established using the **GSS_C_DCE_STYLE** flag
592*7f2fe78bSCy Schubert(described in :rfc:`4757`), wrap tokens compatible with Microsoft DCE
593*7f2fe78bSCy SchubertRPC can be constructed.  In this case, the IOV list must include a
594*7f2fe78bSCy SchubertSIGN_ONLY buffer, a DATA buffer, a second SIGN_ONLY buffer, and a
595*7f2fe78bSCy SchubertHEADER buffer in that order (the order of the buffer contents remains
596*7f2fe78bSCy Schubertarbitrary).  The application must pad the DATA buffer to a multiple of
597*7f2fe78bSCy Schubert16 bytes as no padding or trailer buffer is used.
598*7f2fe78bSCy Schubert
599*7f2fe78bSCy Schubertgss_unwrap_iov may be called with an IOV list just like one which
600*7f2fe78bSCy Schubertwould be provided to gss_wrap_iov.  DATA buffers will be decrypted
601*7f2fe78bSCy Schubertin-place if they were encrypted, and SIGN_ONLY buffers will not be
602*7f2fe78bSCy Schubertmodified.
603*7f2fe78bSCy Schubert
604*7f2fe78bSCy SchubertAlternatively, gss_unwrap_iov may be called with a single STREAM
605*7f2fe78bSCy Schubertbuffer, zero or more SIGN_ONLY buffers, and a single DATA buffer.  The
606*7f2fe78bSCy SchubertSTREAM buffer is interpreted as a complete wrap token.  The STREAM
607*7f2fe78bSCy Schubertbuffer will be modified in-place to decrypt its contents.  The DATA
608*7f2fe78bSCy Schubertbuffer will be initialized to point to the decrypted data within the
609*7f2fe78bSCy SchubertSTREAM buffer, unless it has the **GSS_C_BUFFER_FLAG_ALLOCATE** flag
610*7f2fe78bSCy Schubertset, in which case it will be initialized with a copy of the decrypted
611*7f2fe78bSCy Schubertdata.  Here is an example (*token* and *token_len* are assumed to be a
612*7f2fe78bSCy Schubertpre-existing pointer and length for a modifiable region of data)::
613*7f2fe78bSCy Schubert
614*7f2fe78bSCy Schubert    OM_uint32 major, minor;
615*7f2fe78bSCy Schubert    gss_iov_buffer_desc iov[2];
616*7f2fe78bSCy Schubert
617*7f2fe78bSCy Schubert    iov[0].type = GSS_IOV_BUFFER_TYPE_STREAM;
618*7f2fe78bSCy Schubert    iov[0].buffer.value = token;
619*7f2fe78bSCy Schubert    iov[0].buffer.length = token_len;
620*7f2fe78bSCy Schubert    iov[1].type = GSS_IOV_BUFFER_TYPE_DATA;
621*7f2fe78bSCy Schubert    major = gss_unwrap_iov(&minor, ctx, NULL, NULL, iov, 2);
622*7f2fe78bSCy Schubert    if (GSS_ERROR(major))
623*7f2fe78bSCy Schubert        handle_error(major, minor);
624*7f2fe78bSCy Schubert
625*7f2fe78bSCy Schubert    /* Decrypted data is in iov[1].buffer, pointing to a subregion of
626*7f2fe78bSCy Schubert     * token. */
627*7f2fe78bSCy Schubert
628*7f2fe78bSCy Schubert.. _gssapi_mic_token:
629*7f2fe78bSCy Schubert
630*7f2fe78bSCy SchubertIOV MIC tokens
631*7f2fe78bSCy Schubert--------------
632*7f2fe78bSCy Schubert
633*7f2fe78bSCy SchubertThe following extensions (declared in ``<gssapi/gssapi_ext.h>``) can
634*7f2fe78bSCy Schubertbe used in release 1.12 or later to construct and verify MIC tokens
635*7f2fe78bSCy Schubertusing an IOV list::
636*7f2fe78bSCy Schubert
637*7f2fe78bSCy Schubert    OM_uint32 gss_get_mic_iov(OM_uint32 *minor_status,
638*7f2fe78bSCy Schubert                              gss_ctx_id_t context_handle,
639*7f2fe78bSCy Schubert                              gss_qop_t qop_req,
640*7f2fe78bSCy Schubert                              gss_iov_buffer_desc *iov,
641*7f2fe78bSCy Schubert                              int iov_count);
642*7f2fe78bSCy Schubert
643*7f2fe78bSCy Schubert    OM_uint32 gss_get_mic_iov_length(OM_uint32 *minor_status,
644*7f2fe78bSCy Schubert                                     gss_ctx_id_t context_handle,
645*7f2fe78bSCy Schubert                                     gss_qop_t qop_req,
646*7f2fe78bSCy Schubert                                     gss_iov_buffer_desc *iov,
647*7f2fe78bSCy Schubert                                     iov_count);
648*7f2fe78bSCy Schubert
649*7f2fe78bSCy Schubert    OM_uint32 gss_verify_mic_iov(OM_uint32 *minor_status,
650*7f2fe78bSCy Schubert                                 gss_ctx_id_t context_handle,
651*7f2fe78bSCy Schubert                                 gss_qop_t *qop_state,
652*7f2fe78bSCy Schubert                                 gss_iov_buffer_desc *iov,
653*7f2fe78bSCy Schubert                                 int iov_count);
654*7f2fe78bSCy Schubert
655*7f2fe78bSCy SchubertThe caller of gss_get_mic_iov provides an array of gss_iov_buffer_desc
656*7f2fe78bSCy Schubertstructures, each containing a type and a gss_buffer_desc structure.
657*7f2fe78bSCy SchubertValid types include:
658*7f2fe78bSCy Schubert
659*7f2fe78bSCy Schubert* **GSS_C_BUFFER_TYPE_DATA** and **GSS_C_BUFFER_TYPE_SIGN_ONLY**: The
660*7f2fe78bSCy Schubert  corresponding buffer for each of these types will be signed for the
661*7f2fe78bSCy Schubert  MIC token, in the order provided.
662*7f2fe78bSCy Schubert
663*7f2fe78bSCy Schubert* **GSS_C_BUFFER_TYPE_MIC_TOKEN**: The GSSAPI MIC token.
664*7f2fe78bSCy Schubert
665*7f2fe78bSCy SchubertThe type of the MIC_TOKEN buffer may be combined with
666*7f2fe78bSCy Schubert**GSS_C_BUFFER_FLAG_ALLOCATE** to request that gss_get_mic_iov
667*7f2fe78bSCy Schubertallocate the buffer contents.  If gss_get_mic_iov allocates the
668*7f2fe78bSCy Schubertbuffer, it sets the **GSS_C_BUFFER_FLAG_ALLOCATED** flag on the buffer
669*7f2fe78bSCy Schuberttype.  gss_release_iov_buffer can be used to release all allocated
670*7f2fe78bSCy Schubertbuffers within an iov list and unset their allocated flags.  Here is
671*7f2fe78bSCy Schubertan example of how gss_get_mic_iov can be used with allocation
672*7f2fe78bSCy Schubertrequested (*ctx* is assumed to be a previously established
673*7f2fe78bSCy Schubertgss_ctx_id_t)::
674*7f2fe78bSCy Schubert
675*7f2fe78bSCy Schubert    OM_uint32 major, minor;
676*7f2fe78bSCy Schubert    gss_iov_buffer_desc iov[3];
677*7f2fe78bSCy Schubert
678*7f2fe78bSCy Schubert    iov[0].type = GSS_IOV_BUFFER_TYPE_DATA;
679*7f2fe78bSCy Schubert    iov[0].buffer.value = "sign1";
680*7f2fe78bSCy Schubert    iov[0].buffer.length = 5;
681*7f2fe78bSCy Schubert    iov[1].type = GSS_IOV_BUFFER_TYPE_SIGN_ONLY;
682*7f2fe78bSCy Schubert    iov[1].buffer.value = "sign2";
683*7f2fe78bSCy Schubert    iov[1].buffer.length = 5;
684*7f2fe78bSCy Schubert    iov[2].type = GSS_IOV_BUFFER_TYPE_MIC_TOKEN | GSS_IOV_BUFFER_FLAG_ALLOCATE;
685*7f2fe78bSCy Schubert
686*7f2fe78bSCy Schubert    major = gss_get_mic_iov(&minor, ctx, GSS_C_QOP_DEFAULT, iov, 3);
687*7f2fe78bSCy Schubert    if (GSS_ERROR(major))
688*7f2fe78bSCy Schubert        handle_error(major, minor);
689*7f2fe78bSCy Schubert
690*7f2fe78bSCy Schubert    /* Transmit or otherwise use iov[2].buffer. */
691*7f2fe78bSCy Schubert
692*7f2fe78bSCy Schubert    (void)gss_release_iov_buffer(&minor, iov, 3);
693*7f2fe78bSCy Schubert
694*7f2fe78bSCy SchubertIf the caller does not choose to request buffer allocation by
695*7f2fe78bSCy Schubertgss_get_mic_iov, it should first call gss_get_mic_iov_length to query
696*7f2fe78bSCy Schubertthe length of the MIC_TOKEN buffer.  Here is an example of using
697*7f2fe78bSCy Schubertgss_get_mic_iov_length and gss_get_mic_iov::
698*7f2fe78bSCy Schubert
699*7f2fe78bSCy Schubert    OM_uint32 major, minor;
700*7f2fe78bSCy Schubert    gss_iov_buffer_desc iov[2];
701*7f2fe78bSCy Schubert    char data[1024];
702*7f2fe78bSCy Schubert
703*7f2fe78bSCy Schubert    iov[0].type = GSS_IOV_BUFFER_TYPE_MIC_TOKEN;
704*7f2fe78bSCy Schubert    iov[1].type = GSS_IOV_BUFFER_TYPE_DATA;
705*7f2fe78bSCy Schubert    iov[1].buffer.value = "message";
706*7f2fe78bSCy Schubert    iov[1].buffer.length = 7;
707*7f2fe78bSCy Schubert
708*7f2fe78bSCy Schubert    major = gss_get_mic_iov_length(&minor, ctx, GSS_C_QOP_DEFAULT, iov, 2);
709*7f2fe78bSCy Schubert    if (GSS_ERROR(major))
710*7f2fe78bSCy Schubert        handle_error(major, minor);
711*7f2fe78bSCy Schubert    if (iov[0].buffer.length > sizeof(data))
712*7f2fe78bSCy Schubert        handle_out_of_space_error();
713*7f2fe78bSCy Schubert    iov[0].buffer.value = data;
714*7f2fe78bSCy Schubert
715*7f2fe78bSCy Schubert    major = gss_get_mic_iov(&minor, ctx, GSS_C_QOP_DEFAULT, iov, 2);
716*7f2fe78bSCy Schubert    if (GSS_ERROR(major))
717*7f2fe78bSCy Schubert        handle_error(major, minor);
718*7f2fe78bSCy Schubert
719*7f2fe78bSCy Schubert
720*7f2fe78bSCy Schubert.. _gss_accept_sec_context: https://tools.ietf.org/html/rfc2744.html#section-5.1
721*7f2fe78bSCy Schubert.. _gss_acquire_cred: https://tools.ietf.org/html/rfc2744.html#section-5.2
722*7f2fe78bSCy Schubert.. _gss_export_name: https://tools.ietf.org/html/rfc2744.html#section-5.13
723*7f2fe78bSCy Schubert.. _gss_get_name_attribute: https://tools.ietf.org/html/6680.html#section-7.5
724*7f2fe78bSCy Schubert.. _gss_import_name: https://tools.ietf.org/html/rfc2744.html#section-5.16
725*7f2fe78bSCy Schubert.. _gss_init_sec_context: https://tools.ietf.org/html/rfc2744.html#section-5.19
726*7f2fe78bSCy Schubert.. _gss_inquire_name: https://tools.ietf.org/html/rfc6680.txt#section-7.4
727*7f2fe78bSCy Schubert.. _gss_inquire_cred: https://tools.ietf.org/html/rfc2744.html#section-5.21
728