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 — 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@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"><gssapi/gssapi_krb5.h></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@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"><gssapi/gssapi_krb5.h></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@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@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"><gssapi/gssapi_ext.h></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"><gssapi/gssapi_ext.h></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"><gssapi/gssapi_krb5.h></span></code>) using 414the gss_inquire_cred_by_oid extension (declared in 415<code class="docutils literal notranslate"><span class="pre"><gssapi/gssapi_ext.h></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"><gssapi/gssapi_ext.h></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"><gssapi/gssapi_ext.h></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">"message"</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">&</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">&</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">"message"</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">&</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">></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">&</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">&</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"><gssapi/gssapi_ext.h></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">"sign1"</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">"sign2"</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">&</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">&</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">"message"</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">&</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">></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">&</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 © <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>