logo_kerberos.gif

Projects/VerifyAuthData

From K5Wiki
< Projects
Revision as of 10:25, 31 August 2009 by Lukeh (talk | contribs) (greet_server)

Jump to: navigation, search
This is an early stage project for MIT Kerberos. It is being fleshed out by its proponents. Feel free to help flesh out the details of this project. After the project is ready, it will be presented for review and approval.



Contents

Background

The goals of this project are to:

  • change the behaviour of krb5_rd_req() to always verify known authorization data elements
  • provide an attribute-based GSS interface for inquiry and submission of authorization information (draft-ietf-kitten-gssapi-naming-exts)
  • provide an attribute-based plugin interface for verification and serialization of authorization information
  • encourage the use of positive authorization data by providing sample KDC and application plugins

Architecture

A new opaque type, an authorization data context (krb5_authdata_context) provides an attribute-based accessor onto a set of authorization data elements. The operations which one can perform on this context roughly mirror those specified in draft-ietf-kitten-gssapi-naming-exts.

An authorization data context is always created and verified by krb5_rd_req(); one can also be submitted to krb5_mk_req(). Access to it is provided via the krb5_auth_con_get_authdata_context() API. The public interface is provided via draft-ietf-kitten-gssapi-naming-exts.

The authorization data context encapsulates a set of authorization data systems, each which provide support for one or more authorization data types. Each system is instantiated as a module, one for each authorization data type. This is modelled closely on the client-side preauthentication SPI. The set of systems is extensible at runtime through a plug-in interface.

Windows PAC

