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