xref: /freebsd/crypto/krb5/doc/html/appdev/gssapi.html (revision b670c9bafc0e31c7609969bf374b2e80bdc00211)
1
2<!DOCTYPE html>
3
4<html>
5  <head>
6    <meta charset="utf-8" />
7    <meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="generator" content="Docutils 0.17.1: http://docutils.sourceforge.net/" />
8
9    <title>Developing with GSSAPI &#8212; MIT Kerberos Documentation</title>
10    <link rel="stylesheet" type="text/css" href="../_static/pygments.css" />
11    <link rel="stylesheet" type="text/css" href="../_static/agogo.css" />
12    <link rel="stylesheet" type="text/css" href="../_static/kerb.css" />
13    <script data-url_root="../" id="documentation_options" src="../_static/documentation_options.js"></script>
14    <script src="../_static/jquery.js"></script>
15    <script src="../_static/underscore.js"></script>
16    <script src="../_static/doctools.js"></script>
17    <link rel="author" title="About these documents" href="../about.html" />
18    <link rel="index" title="Index" href="../genindex.html" />
19    <link rel="search" title="Search" href="../search.html" />
20    <link rel="copyright" title="Copyright" href="../copyright.html" />
21    <link rel="next" title="Year 2038 considerations for uses of krb5_timestamp" href="y2038.html" />
22    <link rel="prev" title="For application developers" href="index.html" />
23  </head><body>
24    <div class="header-wrapper">
25        <div class="header">
26
27
28            <h1><a href="../index.html">MIT Kerberos Documentation</a></h1>
29
30            <div class="rel">
31
32        <a href="../index.html" title="Full Table of Contents"
33            accesskey="C">Contents</a> |
34        <a href="index.html" title="For application developers"
35            accesskey="P">previous</a> |
36        <a href="y2038.html" title="Year 2038 considerations for uses of krb5_timestamp"
37            accesskey="N">next</a> |
38        <a href="../genindex.html" title="General Index"
39            accesskey="I">index</a> |
40        <a href="../search.html" title="Enter search criteria"
41            accesskey="S">Search</a> |
42    <a href="mailto:krb5-bugs@mit.edu?subject=Documentation__Developing with GSSAPI">feedback</a>
43            </div>
44        </div>
45    </div>
46
47    <div class="content-wrapper">
48      <div class="content">
49        <div class="document">
50
51      <div class="documentwrapper">
52        <div class="bodywrapper">
53          <div class="body" role="main">
54
55  <section id="developing-with-gssapi">
56<h1>Developing with GSSAPI<a class="headerlink" href="#developing-with-gssapi" title="Permalink to this headline">¶</a></h1>
57<p>The GSSAPI (Generic Security Services API) allows applications to
58communicate securely using Kerberos 5 or other security mechanisms.
59We recommend using the GSSAPI (or a higher-level framework which
60encompasses GSSAPI, such as SASL) for secure network communication
61over using the libkrb5 API directly.</p>
62<p>GSSAPIv2 is specified in <span class="target" id="index-0"></span><a class="rfc reference external" href="https://tools.ietf.org/html/rfc2743.html"><strong>RFC 2743</strong></a> and <span class="target" id="index-1"></span><a class="rfc reference external" href="https://tools.ietf.org/html/rfc2744.html"><strong>RFC 2744</strong></a>.  Also see
63<span class="target" id="index-2"></span><a class="rfc reference external" href="https://tools.ietf.org/html/rfc7546.html"><strong>RFC 7546</strong></a> for a description of how to use the GSSAPI in a client or
64server program.</p>
65<p>This documentation will describe how various ways of using the
66GSSAPI will behave with the krb5 mechanism as implemented in MIT krb5,
67as well as krb5-specific extensions to the GSSAPI.</p>
68<section id="name-types">
69<h2>Name types<a class="headerlink" href="#name-types" title="Permalink to this headline">¶</a></h2>
70<p>A GSSAPI application can name a local or remote entity by calling
71<a class="reference external" href="https://tools.ietf.org/html/rfc2744.html#section-5.16">gss_import_name</a>, specifying a name type and a value.  The following
72name types are supported by the krb5 mechanism:</p>
73<ul class="simple">
74<li><p><strong>GSS_C_NT_HOSTBASED_SERVICE</strong>: The value should be a string of the
75form <code class="docutils literal notranslate"><span class="pre">service</span></code> or <code class="docutils literal notranslate"><span class="pre">service&#64;hostname</span></code>.  This is the most common
76way to name target services when initiating a security context, and
77is the most likely name type to work across multiple mechanisms.</p></li>
78<li><p><strong>GSS_KRB5_NT_PRINCIPAL_NAME</strong>: The value should be a principal name
79string.  This name type only works with the krb5 mechanism, and is
80defined in the <code class="docutils literal notranslate"><span class="pre">&lt;gssapi/gssapi_krb5.h&gt;</span></code> header.</p></li>
81<li><p><strong>GSS_C_NT_USER_NAME</strong> or <strong>GSS_C_NULL_OID</strong>: The value is treated
82as an unparsed principal name string, as above.  These name types
83may work with mechanisms other than krb5, but will have different
84interpretations in those mechanisms.  <strong>GSS_C_NT_USER_NAME</strong> is
85intended to be used with a local username, which will parse into a
86single-component principal in the default realm.</p></li>
87<li><p><strong>GSS_C_NT_ANONYMOUS</strong>: The value is ignored.  The anonymous
88principal is used, allowing a client to authenticate to a server
89without asserting a particular identity (which may or may not be
90allowed by a particular server or Kerberos realm).</p></li>
91<li><p><strong>GSS_C_NT_MACHINE_UID_NAME</strong>: The value is uid_t object.  On
92Unix-like systems, the username of the uid is looked up in the
93system user database and the resulting username is parsed as a
94principal name.</p></li>
95<li><p><strong>GSS_C_NT_STRING_UID_NAME</strong>: As above, but the value is a decimal
96string representation of the uid.</p></li>
97<li><p><strong>GSS_C_NT_EXPORT_NAME</strong>: The value must be the result of a
98<a class="reference external" href="https://tools.ietf.org/html/rfc2744.html#section-5.13">gss_export_name</a> call.</p></li>
99<li><p><strong>GSS_KRB5_NT_ENTERPRISE_NAME</strong>: The value should be a krb5
100enterprise name string (see <span class="target" id="index-3"></span><a class="rfc reference external" href="https://tools.ietf.org/html/rfc6806.html"><strong>RFC 6806</strong></a> section 5), in the form
101<code class="docutils literal notranslate"><span class="pre">user&#64;suffix</span></code>.  This name type is used to convey alias names, and
102is defined in the <code class="docutils literal notranslate"><span class="pre">&lt;gssapi/gssapi_krb5.h&gt;</span></code> header.  (New in
103release 1.17.)</p></li>
104<li><p><strong>GSS_KRB5_NT_X509_CERT</strong>: The value should be an X.509 certificate
105encoded according to <span class="target" id="index-4"></span><a class="rfc reference external" href="https://tools.ietf.org/html/rfc5280.html"><strong>RFC 5280</strong></a>.  This name form can be used for
106the desired_name parameter of gss_acquire_cred_impersonate_name(),
107to identify the S4U2Self user by certificate.  (New in release
1081.19.)</p></li>
109</ul>
110</section>
111<section id="initiator-credentials">
112<h2>Initiator credentials<a class="headerlink" href="#initiator-credentials" title="Permalink to this headline">¶</a></h2>
113<p>A GSSAPI client application uses <a class="reference external" href="https://tools.ietf.org/html/rfc2744.html#section-5.19">gss_init_sec_context</a> to establish a
114security context.  The <em>initiator_cred_handle</em> parameter determines
115what tickets are used to establish the connection.  An application can
116either pass <strong>GSS_C_NO_CREDENTIAL</strong> to use the default client
117credential, or it can use <a class="reference external" href="https://tools.ietf.org/html/rfc2744.html#section-5.2">gss_acquire_cred</a> beforehand to acquire an
118initiator credential.  The call to <a class="reference external" href="https://tools.ietf.org/html/rfc2744.html#section-5.2">gss_acquire_cred</a> may include a
119<em>desired_name</em> parameter, or it may pass <strong>GSS_C_NO_NAME</strong> if it does
120not have a specific name preference.</p>
121<p>If the desired name for a krb5 initiator credential is a host-based
122name, it is converted to a principal name of the form
123<code class="docutils literal notranslate"><span class="pre">service/hostname</span></code> in the local realm, where <em>hostname</em> is the local
124hostname if not specified.  The hostname will be canonicalized using
125forward name resolution, and possibly also using reverse name
126resolution depending on the value of the <strong>rdns</strong> variable in
127<a class="reference internal" href="../admin/conf_files/krb5_conf.html#libdefaults"><span class="std std-ref">[libdefaults]</span></a>.</p>
128<p>If a desired name is specified in the call to <a class="reference external" href="https://tools.ietf.org/html/rfc2744.html#section-5.2">gss_acquire_cred</a>, the
129krb5 mechanism will attempt to find existing tickets for that client
130principal name in the default credential cache or collection.  If the
131default cache type does not support a collection, and the default
132cache contains credentials for a different principal than the desired
133name, a <strong>GSS_S_CRED_UNAVAIL</strong> error will be returned with a minor
134code indicating a mismatch.</p>
135<p>If no existing tickets are available for the desired name, but the
136name has an entry in the default client <a class="reference internal" href="../basic/keytab_def.html#keytab-definition"><span class="std std-ref">keytab</span></a>, the
137krb5 mechanism will acquire initial tickets for the name using the
138default client keytab.</p>
139<p>If no desired name is specified, credential acquisition will be
140deferred until the credential is used in a call to
141<a class="reference external" href="https://tools.ietf.org/html/rfc2744.html#section-5.19">gss_init_sec_context</a> or <a class="reference external" href="https://tools.ietf.org/html/rfc2744.html#section-5.21">gss_inquire_cred</a>.  If the call is to
142<a class="reference external" href="https://tools.ietf.org/html/rfc2744.html#section-5.19">gss_init_sec_context</a>, the target name will be used to choose a client
143principal name using the credential cache selection facility.  (This
144facility might, for instance, try to choose existing tickets for a
145client principal in the same realm as the target service).  If there
146are no existing tickets for the chosen principal, but it is present in
147the default client keytab, the krb5 mechanism will acquire initial
148tickets using the keytab.</p>
149<p>If the target name cannot be used to select a client principal
150(because the credentials are used in a call to <a class="reference external" href="https://tools.ietf.org/html/rfc2744.html#section-5.21">gss_inquire_cred</a>), or
151if the credential cache selection facility cannot choose a principal
152for it, the default credential cache will be selected if it exists and
153contains tickets.</p>
154<p>If the default credential cache does not exist, but the default client
155keytab does, the krb5 mechanism will try to acquire initial tickets
156for the first principal in the default client keytab.</p>
157<p>If the krb5 mechanism acquires initial tickets using the default
158client keytab, the resulting tickets will be stored in the default
159cache or collection, and will be refreshed by future calls to
160<a class="reference external" href="https://tools.ietf.org/html/rfc2744.html#section-5.2">gss_acquire_cred</a> as they approach their expire time.</p>
161</section>
162<section id="acceptor-names">
163<h2>Acceptor names<a class="headerlink" href="#acceptor-names" title="Permalink to this headline">¶</a></h2>
164<p>A GSSAPI server application uses <a class="reference external" href="https://tools.ietf.org/html/rfc2744.html#section-5.1">gss_accept_sec_context</a> to establish
165a security context based on tokens provided by the client.  The
166<em>acceptor_cred_handle</em> parameter determines what
167<a class="reference internal" href="../basic/keytab_def.html#keytab-definition"><span class="std std-ref">keytab</span></a> entries may be authenticated to by the
168client, if the krb5 mechanism is used.</p>
169<p>The simplest choice is to pass <strong>GSS_C_NO_CREDENTIAL</strong> as the acceptor
170credential.  In this case, clients may authenticate to any service
171principal in the default keytab (typically <a class="reference internal" href="../mitK5defaults.html#paths"><span class="std std-ref">DEFKTNAME</span></a>, or the value of
172the <strong>KRB5_KTNAME</strong> environment variable).  This is the recommended
173approach if the server application has no specific requirements to the
174contrary.</p>
175<p>A server may acquire an acceptor credential with <a class="reference external" href="https://tools.ietf.org/html/rfc2744.html#section-5.2">gss_acquire_cred</a> and
176a <em>cred_usage</em> of <strong>GSS_C_ACCEPT</strong> or <strong>GSS_C_BOTH</strong>.  If the
177<em>desired_name</em> parameter is <strong>GSS_C_NO_NAME</strong>, then clients will be
178allowed to authenticate to any service principal in the default
179keytab, just as if no acceptor credential was supplied.</p>
180<p>If a server wishes to specify a <em>desired_name</em> to <a class="reference external" href="https://tools.ietf.org/html/rfc2744.html#section-5.2">gss_acquire_cred</a>,
181the most common choice is a host-based name.  If the host-based
182<em>desired_name</em> contains just a <em>service</em>, then clients will be allowed
183to authenticate to any host-based service principal (that is, a
184principal of the form <code class="docutils literal notranslate"><span class="pre">service/hostname&#64;REALM</span></code>) for the named
185service, regardless of hostname or realm, as long as it is present in
186the default keytab.  If the input name contains both a <em>service</em> and a
187<em>hostname</em>, clients will be allowed to authenticate to any host-based
188principal for the named service and hostname, regardless of realm.</p>
189<div class="admonition note">
190<p class="admonition-title">Note</p>
191<p>If a <em>hostname</em> is specified, it will be canonicalized
192using forward name resolution, and possibly also using
193reverse name resolution depending on the value of the
194<strong>rdns</strong> variable in <a class="reference internal" href="../admin/conf_files/krb5_conf.html#libdefaults"><span class="std std-ref">[libdefaults]</span></a>.</p>
195</div>
196<div class="admonition note">
197<p class="admonition-title">Note</p>
198<p>If the <strong>ignore_acceptor_hostname</strong> variable in
199<a class="reference internal" href="../admin/conf_files/krb5_conf.html#libdefaults"><span class="std std-ref">[libdefaults]</span></a> is enabled, then <em>hostname</em> will be
200ignored even if one is specified in the input name.</p>
201</div>
202<div class="admonition note">
203<p class="admonition-title">Note</p>
204<p>In MIT krb5 versions prior to 1.10, and in Heimdal’s
205implementation of the krb5 mechanism, an input name with
206just a <em>service</em> is treated like an input name of
207<code class="docutils literal notranslate"><span class="pre">service&#64;localhostname</span></code>, where <em>localhostname</em> is the
208string returned by gethostname().</p>
209</div>
210<p>If the <em>desired_name</em> is a krb5 principal name or a local system name
211type which is mapped to a krb5 principal name, clients will only be
212allowed to authenticate to that principal in the default keytab.</p>
213</section>
214<section id="name-attributes">
215<h2>Name Attributes<a class="headerlink" href="#name-attributes" title="Permalink to this headline">¶</a></h2>
216<p>In release 1.8 or later, the <a class="reference external" href="https://tools.ietf.org/html/rfc6680.txt#section-7.4">gss_inquire_name</a> and
217<a class="reference external" href="https://tools.ietf.org/html/6680.html#section-7.5">gss_get_name_attribute</a> functions, specified in <span class="target" id="index-5"></span><a class="rfc reference external" href="https://tools.ietf.org/html/rfc6680.html"><strong>RFC 6680</strong></a>, can be
218used to retrieve name attributes from the <em>src_name</em> returned by
219<a class="reference external" href="https://tools.ietf.org/html/rfc2744.html#section-5.1">gss_accept_sec_context</a>.  The following attributes are defined when
220the krb5 mechanism is used:</p>
221<ul class="simple" id="gssapi-authind-attr">
222<li><p>“auth-indicators” attribute:</p></li>
223</ul>
224<p>This attribute will be included in the <a class="reference external" href="https://tools.ietf.org/html/rfc6680.txt#section-7.4">gss_inquire_name</a> output if the
225ticket contains <a class="reference internal" href="../admin/auth_indicator.html#auth-indicator"><span class="std std-ref">authentication indicators</span></a>.
226One indicator is returned per invocation of <a class="reference external" href="https://tools.ietf.org/html/6680.html#section-7.5">gss_get_name_attribute</a>,
227so multiple invocations may be necessary to retrieve all of the
228indicators from the ticket.  (New in release 1.15.)</p>
229</section>
230<section id="credential-store-extensions">
231<h2>Credential store extensions<a class="headerlink" href="#credential-store-extensions" title="Permalink to this headline">¶</a></h2>
232<p>Beginning with release 1.11, the following GSSAPI extensions declared
233in <code class="docutils literal notranslate"><span class="pre">&lt;gssapi/gssapi_ext.h&gt;</span></code> can be used to specify how credentials
234are acquired or stored:</p>
235<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">struct</span> <span class="n">gss_key_value_element_struct</span> <span class="p">{</span>
236    <span class="n">const</span> <span class="n">char</span> <span class="o">*</span><span class="n">key</span><span class="p">;</span>
237    <span class="n">const</span> <span class="n">char</span> <span class="o">*</span><span class="n">value</span><span class="p">;</span>
238<span class="p">};</span>
239<span class="n">typedef</span> <span class="n">struct</span> <span class="n">gss_key_value_element_struct</span> <span class="n">gss_key_value_element_desc</span><span class="p">;</span>
240
241<span class="n">struct</span> <span class="n">gss_key_value_set_struct</span> <span class="p">{</span>
242    <span class="n">OM_uint32</span> <span class="n">count</span><span class="p">;</span>
243    <span class="n">gss_key_value_element_desc</span> <span class="o">*</span><span class="n">elements</span><span class="p">;</span>
244<span class="p">};</span>
245<span class="n">typedef</span> <span class="n">const</span> <span class="n">struct</span> <span class="n">gss_key_value_set_struct</span> <span class="n">gss_key_value_set_desc</span><span class="p">;</span>
246<span class="n">typedef</span> <span class="n">const</span> <span class="n">gss_key_value_set_desc</span> <span class="o">*</span><span class="n">gss_const_key_value_set_t</span><span class="p">;</span>
247
248<span class="n">OM_uint32</span> <span class="n">gss_acquire_cred_from</span><span class="p">(</span><span class="n">OM_uint32</span> <span class="o">*</span><span class="n">minor_status</span><span class="p">,</span>
249                                <span class="n">const</span> <span class="n">gss_name_t</span> <span class="n">desired_name</span><span class="p">,</span>
250                                <span class="n">OM_uint32</span> <span class="n">time_req</span><span class="p">,</span>
251                                <span class="n">const</span> <span class="n">gss_OID_set</span> <span class="n">desired_mechs</span><span class="p">,</span>
252                                <span class="n">gss_cred_usage_t</span> <span class="n">cred_usage</span><span class="p">,</span>
253                                <span class="n">gss_const_key_value_set_t</span> <span class="n">cred_store</span><span class="p">,</span>
254                                <span class="n">gss_cred_id_t</span> <span class="o">*</span><span class="n">output_cred_handle</span><span class="p">,</span>
255                                <span class="n">gss_OID_set</span> <span class="o">*</span><span class="n">actual_mechs</span><span class="p">,</span>
256                                <span class="n">OM_uint32</span> <span class="o">*</span><span class="n">time_rec</span><span class="p">);</span>
257
258<span class="n">OM_uint32</span> <span class="n">gss_store_cred_into</span><span class="p">(</span><span class="n">OM_uint32</span> <span class="o">*</span><span class="n">minor_status</span><span class="p">,</span>
259                              <span class="n">gss_cred_id_t</span> <span class="n">input_cred_handle</span><span class="p">,</span>
260                              <span class="n">gss_cred_usage_t</span> <span class="n">cred_usage</span><span class="p">,</span>
261                              <span class="n">const</span> <span class="n">gss_OID</span> <span class="n">desired_mech</span><span class="p">,</span>
262                              <span class="n">OM_uint32</span> <span class="n">overwrite_cred</span><span class="p">,</span>
263                              <span class="n">OM_uint32</span> <span class="n">default_cred</span><span class="p">,</span>
264                              <span class="n">gss_const_key_value_set_t</span> <span class="n">cred_store</span><span class="p">,</span>
265                              <span class="n">gss_OID_set</span> <span class="o">*</span><span class="n">elements_stored</span><span class="p">,</span>
266                              <span class="n">gss_cred_usage_t</span> <span class="o">*</span><span class="n">cred_usage_stored</span><span class="p">);</span>
267</pre></div>
268</div>
269<p>The additional <em>cred_store</em> parameter allows the caller to specify
270information about how the credentials should be obtained and stored.
271The following options are supported by the krb5 mechanism:</p>
272<ul class="simple">
273<li><p><strong>ccache</strong>: For acquiring initiator credentials, the name of the
274<a class="reference internal" href="../basic/ccache_def.html#ccache-definition"><span class="std std-ref">credential cache</span></a> to which the handle will
275refer.  For storing credentials, the name of the cache or collection
276where the credentials will be stored (see below).</p></li>
277<li><p><strong>client_keytab</strong>: For acquiring initiator credentials, the name of
278the <a class="reference internal" href="../basic/keytab_def.html#keytab-definition"><span class="std std-ref">keytab</span></a> which will be used, if
279necessary, to refresh the credentials in the cache.</p></li>
280<li><p><strong>keytab</strong>: For acquiring acceptor credentials, the name of the
281<a class="reference internal" href="../basic/keytab_def.html#keytab-definition"><span class="std std-ref">keytab</span></a> to which the handle will refer.
282In release 1.19 and later, this option also determines the keytab to
283be used for verification when initiator credentials are acquired
284using a password and verified.</p></li>
285<li><p><strong>password</strong>: For acquiring initiator credentials, this option
286instructs the mechanism to acquire fresh credentials into a unique
287memory credential cache.  This option may not be used with the
288<strong>ccache</strong> or <strong>client_keytab</strong> options, and a <em>desired_name</em> must
289be specified.  (New in release 1.19.)</p></li>
290<li><p><strong>rcache</strong>: For acquiring acceptor credentials, the name of the
291<a class="reference internal" href="../basic/rcache_def.html#rcache-definition"><span class="std std-ref">replay cache</span></a> to be used when processing
292the initiator tokens.  (New in release 1.13.)</p></li>
293<li><p><strong>verify</strong>: For acquiring initiator credentials, this option
294instructs the mechanism to verify the credentials by obtaining a
295ticket to a service with a known key.  The service key is obtained
296from the keytab specified with the <strong>keytab</strong> option or the default
297keytab.  The value may be the name of a principal in the keytab, or
298the empty string.  If the empty string is given, any <code class="docutils literal notranslate"><span class="pre">host</span></code>
299service principal in the keytab may be used.  (New in release 1.19.)</p></li>
300</ul>
301<p>In release 1.20 or later, if a collection name is specified for
302<strong>cache</strong> in a call to gss_store_cred_into(), an existing cache for
303the client principal within the collection will be selected, or a new
304cache will be created within the collection.  If <em>overwrite_cred</em> is
305false and the selected credential cache already exists, a
306<strong>GSS_S_DUPLICATE_ELEMENT</strong> error will be returned.  If <em>default_cred</em>
307is true, the primary cache of the collection will be switched to the
308selected cache.</p>
309</section>
310<section id="importing-and-exporting-credentials">
311<h2>Importing and exporting credentials<a class="headerlink" href="#importing-and-exporting-credentials" title="Permalink to this headline">¶</a></h2>
312<p>The following GSSAPI extensions can be used to import and export
313credentials (declared in <code class="docutils literal notranslate"><span class="pre">&lt;gssapi/gssapi_ext.h&gt;</span></code>):</p>
314<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">OM_uint32</span> <span class="n">gss_export_cred</span><span class="p">(</span><span class="n">OM_uint32</span> <span class="o">*</span><span class="n">minor_status</span><span class="p">,</span>
315                          <span class="n">gss_cred_id_t</span> <span class="n">cred_handle</span><span class="p">,</span>
316                          <span class="n">gss_buffer_t</span> <span class="n">token</span><span class="p">);</span>
317
318<span class="n">OM_uint32</span> <span class="n">gss_import_cred</span><span class="p">(</span><span class="n">OM_uint32</span> <span class="o">*</span><span class="n">minor_status</span><span class="p">,</span>
319                          <span class="n">gss_buffer_t</span> <span class="n">token</span><span class="p">,</span>
320                          <span class="n">gss_cred_id_t</span> <span class="o">*</span><span class="n">cred_handle</span><span class="p">);</span>
321</pre></div>
322</div>
323<p>The first function serializes a GSSAPI credential handle into a
324buffer; the second unseralizes a buffer into a GSSAPI credential
325handle.  Serializing a credential does not destroy it.  If any of the
326mechanisms used in <em>cred_handle</em> do not support serialization,
327gss_export_cred will return <strong>GSS_S_UNAVAILABLE</strong>.  As with other
328GSSAPI serialization functions, these extensions are only intended to
329work with a matching implementation on the other side; they do not
330serialize credentials in a standardized format.</p>
331<p>A serialized credential may contain secret information such as ticket
332session keys.  The serialization format does not protect this
333information from eavesdropping or tampering.  The calling application
334must take care to protect the serialized credential when communicating
335it over an insecure channel or to an untrusted party.</p>
336<p>A krb5 GSSAPI credential may contain references to a credential cache,
337a client keytab, an acceptor keytab, and a replay cache.  These
338resources are normally serialized as references to their external
339locations (such as the filename of the credential cache).  Because of
340this, a serialized krb5 credential can only be imported by a process
341with similar privileges to the exporter.  A serialized credential
342should not be trusted if it originates from a source with lower
343privileges than the importer, as it may contain references to external
344credential cache, keytab, or replay cache resources not accessible to
345the originator.</p>
346<p>An exception to the above rule applies when a krb5 GSSAPI credential
347refers to a memory credential cache, as is normally the case for
348delegated credentials received by <a class="reference external" href="https://tools.ietf.org/html/rfc2744.html#section-5.1">gss_accept_sec_context</a>.  In this
349case, the contents of the credential cache are serialized, so that the
350resulting token may be imported even if the original memory credential
351cache no longer exists.</p>
352</section>
353<section id="constrained-delegation-s4u">
354<h2>Constrained delegation (S4U)<a class="headerlink" href="#constrained-delegation-s4u" title="Permalink to this headline">¶</a></h2>
355<p>The Microsoft S4U2Self and S4U2Proxy Kerberos protocol extensions
356allow an intermediate service to acquire credentials from a client to
357a target service without requiring the client to delegate a
358ticket-granting ticket, if the KDC is configured to allow it.</p>
359<p>To perform a constrained delegation operation, the intermediate
360service must submit to the KDC an “evidence ticket” from the client to
361the intermediate service.  An evidence ticket can be acquired when the
362client authenticates to the intermediate service with Kerberos, or
363with an S4U2Self request if the KDC allows it.  The MIT krb5 GSSAPI
364library represents an evidence ticket using a “proxy credential”,
365which is a special kind of gss_cred_id_t object whose underlying
366credential cache contains the evidence ticket and a krbtgt ticket for
367the intermediate service.</p>
368<p>To acquire a proxy credential during client authentication, the
369service should first create an acceptor credential using the
370<strong>GSS_C_BOTH</strong> usage.  The application should then pass this
371credential as the <em>acceptor_cred_handle</em> to <a class="reference external" href="https://tools.ietf.org/html/rfc2744.html#section-5.1">gss_accept_sec_context</a>,
372and also pass a <em>delegated_cred_handle</em> output parameter to receive a
373proxy credential containing the evidence ticket.  The output value of
374<em>delegated_cred_handle</em> may be a delegated ticket-granting ticket if
375the client sent one, or a proxy credential if not.  If the library can
376determine that the client’s ticket is not a valid evidence ticket, it
377will place <strong>GSS_C_NO_CREDENTIAL</strong> in <em>delegated_cred_handle</em>.</p>
378<p>To acquire a proxy credential using an S4U2Self request, the service
379can use the following GSSAPI extension:</p>
380<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">OM_uint32</span> <span class="n">gss_acquire_cred_impersonate_name</span><span class="p">(</span><span class="n">OM_uint32</span> <span class="o">*</span><span class="n">minor_status</span><span class="p">,</span>
381                                            <span class="n">gss_cred_id_t</span> <span class="n">icred</span><span class="p">,</span>
382                                            <span class="n">gss_name_t</span> <span class="n">desired_name</span><span class="p">,</span>
383                                            <span class="n">OM_uint32</span> <span class="n">time_req</span><span class="p">,</span>
384                                            <span class="n">gss_OID_set</span> <span class="n">desired_mechs</span><span class="p">,</span>
385                                            <span class="n">gss_cred_usage_t</span> <span class="n">cred_usage</span><span class="p">,</span>
386                                            <span class="n">gss_cred_id_t</span> <span class="o">*</span><span class="n">output_cred</span><span class="p">,</span>
387                                            <span class="n">gss_OID_set</span> <span class="o">*</span><span class="n">actual_mechs</span><span class="p">,</span>
388                                            <span class="n">OM_uint32</span> <span class="o">*</span><span class="n">time_rec</span><span class="p">);</span>
389</pre></div>
390</div>
391<p>The parameters to this function are similar to those of
392<a class="reference external" href="https://tools.ietf.org/html/rfc2744.html#section-5.2">gss_acquire_cred</a>, except that <em>icred</em> is used to make an S4U2Self
393request to the KDC for a ticket from <em>desired_name</em> to the
394intermediate service.  Both <em>icred</em> and <em>desired_name</em> are required
395for this function; passing <strong>GSS_C_NO_CREDENTIAL</strong> or
396<strong>GSS_C_NO_NAME</strong> will cause the call to fail.  <em>icred</em> must contain a
397krbtgt ticket for the intermediate service.  The result of this
398operation is a proxy credential.  (Prior to release 1.18, the result
399of this operation may be a regular credential for <em>desired_name</em>, if
400the KDC issues a non-forwardable ticket.)</p>
401<p>Once the intermediate service has a proxy credential, it can simply
402pass it to <a class="reference external" href="https://tools.ietf.org/html/rfc2744.html#section-5.19">gss_init_sec_context</a> as the <em>initiator_cred_handle</em>
403parameter, and the desired service as the <em>target_name</em> parameter.
404The GSSAPI library will present the krbtgt ticket and evidence ticket
405in the proxy credential to the KDC in an S4U2Proxy request; if the
406intermediate service has the appropriate permissions, the KDC will
407issue a ticket from the client to the target service.  The GSSAPI
408library will then use this ticket to authenticate to the target
409service.</p>
410<p>If an application needs to find out whether a credential it holds is a
411proxy credential and the name of the intermediate service, it can
412query the credential with the <strong>GSS_KRB5_GET_CRED_IMPERSONATOR</strong> OID
413(new in release 1.16, declared in <code class="docutils literal notranslate"><span class="pre">&lt;gssapi/gssapi_krb5.h&gt;</span></code>) using
414the gss_inquire_cred_by_oid extension (declared in
415<code class="docutils literal notranslate"><span class="pre">&lt;gssapi/gssapi_ext.h&gt;</span></code>):</p>
416<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">OM_uint32</span> <span class="n">gss_inquire_cred_by_oid</span><span class="p">(</span><span class="n">OM_uint32</span> <span class="o">*</span><span class="n">minor_status</span><span class="p">,</span>
417                                  <span class="n">const</span> <span class="n">gss_cred_id_t</span> <span class="n">cred_handle</span><span class="p">,</span>
418                                  <span class="n">gss_OID</span> <span class="n">desired_object</span><span class="p">,</span>
419                                  <span class="n">gss_buffer_set_t</span> <span class="o">*</span><span class="n">data_set</span><span class="p">);</span>
420</pre></div>
421</div>
422<p>If the call succeeds and <em>cred_handle</em> is a proxy credential,
423<em>data_set</em> will be set to a single-element buffer set containing the
424unparsed principal name of the intermediate service.  If <em>cred_handle</em>
425is not a proxy credential, <em>data_set</em> will be set to an empty buffer
426set.  If the library does not support the query,
427gss_inquire_cred_by_oid will return <strong>GSS_S_UNAVAILABLE</strong>.</p>
428</section>
429<section id="aead-message-wrapping">
430<h2>AEAD message wrapping<a class="headerlink" href="#aead-message-wrapping" title="Permalink to this headline">¶</a></h2>
431<p>The following GSSAPI extensions (declared in
432<code class="docutils literal notranslate"><span class="pre">&lt;gssapi/gssapi_ext.h&gt;</span></code>) can be used to wrap and unwrap messages
433with additional “associated data” which is integrity-checked but is
434not included in the output buffer:</p>
435<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">OM_uint32</span> <span class="n">gss_wrap_aead</span><span class="p">(</span><span class="n">OM_uint32</span> <span class="o">*</span><span class="n">minor_status</span><span class="p">,</span>
436                        <span class="n">gss_ctx_id_t</span> <span class="n">context_handle</span><span class="p">,</span>
437                        <span class="nb">int</span> <span class="n">conf_req_flag</span><span class="p">,</span> <span class="n">gss_qop_t</span> <span class="n">qop_req</span><span class="p">,</span>
438                        <span class="n">gss_buffer_t</span> <span class="n">input_assoc_buffer</span><span class="p">,</span>
439                        <span class="n">gss_buffer_t</span> <span class="n">input_payload_buffer</span><span class="p">,</span>
440                        <span class="nb">int</span> <span class="o">*</span><span class="n">conf_state</span><span class="p">,</span>
441                        <span class="n">gss_buffer_t</span> <span class="n">output_message_buffer</span><span class="p">);</span>
442
443<span class="n">OM_uint32</span> <span class="n">gss_unwrap_aead</span><span class="p">(</span><span class="n">OM_uint32</span> <span class="o">*</span><span class="n">minor_status</span><span class="p">,</span>
444                          <span class="n">gss_ctx_id_t</span> <span class="n">context_handle</span><span class="p">,</span>
445                          <span class="n">gss_buffer_t</span> <span class="n">input_message_buffer</span><span class="p">,</span>
446                          <span class="n">gss_buffer_t</span> <span class="n">input_assoc_buffer</span><span class="p">,</span>
447                          <span class="n">gss_buffer_t</span> <span class="n">output_payload_buffer</span><span class="p">,</span>
448                          <span class="nb">int</span> <span class="o">*</span><span class="n">conf_state</span><span class="p">,</span>
449                          <span class="n">gss_qop_t</span> <span class="o">*</span><span class="n">qop_state</span><span class="p">);</span>
450</pre></div>
451</div>
452<p>Wrap tokens created with gss_wrap_aead will successfully unwrap only
453if the same <em>input_assoc_buffer</em> contents are presented to
454gss_unwrap_aead.</p>
455</section>
456<section id="iov-message-wrapping">
457<h2>IOV message wrapping<a class="headerlink" href="#iov-message-wrapping" title="Permalink to this headline">¶</a></h2>
458<p>The following extensions (declared in <code class="docutils literal notranslate"><span class="pre">&lt;gssapi/gssapi_ext.h&gt;</span></code>) can
459be used for in-place encryption, fine-grained control over wrap token
460layout, and for constructing wrap tokens compatible with Microsoft DCE
461RPC:</p>
462<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">typedef</span> <span class="n">struct</span> <span class="n">gss_iov_buffer_desc_struct</span> <span class="p">{</span>
463    <span class="n">OM_uint32</span> <span class="nb">type</span><span class="p">;</span>
464    <span class="n">gss_buffer_desc</span> <span class="n">buffer</span><span class="p">;</span>
465<span class="p">}</span> <span class="n">gss_iov_buffer_desc</span><span class="p">,</span> <span class="o">*</span><span class="n">gss_iov_buffer_t</span><span class="p">;</span>
466
467<span class="n">OM_uint32</span> <span class="n">gss_wrap_iov</span><span class="p">(</span><span class="n">OM_uint32</span> <span class="o">*</span><span class="n">minor_status</span><span class="p">,</span>
468                       <span class="n">gss_ctx_id_t</span> <span class="n">context_handle</span><span class="p">,</span>
469                       <span class="nb">int</span> <span class="n">conf_req_flag</span><span class="p">,</span> <span class="n">gss_qop_t</span> <span class="n">qop_req</span><span class="p">,</span>
470                       <span class="nb">int</span> <span class="o">*</span><span class="n">conf_state</span><span class="p">,</span>
471                       <span class="n">gss_iov_buffer_desc</span> <span class="o">*</span><span class="n">iov</span><span class="p">,</span> <span class="nb">int</span> <span class="n">iov_count</span><span class="p">);</span>
472
473<span class="n">OM_uint32</span> <span class="n">gss_unwrap_iov</span><span class="p">(</span><span class="n">OM_uint32</span> <span class="o">*</span><span class="n">minor_status</span><span class="p">,</span>
474                         <span class="n">gss_ctx_id_t</span> <span class="n">context_handle</span><span class="p">,</span>
475                         <span class="nb">int</span> <span class="o">*</span><span class="n">conf_state</span><span class="p">,</span> <span class="n">gss_qop_t</span> <span class="o">*</span><span class="n">qop_state</span><span class="p">,</span>
476                         <span class="n">gss_iov_buffer_desc</span> <span class="o">*</span><span class="n">iov</span><span class="p">,</span> <span class="nb">int</span> <span class="n">iov_count</span><span class="p">);</span>
477
478<span class="n">OM_uint32</span> <span class="n">gss_wrap_iov_length</span><span class="p">(</span><span class="n">OM_uint32</span> <span class="o">*</span><span class="n">minor_status</span><span class="p">,</span>
479                              <span class="n">gss_ctx_id_t</span> <span class="n">context_handle</span><span class="p">,</span>
480                              <span class="nb">int</span> <span class="n">conf_req_flag</span><span class="p">,</span>
481                              <span class="n">gss_qop_t</span> <span class="n">qop_req</span><span class="p">,</span> <span class="nb">int</span> <span class="o">*</span><span class="n">conf_state</span><span class="p">,</span>
482                              <span class="n">gss_iov_buffer_desc</span> <span class="o">*</span><span class="n">iov</span><span class="p">,</span>
483                              <span class="nb">int</span> <span class="n">iov_count</span><span class="p">);</span>
484
485<span class="n">OM_uint32</span> <span class="n">gss_release_iov_buffer</span><span class="p">(</span><span class="n">OM_uint32</span> <span class="o">*</span><span class="n">minor_status</span><span class="p">,</span>
486                                 <span class="n">gss_iov_buffer_desc</span> <span class="o">*</span><span class="n">iov</span><span class="p">,</span>
487                                 <span class="nb">int</span> <span class="n">iov_count</span><span class="p">);</span>
488</pre></div>
489</div>
490<p>The caller of gss_wrap_iov provides an array of gss_iov_buffer_desc
491structures, each containing a type and a gss_buffer_desc structure.
492Valid types include:</p>
493<ul class="simple">
494<li><p><strong>GSS_C_BUFFER_TYPE_DATA</strong>: A data buffer to be included in the
495token, and to be encrypted or decrypted in-place if the token is
496confidentiality-protected.</p></li>
497<li><p><strong>GSS_C_BUFFER_TYPE_HEADER</strong>: The GSSAPI wrap token header and
498underlying cryptographic header.</p></li>
499<li><p><strong>GSS_C_BUFFER_TYPE_TRAILER</strong>: The cryptographic trailer, if one is
500required.</p></li>
501<li><p><strong>GSS_C_BUFFER_TYPE_PADDING</strong>: Padding to be combined with the data
502during encryption and decryption.  (The implementation may choose to
503place padding in the trailer buffer, in which case it will set the
504padding buffer length to 0.)</p></li>
505<li><p><strong>GSS_C_BUFFER_TYPE_STREAM</strong>: For unwrapping only, a buffer
506containing a complete wrap token in standard format to be unwrapped.</p></li>
507<li><p><strong>GSS_C_BUFFER_TYPE_SIGN_ONLY</strong>: A buffer to be included in the
508token’s integrity protection checksum, but not to be encrypted or
509included in the token itself.</p></li>
510</ul>
511<p>For gss_wrap_iov, the IOV list should contain one HEADER buffer,
512followed by zero or more SIGN_ONLY buffers, followed by one or more
513DATA buffers, followed by a TRAILER buffer.  The memory pointed to by
514the buffers is not required to be contiguous or in any particular
515order.  If <em>conf_req_flag</em> is true, DATA buffers will be encrypted
516in-place, while SIGN_ONLY buffers will not be modified.</p>
517<p>The type of an output buffer may be combined with
518<strong>GSS_C_BUFFER_FLAG_ALLOCATE</strong> to request that gss_wrap_iov allocate
519the buffer contents.  If gss_wrap_iov allocates a buffer, it sets the
520<strong>GSS_C_BUFFER_FLAG_ALLOCATED</strong> flag on the buffer type.
521gss_release_iov_buffer can be used to release all allocated buffers
522within an iov list and unset their allocated flags.  Here is an
523example of how gss_wrap_iov can be used with allocation requested
524(<em>ctx</em> is assumed to be a previously established gss_ctx_id_t):</p>
525<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">OM_uint32</span> <span class="n">major</span><span class="p">,</span> <span class="n">minor</span><span class="p">;</span>
526<span class="n">gss_iov_buffer_desc</span> <span class="n">iov</span><span class="p">[</span><span class="mi">4</span><span class="p">];</span>
527<span class="n">char</span> <span class="nb">str</span><span class="p">[]</span> <span class="o">=</span> <span class="s2">&quot;message&quot;</span><span class="p">;</span>
528
529<span class="n">iov</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">.</span><span class="n">type</span> <span class="o">=</span> <span class="n">GSS_IOV_BUFFER_TYPE_HEADER</span> <span class="o">|</span> <span class="n">GSS_IOV_BUFFER_FLAG_ALLOCATE</span><span class="p">;</span>
530<span class="n">iov</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span><span class="o">.</span><span class="n">type</span> <span class="o">=</span> <span class="n">GSS_IOV_BUFFER_TYPE_DATA</span><span class="p">;</span>
531<span class="n">iov</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span><span class="o">.</span><span class="n">buffer</span><span class="o">.</span><span class="n">value</span> <span class="o">=</span> <span class="nb">str</span><span class="p">;</span>
532<span class="n">iov</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span><span class="o">.</span><span class="n">buffer</span><span class="o">.</span><span class="n">length</span> <span class="o">=</span> <span class="n">strlen</span><span class="p">(</span><span class="nb">str</span><span class="p">);</span>
533<span class="n">iov</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span><span class="o">.</span><span class="n">type</span> <span class="o">=</span> <span class="n">GSS_IOV_BUFFER_TYPE_PADDING</span> <span class="o">|</span> <span class="n">GSS_IOV_BUFFER_FLAG_ALLOCATE</span><span class="p">;</span>
534<span class="n">iov</span><span class="p">[</span><span class="mi">3</span><span class="p">]</span><span class="o">.</span><span class="n">type</span> <span class="o">=</span> <span class="n">GSS_IOV_BUFFER_TYPE_TRAILER</span> <span class="o">|</span> <span class="n">GSS_IOV_BUFFER_FLAG_ALLOCATE</span><span class="p">;</span>
535
536<span class="n">major</span> <span class="o">=</span> <span class="n">gss_wrap_iov</span><span class="p">(</span><span class="o">&amp;</span><span class="n">minor</span><span class="p">,</span> <span class="n">ctx</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="n">GSS_C_QOP_DEFAULT</span><span class="p">,</span> <span class="n">NULL</span><span class="p">,</span>
537                     <span class="n">iov</span><span class="p">,</span> <span class="mi">4</span><span class="p">);</span>
538<span class="k">if</span> <span class="p">(</span><span class="n">GSS_ERROR</span><span class="p">(</span><span class="n">major</span><span class="p">))</span>
539    <span class="n">handle_error</span><span class="p">(</span><span class="n">major</span><span class="p">,</span> <span class="n">minor</span><span class="p">);</span>
540
541<span class="o">/*</span> <span class="n">Transmit</span> <span class="ow">or</span> <span class="n">otherwise</span> <span class="n">use</span> <span class="n">resulting</span> <span class="n">buffers</span><span class="o">.</span> <span class="o">*/</span>
542
543<span class="p">(</span><span class="n">void</span><span class="p">)</span><span class="n">gss_release_iov_buffer</span><span class="p">(</span><span class="o">&amp;</span><span class="n">minor</span><span class="p">,</span> <span class="n">iov</span><span class="p">,</span> <span class="mi">4</span><span class="p">);</span>
544</pre></div>
545</div>
546<p>If the caller does not choose to request buffer allocation by
547gss_wrap_iov, it should first call gss_wrap_iov_length to query the
548lengths of the HEADER, PADDING, and TRAILER buffers.  DATA buffers
549must be provided in the iov list so that padding length can be
550computed correctly, but the output buffers need not be initialized.
551Here is an example of using gss_wrap_iov_length and gss_wrap_iov:</p>
552<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">OM_uint32</span> <span class="n">major</span><span class="p">,</span> <span class="n">minor</span><span class="p">;</span>
553<span class="n">gss_iov_buffer_desc</span> <span class="n">iov</span><span class="p">[</span><span class="mi">4</span><span class="p">];</span>
554<span class="n">char</span> <span class="nb">str</span><span class="p">[</span><span class="mi">1024</span><span class="p">]</span> <span class="o">=</span> <span class="s2">&quot;message&quot;</span><span class="p">,</span> <span class="o">*</span><span class="n">ptr</span><span class="p">;</span>
555
556<span class="n">iov</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">.</span><span class="n">type</span> <span class="o">=</span> <span class="n">GSS_IOV_BUFFER_TYPE_HEADER</span><span class="p">;</span>
557<span class="n">iov</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span><span class="o">.</span><span class="n">type</span> <span class="o">=</span> <span class="n">GSS_IOV_BUFFER_TYPE_DATA</span><span class="p">;</span>
558<span class="n">iov</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span><span class="o">.</span><span class="n">buffer</span><span class="o">.</span><span class="n">value</span> <span class="o">=</span> <span class="nb">str</span><span class="p">;</span>
559<span class="n">iov</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span><span class="o">.</span><span class="n">buffer</span><span class="o">.</span><span class="n">length</span> <span class="o">=</span> <span class="n">strlen</span><span class="p">(</span><span class="nb">str</span><span class="p">);</span>
560
561<span class="n">iov</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span><span class="o">.</span><span class="n">type</span> <span class="o">=</span> <span class="n">GSS_IOV_BUFFER_TYPE_PADDING</span><span class="p">;</span>
562<span class="n">iov</span><span class="p">[</span><span class="mi">3</span><span class="p">]</span><span class="o">.</span><span class="n">type</span> <span class="o">=</span> <span class="n">GSS_IOV_BUFFER_TYPE_TRAILER</span><span class="p">;</span>
563
564<span class="n">major</span> <span class="o">=</span> <span class="n">gss_wrap_iov_length</span><span class="p">(</span><span class="o">&amp;</span><span class="n">minor</span><span class="p">,</span> <span class="n">ctx</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="n">GSS_C_QOP_DEFAULT</span><span class="p">,</span>
565                            <span class="n">NULL</span><span class="p">,</span> <span class="n">iov</span><span class="p">,</span> <span class="mi">4</span><span class="p">);</span>
566<span class="k">if</span> <span class="p">(</span><span class="n">GSS_ERROR</span><span class="p">(</span><span class="n">major</span><span class="p">))</span>
567    <span class="n">handle_error</span><span class="p">(</span><span class="n">major</span><span class="p">,</span> <span class="n">minor</span><span class="p">);</span>
568<span class="k">if</span> <span class="p">(</span><span class="n">strlen</span><span class="p">(</span><span class="nb">str</span><span class="p">)</span> <span class="o">+</span> <span class="n">iov</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">.</span><span class="n">buffer</span><span class="o">.</span><span class="n">length</span> <span class="o">+</span> <span class="n">iov</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span><span class="o">.</span><span class="n">buffer</span><span class="o">.</span><span class="n">length</span> <span class="o">+</span>
569    <span class="n">iov</span><span class="p">[</span><span class="mi">3</span><span class="p">]</span><span class="o">.</span><span class="n">buffer</span><span class="o">.</span><span class="n">length</span> <span class="o">&gt;</span> <span class="n">sizeof</span><span class="p">(</span><span class="nb">str</span><span class="p">))</span>
570    <span class="n">handle_out_of_space_error</span><span class="p">();</span>
571<span class="n">ptr</span> <span class="o">=</span> <span class="nb">str</span> <span class="o">+</span> <span class="n">strlen</span><span class="p">(</span><span class="nb">str</span><span class="p">);</span>
572<span class="n">iov</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">.</span><span class="n">buffer</span><span class="o">.</span><span class="n">value</span> <span class="o">=</span> <span class="n">ptr</span><span class="p">;</span>
573<span class="n">ptr</span> <span class="o">+=</span> <span class="n">iov</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">.</span><span class="n">buffer</span><span class="o">.</span><span class="n">length</span><span class="p">;</span>
574<span class="n">iov</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span><span class="o">.</span><span class="n">buffer</span><span class="o">.</span><span class="n">value</span> <span class="o">=</span> <span class="n">ptr</span><span class="p">;</span>
575<span class="n">ptr</span> <span class="o">+=</span> <span class="n">iov</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span><span class="o">.</span><span class="n">buffer</span><span class="o">.</span><span class="n">length</span><span class="p">;</span>
576<span class="n">iov</span><span class="p">[</span><span class="mi">3</span><span class="p">]</span><span class="o">.</span><span class="n">buffer</span><span class="o">.</span><span class="n">value</span> <span class="o">=</span> <span class="n">ptr</span><span class="p">;</span>
577
578<span class="n">major</span> <span class="o">=</span> <span class="n">gss_wrap_iov</span><span class="p">(</span><span class="o">&amp;</span><span class="n">minor</span><span class="p">,</span> <span class="n">ctx</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="n">GSS_C_QOP_DEFAULT</span><span class="p">,</span> <span class="n">NULL</span><span class="p">,</span>
579                     <span class="n">iov</span><span class="p">,</span> <span class="mi">4</span><span class="p">);</span>
580<span class="k">if</span> <span class="p">(</span><span class="n">GSS_ERROR</span><span class="p">(</span><span class="n">major</span><span class="p">))</span>
581    <span class="n">handle_error</span><span class="p">(</span><span class="n">major</span><span class="p">,</span> <span class="n">minor</span><span class="p">);</span>
582</pre></div>
583</div>
584<p>If the context was established using the <strong>GSS_C_DCE_STYLE</strong> flag
585(described in <span class="target" id="index-6"></span><a class="rfc reference external" href="https://tools.ietf.org/html/rfc4757.html"><strong>RFC 4757</strong></a>), wrap tokens compatible with Microsoft DCE
586RPC can be constructed.  In this case, the IOV list must include a
587SIGN_ONLY buffer, a DATA buffer, a second SIGN_ONLY buffer, and a
588HEADER buffer in that order (the order of the buffer contents remains
589arbitrary).  The application must pad the DATA buffer to a multiple of
59016 bytes as no padding or trailer buffer is used.</p>
591<p>gss_unwrap_iov may be called with an IOV list just like one which
592would be provided to gss_wrap_iov.  DATA buffers will be decrypted
593in-place if they were encrypted, and SIGN_ONLY buffers will not be
594modified.</p>
595<p>Alternatively, gss_unwrap_iov may be called with a single STREAM
596buffer, zero or more SIGN_ONLY buffers, and a single DATA buffer.  The
597STREAM buffer is interpreted as a complete wrap token.  The STREAM
598buffer will be modified in-place to decrypt its contents.  The DATA
599buffer will be initialized to point to the decrypted data within the
600STREAM buffer, unless it has the <strong>GSS_C_BUFFER_FLAG_ALLOCATE</strong> flag
601set, in which case it will be initialized with a copy of the decrypted
602data.  Here is an example (<em>token</em> and <em>token_len</em> are assumed to be a
603pre-existing pointer and length for a modifiable region of data):</p>
604<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">OM_uint32</span> <span class="n">major</span><span class="p">,</span> <span class="n">minor</span><span class="p">;</span>
605<span class="n">gss_iov_buffer_desc</span> <span class="n">iov</span><span class="p">[</span><span class="mi">2</span><span class="p">];</span>
606
607<span class="n">iov</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">.</span><span class="n">type</span> <span class="o">=</span> <span class="n">GSS_IOV_BUFFER_TYPE_STREAM</span><span class="p">;</span>
608<span class="n">iov</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">.</span><span class="n">buffer</span><span class="o">.</span><span class="n">value</span> <span class="o">=</span> <span class="n">token</span><span class="p">;</span>
609<span class="n">iov</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">.</span><span class="n">buffer</span><span class="o">.</span><span class="n">length</span> <span class="o">=</span> <span class="n">token_len</span><span class="p">;</span>
610<span class="n">iov</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span><span class="o">.</span><span class="n">type</span> <span class="o">=</span> <span class="n">GSS_IOV_BUFFER_TYPE_DATA</span><span class="p">;</span>
611<span class="n">major</span> <span class="o">=</span> <span class="n">gss_unwrap_iov</span><span class="p">(</span><span class="o">&amp;</span><span class="n">minor</span><span class="p">,</span> <span class="n">ctx</span><span class="p">,</span> <span class="n">NULL</span><span class="p">,</span> <span class="n">NULL</span><span class="p">,</span> <span class="n">iov</span><span class="p">,</span> <span class="mi">2</span><span class="p">);</span>
612<span class="k">if</span> <span class="p">(</span><span class="n">GSS_ERROR</span><span class="p">(</span><span class="n">major</span><span class="p">))</span>
613    <span class="n">handle_error</span><span class="p">(</span><span class="n">major</span><span class="p">,</span> <span class="n">minor</span><span class="p">);</span>
614
615<span class="o">/*</span> <span class="n">Decrypted</span> <span class="n">data</span> <span class="ow">is</span> <span class="ow">in</span> <span class="n">iov</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span><span class="o">.</span><span class="n">buffer</span><span class="p">,</span> <span class="n">pointing</span> <span class="n">to</span> <span class="n">a</span> <span class="n">subregion</span> <span class="n">of</span>
616 <span class="o">*</span> <span class="n">token</span><span class="o">.</span> <span class="o">*/</span>
617</pre></div>
618</div>
619</section>
620<section id="iov-mic-tokens">
621<span id="gssapi-mic-token"></span><h2>IOV MIC tokens<a class="headerlink" href="#iov-mic-tokens" title="Permalink to this headline">¶</a></h2>
622<p>The following extensions (declared in <code class="docutils literal notranslate"><span class="pre">&lt;gssapi/gssapi_ext.h&gt;</span></code>) can
623be used in release 1.12 or later to construct and verify MIC tokens
624using an IOV list:</p>
625<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">OM_uint32</span> <span class="n">gss_get_mic_iov</span><span class="p">(</span><span class="n">OM_uint32</span> <span class="o">*</span><span class="n">minor_status</span><span class="p">,</span>
626                          <span class="n">gss_ctx_id_t</span> <span class="n">context_handle</span><span class="p">,</span>
627                          <span class="n">gss_qop_t</span> <span class="n">qop_req</span><span class="p">,</span>
628                          <span class="n">gss_iov_buffer_desc</span> <span class="o">*</span><span class="n">iov</span><span class="p">,</span>
629                          <span class="nb">int</span> <span class="n">iov_count</span><span class="p">);</span>
630
631<span class="n">OM_uint32</span> <span class="n">gss_get_mic_iov_length</span><span class="p">(</span><span class="n">OM_uint32</span> <span class="o">*</span><span class="n">minor_status</span><span class="p">,</span>
632                                 <span class="n">gss_ctx_id_t</span> <span class="n">context_handle</span><span class="p">,</span>
633                                 <span class="n">gss_qop_t</span> <span class="n">qop_req</span><span class="p">,</span>
634                                 <span class="n">gss_iov_buffer_desc</span> <span class="o">*</span><span class="n">iov</span><span class="p">,</span>
635                                 <span class="n">iov_count</span><span class="p">);</span>
636
637<span class="n">OM_uint32</span> <span class="n">gss_verify_mic_iov</span><span class="p">(</span><span class="n">OM_uint32</span> <span class="o">*</span><span class="n">minor_status</span><span class="p">,</span>
638                             <span class="n">gss_ctx_id_t</span> <span class="n">context_handle</span><span class="p">,</span>
639                             <span class="n">gss_qop_t</span> <span class="o">*</span><span class="n">qop_state</span><span class="p">,</span>
640                             <span class="n">gss_iov_buffer_desc</span> <span class="o">*</span><span class="n">iov</span><span class="p">,</span>
641                             <span class="nb">int</span> <span class="n">iov_count</span><span class="p">);</span>
642</pre></div>
643</div>
644<p>The caller of gss_get_mic_iov provides an array of gss_iov_buffer_desc
645structures, each containing a type and a gss_buffer_desc structure.
646Valid types include:</p>
647<ul class="simple">
648<li><p><strong>GSS_C_BUFFER_TYPE_DATA</strong> and <strong>GSS_C_BUFFER_TYPE_SIGN_ONLY</strong>: The
649corresponding buffer for each of these types will be signed for the
650MIC token, in the order provided.</p></li>
651<li><p><strong>GSS_C_BUFFER_TYPE_MIC_TOKEN</strong>: The GSSAPI MIC token.</p></li>
652</ul>
653<p>The type of the MIC_TOKEN buffer may be combined with
654<strong>GSS_C_BUFFER_FLAG_ALLOCATE</strong> to request that gss_get_mic_iov
655allocate the buffer contents.  If gss_get_mic_iov allocates the
656buffer, it sets the <strong>GSS_C_BUFFER_FLAG_ALLOCATED</strong> flag on the buffer
657type.  gss_release_iov_buffer can be used to release all allocated
658buffers within an iov list and unset their allocated flags.  Here is
659an example of how gss_get_mic_iov can be used with allocation
660requested (<em>ctx</em> is assumed to be a previously established
661gss_ctx_id_t):</p>
662<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">OM_uint32</span> <span class="n">major</span><span class="p">,</span> <span class="n">minor</span><span class="p">;</span>
663<span class="n">gss_iov_buffer_desc</span> <span class="n">iov</span><span class="p">[</span><span class="mi">3</span><span class="p">];</span>
664
665<span class="n">iov</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">.</span><span class="n">type</span> <span class="o">=</span> <span class="n">GSS_IOV_BUFFER_TYPE_DATA</span><span class="p">;</span>
666<span class="n">iov</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">.</span><span class="n">buffer</span><span class="o">.</span><span class="n">value</span> <span class="o">=</span> <span class="s2">&quot;sign1&quot;</span><span class="p">;</span>
667<span class="n">iov</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">.</span><span class="n">buffer</span><span class="o">.</span><span class="n">length</span> <span class="o">=</span> <span class="mi">5</span><span class="p">;</span>
668<span class="n">iov</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span><span class="o">.</span><span class="n">type</span> <span class="o">=</span> <span class="n">GSS_IOV_BUFFER_TYPE_SIGN_ONLY</span><span class="p">;</span>
669<span class="n">iov</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span><span class="o">.</span><span class="n">buffer</span><span class="o">.</span><span class="n">value</span> <span class="o">=</span> <span class="s2">&quot;sign2&quot;</span><span class="p">;</span>
670<span class="n">iov</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span><span class="o">.</span><span class="n">buffer</span><span class="o">.</span><span class="n">length</span> <span class="o">=</span> <span class="mi">5</span><span class="p">;</span>
671<span class="n">iov</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span><span class="o">.</span><span class="n">type</span> <span class="o">=</span> <span class="n">GSS_IOV_BUFFER_TYPE_MIC_TOKEN</span> <span class="o">|</span> <span class="n">GSS_IOV_BUFFER_FLAG_ALLOCATE</span><span class="p">;</span>
672
673<span class="n">major</span> <span class="o">=</span> <span class="n">gss_get_mic_iov</span><span class="p">(</span><span class="o">&amp;</span><span class="n">minor</span><span class="p">,</span> <span class="n">ctx</span><span class="p">,</span> <span class="n">GSS_C_QOP_DEFAULT</span><span class="p">,</span> <span class="n">iov</span><span class="p">,</span> <span class="mi">3</span><span class="p">);</span>
674<span class="k">if</span> <span class="p">(</span><span class="n">GSS_ERROR</span><span class="p">(</span><span class="n">major</span><span class="p">))</span>
675    <span class="n">handle_error</span><span class="p">(</span><span class="n">major</span><span class="p">,</span> <span class="n">minor</span><span class="p">);</span>
676
677<span class="o">/*</span> <span class="n">Transmit</span> <span class="ow">or</span> <span class="n">otherwise</span> <span class="n">use</span> <span class="n">iov</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span><span class="o">.</span><span class="n">buffer</span><span class="o">.</span> <span class="o">*/</span>
678
679<span class="p">(</span><span class="n">void</span><span class="p">)</span><span class="n">gss_release_iov_buffer</span><span class="p">(</span><span class="o">&amp;</span><span class="n">minor</span><span class="p">,</span> <span class="n">iov</span><span class="p">,</span> <span class="mi">3</span><span class="p">);</span>
680</pre></div>
681</div>
682<p>If the caller does not choose to request buffer allocation by
683gss_get_mic_iov, it should first call gss_get_mic_iov_length to query
684the length of the MIC_TOKEN buffer.  Here is an example of using
685gss_get_mic_iov_length and gss_get_mic_iov:</p>
686<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">OM_uint32</span> <span class="n">major</span><span class="p">,</span> <span class="n">minor</span><span class="p">;</span>
687<span class="n">gss_iov_buffer_desc</span> <span class="n">iov</span><span class="p">[</span><span class="mi">2</span><span class="p">];</span>
688<span class="n">char</span> <span class="n">data</span><span class="p">[</span><span class="mi">1024</span><span class="p">];</span>
689
690<span class="n">iov</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">.</span><span class="n">type</span> <span class="o">=</span> <span class="n">GSS_IOV_BUFFER_TYPE_MIC_TOKEN</span><span class="p">;</span>
691<span class="n">iov</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span><span class="o">.</span><span class="n">type</span> <span class="o">=</span> <span class="n">GSS_IOV_BUFFER_TYPE_DATA</span><span class="p">;</span>
692<span class="n">iov</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span><span class="o">.</span><span class="n">buffer</span><span class="o">.</span><span class="n">value</span> <span class="o">=</span> <span class="s2">&quot;message&quot;</span><span class="p">;</span>
693<span class="n">iov</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span><span class="o">.</span><span class="n">buffer</span><span class="o">.</span><span class="n">length</span> <span class="o">=</span> <span class="mi">7</span><span class="p">;</span>
694
695<span class="n">major</span> <span class="o">=</span> <span class="n">gss_get_mic_iov_length</span><span class="p">(</span><span class="o">&amp;</span><span class="n">minor</span><span class="p">,</span> <span class="n">ctx</span><span class="p">,</span> <span class="n">GSS_C_QOP_DEFAULT</span><span class="p">,</span> <span class="n">iov</span><span class="p">,</span> <span class="mi">2</span><span class="p">);</span>
696<span class="k">if</span> <span class="p">(</span><span class="n">GSS_ERROR</span><span class="p">(</span><span class="n">major</span><span class="p">))</span>
697    <span class="n">handle_error</span><span class="p">(</span><span class="n">major</span><span class="p">,</span> <span class="n">minor</span><span class="p">);</span>
698<span class="k">if</span> <span class="p">(</span><span class="n">iov</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">.</span><span class="n">buffer</span><span class="o">.</span><span class="n">length</span> <span class="o">&gt;</span> <span class="n">sizeof</span><span class="p">(</span><span class="n">data</span><span class="p">))</span>
699    <span class="n">handle_out_of_space_error</span><span class="p">();</span>
700<span class="n">iov</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">.</span><span class="n">buffer</span><span class="o">.</span><span class="n">value</span> <span class="o">=</span> <span class="n">data</span><span class="p">;</span>
701
702<span class="n">major</span> <span class="o">=</span> <span class="n">gss_get_mic_iov</span><span class="p">(</span><span class="o">&amp;</span><span class="n">minor</span><span class="p">,</span> <span class="n">ctx</span><span class="p">,</span> <span class="n">GSS_C_QOP_DEFAULT</span><span class="p">,</span> <span class="n">iov</span><span class="p">,</span> <span class="mi">2</span><span class="p">);</span>
703<span class="k">if</span> <span class="p">(</span><span class="n">GSS_ERROR</span><span class="p">(</span><span class="n">major</span><span class="p">))</span>
704    <span class="n">handle_error</span><span class="p">(</span><span class="n">major</span><span class="p">,</span> <span class="n">minor</span><span class="p">);</span>
705</pre></div>
706</div>
707</section>
708</section>
709
710
711            <div class="clearer"></div>
712          </div>
713        </div>
714      </div>
715        </div>
716        <div class="sidebar">
717
718    <h2>On this page</h2>
719    <ul>
720<li><a class="reference internal" href="#">Developing with GSSAPI</a><ul>
721<li><a class="reference internal" href="#name-types">Name types</a></li>
722<li><a class="reference internal" href="#initiator-credentials">Initiator credentials</a></li>
723<li><a class="reference internal" href="#acceptor-names">Acceptor names</a></li>
724<li><a class="reference internal" href="#name-attributes">Name Attributes</a></li>
725<li><a class="reference internal" href="#credential-store-extensions">Credential store extensions</a></li>
726<li><a class="reference internal" href="#importing-and-exporting-credentials">Importing and exporting credentials</a></li>
727<li><a class="reference internal" href="#constrained-delegation-s4u">Constrained delegation (S4U)</a></li>
728<li><a class="reference internal" href="#aead-message-wrapping">AEAD message wrapping</a></li>
729<li><a class="reference internal" href="#iov-message-wrapping">IOV message wrapping</a></li>
730<li><a class="reference internal" href="#iov-mic-tokens">IOV MIC tokens</a></li>
731</ul>
732</li>
733</ul>
734
735    <br/>
736    <h2>Table of contents</h2>
737    <ul class="current">
738<li class="toctree-l1"><a class="reference internal" href="../user/index.html">For users</a></li>
739<li class="toctree-l1"><a class="reference internal" href="../admin/index.html">For administrators</a></li>
740<li class="toctree-l1 current"><a class="reference internal" href="index.html">For application developers</a><ul class="current">
741<li class="toctree-l2 current"><a class="current reference internal" href="#">Developing with GSSAPI</a></li>
742<li class="toctree-l2"><a class="reference internal" href="y2038.html">Year 2038 considerations for uses of krb5_timestamp</a></li>
743<li class="toctree-l2"><a class="reference internal" href="h5l_mit_apidiff.html">Differences between Heimdal and MIT Kerberos API</a></li>
744<li class="toctree-l2"><a class="reference internal" href="init_creds.html">Initial credentials</a></li>
745<li class="toctree-l2"><a class="reference internal" href="princ_handle.html">Principal manipulation and parsing</a></li>
746<li class="toctree-l2"><a class="reference internal" href="refs/index.html">Complete reference - API and datatypes</a></li>
747</ul>
748</li>
749<li class="toctree-l1"><a class="reference internal" href="../plugindev/index.html">For plugin module developers</a></li>
750<li class="toctree-l1"><a class="reference internal" href="../build/index.html">Building Kerberos V5</a></li>
751<li class="toctree-l1"><a class="reference internal" href="../basic/index.html">Kerberos V5 concepts</a></li>
752<li class="toctree-l1"><a class="reference internal" href="../formats/index.html">Protocols and file formats</a></li>
753<li class="toctree-l1"><a class="reference internal" href="../mitK5features.html">MIT Kerberos features</a></li>
754<li class="toctree-l1"><a class="reference internal" href="../build_this.html">How to build this documentation from the source</a></li>
755<li class="toctree-l1"><a class="reference internal" href="../about.html">Contributing to the MIT Kerberos Documentation</a></li>
756<li class="toctree-l1"><a class="reference internal" href="../resources.html">Resources</a></li>
757</ul>
758
759    <br/>
760    <h4><a href="../index.html">Full Table of Contents</a></h4>
761    <h4>Search</h4>
762    <form class="search" action="../search.html" method="get">
763      <input type="text" name="q" size="18" />
764      <input type="submit" value="Go" />
765      <input type="hidden" name="check_keywords" value="yes" />
766      <input type="hidden" name="area" value="default" />
767    </form>
768
769        </div>
770        <div class="clearer"></div>
771      </div>
772    </div>
773
774    <div class="footer-wrapper">
775        <div class="footer" >
776            <div class="right" ><i>Release: 1.21.3</i><br />
777                &copy; <a href="../copyright.html">Copyright</a> 1985-2024, MIT.
778            </div>
779            <div class="left">
780
781        <a href="../index.html" title="Full Table of Contents"
782            >Contents</a> |
783        <a href="index.html" title="For application developers"
784            >previous</a> |
785        <a href="y2038.html" title="Year 2038 considerations for uses of krb5_timestamp"
786            >next</a> |
787        <a href="../genindex.html" title="General Index"
788            >index</a> |
789        <a href="../search.html" title="Enter search criteria"
790            >Search</a> |
791    <a href="mailto:krb5-bugs@mit.edu?subject=Documentation__Developing with GSSAPI">feedback</a>
792            </div>
793        </div>
794    </div>
795
796  </body>
797</html>