An authorization data system for the Windows 2000 PAC is built into libkrb5, as a wrapper around the krb5_pac APIs introduced in MIT Kerberos 1.7. Each PAC buffer is surfaced as a separate attribute. A vendor that wished to surface fields within buffers (for example, SIDs representing a user's group membership) could do so by registering the appropriate plug-in, avoiding the overhead of building a NDR parser into libkrb5.

Initiator/acceptor data

Systems that implement the AD_USAGE_AP_REQ usage can serialize attributes for inclusion in an AP-REQ. The "greet_client" plugin is one such system: it conveys a single string from initiator to acceptor in the authorization data of the AP-REQ authenticator. (AD_USAGE_TGS_REQ is also supported.) Plugins that only need to verify and inquiry about KDC issued authorization data, such as the Windows 2000 PAC, advertise the AD_USAGE_KDC_ISSUED usage.

KDC

The existing KDC authorization data SPI contributed by Apple and Novell in unchanged by this project. However, in order to encourage the use of positive authorization data, we have provided helper routines for marshalling and verifying AD-KDCIssued, as well sample application- and KDC-side plugins. A few hundred lines of code in total, they may be easily adapted to vendor-specific requirements such as NFSv4, POSIX, or SAML. Further, an enterprising developer might choose to build a KDC authorization data plugin on top of the authorization data ontexts APIs (and perform the majority of work in a "client" plug-in).

Implementation

GSS

Naming extension APIs

The reader is referred to draft-ietf-kitten-gssapi-naming-exts for details. The following new APIs are defined in gssapi_ext.h:

  • gss_display_name_ext()
  • gss_nquire_name()
  • gss_get_name_attribute()
  • gss_set_name_attribute()
  • gss_delete_name_attribute()
  • gss_export_name_composite()
  • gss_map_name_to_any()
  • gss_release_any_name_mapping()

The following changes were made from draft-ietf-kitten-gssapi-naming-exts-05 (obviously, until the draft becomes an RFC, we may expect further changes):

  • the output argument of gss_map_name_to_any() is a pointer to gss_any_t (presumably this is a typo in the document)
  • the authenticated, asserted and all_attrs arguments to gss_inquire_name() are pointers to gss_buffer_set_t

Changes to mechanism glue

The mechglue exports the naming extension functions named above. New files have been added to implement them, and the gss_mechanism type updated accordingly. Note that the mechglue does not provide its own attribute store: as such, the naming extensions APIs must be used with mechanism names. This may require the caller to explicitly canonicalize the name first.

Changes to SPNEGO

Wrappers for the naming extension APIs have been added to SPNEGO.

Changes to Kerberos 5 mechanism

All of the naming extension APIs, save for gss_display_name_ext(), have been implemented in the Kerberos 5 mechanism. Most of the code is to be found in naming_exts.c.

Previously, a Kerberos 5 mechanism name was represented by the type krb5_principal. This is now a structure containing an authorization data context as well as the principal name:

typedef struct _krb5_gss_name_rec {
    krb5_principal princ; /* immutable */
    k5_mutex_t lock; /* protects ad_context only for now */
    krb5_authdata_context ad_context;
} krb5_gss_name_rec, *krb5_gss_name_t;

Note that the lock protects ad_context only; the principal name is immutable. The initialization of ad_context is deferred until an attribute it set or authorization data imported. Some helper APIs are provided to manage the creation, copying and destruction of Kerberos 5 mechanism names.

A summary of changes to existing functions follows, excluding changes required to use the new krb5_gss_name_t data structure:

krb5_gss_init_sec_context()

Note: the terms "flatten" and "export" are used interchangeably below and hereafter.

  • If the initiator name has an authorization data context, then the authorization data for all AD_USAGE_TGS_REQ systems is flattened, and included in the TGS request
  • If the initiator name has an authorization data context, then the authorization data for all AD_USAGE_AP_REQ systems is flattened, and included in the AP request
krb5_gss_import_name()
  • Support is added for importing composite names that include authorization data elements (note that re-imported names will lose their authenticated state)
krb5_gss_inquire_name()

This new function is a wrapper around krb5_authdata_get_attribute_types().

krb5_gss_get_name_attribute()

This new function is a wrapper around krb5_authdata_get_attribute().

krb5_gss_set_name_attribute()

This new function is a wrapper around krb5_authdata_set_attribute().

krb5_gss_delete_name_attribute()

This new function is a wrapper around krb5_authdata_delete_attribute().

krb5_gss_map_name_to_any()

This new function is a wrapper around krb5_authdata_export_internal().

krb5_gss_release_any_name_mapping()

This new function is a wrapper around krb5_authdata_free_internal().

krb5_gss_export_name_composite()

This new function is a wrapper around krb5_authdata_export_attributes().

krb5_gss_display_name_ext()

This is not yet implemented.

krb5_gss_accept_sec_context()
  • Update to use kg_XXX_name() helper functions
  • Extract authorization data context from authentication context and store in source name

libkrb5

Public APIs

krb5_make_authdata_kdc_issued()
krb5_error_code KRB5_CALLCONV
krb5_make_authdata_kdc_issued(krb5_context context,
    const krb5_keyblock *key,
    krb5_const_principal issuer,
    krb5_authdata *const *authdata,
    krb5_authdata ***ad_kdcissued);

This function both encodes and signs AD-KDCIssued authorization data (RFC 4120 section 5.2.6.2). A set of authorization data containing a single AD-KDCIssued element is returned to the caller.

krb5_verify_authdata_kdc_issued()
krb5_error_code KRB5_CALLCONV
krb5_verify_authdata_kdc_issued(krb5_context context,
    const krb5_keyblock *key,
    const krb5_authdata *ad_kdcissued,
    krb5_principal *issuer,
    krb5_authdata ***authdata);

This function both decodes and verifies AD-KDCIssued authorization data (RFC 4120 section 5.2.6.2). The issuer and unwrapped authorization data are returned to the called.

Exported, private APIs

krb5int_free_data_list()
void KRB5_CALLCONV krb5int_free_data_list
(krb5_context context, krb5_data *data);

Frees an array of krb5_data objects, terminated by the last element's data member being NULL.

krb5_authdata_context_init()
krb5_error_code KRB5_CALLCONV
krb5_authdata_context_init(krb5_context kcontext,
                           krb5_authdata_context *pcontext);

Initialises an authorization data context, loading both built- and plug-in authorization data systems. Note that in the present implementation, the plug-in list is not cached between calls to this function; this may change in the future.

krb5_authdata_context_free()
void KRB5_CALLCONV
krb5_authdata_context_free(krb5_context kcontext,
                           krb5_authdata_context context);

Releases and authorization data context.

krb5_authdata_get_attribute_types()
krb5_error_code KRB5_CALLCONV
krb5_authdata_get_attribute_types(krb5_context kcontext,
                                  krb5_authdata_context context,
                                  krb5_data **verified_attrs,
                                  krb5_data **asserted_attrs,
                                  krb5_data **all_attrs);

Returns the union of attributes supported by all registered authorization data systems. Note that the meaning of all_attrs is unclear from draft-ietf-kitten-gssapi-naming-exts; we may remove this in the future.

krb5_authdata_get_attribute()
krb5_error_code KRB5_CALLCONV
krb5_authdata_get_attribute(krb5_context kcontext,
                            krb5_authdata_context context,
                            const krb5_data *attribute,
                            krb5_boolean *authenticated,
                            krb5_boolean *complete,
                            krb5_data *value,
                            krb5_data *display_value,
                            int *more);

Retrieves an attribute named by attribute from the set of authorization data systems. Note that presently a single attribute type cannot be federated amongst multiple systems. more must be set to -1 on the first call; this function should be called repeatedly until more is 0, or an error returned.

krb5_authdata_set_attribute()
krb5_error_code KRB5_CALLCONV
krb5_authdata_set_attribute(krb5_context kcontext,
                            krb5_authdata_context context,
                            krb5_boolean complete,
                            const krb5_data *attribute,
                            const krb5_data *value);

Sets/adds an attribute value. Whether an attribute is multi-valued or not is left to the authorization data system. To replace an attribute's every value delete the attribute's values first with krb5_authdata_delete_attribute().

Return values: EEXIST indicates the attribute already exists, EINVAL indicates an invalid argument, ENOENT indicates that the attribute type is not recognised by any authorization data system.

krb5_authdata_delete_attribute()
krb5_error_code KRB5_CALLCONV
krb5_authdata_delete_attribute(krb5_context kcontext,
                               krb5_authdata_context context,
                               const krb5_data *attribute);

Deletes an attribute.

krb5_authdata_import_attributes()
krb5_error_code KRB5_CALLCONV
krb5_authdata_import_attributes(krb5_context kcontext,
                                krb5_authdata_context context,
                                krb5_flags usage,
                                krb5_authdata **authdata_to_import);

Imports a set of authorization data with the given usage. Typically usage will be AD_USAGE_MASK, to indicate to all registered authorization data systems to import the authorization data. There is no way to convey the authorization data's authentication state using this function.

krb5_authdata_export_attributes()
krb5_error_code KRB5_CALLCONV
krb5_authdata_export_attributes(krb5_context kcontext,
                                krb5_authdata_context context,
                                krb5_flags usage,
                                krb5_authdata ***pauthdata);

Exports, or flattens, the authorization data context's systems' attributes into a set of Kerberos authorization data. The usage argument is used to determine which systems will be called, so that only the authorization data appropriate to the type of request being made is exported.

krb5_authdata_export_internal()
krb5_error_code KRB5_CALLCONV
krb5_authdata_export_internal(krb5_context kcontext,
                              krb5_authdata_context context,
                              krb5_boolean restrict_authenticated,
                              const char *module_name,
                              void **ptr);

Exports an internal representation of the authorization data state. This might, for example, be used to retrieve an operating system-specific representation of authorization information, such as a struct ucred.

krb5_authdata_free_internal()
krb5_error_code KRB5_CALLCONV
krb5_authdata_free_internal(krb5_context kcontext,
                            krb5_authdata_context context,
                            const char *module_name,
                            void *ptr);

Frees an internal representation exported by krb5_authdata_export_internal().

krb5_authdata_context_copy()
krb5_error_code KRB5_CALLCONV
krb5_authdata_context_copy(krb5_context kcontext,
                           krb5_authdata_context src,
                           krb5_authdata_context *pdst);

Duplicates an authorization data context. In the present implementation this involves reloading the authorization data plug-in list, which could be expensive, so this should be used sparingly.

krb5_auth_con_get_authdata_context()
krb5_error_code KRB5_CALLCONV
krb5_auth_con_get_authdata_context(krb5_context context,
                                   krb5_auth_context auth_context,
                                   krb5_authdata_context *ad_context);

Retrieves the authorization data context associated with an authentication context. This is a weak reference; if the caller wishes to retain a reference to this after the authentication context has been destroyed, it should make a copy or take ownership by calling krb5_auth_con_set_authdata_context(... NULL).

krb5_auth_con_set_authdata_context()
krb5_error_code KRB5_CALLCONV
krb5_auth_con_set_authdata_context(krb5_context context,
                                   krb5_auth_context auth_context,
                                   krb5_authdata_context ad_context);

Sets the authorization data context associated with an authentication context. The context will be freed by krb5_auth_con_free(), so if the caller wishes to retain ownership it should call krb5_auth_con_set_authdata_context(... NULL). This API usage is in line with the management of other pointer types associated with an authentication context.

encode_krb5_ad_kdcissued()

ASN.1 encoder for AD-KDCIssued.

decode_krb5_ad_kdcissued()

ASN.1 decoder for AD-KDCIssued.

krb5_free_ad_kdcissued()
void KRB5_CALLCONV
krb5_free_ad_kdcissued(krb5_context context, krb5_ad_kdcissued *val);

Free a krb5_ad_kdcissued structure; this structure is only used within libkrb5.

Non-exported, private APIs

krb5_error_code
krb5int_authdata_verify(krb5_context context,
                        krb5_authdata_context,
                        krb5_flags usage,
                        const krb5_auth_context *auth_context,
                        const krb5_keyblock *key,
                        const krb5_ap_req *ap_req);

Verifies and imports authorization data from an AP-REQ.

SPI

KDC

The only changes to the KDC are as follows:

  • Add a session_key argument to kdb_sign_auth_data_req, for database backends that wish to use AD-KDCIssued
  • In do_tgs_req(), ensure that the session key is made available to handle_authdata()
  • In handle_authdata(), give preference to plug-ins over internal systems
  • Rename krb5plugin_authdata_ftable_vX to krb5plugin_server_authdata_ftable_vX (typedefs to the old types are retained)

Example

greet_client

Note the "greet:greeting" attribute; rather than being issued by the KDC, this was set on the claimant credential's name using gss_set_name_attribute(), and conveyed in the AP-REQ. The acceptor retrieves it like any other attribute, but note it is not marked "Authenticated". (By changing the flags in the greet plug-in, it's also possible to have the data conveyed in the TGS-REQ, and thus the service ticket.)

% ./t_namingexts test.keytab
init module "greet", ad_type -42, flags 00000014
init module "mspac", ad_type 128, flags 00000008
Source name:	host/test.de.padl.com@DE.PADL.COM

Attribute mspac: Authenticated Complete 

050000000000000001000000b001000058000000000000000a00000034000000
...

Attribute mspac:logon-info Authenticated Complete 

01100800cccccccca001000000000000000002006ed28d68cd25ca01ffffffff
...

Attribute mspac:client-info Authenticated Complete 

802862d64026ca012a0068006f00730074002f00720061006e0064002e006400
...

Attribute mspac:upn-dns-info Authenticated Complete 

2a00100016004000000000000000000068006f00730074002f00720061006e00
...

Attribute mspac:server-checksum Authenticated Complete 

100000004b12be9500319e6fb731cb07

Attribute mspac:privsvr-checksum Authenticated Complete 

76ffffff812d7a725e999ca41dd6e51fdc64d501

Attribute greet:greeting  Complete 

48656c6c6f2c206163636570746f7220776f726c6421
Exported name:

0402000b06092a864886f71201020200000021686f73742f72616e642e64652e
...

greet_server

This plug-in is a simple demonstration of the generation and verification of positive (KDC issued) authorization data.

Open issues

  • Should we refactor the server side auth data plugin interface to more closely mirror this one?

Status

Code is in the users/lhoward/authdata branch.