aboutsummaryrefslogtreecommitdiffstats
path: root/src/include
diff options
context:
space:
mode:
authorCy Schubert <cy@FreeBSD.org>2017-07-07 17:03:42 +0000
committerCy Schubert <cy@FreeBSD.org>2017-07-07 17:03:42 +0000
commit33a9b234e7087f573ef08cd7318c6497ba08b439 (patch)
treed0ea40ad3bf5463a3c55795977c71bcb7d781b4b /src/include
downloadsrc-33a9b234e7087f573ef08cd7318c6497ba08b439.tar.gz
src-33a9b234e7087f573ef08cd7318c6497ba08b439.zip
Import MIT KRB5 1.15.1, which will gracefully replace KTH Heimdal.vendor/krb5/1.15.1
The tarball used in this import is the same tarball used in ports/krb5-115 r435378. Obtained from: http://web.mit.edu/kerberos/dist/ Thanks to: pfg (for all your tireless behind-the-scenes effort)
Notes
Notes: svn path=/vendor-crypto/krb5/dist/; revision=320790 svn path=/vendor-crypto/krb5/1.15.1/; revision=320791; tag=vendor/krb5/1.15.1
Diffstat (limited to 'src/include')
-rw-r--r--src/include/CredentialsCache.h1605
-rw-r--r--src/include/CredentialsCache2.h326
-rw-r--r--src/include/Makefile.in157
-rw-r--r--src/include/adm_proto.h92
-rw-r--r--src/include/autoconf.h.in770
-rw-r--r--src/include/copyright.h41
-rw-r--r--src/include/deps1
-rw-r--r--src/include/fake-addrinfo.h234
-rw-r--r--src/include/foreachaddr.h66
-rw-r--r--src/include/gssapi.h6
-rw-r--r--src/include/gssrpc/auth.h221
-rw-r--r--src/include/gssrpc/auth_gss.h148
-rw-r--r--src/include/gssrpc/auth_gssapi.h162
-rw-r--r--src/include/gssrpc/auth_unix.h82
-rw-r--r--src/include/gssrpc/clnt.h346
-rw-r--r--src/include/gssrpc/netdb.h58
-rw-r--r--src/include/gssrpc/pmap_clnt.h83
-rw-r--r--src/include/gssrpc/pmap_prot.h103
-rw-r--r--src/include/gssrpc/pmap_rmt.h65
-rw-r--r--src/include/gssrpc/rename.h311
-rw-r--r--src/include/gssrpc/rpc.h102
-rw-r--r--src/include/gssrpc/rpc_msg.h207
-rw-r--r--src/include/gssrpc/svc.h343
-rw-r--r--src/include/gssrpc/svc_auth.h119
-rw-r--r--src/include/gssrpc/types.hin137
-rw-r--r--src/include/gssrpc/xdr.h338
-rw-r--r--src/include/iprop.h275
-rw-r--r--src/include/iprop_hdr.h50
-rw-r--r--src/include/k5-base64.h52
-rw-r--r--src/include/k5-buf.h99
-rw-r--r--src/include/k5-err.h69
-rw-r--r--src/include/k5-gmt_mktime.h53
-rw-r--r--src/include/k5-input.h143
-rw-r--r--src/include/k5-int-pkinit.h283
-rw-r--r--src/include/k5-int.h2389
-rw-r--r--src/include/k5-ipc_stream.h77
-rw-r--r--src/include/k5-json.h218
-rw-r--r--src/include/k5-platform.h1102
-rw-r--r--src/include/k5-plugin.h121
-rw-r--r--src/include/k5-queue.h637
-rw-r--r--src/include/k5-thread.h427
-rw-r--r--src/include/k5-tls.h104
-rw-r--r--src/include/k5-trace.h457
-rw-r--r--src/include/k5-unicode.h130
-rw-r--r--src/include/k5-utf8.h223
-rw-r--r--src/include/k5-util.h88
-rw-r--r--src/include/kcm.h95
-rw-r--r--src/include/kdb.h1400
-rw-r--r--src/include/kdb_kt.h38
-rw-r--r--src/include/kdb_log.h114
-rw-r--r--src/include/krad.h265
-rw-r--r--src/include/krb5.h8
-rw-r--r--src/include/krb5/audit_plugin.h270
-rw-r--r--src/include/krb5/authdata_plugin.h216
-rw-r--r--src/include/krb5/ccselect_plugin.h105
-rw-r--r--src/include/krb5/clpreauth_plugin.h333
-rw-r--r--src/include/krb5/hostrealm_plugin.h135
-rw-r--r--src/include/krb5/kadm5_hook_plugin.h154
-rw-r--r--src/include/krb5/kdcauthdata_plugin.h129
-rw-r--r--src/include/krb5/kdcpreauth_plugin.h366
-rw-r--r--src/include/krb5/krb5.hin8470
-rw-r--r--src/include/krb5/localauth_plugin.h138
-rw-r--r--src/include/krb5/locate_plugin.h61
-rw-r--r--src/include/krb5/plugin.h46
-rw-r--r--src/include/krb5/preauth_plugin.h41
-rw-r--r--src/include/krb5/pwqual_plugin.h109
-rw-r--r--src/include/net-server.h102
-rw-r--r--src/include/osconf.hin130
-rw-r--r--src/include/port-sockets.h259
-rw-r--r--src/include/socket-utils.h135
-rw-r--r--src/include/win-mac.h250
71 files changed, 26489 insertions, 0 deletions
diff --git a/src/include/CredentialsCache.h b/src/include/CredentialsCache.h
new file mode 100644
index 000000000000..54f71a1a0280
--- /dev/null
+++ b/src/include/CredentialsCache.h
@@ -0,0 +1,1605 @@
+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/* include/CredentialsCache.h */
+/*
+ * Copyright 1998-2006 Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ * require a specific license from the United States Government.
+ * It is the responsibility of any person or organization contemplating
+ * export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission. Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose. It is provided "as is" without express
+ * or implied warranty.
+ */
+
+#ifndef __CREDENTIALSCACHE__
+#define __CREDENTIALSCACHE__
+
+#if defined(macintosh) || (defined(__MACH__) && defined(__APPLE__))
+#include <TargetConditionals.h>
+
+/* Notifications which are sent when the ccache collection or a ccache change.
+ * Notifications are sent to the distributed notification center.
+ * The object for kCCAPICacheCollectionChangedNotification is NULL.
+ * The object for kCCAPICCacheChangedNotification is a CFString containing the
+ * name of the ccache.
+ *
+ * Note: Notifications are not sent if the CCacheServer crashes. */
+#define kCCAPICacheCollectionChangedNotification CFSTR ("CCAPICacheCollectionChangedNotification")
+#define kCCAPICCacheChangedNotification CFSTR ("CCAPICCacheChangedNotification")
+#endif
+
+#if defined(_WIN32)
+#include <winsock.h>
+#include "win-mac.h"
+#else
+#include <stdint.h>
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+#if TARGET_OS_MAC
+#pragma pack(push,2)
+#endif
+
+#if defined(_WIN32)
+#define CCACHE_API __declspec(dllexport)
+
+#if _INTEGRAL_MAX_BITS >= 64 && _MSC_VER >= 1500 && !defined(_WIN64) && !defined(_USE_32BIT_TIME_T)
+#if defined(_TIME_T_DEFINED) || defined(_INC_IO) || defined(_INC_TIME) || defined(_INC_WCHAR)
+#error time_t has been defined as a 64-bit integer which is incompatible with Kerberos on this platform.
+#endif /* _TIME_T_DEFINED */
+#define _USE_32BIT_TIME_T
+#endif
+#else
+#define CCACHE_API
+#endif
+
+/*!
+ * \mainpage Credentials Cache API (CCAPI) Documentation
+ *
+ * \section toc Table of Contents
+ *
+ * \li \ref introduction
+ * \li \ref error_handling
+ * \li \ref synchronization_atomicity
+ * \li \ref memory_management
+ * \li \ref opaque_types
+ *
+ * \li \ref ccapi_constants_reference
+ * \li \ref ccapi_types_reference
+ *
+ * \li \ref cc_context_reference
+ * \li \ref cc_context_f "cc_context_t Functions"
+ *
+ * \li \ref cc_ccache_reference
+ * \li \ref cc_ccache_f "cc_ccache_t Functions"
+ *
+ * \li \ref cc_credentials_reference
+ * \li \ref cc_credentials_f "cc_credentials_t Functions"
+ *
+ * \li \ref cc_ccache_iterator_reference
+ * \li \ref cc_ccache_iterator_f "cc_ccache_iterator_t Functions"
+ *
+ * \li \ref cc_credentials_iterator_reference
+ * \li \ref cc_credentials_iterator_f "cc_credentials_iterator_t Functions"
+ *
+ * \li \ref cc_string_reference
+ * \li \ref cc_string_f "cc_string_t Functions"
+ *
+ * \section introduction Introduction
+ *
+ * This is the specification for an API which provides Credentials Cache
+ * services for both Kerberos v5 and v4. The idea behind this API is that
+ * multiple Kerberos implementations can share a single collection of
+ * credentials caches, mediated by this API specification. On the Mac OS
+ * and Microsoft Windows platforms this will allow single-login, even when
+ * more than one Kerberos shared library is in use on a particular system.
+ *
+ * Abstractly, a credentials cache collection contains one or more credentials
+ * caches, or ccaches. A ccache is uniquely identified by its name, which is
+ * a string internal to the API and not intended to be presented to users.
+ * The user presentable identifier of a ccache is its principal.
+ *
+ * Unlike the previous versions of the API, version 3 of the API stores both
+ * Kerberos v4 and v5 credentials in the same ccache.
+ *
+ * At any given time, one ccache is the "default" ccache. The exact meaning
+ * of a default ccache is OS-specific; refer to implementation requirements
+ * for details.
+ *
+ * \section error_handling Error Handling
+ *
+ * All functions of the API return some of the error constants listed FIXME;
+ * the exact list of error constants returned by any API function is provided
+ * in the function descriptions below.
+ *
+ * When returning an error constant other than ccNoError or ccIteratorEnd, API
+ * functions never modify any of the values passed in by reference.
+ *
+ * \section synchronization_atomicity Synchronization and Atomicity
+ *
+ * Every function in the API is atomic. In order to make a series of calls
+ * atomic, callers should lock the ccache or cache collection they are working
+ * with to advise other callers not to modify that container. Note that
+ * advisory locks are per container so even if you have a read lock on the cache
+ * collection other callers can obtain write locks on ccaches in that cache
+ * collection.
+ *
+ * Note that iterators do not iterate over ccaches and credentials atomically
+ * because locking ccaches and the cache collection over every iteration would
+ * degrade performance considerably under high load. However, iterators do
+ * guarantee a consistent view of items they are iterating over. Iterators
+ * will never return duplicate entries or skip entries when items are removed
+ * or added to the container they are iterating over.
+ *
+ * An application can always lock a ccache or the cache collection to guarantee
+ * that other callers participating in the advisory locking system do not
+ * modify the ccache or cache collection.
+ *
+ * Implementations should not use copy-on-write techniques to implement locks
+ * because those techniques imply that same parts of the ccache collection
+ * remain visible to some callers even though they are not present in the
+ * collection, which is a potential security risk. For example, a copy-on-write
+ * technique might make a copy of the entire collection when a read lock is
+ * acquired, so as to allow the owner of the lock to access the collection in
+ * an apparently unmodified state, while also allowing others to make
+ * modifications to the collection. However, this would also enable the owner
+ * of the lock to indefinitely (until the expiration time) use credentials that
+ * have actually been deleted from the collection.
+ *
+ * \section memory_management Object Memory Management
+ *
+ * The lifetime of an object returned by the API is until release() is called
+ * for it. Releasing one object has no effect on existence of any other object.
+ * For example, a ccache obtained within a context continue to exist when the
+ * context is released.
+ *
+ * Every object returned by the API (cc_context_t, cc_ccache_t, cc_ccache_iterator_t,
+ * cc_credentials_t, cc_credentials_iterator_t, cc_string_t) is owned by the
+ * caller of the API, and it is the responsibility of the caller to call release()
+ * for every object to prevent memory leaks.
+ *
+ * \section opaque_types Opaque Types
+ *
+ * All of the opaque high-level types in CCache API are implemented as structures
+ * of function pointers and private data. To perform some operation on a type, the
+ * caller of the API has to first obtain an instance of that type, and then call the
+ * appropriate function pointer from that instance. For example, to call
+ * get_change_time() on a cc_context_t, one would call cc_initialize() which creates
+ * a new cc_context_t and then call its get_change_time(), like this:
+ *
+ * \code
+ * cc_context_t context;
+ * cc_int32 err = cc_initialize (&context, ccapi_version_3, nil, nil);
+ * if (err == ccNoError)
+ * time = context->functions->get_change_time (context)
+ * \endcode
+ *
+ * All API functions also have convenience preprocessor macros, which make the API
+ * seem completely function-based. For example, cc_context_get_change_time
+ * (context, time) is equivalent to context->functions->get_change_time
+ * (context, time). The convenience macros follow the following naming convention:
+ *
+ * The API function some_function()
+ * \code
+ * cc_type_t an_object;
+ * result = an_object->functions->some_function (opaque_pointer, args)
+ * \endcode
+ *
+ * has an equivalent convenience macro of the form cc_type_some_function():
+ * \code
+ * cc_type_t an_object;
+ * result = cc_type_some_function (an_object, args)
+ * \endcode
+ *
+ * The specifications below include the names for both the functions and the
+ * convenience macros, in that order. For clarity, it is recommended that clients
+ * using the API use the convenience macros, but that is merely a stylistic choice.
+ *
+ * Implementing the API in this manner allows us to extend and change the interface
+ * in the future, while preserving compatibility with older clients.
+ *
+ * For example, consider the case when the signature or the semantics of a cc_ccache_t
+ * function is changed. The API version number is incremented. The library
+ * implementation contains both a function with the old signature and semantics and
+ * a function with the new signature and semantics. When a context is created, the API
+ * version number used in that context is stored in the context, and therefore it can
+ * be used whenever a ccache is created in that context. When a ccache is created in a
+ * context with the old API version number, the function pointer structure for the
+ * ccache is filled with pointers to functions implementing the old semantics; when a
+ * ccache is created in a context with the new API version number, the function pointer
+ * structure for the ccache is filled with poitners to functions implementing the new
+ * semantics.
+ *
+ * Similarly, if a function is added to the API, the version number in the context can
+ * be used to decide whether to include the implementation of the new function in the
+ * appropriate function pointer structure or not.
+ */
+
+/*!
+ * \defgroup ccapi_constants_reference Constants
+ * @{
+ */
+
+/*!
+ * API version numbers
+ *
+ * These constants are passed into cc_initialize() to indicate the version
+ * of the API the caller wants to use.
+ *
+ * CCAPI v1 and v2 are deprecated and should not be used.
+ */
+enum {
+ ccapi_version_2 = 2,
+ ccapi_version_3 = 3,
+ ccapi_version_4 = 4,
+ ccapi_version_5 = 5,
+ ccapi_version_6 = 6,
+ ccapi_version_7 = 7,
+ ccapi_version_max = ccapi_version_7
+};
+
+/*!
+ * Error codes
+ */
+enum {
+
+ ccNoError = 0, /*!< Success. */
+
+ ccIteratorEnd = 201, /*!< Iterator is done iterating. */
+ ccErrBadParam, /*!< Bad parameter (NULL or invalid pointer where valid pointer expected). */
+ ccErrNoMem, /*!< Not enough memory to complete the operation. */
+ ccErrInvalidContext, /*!< Context is invalid (e.g., it was released). */
+ ccErrInvalidCCache, /*!< CCache is invalid (e.g., it was released or destroyed). */
+
+ /* 206 */
+ ccErrInvalidString, /*!< String is invalid (e.g., it was released). */
+ ccErrInvalidCredentials, /*!< Credentials are invalid (e.g., they were released), or they have a bad version. */
+ ccErrInvalidCCacheIterator, /*!< CCache iterator is invalid (e.g., it was released). */
+ ccErrInvalidCredentialsIterator, /*!< Credentials iterator is invalid (e.g., it was released). */
+ ccErrInvalidLock, /*!< Lock is invalid (e.g., it was released). */
+
+ /* 211 */
+ ccErrBadName, /*!< Bad credential cache name format. */
+ ccErrBadCredentialsVersion, /*!< Credentials version is invalid. */
+ ccErrBadAPIVersion, /*!< Unsupported API version. */
+ ccErrContextLocked, /*!< Context is already locked. */
+ ccErrContextUnlocked, /*!< Context is not locked by the caller. */
+
+ /* 216 */
+ ccErrCCacheLocked, /*!< CCache is already locked. */
+ ccErrCCacheUnlocked, /*!< CCache is not locked by the caller. */
+ ccErrBadLockType, /*!< Bad lock type. */
+ ccErrNeverDefault, /*!< CCache was never default. */
+ ccErrCredentialsNotFound, /*!< Matching credentials not found in the ccache. */
+
+ /* 221 */
+ ccErrCCacheNotFound, /*!< Matching ccache not found in the collection. */
+ ccErrContextNotFound, /*!< Matching cache collection not found. */
+ ccErrServerUnavailable, /*!< CCacheServer is unavailable. */
+ ccErrServerInsecure, /*!< CCacheServer has detected that it is running as the wrong user. */
+ ccErrServerCantBecomeUID, /*!< CCacheServer failed to start running as the user. */
+
+ /* 226 */
+ ccErrTimeOffsetNotSet, /*!< KDC time offset not set for this ccache. */
+ ccErrBadInternalMessage, /*!< The client and CCacheServer can't communicate (e.g., a version mismatch). */
+ ccErrNotImplemented, /*!< API function not supported by this implementation. */
+ ccErrClientNotFound /*!< CCacheServer has no record of the caller's process (e.g., the server crashed). */
+};
+
+/*!
+ * Credentials versions
+ *
+ * These constants are used in several places in the API to discern
+ * between Kerberos v4 and Kerberos v5. Not all values are valid
+ * inputs and outputs for all functions; function specifications
+ * below detail the allowed values.
+ *
+ * Kerberos version constants will always be a bit-field, and can be
+ * tested as such; for example the following test will tell you if
+ * a ccacheVersion includes v5 credentials:
+ *
+ * if ((ccacheVersion & cc_credentials_v5) != 0)
+ */
+enum cc_credential_versions {
+ cc_credentials_v4 = 1,
+ cc_credentials_v5 = 2,
+ cc_credentials_v4_v5 = 3
+};
+
+/*!
+ * Lock types
+ *
+ * These constants are used in the locking functions to describe the
+ * type of lock requested. Note that all CCAPI locks are advisory
+ * so only callers using the lock calls will be blocked by each other.
+ * This is because locking functions were introduced after the CCAPI
+ * came into common use and we did not want to break existing callers.
+ */
+enum cc_lock_types {
+ cc_lock_read = 0,
+ cc_lock_write = 1,
+ cc_lock_upgrade = 2,
+ cc_lock_downgrade = 3
+};
+
+/*!
+ * Locking Modes
+ *
+ * These constants are used in the advisory locking functions to
+ * describe whether or not the lock function should block waiting for
+ * a lock or return an error immediately. For example, attempting to
+ * acquire a lock with a non-blocking call will result in an error if the
+ * lock cannot be acquired; otherwise, the call will block until the lock
+ * can be acquired.
+ */
+enum cc_lock_modes {
+ cc_lock_noblock = 0,
+ cc_lock_block = 1
+};
+
+/*!
+ * Sizes of fields in cc_credentials_v4_t.
+ */
+enum {
+ /* Make sure all of these are multiples of four (for alignment sanity) */
+ cc_v4_name_size = 40,
+ cc_v4_instance_size = 40,
+ cc_v4_realm_size = 40,
+ cc_v4_ticket_size = 1254,
+ cc_v4_key_size = 8
+};
+
+/*!
+ * String to key type (Kerberos v4 only)
+ */
+enum cc_string_to_key_type {
+ cc_v4_stk_afs = 0,
+ cc_v4_stk_des = 1,
+ cc_v4_stk_columbia_special = 2,
+ cc_v4_stk_krb5 = 3,
+ cc_v4_stk_unknown = 4
+};
+
+/*!@}*/
+
+/*!
+ * \defgroup ccapi_types_reference Basic Types
+ * @{
+ */
+
+/*! Unsigned 32-bit integer type */
+typedef uint32_t cc_uint32;
+/*! Signed 32-bit integer type */
+typedef int32_t cc_int32;
+#if defined (WIN32)
+typedef __int64 cc_int64;
+typedef unsigned __int64 cc_uint64;
+#else
+/*! Unsigned 64-bit integer type */
+typedef int64_t cc_int64;
+/*! Signed 64-bit integer type */
+typedef uint64_t cc_uint64;
+#endif
+/*!
+ * The cc_time_t type is used to represent a time in seconds. The time must
+ * be stored as the number of seconds since midnight GMT on January 1, 1970.
+ */
+typedef cc_uint32 cc_time_t;
+
+/*!@}*/
+
+/*!
+ * \defgroup cc_context_reference cc_context_t Overview
+ * @{
+ *
+ * The cc_context_t type gives the caller access to a ccache collection.
+ * Before being able to call any functions in the CCache API, the caller
+ * needs to acquire an instance of cc_context_t by calling cc_initialize().
+ *
+ * For API function documentation see \ref cc_context_f.
+ */
+struct cc_context_f;
+typedef struct cc_context_f cc_context_f;
+
+struct cc_context_d {
+ const cc_context_f *functions;
+#if TARGET_OS_MAC
+ const cc_context_f *vector_functions;
+#endif
+};
+typedef struct cc_context_d cc_context_d;
+typedef cc_context_d *cc_context_t;
+
+/*!@}*/
+
+/*!
+ * \defgroup cc_ccache_reference cc_ccache_t Overview
+ * @{
+ *
+ * The cc_ccache_t type represents a reference to a ccache.
+ * Callers can access a ccache and the credentials stored in it
+ * via a cc_ccache_t. A cc_ccache_t can be acquired via
+ * cc_context_open_ccache(), cc_context_open_default_ccache(), or
+ * cc_ccache_iterator_next().
+ *
+ * For API function documentation see \ref cc_ccache_f.
+ */
+struct cc_ccache_f;
+typedef struct cc_ccache_f cc_ccache_f;
+
+struct cc_ccache_d {
+ const cc_ccache_f *functions;
+#if TARGET_OS_MAC
+ const cc_ccache_f *vector_functions;
+#endif
+};
+typedef struct cc_ccache_d cc_ccache_d;
+typedef cc_ccache_d *cc_ccache_t;
+
+/*!@}*/
+
+/*!
+ * \defgroup cc_ccache_iterator_reference cc_ccache_iterator_t Overview
+ * @{
+ *
+ * The cc_ccache_iterator_t type represents an iterator that
+ * iterates over a set of ccaches and returns them in all in some
+ * order. A new instance of this type can be obtained by calling
+ * cc_context_new_ccache_iterator().
+ *
+ * For API function documentation see \ref cc_ccache_iterator_f.
+ */
+struct cc_ccache_iterator_f;
+typedef struct cc_ccache_iterator_f cc_ccache_iterator_f;
+
+struct cc_ccache_iterator_d {
+ const cc_ccache_iterator_f *functions;
+#if TARGET_OS_MAC
+ const cc_ccache_iterator_f *vector_functions;
+#endif
+};
+typedef struct cc_ccache_iterator_d cc_ccache_iterator_d;
+typedef cc_ccache_iterator_d *cc_ccache_iterator_t;
+/*!@}*/
+
+/*!
+ * \defgroup cc_credentials_reference cc_credentials_t Overview
+ * @{
+ *
+ * The cc_credentials_t type is used to store a single set of
+ * credentials for either Kerberos v4 or Kerberos v5. In addition
+ * to its only function, release(), it contains a pointer to a
+ * cc_credentials_union structure. A cc_credentials_union
+ * structure contains an integer of the enumerator type
+ * cc_credentials_version, which is either #cc_credentials_v4 or
+ * #cc_credentials_v5, and a pointer union, which contains either a
+ * cc_credentials_v4_t pointer or a cc_credentials_v5_t pointer,
+ * depending on the value in version.
+ *
+ * Variables of the type cc_credentials_t are allocated by the CCAPI
+ * implementation, and should be released with their release()
+ * function. API functions which receive credentials structures
+ * from the caller always accept cc_credentials_union, which is
+ * allocated by the caller, and accordingly disposed by the caller.
+ *
+ * For API functions see \ref cc_credentials_f.
+ */
+
+/*!
+ * If a cc_credentials_t variable is used to store Kerberos v4
+ * credentials, then credentials.credentials_v4 points to a v4
+ * credentials structure. This structure is similar to a
+ * krb4 API CREDENTIALS structure.
+ */
+struct cc_credentials_v4_t {
+ cc_uint32 version;
+ /*! A properly quoted string representation of the first component of the client principal */
+ char principal [cc_v4_name_size];
+ /*! A properly quoted string representation of the second component of the client principal */
+ char principal_instance [cc_v4_instance_size];
+ /*! A properly quoted string representation of the first component of the service principal */
+ char service [cc_v4_name_size];
+ /*! A properly quoted string representation of the second component of the service principal */
+ char service_instance [cc_v4_instance_size];
+ /*! A properly quoted string representation of the realm */
+ char realm [cc_v4_realm_size];
+ /*! Ticket session key */
+ unsigned char session_key [cc_v4_key_size];
+ /*! Key version number */
+ cc_int32 kvno;
+ /*! String to key type used. See cc_string_to_key_type for valid values */
+ cc_int32 string_to_key_type;
+ /*! Time when the ticket was issued */
+ cc_time_t issue_date;
+ /*! Ticket lifetime in 5 minute units */
+ cc_int32 lifetime;
+ /*! IPv4 address of the client the ticket was issued for */
+ cc_uint32 address;
+ /*! Ticket size (no greater than cc_v4_ticket_size) */
+ cc_int32 ticket_size;
+ /*! Ticket data */
+ unsigned char ticket [cc_v4_ticket_size];
+};
+typedef struct cc_credentials_v4_t cc_credentials_v4_t;
+
+/*!
+ * The CCAPI data structure. This structure is similar to a krb5_data structure.
+ * In a v5 credentials structure, cc_data structures are used
+ * to store tagged variable-length binary data. Specifically,
+ * for cc_credentials_v5.ticket and
+ * cc_credentials_v5.second_ticket, the cc_data.type field must
+ * be zero. For the cc_credentials_v5.addresses,
+ * cc_credentials_v5.authdata, and cc_credentials_v5.keyblock,
+ * the cc_data.type field should be the address type,
+ * authorization data type, and encryption type, as defined by
+ * the Kerberos v5 protocol definition.
+ */
+struct cc_data {
+ /*! The type of the data as defined by the krb5_data structure. */
+ cc_uint32 type;
+ /*! The length of \a data. */
+ cc_uint32 length;
+ /*! The data buffer. */
+ void* data;
+};
+typedef struct cc_data cc_data;
+
+/*!
+ * If a cc_credentials_t variable is used to store Kerberos v5 c
+ * redentials, and then credentials.credentials_v5 points to a
+ * v5 credentials structure. This structure is similar to a
+ * krb5_creds structure.
+ */
+struct cc_credentials_v5_t {
+ /*! A properly quoted string representation of the client principal. */
+ char* client;
+ /*! A properly quoted string representation of the service principal. */
+ char* server;
+ /*! Session encryption key info. */
+ cc_data keyblock;
+ /*! The time when the ticket was issued. */
+ cc_time_t authtime;
+ /*! The time when the ticket becomes valid. */
+ cc_time_t starttime;
+ /*! The time when the ticket expires. */
+ cc_time_t endtime;
+ /*! The time when the ticket becomes no longer renewable (if renewable). */
+ cc_time_t renew_till;
+ /*! 1 if the ticket is encrypted in another ticket's key, or 0 otherwise. */
+ cc_uint32 is_skey;
+ /*! Ticket flags, as defined by the Kerberos 5 API. */
+ cc_uint32 ticket_flags;
+ /*! The the list of network addresses of hosts that are allowed to authenticate
+ * using this ticket. */
+ cc_data** addresses;
+ /*! Ticket data. */
+ cc_data ticket;
+ /*! Second ticket data. */
+ cc_data second_ticket;
+ /*! Authorization data. */
+ cc_data** authdata;
+};
+typedef struct cc_credentials_v5_t cc_credentials_v5_t;
+
+struct cc_credentials_union {
+ /*! The credentials version of this credentials object. */
+ cc_uint32 version;
+ /*! The credentials. */
+ union {
+ /*! If \a version is #cc_credentials_v4, a pointer to a cc_credentials_v4_t. */
+ cc_credentials_v4_t* credentials_v4;
+ /*! If \a version is #cc_credentials_v5, a pointer to a cc_credentials_v5_t. */
+ cc_credentials_v5_t* credentials_v5;
+ } credentials;
+};
+typedef struct cc_credentials_union cc_credentials_union;
+
+struct cc_credentials_f;
+typedef struct cc_credentials_f cc_credentials_f;
+
+struct cc_credentials_d {
+ const cc_credentials_union *data;
+ const cc_credentials_f *functions;
+#if TARGET_OS_MAC
+ const cc_credentials_f *otherFunctions;
+#endif
+};
+typedef struct cc_credentials_d cc_credentials_d;
+typedef cc_credentials_d *cc_credentials_t;
+/*!@}*/
+
+/*!
+ * \defgroup cc_credentials_iterator_reference cc_credentials_iterator_t
+ * @{
+ * The cc_credentials_iterator_t type represents an iterator that
+ * iterates over a set of credentials. A new instance of this type
+ * can be obtained by calling cc_ccache_new_credentials_iterator().
+ *
+ * For API function documentation see \ref cc_credentials_iterator_f.
+ */
+struct cc_credentials_iterator_f;
+typedef struct cc_credentials_iterator_f cc_credentials_iterator_f;
+
+struct cc_credentials_iterator_d {
+ const cc_credentials_iterator_f *functions;
+#if TARGET_OS_MAC
+ const cc_credentials_iterator_f *vector_functions;
+#endif
+};
+typedef struct cc_credentials_iterator_d cc_credentials_iterator_d;
+typedef cc_credentials_iterator_d *cc_credentials_iterator_t;
+/*!@}*/
+
+/*!
+ * \defgroup cc_string_reference cc_string_t Overview
+ * @{
+ * The cc_string_t represents a C string returned by the API.
+ * It has a pointer to the string data and a release() function.
+ * This type is used for both principal names and ccache names
+ * returned by the API. Principal names may contain UTF-8 encoded
+ * strings for internationalization purposes.
+ *
+ * For API function documentation see \ref cc_string_f.
+ */
+struct cc_string_f;
+typedef struct cc_string_f cc_string_f;
+
+struct cc_string_d {
+ const char *data;
+ const cc_string_f *functions;
+#if TARGET_OS_MAC
+ const cc_string_f *vector_functions;
+#endif
+};
+typedef struct cc_string_d cc_string_d;
+typedef cc_string_d *cc_string_t;
+/*!@}*/
+
+/*!
+ * Function pointer table for cc_context_t. For more information see
+ * \ref cc_context_reference.
+ */
+struct cc_context_f {
+ /*!
+ * \param io_context the context object to free.
+ * \return On success, #ccNoError. On failure, an error code representing the failure.
+ * \brief \b cc_context_release(): Release memory associated with a cc_context_t.
+ */
+ cc_int32 (*release) (cc_context_t io_context);
+
+ /*!
+ * \param in_context the context object for the cache collection to examine.
+ * \param out_time on exit, the time of the most recent change for the entire ccache collection.
+ * \return On success, #ccNoError. On failure, an error code representing the failure.
+ * \brief \b cc_context_get_change_time(): Get the last time the cache collection changed.
+ *
+ * This function returns the time of the most recent change for the entire ccache collection.
+ * By maintaining a local copy the caller can deduce whether or not the ccache collection has
+ * been modified since the previous call to cc_context_get_change_time().
+ *
+ * The time returned by cc_context_get_changed_time() increases whenever:
+ *
+ * \li a ccache is created
+ * \li a ccache is destroyed
+ * \li a credential is stored
+ * \li a credential is removed
+ * \li a ccache principal is changed
+ * \li the default ccache is changed
+ *
+ * \note In order to be able to compare two values returned by cc_context_get_change_time(),
+ * the caller must use the same context to acquire them. Callers should maintain a single
+ * context in memory for cc_context_get_change_time() calls rather than creating a new
+ * context for every call.
+ *
+ * \sa wait_for_change
+ */
+ cc_int32 (*get_change_time) (cc_context_t in_context,
+ cc_time_t *out_time);
+
+ /*!
+ * \param in_context the context object for the cache collection.
+ * \param out_name on exit, the name of the default ccache.
+ * \return On success, #ccNoError. On failure, an error code representing the failure.
+ * \brief \b cc_context_get_default_ccache_name(): Get the name of the default ccache.
+ *
+ * This function returns the name of the default ccache. When the default ccache
+ * exists, its name is returned. If there are no ccaches in the collection, and
+ * thus there is no default ccache, the name that the default ccache should have
+ * is returned. The ccache with that name will be used as the default ccache by
+ * all processes which initialized Kerberos libraries before the ccache was created.
+ *
+ * If there is no default ccache, and the client is creating a new ccache, it
+ * should be created with the default name. If there already is a default ccache,
+ * and the client wants to create a new ccache (as opposed to reusing an existing
+ * ccache), it should be created with any unique name; #create_new_ccache()
+ * can be used to accomplish that more easily.
+ *
+ * If the first ccache is created with a name other than the default name, then
+ * the processes already running will not notice the credentials stored in the
+ * new ccache, which is normally undesirable.
+ */
+ cc_int32 (*get_default_ccache_name) (cc_context_t in_context,
+ cc_string_t *out_name);
+
+ /*!
+ * \param in_context the context object for the cache collection.
+ * \param in_name the name of the ccache to open.
+ * \param out_ccache on exit, a ccache object for the ccache
+ * \return On success, #ccNoError. If no ccache named \a in_name exists,
+ * #ccErrCCacheNotFound. On failure, an error code representing the failure.
+ * \brief \b cc_context_open_ccache(): Open a ccache.
+ *
+ * Opens an already existing ccache identified by its name. It returns a reference
+ * to the ccache in \a out_ccache.
+ *
+ * The list of all ccache names, principals, and credentials versions may be retrieved
+ * by calling cc_context_new_cache_iterator(), cc_ccache_get_name(),
+ * cc_ccache_get_principal(), and cc_ccache_get_cred_version().
+ */
+ cc_int32 (*open_ccache) (cc_context_t in_context,
+ const char *in_name,
+ cc_ccache_t *out_ccache);
+
+ /*!
+ * \param in_context the context object for the cache collection.
+ * \param out_ccache on exit, a ccache object for the default ccache
+ * \return On success, #ccNoError. If no default ccache exists,
+ * #ccErrCCacheNotFound. On failure, an error code representing the failure.
+ * \brief \b cc_context_open_default_ccache(): Open the default ccache.
+ *
+ * Opens the default ccache. It returns a reference to the ccache in *ccache.
+ *
+ * This function performs the same function as calling
+ * cc_context_get_default_ccache_name followed by cc_context_open_ccache,
+ * but it performs it atomically.
+ */
+ cc_int32 (*open_default_ccache) (cc_context_t in_context,
+ cc_ccache_t *out_ccache);
+
+ /*!
+ * \param in_context the context object for the cache collection.
+ * \param in_name the name of the new ccache to create
+ * \param in_cred_vers the version of the credentials the new ccache will hold
+ * \param in_principal the client principal of the credentials the new ccache will hold
+ * \param out_ccache on exit, a ccache object for the newly created ccache
+ * \return On success, #ccNoError. On failure, an error code representing the failure.
+ * \brief \b cc_context_create_ccache(): Create a new ccache.
+ *
+ * Create a new credentials cache. The ccache is uniquely identified by its name.
+ * The principal given is also associated with the ccache and the credentials
+ * version specified. A NULL name is not allowed (and ccErrBadName is returned
+ * if one is passed in). Only cc_credentials_v4 and cc_credentials_v5 are valid
+ * input values for cred_vers. If you want to create a new ccache that will hold
+ * both versions of credentials, call cc_context_create_ccache() with one version,
+ * and then cc_ccache_set_principal() with the other version.
+ *
+ * If you want to create a new ccache (with a unique name), you should use
+ * cc_context_create_new_ccache() instead. If you want to create or reinitialize
+ * the default cache, you should use cc_context_create_default_ccache().
+ *
+ * If name is non-NULL and there is already a ccache named name:
+ *
+ * \li the credentials in the ccache whose version is cred_vers are removed
+ * \li the principal (of the existing ccache) associated with cred_vers is set to principal
+ * \li a handle for the existing ccache is returned and all existing handles for the ccache remain valid
+ *
+ * If no ccache named name already exists:
+ *
+ * \li a new empty ccache is created
+ * \li the principal of the new ccache associated with cred_vers is set to principal
+ * \li a handle for the new ccache is returned
+ *
+ * For a new ccache, the name should be any unique string. The name is not
+ * intended to be presented to users.
+ *
+ * If the created ccache is the first ccache in the collection, it is made
+ * the default ccache. Note that normally it is undesirable to create the first
+ * ccache with a name different from the default ccache name (as returned by
+ * cc_context_get_default_ccache_name()); see the description of
+ * cc_context_get_default_ccache_name() for details.
+ *
+ * The principal should be a C string containing an unparsed Kerberos principal
+ * in the format of the appropriate Kerberos version, i.e. \verbatim foo.bar/@BAZ
+ * \endverbatim for Kerberos v4 and \verbatim foo/bar/@BAZ \endverbatim
+ * for Kerberos v5.
+ */
+ cc_int32 (*create_ccache) (cc_context_t in_context,
+ const char *in_name,
+ cc_uint32 in_cred_vers,
+ const char *in_principal,
+ cc_ccache_t *out_ccache);
+
+ /*!
+ * \param in_context the context object for the cache collection.
+ * \param in_cred_vers the version of the credentials the new default ccache will hold
+ * \param in_principal the client principal of the credentials the new default ccache will hold
+ * \param out_ccache on exit, a ccache object for the newly created default ccache
+ * \return On success, #ccNoError. On failure, an error code representing the failure.
+ * \brief \b cc_context_create_default_ccache(): Create a new default ccache.
+ *
+ * Create the default credentials cache. The behavior of this function is
+ * similar to that of cc_create_ccache(). If there is a default ccache
+ * (which is always the case except when there are no ccaches at all in
+ * the collection), it is initialized with the specified credentials version
+ * and principal, as per cc_create_ccache(); otherwise, a new ccache is
+ * created, and its name is the name returned by
+ * cc_context_get_default_ccache_name().
+ */
+ cc_int32 (*create_default_ccache) (cc_context_t in_context,
+ cc_uint32 in_cred_vers,
+ const char *in_principal,
+ cc_ccache_t *out_ccache);
+
+ /*!
+ * \param in_context the context object for the cache collection.
+ * \param in_cred_vers the version of the credentials the new ccache will hold
+ * \param in_principal the client principal of the credentials the new ccache will hold
+ * \param out_ccache on exit, a ccache object for the newly created ccache
+ * \return On success, #ccNoError. On failure, an error code representing the failure.
+ * \brief \b cc_context_create_new_ccache(): Create a new uniquely named ccache.
+ *
+ * Create a new unique credentials cache. The behavior of this function
+ * is similar to that of cc_create_ccache(). If there are no ccaches, and
+ * therefore no default ccache, the new ccache is created with the default
+ * ccache name as would be returned by get_default_ccache_name(). If there
+ * are some ccaches, and therefore there is a default ccache, the new ccache
+ * is created with a new unique name. Clearly, this function never reinitializes
+ * a ccache, since it always uses a unique name.
+ */
+ cc_int32 (*create_new_ccache) (cc_context_t in_context,
+ cc_uint32 in_cred_vers,
+ const char *in_principal,
+ cc_ccache_t *out_ccache);
+
+ /*!
+ * \param in_context the context object for the cache collection.
+ * \param out_iterator on exit, a ccache iterator object for the ccache collection.
+ * \return On success, #ccNoError. On failure, an error code representing the failure.
+ * \brief \b cc_context_new_ccache_iterator(): Get an iterator for the cache collection.
+ *
+ * Used to allocate memory and initialize iterator. Successive calls to iterator's
+ * next() function will return ccaches in the collection.
+ *
+ * If changes are made to the collection while an iterator is being used
+ * on it, the iterator must return at least the intersection, and at most
+ * the union, of the set of ccaches that were present when the iteration
+ * began and the set of ccaches that are present when it ends.
+ */
+ cc_int32 (*new_ccache_iterator) (cc_context_t in_context,
+ cc_ccache_iterator_t *out_iterator);
+
+ /*!
+ * \param in_context the context object for the cache collection.
+ * \param in_lock_type the type of lock to obtain.
+ * \param in_block whether or not the function should block if the lock cannot be obtained immediately.
+ * \return On success, #ccNoError. On failure, an error code representing the failure.
+ * \brief \b cc_context_lock(): Lock the cache collection.
+ *
+ * Attempts to acquire an advisory lock for the ccache collection. Allowed values
+ * for lock_type are:
+ *
+ * \li cc_lock_read: a read lock.
+ * \li cc_lock_write: a write lock
+ * \li cc_lock_upgrade: upgrade an already-obtained read lock to a write lock
+ * \li cc_lock_downgrade: downgrade an already-obtained write lock to a read lock
+ *
+ * If block is cc_lock_block, lock() will not return until the lock is acquired.
+ * If block is cc_lock_noblock, lock() will return immediately, either acquiring
+ * the lock and returning ccNoError, or failing to acquire the lock and returning
+ * an error explaining why.
+ *
+ * Locks apply only to the list of ccaches, not the contents of those ccaches. To
+ * prevent callers participating in the advisory locking from changing the credentials
+ * in a cache you must also lock that ccache with cc_ccache_lock(). This is so
+ * that you can get the list of ccaches without preventing applications from
+ * simultaneously obtaining service tickets.
+ *
+ * To avoid having to deal with differences between thread semantics on different
+ * platforms, locks are granted per context, rather than per thread or per process.
+ * That means that different threads of execution have to acquire separate contexts
+ * in order to be able to synchronize with each other.
+ *
+ * The lock should be unlocked by using cc_context_unlock().
+ *
+ * \note All locks are advisory. For example, callers which do not call
+ * cc_context_lock() and cc_context_unlock() will not be prevented from writing
+ * to the cache collection when you have a read lock. This is because the CCAPI
+ * locking was added after the first release and thus adding mandatory locks would
+ * have changed the user experience and performance of existing applications.
+ */
+ cc_int32 (*lock) (cc_context_t in_context,
+ cc_uint32 in_lock_type,
+ cc_uint32 in_block);
+
+ /*!
+ * \param in_context the context object for the cache collection.
+ * \return On success, #ccNoError. On failure, an error code representing the failure.
+ * \brief \b cc_context_unlock(): Unlock the cache collection.
+ */
+ cc_int32 (*unlock) (cc_context_t in_cc_context);
+
+ /*!
+ * \param in_context a context object.
+ * \param in_compare_to_context a context object to compare with \a in_context.
+ * \param out_equal on exit, whether or not the two contexts refer to the same cache collection.
+ * \return On success, #ccNoError. On failure, an error code representing the failure.
+ * \brief \b cc_context_compare(): Compare two context objects.
+ */
+ cc_int32 (*compare) (cc_context_t in_cc_context,
+ cc_context_t in_compare_to_context,
+ cc_uint32 *out_equal);
+
+ /*!
+ * \param in_context a context object.
+ * \return On success, #ccNoError. On failure, an error code representing the failure.
+ * \brief \b cc_context_wait_for_change(): Wait for the next change in the cache collection.
+ *
+ * This function blocks until the next change is made to the cache collection
+ * ccache collection. By repeatedly calling cc_context_wait_for_change() from
+ * a worker thread the caller can effectively receive callbacks whenever the
+ * cache collection changes. This is considerably more efficient than polling
+ * with cc_context_get_change_time().
+ *
+ * cc_context_wait_for_change() will return whenever:
+ *
+ * \li a ccache is created
+ * \li a ccache is destroyed
+ * \li a credential is stored
+ * \li a credential is removed
+ * \li a ccache principal is changed
+ * \li the default ccache is changed
+ *
+ * \note In order to make sure that the caller doesn't miss any changes,
+ * cc_context_wait_for_change() always returns immediately after the first time it
+ * is called on a new context object. Callers must use the same context object
+ * for successive calls to cc_context_wait_for_change() rather than creating a new
+ * context for every call.
+ *
+ * \sa get_change_time
+ */
+ cc_int32 (*wait_for_change) (cc_context_t in_cc_context);
+};
+
+/*!
+ * Function pointer table for cc_ccache_t. For more information see
+ * \ref cc_ccache_reference.
+ */
+struct cc_ccache_f {
+ /*!
+ * \param io_ccache the ccache object to release.
+ * \return On success, #ccNoError. On failure, an error code representing the failure.
+ * \brief \b cc_ccache_release(): Release memory associated with a cc_ccache_t object.
+ * \note Does not modify the ccache. If you wish to remove the ccache see cc_ccache_destroy().
+ */
+ cc_int32 (*release) (cc_ccache_t io_ccache);
+
+ /*!
+ * \param io_ccache the ccache object to destroy and release.
+ * \return On success, #ccNoError. On failure, an error code representing the failure.
+ * \brief \b cc_ccache_destroy(): Destroy a ccache.
+ *
+ * Destroy the ccache referred to by \a io_ccache and releases memory associated with
+ * the \a io_ccache object. After this call \a io_ccache becomes invalid. If
+ * \a io_ccache was the default ccache, the next ccache in the cache collection (if any)
+ * becomes the new default.
+ */
+ cc_int32 (*destroy) (cc_ccache_t io_ccache);
+
+ /*!
+ * \param io_ccache a ccache object to make the new default ccache.
+ * \return On success, #ccNoError. On failure, an error code representing the failure.
+ * \brief \b cc_ccache_set_default(): Make a ccache the default ccache.
+ */
+ cc_int32 (*set_default) (cc_ccache_t io_ccache);
+
+ /*!
+ * \param in_ccache a ccache object.
+ * \param out_credentials_version on exit, the credentials version of \a in_ccache.
+ * \return On success, #ccNoError. On failure, an error code representing the failure.
+ * \brief \b cc_ccache_get_credentials_version(): Get the credentials version of a ccache.
+ *
+ * cc_ccache_get_credentials_version() returns one value of the enumerated type
+ * cc_credentials_vers. The possible return values are #cc_credentials_v4
+ * (if ccache's v4 principal has been set), #cc_credentials_v5
+ * (if ccache's v5 principal has been set), or #cc_credentials_v4_v5
+ * (if both ccache's v4 and v5 principals have been set). A ccache's
+ * principal is set with one of cc_context_create_ccache(),
+ * cc_context_create_new_ccache(), cc_context_create_default_ccache(), or
+ * cc_ccache_set_principal().
+ */
+ cc_int32 (*get_credentials_version) (cc_ccache_t in_ccache,
+ cc_uint32 *out_credentials_version);
+
+ /*!
+ * \param in_ccache a ccache object.
+ * \param out_name on exit, a cc_string_t representing the name of \a in_ccache.
+ * \a out_name must be released with cc_string_release().
+ * \return On success, #ccNoError. On failure, an error code representing the failure.
+ * \brief \b cc_ccache_get_name(): Get the name of a ccache.
+ */
+ cc_int32 (*get_name) (cc_ccache_t in_ccache,
+ cc_string_t *out_name);
+
+ /*!
+ * \param in_ccache a ccache object.
+ * \param in_credentials_version the credentials version to get the principal for.
+ * \param out_principal on exit, a cc_string_t representing the principal of \a in_ccache.
+ * \a out_principal must be released with cc_string_release().
+ * \return On success, #ccNoError. On failure, an error code representing the failure.
+ * \brief \b cc_ccache_get_principal(): Get the principal of a ccache.
+ *
+ * Return the principal for the ccache that was set via cc_context_create_ccache(),
+ * cc_context_create_default_ccache(), cc_context_create_new_ccache(), or
+ * cc_ccache_set_principal(). Principals for v4 and v5 are separate, but
+ * should be kept synchronized for each ccache; they can be retrieved by
+ * passing cc_credentials_v4 or cc_credentials_v5 in cred_vers. Passing
+ * cc_credentials_v4_v5 will result in the error ccErrBadCredentialsVersion.
+ */
+ cc_int32 (*get_principal) (cc_ccache_t in_ccache,
+ cc_uint32 in_credentials_version,
+ cc_string_t *out_principal);
+
+
+ /*!
+ * \param in_ccache a ccache object.
+ * \param in_credentials_version the credentials version to set the principal for.
+ * \param in_principal a C string representing the new principal of \a in_ccache.
+ * \return On success, #ccNoError. On failure, an error code representing the failure.
+ * \brief \b cc_ccache_set_principal(): Set the principal of a ccache.
+ *
+ * Set the a principal for ccache. The v4 and v5 principals can be set
+ * independently, but they should always be kept equal, up to differences in
+ * string representation between v4 and v5. Passing cc_credentials_v4_v5 in
+ * cred_vers will result in the error ccErrBadCredentialsVersion.
+ */
+ cc_int32 (*set_principal) (cc_ccache_t io_ccache,
+ cc_uint32 in_credentials_version,
+ const char *in_principal);
+
+ /*!
+ * \param io_ccache a ccache object.
+ * \param in_credentials_union the credentials to store in \a io_ccache.
+ * \return On success, #ccNoError. On failure, an error code representing the failure.
+ * \brief \b cc_ccache_store_credentials(): Store credentials in a ccache.
+ *
+ * Store a copy of credentials in the ccache.
+ *
+ * See the description of the credentials types for the meaning of
+ * cc_credentials_union fields.
+ *
+ * Before credentials of a specific credential type can be stored in a ccache,
+ * the corresponding principal version has to be set. For example, before you can
+ * store Kerberos v4 credentials in a ccache, the Kerberos v4 principal has to be set
+ * either by cc_context_create_ccache(), cc_context_create_default_ccache(),
+ * cc_context_create_new_ccache(), or cc_ccache_set_principal(); likewise for
+ * Kerberos v5. Otherwise, ccErrBadCredentialsVersion is returned.
+ */
+ cc_int32 (*store_credentials) (cc_ccache_t io_ccache,
+ const cc_credentials_union *in_credentials_union);
+
+ /*!
+ * \param io_ccache a ccache object.
+ * \param in_credentials the credentials to remove from \a io_ccache.
+ * \return On success, #ccNoError. On failure, an error code representing the failure.
+ * \brief \b cc_ccache_remove_credentials(): Remove credentials from a ccache.
+ *
+ * Removes credentials from a ccache. Note that credentials must be previously
+ * acquired from the CCache API; only exactly matching credentials will be
+ * removed. (This places the burden of determining exactly which credentials
+ * to remove on the caller, but ensures there is no ambigity about which
+ * credentials will be removed.) cc_credentials_t objects can be obtained by
+ * iterating over the ccache's credentials with cc_ccache_new_credentials_iterator().
+ *
+ * If found, the credentials are removed from the ccache. The credentials
+ * parameter is not modified and should be freed by the caller. It is
+ * legitimate to call this function while an iterator is traversing the
+ * ccache, and the deletion of a credential already returned by
+ * cc_credentials_iterator_next() will not disturb sequence of credentials
+ * returned by cc_credentials_iterator_next().
+ */
+ cc_int32 (*remove_credentials) (cc_ccache_t io_ccache,
+ cc_credentials_t in_credentials);
+
+ /*!
+ * \param in_ccache a ccache object.
+ * \param out_credentials_iterator a credentials iterator for \a io_ccache.
+ * \return On success, #ccNoError. On failure, an error code representing the failure.
+ * \brief \b cc_ccache_new_credentials_iterator(): Iterate over credentials in a ccache.
+ *
+ * Allocates memory for iterator and initializes it. Successive calls to
+ * cc_credentials_iterator_next() will return credentials from the ccache.
+ *
+ * If changes are made to the ccache while an iterator is being used on it,
+ * the iterator must return at least the intersection, and at most the union,
+ * of the set of credentials that were in the ccache when the iteration began
+ * and the set of credentials that are in the ccache when it ends.
+ */
+ cc_int32 (*new_credentials_iterator) (cc_ccache_t in_ccache,
+ cc_credentials_iterator_t *out_credentials_iterator);
+
+ /*!
+ * \param io_source_ccache a ccache object to move.
+ * \param io_destination_ccache a ccache object replace with the contents of \a io_source_ccache.
+ * \return On success, #ccNoError. On failure, an error code representing the failure.
+ * \brief \b cc_ccache_move(): Move the contents of one ccache into another, destroying the source.
+ *
+ * cc_ccache_move() atomically copies the credentials, credential versions and principals
+ * from one ccache to another. On successful completion \a io_source_ccache will be
+ * released and the ccache it points to will be destroyed. Any credentials previously
+ * in \a io_destination_ccache will be replaced with credentials from \a io_source_ccache.
+ * The only part of \a io_destination_ccache which remains constant is the name. Any other
+ * callers referring to \a io_destination_ccache will suddenly see new data in it.
+ *
+ * Typically cc_ccache_move() is used when the caller wishes to safely overwrite the
+ * contents of a ccache with new data which requires several steps to generate.
+ * cc_ccache_move() allows the caller to create a temporary ccache
+ * (which can be destroyed if any intermediate step fails) and the atomically copy
+ * the temporary cache into the destination.
+ */
+ cc_int32 (*move) (cc_ccache_t io_source_ccache,
+ cc_ccache_t io_destination_ccache);
+
+ /*!
+ * \param io_ccache the ccache object for the ccache you wish to lock.
+ * \param in_lock_type the type of lock to obtain.
+ * \param in_block whether or not the function should block if the lock cannot be obtained immediately.
+ * \return On success, #ccNoError. On failure, an error code representing the failure.
+ * \brief \b cc_ccache_lock(): Lock a ccache.
+ *
+ * Attempts to acquire an advisory lock for a ccache. Allowed values for lock_type are:
+ *
+ * \li cc_lock_read: a read lock.
+ * \li cc_lock_write: a write lock
+ * \li cc_lock_upgrade: upgrade an already-obtained read lock to a write lock
+ * \li cc_lock_downgrade: downgrade an already-obtained write lock to a read lock
+ *
+ * If block is cc_lock_block, lock() will not return until the lock is acquired.
+ * If block is cc_lock_noblock, lock() will return immediately, either acquiring
+ * the lock and returning ccNoError, or failing to acquire the lock and returning
+ * an error explaining why.
+ *
+ * To avoid having to deal with differences between thread semantics on different
+ * platforms, locks are granted per ccache, rather than per thread or per process.
+ * That means that different threads of execution have to acquire separate contexts
+ * in order to be able to synchronize with each other.
+ *
+ * The lock should be unlocked by using cc_ccache_unlock().
+ *
+ * \note All locks are advisory. For example, callers which do not call
+ * cc_ccache_lock() and cc_ccache_unlock() will not be prevented from writing
+ * to the ccache when you have a read lock. This is because the CCAPI
+ * locking was added after the first release and thus adding mandatory locks would
+ * have changed the user experience and performance of existing applications.
+ */
+ cc_int32 (*lock) (cc_ccache_t io_ccache,
+ cc_uint32 in_lock_type,
+ cc_uint32 in_block);
+
+ /*!
+ * \param io_ccache a ccache object.
+ * \return On success, #ccNoError. On failure, an error code representing the failure.
+ * \brief \b cc_ccache_unlock(): Unlock a ccache.
+ */
+ cc_int32 (*unlock) (cc_ccache_t io_ccache);
+
+ /*!
+ * \param in_ccache a cache object.
+ * \param out_last_default_time on exit, the last time the ccache was default.
+ * \return On success, #ccNoError. On failure, an error code representing the failure.
+ * \brief \b cc_ccache_get_change_time(): Get the last time a ccache was the default ccache.
+ *
+ * This function returns the last time when the ccache was made the default ccache.
+ * This allows clients to sort the ccaches by how recently they were default, which
+ * is useful for user listing of ccaches. If the ccache was never default,
+ * ccErrNeverDefault is returned.
+ */
+ cc_int32 (*get_last_default_time) (cc_ccache_t in_ccache,
+ cc_time_t *out_last_default_time);
+
+ /*!
+ * \param in_ccache a cache object.
+ * \param out_change_time on exit, the last time the ccache changed.
+ * \return On success, #ccNoError. If the ccache was never the default ccache,
+ * #ccErrNeverDefault. Otherwise, an error code representing the failure.
+ * \brief \b cc_ccache_get_change_time(): Get the last time a ccache changed.
+ *
+ * This function returns the time of the most recent change made to a ccache.
+ * By maintaining a local copy the caller can deduce whether or not the ccache has
+ * been modified since the previous call to cc_ccache_get_change_time().
+ *
+ * The time returned by cc_ccache_get_change_time() increases whenever:
+ *
+ * \li a credential is stored
+ * \li a credential is removed
+ * \li a ccache principal is changed
+ * \li the ccache becomes the default ccache
+ * \li the ccache is no longer the default ccache
+ *
+ * \note In order to be able to compare two values returned by cc_ccache_get_change_time(),
+ * the caller must use the same ccache object to acquire them. Callers should maintain a
+ * single ccache object in memory for cc_ccache_get_change_time() calls rather than
+ * creating a new ccache object for every call.
+ *
+ * \sa wait_for_change
+ */
+ cc_int32 (*get_change_time) (cc_ccache_t in_ccache,
+ cc_time_t *out_change_time);
+
+ /*!
+ * \param in_ccache a ccache object.
+ * \param in_compare_to_ccache a ccache object to compare with \a in_ccache.
+ * \param out_equal on exit, whether or not the two ccaches refer to the same ccache.
+ * \return On success, #ccNoError. On failure, an error code representing the failure.
+ * \brief \b cc_ccache_compare(): Compare two ccache objects.
+ */
+ cc_int32 (*compare) (cc_ccache_t in_ccache,
+ cc_ccache_t in_compare_to_ccache,
+ cc_uint32 *out_equal);
+
+ /*!
+ * \param in_ccache a ccache object.
+ * \param in_credentials_version the credentials version to get the time offset for.
+ * \param out_time_offset on exit, the KDC time offset for \a in_ccache for credentials version
+ * \a in_credentials_version.
+ * \return On success, #ccNoError if a time offset was obtained or #ccErrTimeOffsetNotSet
+ * if a time offset has not been set. On failure, an error code representing the failure.
+ * \brief \b cc_ccache_get_kdc_time_offset(): Get the KDC time offset for credentials in a ccache.
+ * \sa set_kdc_time_offset, clear_kdc_time_offset
+ *
+ * Sometimes the KDC and client's clocks get out of sync. cc_ccache_get_kdc_time_offset()
+ * returns the difference between the KDC and client's clocks at the time credentials were
+ * acquired. This offset allows callers to figure out how much time is left on a given
+ * credential even though the end_time is based on the KDC's clock not the client's clock.
+ */
+ cc_int32 (*get_kdc_time_offset) (cc_ccache_t in_ccache,
+ cc_uint32 in_credentials_version,
+ cc_time_t *out_time_offset);
+
+ /*!
+ * \param in_ccache a ccache object.
+ * \param in_credentials_version the credentials version to get the time offset for.
+ * \param in_time_offset the new KDC time offset for \a in_ccache for credentials version
+ * \a in_credentials_version.
+ * \return On success, #ccNoError. On failure, an error code representing the failure.
+ * \brief \b cc_ccache_set_kdc_time_offset(): Set the KDC time offset for credentials in a ccache.
+ * \sa get_kdc_time_offset, clear_kdc_time_offset
+ *
+ * Sometimes the KDC and client's clocks get out of sync. cc_ccache_set_kdc_time_offset()
+ * sets the difference between the KDC and client's clocks at the time credentials were
+ * acquired. This offset allows callers to figure out how much time is left on a given
+ * credential even though the end_time is based on the KDC's clock not the client's clock.
+ */
+ cc_int32 (*set_kdc_time_offset) (cc_ccache_t io_ccache,
+ cc_uint32 in_credentials_version,
+ cc_time_t in_time_offset);
+
+ /*!
+ * \param in_ccache a ccache object.
+ * \param in_credentials_version the credentials version to get the time offset for.
+ * \return On success, #ccNoError. On failure, an error code representing the failure.
+ * \brief \b cc_ccache_clear_kdc_time_offset(): Clear the KDC time offset for credentials in a ccache.
+ * \sa get_kdc_time_offset, set_kdc_time_offset
+ *
+ * Sometimes the KDC and client's clocks get out of sync. cc_ccache_clear_kdc_time_offset()
+ * clears the difference between the KDC and client's clocks at the time credentials were
+ * acquired. This offset allows callers to figure out how much time is left on a given
+ * credential even though the end_time is based on the KDC's clock not the client's clock.
+ */
+ cc_int32 (*clear_kdc_time_offset) (cc_ccache_t io_ccache,
+ cc_uint32 in_credentials_version);
+
+ /*!
+ * \param in_ccache a ccache object.
+ * \return On success, #ccNoError. On failure, an error code representing the failure.
+ * \brief \b cc_ccache_wait_for_change(): Wait for the next change to a ccache.
+ *
+ * This function blocks until the next change is made to the ccache referenced by
+ * \a in_ccache. By repeatedly calling cc_ccache_wait_for_change() from
+ * a worker thread the caller can effectively receive callbacks whenever the
+ * ccache changes. This is considerably more efficient than polling
+ * with cc_ccache_get_change_time().
+ *
+ * cc_ccache_wait_for_change() will return whenever:
+ *
+ * \li a credential is stored
+ * \li a credential is removed
+ * \li the ccache principal is changed
+ * \li the ccache becomes the default ccache
+ * \li the ccache is no longer the default ccache
+ *
+ * \note In order to make sure that the caller doesn't miss any changes,
+ * cc_ccache_wait_for_change() always returns immediately after the first time it
+ * is called on a new ccache object. Callers must use the same ccache object
+ * for successive calls to cc_ccache_wait_for_change() rather than creating a new
+ * ccache object for every call.
+ *
+ * \sa get_change_time
+ */
+ cc_int32 (*wait_for_change) (cc_ccache_t in_ccache);
+};
+
+/*!
+ * Function pointer table for cc_string_t. For more information see
+ * \ref cc_string_reference.
+ */
+struct cc_string_f {
+ /*!
+ * \param io_string the string object to release.
+ * \return On success, #ccNoError. On failure, an error code representing the failure.
+ * \brief \b cc_string_release(): Release memory associated with a cc_string_t object.
+ */
+ cc_int32 (*release) (cc_string_t io_string);
+};
+
+/*!
+ * Function pointer table for cc_credentials_t. For more information see
+ * \ref cc_credentials_reference.
+ */
+struct cc_credentials_f {
+ /*!
+ * \param io_credentials the credentials object to release.
+ * \return On success, #ccNoError. On failure, an error code representing the failure.
+ * \brief \b cc_credentials_release(): Release memory associated with a cc_credentials_t object.
+ */
+ cc_int32 (*release) (cc_credentials_t io_credentials);
+
+ /*!
+ * \param in_credentials a credentials object.
+ * \param in_compare_to_credentials a credentials object to compare with \a in_credentials.
+ * \param out_equal on exit, whether or not the two credentials objects refer to the
+ * same credentials in the cache collection.
+ * \return On success, #ccNoError. On failure, an error code representing the failure.
+ * \brief \b cc_credentials_compare(): Compare two credentials objects.
+ */
+ cc_int32 (*compare) (cc_credentials_t in_credentials,
+ cc_credentials_t in_compare_to_credentials,
+ cc_uint32 *out_equal);
+};
+
+/*!
+ * Function pointer table for cc_ccache_iterator_t. For more information see
+ * \ref cc_ccache_iterator_reference.
+ */
+struct cc_ccache_iterator_f {
+ /*!
+ * \param io_ccache_iterator the ccache iterator object to release.
+ * \return On success, #ccNoError. On failure, an error code representing the failure.
+ * \brief \b cc_ccache_iterator_release(): Release memory associated with a cc_ccache_iterator_t object.
+ */
+ cc_int32 (*release) (cc_ccache_iterator_t io_ccache_iterator);
+
+ /*!
+ * \param in_ccache_iterator a ccache iterator object.
+ * \param out_ccache on exit, the next ccache in the cache collection.
+ * \return On success, #ccNoError if the next ccache in the cache collection was
+ * obtained or #ccIteratorEnd if there are no more ccaches.
+ * On failure, an error code representing the failure.
+ * \brief \b cc_ccache_iterator_next(): Get the next ccache in the cache collection.
+ */
+ cc_int32 (*next) (cc_ccache_iterator_t in_ccache_iterator,
+ cc_ccache_t *out_ccache);
+
+ /*!
+ * \param in_ccache_iterator a ccache iterator object.
+ * \param out_ccache_iterator on exit, a copy of \a in_ccache_iterator.
+ * \return On success, #ccNoError. On failure, an error code representing the failure.
+ * \brief \b cc_ccache_iterator_clone(): Make a copy of a ccache iterator.
+ */
+ cc_int32 (*clone) (cc_ccache_iterator_t in_ccache_iterator,
+ cc_ccache_iterator_t *out_ccache_iterator);
+};
+
+/*!
+ * Function pointer table for cc_credentials_iterator_t. For more information see
+ * \ref cc_credentials_iterator_reference.
+ */
+struct cc_credentials_iterator_f {
+ /*!
+ * \param io_credentials_iterator the credentials iterator object to release.
+ * \return On success, #ccNoError. On failure, an error code representing the failure.
+ * \brief \b cc_credentials_iterator_release(): Release memory associated with a cc_credentials_iterator_t object.
+ */
+ cc_int32 (*release) (cc_credentials_iterator_t io_credentials_iterator);
+
+ /*!
+ * \param in_credentials_iterator a credentials iterator object.
+ * \param out_credentials on exit, the next credentials in the ccache.
+ * \return On success, #ccNoError if the next credential in the ccache was obtained
+ * or #ccIteratorEnd if there are no more credentials.
+ * On failure, an error code representing the failure.
+ * \brief \b cc_credentials_iterator_next(): Get the next credentials in the ccache.
+ */
+ cc_int32 (*next) (cc_credentials_iterator_t in_credentials_iterator,
+ cc_credentials_t *out_credentials);
+
+ /*!
+ * \ingroup cc_credentials_iterator_reference
+ * \param in_credentials_iterator a credentials iterator object.
+ * \param out_credentials_iterator on exit, a copy of \a in_credentials_iterator.
+ * \return On success, #ccNoError. On failure, an error code representing the failure.
+ * \brief \b cc_credentials_iterator_clone(): Make a copy of a credentials iterator.
+ */
+ cc_int32 (*clone) (cc_credentials_iterator_t in_credentials_iterator,
+ cc_credentials_iterator_t *out_credentials_iterator);
+};
+
+/*!
+ * \ingroup cc_context_reference
+ * \param out_context on exit, a new context object. Must be free with cc_context_release().
+ * \param in_version the requested API version. This should be the maximum version the
+ * application supports.
+ * \param out_supported_version if non-NULL, on exit contains the maximum API version
+ * supported by the implementation.
+ * \param out_vendor if non-NULL, on exit contains a pointer to a read-only C string which
+ * contains a string describing the vendor which implemented the credentials cache API.
+ * \return On success, #ccNoError. On failure, an error code representing the failure.
+ * May return CCAPI v2 error CC_BAD_API_VERSION if #ccapi_version_2 is passed in.
+ * \brief Initialize a new cc_context.
+ */
+CCACHE_API cc_int32 cc_initialize (cc_context_t *out_context,
+ cc_int32 in_version,
+ cc_int32 *out_supported_version,
+ char const **out_vendor);
+
+
+/*! \defgroup helper_macros CCAPI Function Helper Macros
+ * @{ */
+
+/*! Helper macro for cc_context_f release() */
+#define cc_context_release(context) \
+ ((context) -> functions -> release (context))
+/*! Helper macro for cc_context_f get_change_time() */
+#define cc_context_get_change_time(context, change_time) \
+ ((context) -> functions -> get_change_time (context, change_time))
+/*! Helper macro for cc_context_f get_default_ccache_name() */
+#define cc_context_get_default_ccache_name(context, name) \
+ ((context) -> functions -> get_default_ccache_name (context, name))
+/*! Helper macro for cc_context_f open_ccache() */
+#define cc_context_open_ccache(context, name, ccache) \
+ ((context) -> functions -> open_ccache (context, name, ccache))
+/*! Helper macro for cc_context_f open_default_ccache() */
+#define cc_context_open_default_ccache(context, ccache) \
+ ((context) -> functions -> open_default_ccache (context, ccache))
+/*! Helper macro for cc_context_f create_ccache() */
+#define cc_context_create_ccache(context, name, version, principal, ccache) \
+ ((context) -> functions -> create_ccache (context, name, version, principal, ccache))
+/*! Helper macro for cc_context_f create_default_ccache() */
+#define cc_context_create_default_ccache(context, version, principal, ccache) \
+ ((context) -> functions -> create_default_ccache (context, version, principal, ccache))
+/*! Helper macro for cc_context_f create_new_ccache() */
+#define cc_context_create_new_ccache(context, version, principal, ccache) \
+ ((context) -> functions -> create_new_ccache (context, version, principal, ccache))
+/*! Helper macro for cc_context_f new_ccache_iterator() */
+#define cc_context_new_ccache_iterator(context, iterator) \
+ ((context) -> functions -> new_ccache_iterator (context, iterator))
+/*! Helper macro for cc_context_f lock() */
+#define cc_context_lock(context, type, block) \
+ ((context) -> functions -> lock (context, type, block))
+/*! Helper macro for cc_context_f unlock() */
+#define cc_context_unlock(context) \
+ ((context) -> functions -> unlock (context))
+/*! Helper macro for cc_context_f compare() */
+#define cc_context_compare(context, compare_to, equal) \
+ ((context) -> functions -> compare (context, compare_to, equal))
+/*! Helper macro for cc_context_f wait_for_change() */
+#define cc_context_wait_for_change(context) \
+ ((context) -> functions -> wait_for_change (context))
+
+/*! Helper macro for cc_ccache_f release() */
+#define cc_ccache_release(ccache) \
+ ((ccache) -> functions -> release (ccache))
+/*! Helper macro for cc_ccache_f destroy() */
+#define cc_ccache_destroy(ccache) \
+ ((ccache) -> functions -> destroy (ccache))
+/*! Helper macro for cc_ccache_f set_default() */
+#define cc_ccache_set_default(ccache) \
+ ((ccache) -> functions -> set_default (ccache))
+/*! Helper macro for cc_ccache_f get_credentials_version() */
+#define cc_ccache_get_credentials_version(ccache, version) \
+ ((ccache) -> functions -> get_credentials_version (ccache, version))
+/*! Helper macro for cc_ccache_f get_name() */
+#define cc_ccache_get_name(ccache, name) \
+ ((ccache) -> functions -> get_name (ccache, name))
+/*! Helper macro for cc_ccache_f get_principal() */
+#define cc_ccache_get_principal(ccache, version, principal) \
+ ((ccache) -> functions -> get_principal (ccache, version, principal))
+/*! Helper macro for cc_ccache_f set_principal() */
+#define cc_ccache_set_principal(ccache, version, principal) \
+ ((ccache) -> functions -> set_principal (ccache, version, principal))
+/*! Helper macro for cc_ccache_f store_credentials() */
+#define cc_ccache_store_credentials(ccache, credentials) \
+ ((ccache) -> functions -> store_credentials (ccache, credentials))
+/*! Helper macro for cc_ccache_f remove_credentials() */
+#define cc_ccache_remove_credentials(ccache, credentials) \
+ ((ccache) -> functions -> remove_credentials (ccache, credentials))
+/*! Helper macro for cc_ccache_f new_credentials_iterator() */
+#define cc_ccache_new_credentials_iterator(ccache, iterator) \
+ ((ccache) -> functions -> new_credentials_iterator (ccache, iterator))
+/*! Helper macro for cc_ccache_f lock() */
+#define cc_ccache_lock(ccache, type, block) \
+ ((ccache) -> functions -> lock (ccache, type, block))
+/*! Helper macro for cc_ccache_f unlock() */
+#define cc_ccache_unlock(ccache) \
+ ((ccache) -> functions -> unlock (ccache))
+/*! Helper macro for cc_ccache_f get_last_default_time() */
+#define cc_ccache_get_last_default_time(ccache, last_default_time) \
+ ((ccache) -> functions -> get_last_default_time (ccache, last_default_time))
+/*! Helper macro for cc_ccache_f get_change_time() */
+#define cc_ccache_get_change_time(ccache, change_time) \
+ ((ccache) -> functions -> get_change_time (ccache, change_time))
+/*! Helper macro for cc_ccache_f move() */
+#define cc_ccache_move(source, destination) \
+ ((source) -> functions -> move (source, destination))
+/*! Helper macro for cc_ccache_f compare() */
+#define cc_ccache_compare(ccache, compare_to, equal) \
+ ((ccache) -> functions -> compare (ccache, compare_to, equal))
+/*! Helper macro for cc_ccache_f get_kdc_time_offset() */
+#define cc_ccache_get_kdc_time_offset(ccache, version, time_offset) \
+ ((ccache) -> functions -> get_kdc_time_offset (ccache, version, time_offset))
+/*! Helper macro for cc_ccache_f set_kdc_time_offset() */
+#define cc_ccache_set_kdc_time_offset(ccache, version, time_offset) \
+ ((ccache) -> functions -> set_kdc_time_offset (ccache, version, time_offset))
+/*! Helper macro for cc_ccache_f clear_kdc_time_offset() */
+#define cc_ccache_clear_kdc_time_offset(ccache, version) \
+ ((ccache) -> functions -> clear_kdc_time_offset (ccache, version))
+/*! Helper macro for cc_ccache_f wait_for_change() */
+#define cc_ccache_wait_for_change(ccache) \
+ ((ccache) -> functions -> wait_for_change (ccache))
+
+/*! Helper macro for cc_string_f release() */
+#define cc_string_release(string) \
+ ((string) -> functions -> release (string))
+
+/*! Helper macro for cc_credentials_f release() */
+#define cc_credentials_release(credentials) \
+ ((credentials) -> functions -> release (credentials))
+/*! Helper macro for cc_credentials_f compare() */
+#define cc_credentials_compare(credentials, compare_to, equal) \
+ ((credentials) -> functions -> compare (credentials, compare_to, equal))
+
+/*! Helper macro for cc_ccache_iterator_f release() */
+#define cc_ccache_iterator_release(iterator) \
+ ((iterator) -> functions -> release (iterator))
+/*! Helper macro for cc_ccache_iterator_f next() */
+#define cc_ccache_iterator_next(iterator, ccache) \
+ ((iterator) -> functions -> next (iterator, ccache))
+/*! Helper macro for cc_ccache_iterator_f clone() */
+#define cc_ccache_iterator_clone(iterator, new_iterator) \
+ ((iterator) -> functions -> clone (iterator, new_iterator))
+
+/*! Helper macro for cc_credentials_iterator_f release() */
+#define cc_credentials_iterator_release(iterator) \
+ ((iterator) -> functions -> release (iterator))
+/*! Helper macro for cc_credentials_iterator_f next() */
+#define cc_credentials_iterator_next(iterator, credentials) \
+ ((iterator) -> functions -> next (iterator, credentials))
+/*! Helper macro for cc_credentials_iterator_f clone() */
+#define cc_credentials_iterator_clone(iterator, new_iterator) \
+ ((iterator) -> functions -> clone (iterator, new_iterator))
+/*!@}*/
+
+#if TARGET_OS_MAC
+#pragma pack(pop)
+#endif
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __CREDENTIALSCACHE__ */
diff --git a/src/include/CredentialsCache2.h b/src/include/CredentialsCache2.h
new file mode 100644
index 000000000000..b3b48996d8fd
--- /dev/null
+++ b/src/include/CredentialsCache2.h
@@ -0,0 +1,326 @@
+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/* include/CredentialsCache2.h */
+/*
+ * Copyright 2006 Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ * require a specific license from the United States Government.
+ * It is the responsibility of any person or organization contemplating
+ * export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission. Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose. It is provided "as is" without express
+ * or implied warranty.
+ */
+
+/*
+ * This is backwards compatibility for CCache API v2 clients to be able to run
+ * against the CCache API v3 library
+ */
+
+#ifndef CCAPI_V2_H
+#define CCAPI_V2_H
+
+#include <CredentialsCache.h>
+
+#if defined(macintosh) || (defined(__MACH__) && defined(__APPLE__))
+#include <TargetConditionals.h>
+#include <AvailabilityMacros.h>
+#ifdef DEPRECATED_IN_MAC_OS_X_VERSION_10_5_AND_LATER
+#define CCAPI_DEPRECATED DEPRECATED_IN_MAC_OS_X_VERSION_10_5_AND_LATER
+#endif
+#endif
+
+#ifndef CCAPI_DEPRECATED
+#define CCAPI_DEPRECATED
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+#if TARGET_OS_MAC
+#pragma pack(push,2)
+#endif
+
+/* Some old types get directly mapped to new types */
+
+typedef cc_context_d apiCB;
+typedef cc_ccache_d ccache_p;
+typedef cc_credentials_iterator_d ccache_cit_creds;
+typedef cc_ccache_iterator_d ccache_cit_ccache;
+typedef cc_data cc_data_compat;
+typedef cc_int32 cc_cred_vers;
+typedef cc_int32 cc_result;
+
+/* This doesn't exist in API v3 */
+typedef cc_uint32 cc_flags;
+
+/* Credentials types are visible to the caller so we have to keep binary compatibility */
+
+typedef struct cc_credentials_v5_compat {
+ char* client;
+ char* server;
+ cc_data_compat keyblock;
+ cc_time_t authtime;
+ cc_time_t starttime;
+ cc_time_t endtime;
+ cc_time_t renew_till;
+ cc_uint32 is_skey;
+ cc_uint32 ticket_flags;
+ cc_data_compat** addresses;
+ cc_data_compat ticket;
+ cc_data_compat second_ticket;
+ cc_data_compat** authdata;
+} cc_credentials_v5_compat;
+
+enum {
+ MAX_V4_CRED_LEN = 1250
+};
+
+enum {
+ KRB_NAME_SZ = 40,
+ KRB_INSTANCE_SZ = 40,
+ KRB_REALM_SZ = 40
+};
+
+typedef struct cc_credentials_v4_compat {
+ unsigned char kversion;
+ char principal[KRB_NAME_SZ+1];
+ char principal_instance[KRB_INSTANCE_SZ+1];
+ char service[KRB_NAME_SZ+1];
+ char service_instance[KRB_INSTANCE_SZ+1];
+ char realm[KRB_REALM_SZ+1];
+ unsigned char session_key[8];
+ cc_int32 kvno;
+ cc_int32 str_to_key;
+ long issue_date;
+ cc_int32 lifetime;
+ cc_uint32 address;
+ cc_int32 ticket_sz;
+ unsigned char ticket[MAX_V4_CRED_LEN];
+ unsigned long oops;
+} cc_credentials_v4_compat;
+
+typedef union cred_ptr_union_compat {
+ cc_credentials_v4_compat* pV4Cred;
+ cc_credentials_v5_compat* pV5Cred;
+} cred_ptr_union_compat;
+
+typedef struct cred_union {
+ cc_int32 cred_type; /* cc_cred_vers */
+ cred_ptr_union_compat cred;
+} cred_union;
+
+/* NC info structure is gone in v3 */
+
+struct infoNC {
+ char* name;
+ char* principal;
+ cc_int32 vers;
+};
+
+typedef struct infoNC infoNC;
+
+/* Some old type names */
+
+typedef cc_credentials_v4_compat V4Cred_type;
+typedef cc_credentials_v5_compat cc_creds;
+struct ccache_cit;
+typedef struct ccache_cit ccache_cit;
+
+enum {
+ CC_API_VER_2 = ccapi_version_2
+};
+
+enum {
+ CC_NOERROR,
+ CC_BADNAME,
+ CC_NOTFOUND,
+ CC_END,
+ CC_IO,
+ CC_WRITE,
+ CC_NOMEM,
+ CC_FORMAT,
+ CC_LOCKED,
+ CC_BAD_API_VERSION,
+ CC_NO_EXIST,
+ CC_NOT_SUPP,
+ CC_BAD_PARM,
+ CC_ERR_CACHE_ATTACH,
+ CC_ERR_CACHE_RELEASE,
+ CC_ERR_CACHE_FULL,
+ CC_ERR_CRED_VERSION
+};
+
+enum {
+ CC_CRED_UNKNOWN,
+ CC_CRED_V4,
+ CC_CRED_V5,
+ CC_CRED_MAX
+};
+
+enum {
+ CC_LOCK_UNLOCK = 1,
+ CC_LOCK_READER = 2,
+ CC_LOCK_WRITER = 3,
+ CC_LOCK_NOBLOCK = 16
+};
+
+CCACHE_API cc_int32
+cc_shutdown (apiCB **io_context)
+ CCAPI_DEPRECATED;
+
+CCACHE_API cc_int32
+cc_get_NC_info (apiCB *in_context,
+ infoNC ***out_info)
+ CCAPI_DEPRECATED;
+
+CCACHE_API cc_int32
+cc_get_change_time (apiCB *in_context,
+ cc_time_t *out_change_time)
+ CCAPI_DEPRECATED;
+
+CCACHE_API cc_int32
+cc_open (apiCB *in_context,
+ const char *in_name,
+ cc_int32 in_version,
+ cc_uint32 in_flags,
+ ccache_p **out_ccache)
+ CCAPI_DEPRECATED;
+
+CCACHE_API cc_int32
+cc_create (apiCB *in_context,
+ const char *in_name,
+ const char *in_principal,
+ cc_int32 in_version,
+ cc_uint32 in_flags,
+ ccache_p **out_ccache)
+ CCAPI_DEPRECATED;
+
+CCACHE_API cc_int32
+cc_close (apiCB *in_context,
+ ccache_p **ioCCache)
+ CCAPI_DEPRECATED;
+
+CCACHE_API cc_int32
+cc_destroy (apiCB *in_context,
+ ccache_p **io_ccache)
+ CCAPI_DEPRECATED;
+
+CCACHE_API cc_int32
+cc_seq_fetch_NCs_begin (apiCB *in_context,
+ ccache_cit **out_nc_iterator)
+ CCAPI_DEPRECATED;
+
+CCACHE_API cc_int32
+cc_seq_fetch_NCs_next (apiCB *in_context,
+ ccache_p **out_ccache,
+ ccache_cit *in_nc_iterator)
+ CCAPI_DEPRECATED;
+
+CCACHE_API cc_int32
+cc_seq_fetch_NCs_end (apiCB *in_context,
+ ccache_cit **io_nc_iterator)
+ CCAPI_DEPRECATED;
+
+CCACHE_API cc_int32
+cc_get_name (apiCB *in_context,
+ ccache_p *in_ccache,
+ char **out_name)
+ CCAPI_DEPRECATED;
+
+CCACHE_API cc_int32
+cc_get_cred_version (apiCB *in_context,
+ ccache_p *in_ccache,
+ cc_int32 *out_version)
+ CCAPI_DEPRECATED;
+
+CCACHE_API cc_int32
+cc_set_principal (apiCB *in_context,
+ ccache_p *in_ccache,
+ cc_int32 in_version,
+ char *in_principal)
+ CCAPI_DEPRECATED;
+
+CCACHE_API cc_int32
+cc_get_principal (apiCB *in_context,
+ ccache_p *in_ccache,
+ char **out_principal)
+ CCAPI_DEPRECATED;
+
+CCACHE_API cc_int32
+cc_store (apiCB *in_context,
+ ccache_p *in_ccache,
+ cred_union in_credentials)
+ CCAPI_DEPRECATED;
+
+CCACHE_API cc_int32
+cc_remove_cred (apiCB *in_context,
+ ccache_p *in_ccache,
+ cred_union in_credentials)
+ CCAPI_DEPRECATED;
+
+CCACHE_API cc_int32
+cc_seq_fetch_creds_begin (apiCB *in_context,
+ const ccache_p *in_ccache,
+ ccache_cit **out_ccache_iterator)
+ CCAPI_DEPRECATED;
+
+CCACHE_API cc_int32
+cc_seq_fetch_creds_next (apiCB *in_context,
+ cred_union **out_cred_union,
+ ccache_cit *in_ccache_iterator)
+ CCAPI_DEPRECATED;
+
+CCACHE_API cc_int32
+cc_seq_fetch_creds_end (apiCB *in_context,
+ ccache_cit **io_ccache_iterator)
+ CCAPI_DEPRECATED;
+
+CCACHE_API cc_int32
+cc_free_principal (apiCB *in_context,
+ char **io_principal)
+ CCAPI_DEPRECATED;
+
+CCACHE_API cc_int32
+cc_free_name (apiCB *in_context,
+ char **io_name)
+ CCAPI_DEPRECATED;
+
+CCACHE_API cc_int32
+cc_free_creds (apiCB *in_context,
+ cred_union **io_cred_union)
+ CCAPI_DEPRECATED;
+
+CCACHE_API cc_int32
+cc_free_NC_info (apiCB *in_context,
+ infoNC ***io_info)
+ CCAPI_DEPRECATED;
+
+CCACHE_API cc_int32
+cc_lock_request (apiCB *in_context,
+ const ccache_p *in_ccache,
+ const cc_int32 in_lock_type)
+ CCAPI_DEPRECATED;
+
+#if TARGET_OS_MAC
+#pragma pack(pop)
+#endif
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* CCAPI_V2_H */
diff --git a/src/include/Makefile.in b/src/include/Makefile.in
new file mode 100644
index 000000000000..f5b921833071
--- /dev/null
+++ b/src/include/Makefile.in
@@ -0,0 +1,157 @@
+mydir=include
+BUILDTOP=$(REL)..
+KRB5RCTMPDIR= @KRB5_RCTMPDIR@
+##DOSBUILDTOP = ..
+NO_OUTPRE=1
+
+all-unix: krb5/krb5.h
+
+all-unix: maybe-make-db.h-@DB_HEADER_VERSION@
+
+generate-files-mac: krb5/krb5.h
+
+maybe-make-db.h-k5:
+ : db.h will be installed by util/db2
+maybe-make-db.h-sys:
+ : fall back to system db.h
+maybe-make-db.h-redirect:
+ test -r db.h || echo '#include <@DB_HEADER@>' > db.h
+
+ET_HEADERS = adm_err.h asn1_err.h kdb5_err.h krb5_err.h k5e1_err.h
+K5_ET_HEADERS = \
+ ../lib/krb5/error_tables/krb5_err.h \
+ ../lib/krb5/error_tables/k5e1_err.h \
+ ../lib/krb5/error_tables/kdb5_err.h \
+ ../lib/krb5/error_tables/kv5m_err.h \
+ ../lib/krb5/error_tables/krb524_err.h \
+ ../lib/krb5/error_tables/asn1_err.h
+BUILT_HEADERS = osconf.h
+
+all-unix: autoconf.h $(BUILT_HEADERS)
+all-windows: autoconf.h $(BUILT_HEADERS) verify-calling-conventions-krb5
+
+all-unix: @MAINT@ verify-calling-conventions-krb5
+
+$(srcdir)/autoconf.h.in: @MAINT@ $(srcdir)/autoconf.stmp
+$(srcdir)/autoconf.stmp: $(top_srcdir)/configure.in $(top_srcdir)/aclocal.m4
+ (cd $(top_srcdir) && $(AUTOHEADER) --include=$(CONFIG_RELTOPDIR) $(AUTOHEADERFLAGS))
+ touch $(srcdir)/autoconf.stmp
+
+##DOS##autoconf.h: win-mac.h
+##DOS## $(CP) win-mac.h $@
+##DOS##osconf.h: osconf.hin
+##DOS## $(CP) osconf.hin $@
+
+###############################################################################
+##DOS##!if 0
+# config.status will now update autoconf.stamp itself.
+autoconf.h: autoconf.stamp
+autoconf.stamp: $(srcdir)/autoconf.h.in $(BUILDTOP)/config.status
+ (cd $(BUILDTOP) && $(SHELL) config.status $(mydir)/autoconf.h)
+
+SYSCONFDIR = @sysconfdir@
+LOCALSTATEDIR = @localstatedir@
+RUNSTATEDIR = @runstatedir@
+BINDIR = @bindir@
+SBINDIR = @sbindir@
+LIBDIR = @libdir@
+SYSCONFCONF = @SYSCONFCONF@
+
+PROCESS_REPLACE = -e "s\"@KRB5RCTMPDIR\"$(KRB5RCTMPDIR)\"" \
+ -e "s\"@PREFIX\"$(INSTALL_PREFIX)\"" \
+ -e "s\"@EXEC_PREFIX\"$(INSTALL_EXEC_PREFIX)\"" \
+ -e "s\"@BINDIR\"$(BINDIR)\"" \
+ -e "s\"@LIBDIR\"$(LIBDIR)\"" \
+ -e "s\"@SBINDIR\"$(SBINDIR)\"" \
+ -e "s\"@MODULEDIR\"$(MODULE_DIR)\"" \
+ -e "s\"@GSSMODULEDIR\"$(GSS_MODULE_DIR)\"" \
+ -e "s\"@LOCALSTATEDIR\"$(LOCALSTATEDIR)\"" \
+ -e "s\"@RUNSTATEDIR\"$(RUNSTATEDIR)\"" \
+ -e "s\"@SYSCONFDIR\"$(SYSCONFDIR)\"" \
+ -e "s\"@DYNOBJEXT\"$(DYNOBJEXT)\"" \
+ -e "s\"@SYSCONFCONF\"$(SYSCONFCONF)\""
+
+OSCONFSRC = $(srcdir)/osconf.hin
+
+osconf.h: $(OSCONFSRC) Makefile
+ cat $(OSCONFSRC) | sed $(PROCESS_REPLACE) > osconf.new
+ $(MOVEIFCHANGED) osconf.new osconf.h
+##DOS##!endif
+###############################################################################
+
+krb5/krb5.h: krb5.stamp; : krb5.h
+krb5.stamp: $(srcdir)/krb5/krb5.hin $(K5_ET_HEADERS)
+ test -d krb5 || mkdir krb5
+ if test -r krb5.h; then \
+ if cmp -s krb5.h $(srcdir)/krb5.h; then :; else rm -f krb5.h; fi; \
+ else :; fi
+ echo "/* This file is generated, please don't edit it directly. */" > krb5/krb5.new
+ echo "#ifndef KRB5_KRB5_H_INCLUDED" >> krb5/krb5.new
+ echo "#define KRB5_KRB5_H_INCLUDED" >> krb5/krb5.new
+ cat $(srcdir)/krb5/krb5.hin $(K5_ET_HEADERS) >> krb5/krb5.new
+ echo "#endif /* KRB5_KRB5_H_INCLUDED */" >> krb5/krb5.new
+ $(MOVEIFCHANGED) krb5/krb5.new krb5/krb5.h
+ touch krb5.stamp
+
+verify-calling-conventions-krb5: private-and-public-decls
+ $(PERL) -w $(top_srcdir)/util/def-check.pl private-and-public-decls $(top_srcdir)/lib/krb5_32.def
+
+##DOS##!if 0
+HEADERS_TO_CHECK = krb5/krb5.h $(srcdir)/k5-int.h $(srcdir)/krb5/clpreauth_plugin.h
+
+private-and-public-decls: $(HEADERS_TO_CHECK)
+ cat $(HEADERS_TO_CHECK) > $@
+##DOS##!endif
+##DOS##private-and-public-decls:
+##DOS## copy /y krb5\krb5.h+k5-int.h+krb5\clpreauth_plugin.h $@
+
+#
+# Build the error table include files:
+# asn1_err.h kdb5_err.h krb5_err.h k5e1_err.h kv5m_err.h krb524_err.h
+
+$(K5_ET_HEADERS): rebuild-error-tables
+ : $@
+rebuild-error-tables:
+ (cd ../lib/krb5/error_tables && $(MAKE) includes)
+
+.PHONY: force rebuild-error-tables
+force:
+
+clean-unix::
+ $(RM) krb5/krb5.h krb5_err.h k5e1_err.h kdb5_err.h kv5m_err.h \
+ krb524_err.h asn1_err.h private-and-public-decls krb5.stamp
+ $(RM) $(ET_HEADERS) autoconf.stamp
+
+clean-windows::
+ $(RM) com_err.h profile.h
+ $(RM) gssapi\gssapi.h gssapi\gssapi_generic.h gssapi\gssapi_krb5.h
+ $(RM) gssapi\gssapi_alloc.h gssapi\gssapi_ext.h gssapi\timestamp
+ if exist gssapi\nul rmdir /s /q gssapi
+ $(RM) osconf.h autoconf.h autoconf.stamp
+ @echo Making clean in include
+
+clean:
+ $(RM) osconf.new $(BUILT_HEADERS)
+
+distclean:
+ $(RM) autoconf.h $(srcdir)/autoconf.stmp
+
+install-headers-unix install: krb5/krb5.h profile.h
+ $(INSTALL_DATA) $(srcdir)/krb5.h $(DESTDIR)$(KRB5_INCDIR)$(S)krb5.h
+ $(INSTALL_DATA) $(srcdir)/kdb.h $(DESTDIR)$(KRB5_INCDIR)$(S)kdb.h
+ $(INSTALL_DATA) krb5/krb5.h $(DESTDIR)$(KRB5_INCDIR)$(S)krb5$(S)krb5.h
+ $(INSTALL_DATA) $(srcdir)/krb5/ccselect_plugin.h $(DESTDIR)$(KRB5_INCDIR)$(S)krb5$(S)ccselect_plugin.h
+ $(INSTALL_DATA) $(srcdir)/krb5/clpreauth_plugin.h $(DESTDIR)$(KRB5_INCDIR)$(S)krb5$(S)clpreauth_plugin.h
+ $(INSTALL_DATA) $(srcdir)/krb5/hostrealm_plugin.h $(DESTDIR)$(KRB5_INCDIR)$(S)krb5$(S)hostrealm_plugin.h
+ $(INSTALL_DATA) $(srcdir)/krb5/kdcpreauth_plugin.h $(DESTDIR)$(KRB5_INCDIR)$(S)krb5$(S)kdcpreauth_plugin.h
+ $(INSTALL_DATA) $(srcdir)/krb5/localauth_plugin.h $(DESTDIR)$(KRB5_INCDIR)$(S)krb5$(S)localauth_plugin.h
+ $(INSTALL_DATA) $(srcdir)/krb5/locate_plugin.h $(DESTDIR)$(KRB5_INCDIR)$(S)krb5$(S)locate_plugin.h
+ $(INSTALL_DATA) $(srcdir)/krb5/plugin.h $(DESTDIR)$(KRB5_INCDIR)$(S)krb5$(S)plugin.h
+ $(INSTALL_DATA) $(srcdir)/krb5/preauth_plugin.h $(DESTDIR)$(KRB5_INCDIR)$(S)krb5$(S)preauth_plugin.h
+ $(INSTALL_DATA) $(srcdir)/krb5/pwqual_plugin.h $(DESTDIR)$(KRB5_INCDIR)$(S)krb5$(S)pwqual_plugin.h
+ $(INSTALL_DATA) $(srcdir)/krb5/kadm5_hook_plugin.h $(DESTDIR)$(KRB5_INCDIR)$(S)krb5$(S)kadm5_hook_plugin.h
+ $(INSTALL_DATA) profile.h $(DESTDIR)$(KRB5_INCDIR)$(S)profile.h
+ $(INSTALL_DATA) $(srcdir)/gssapi.h $(DESTDIR)$(KRB5_INCDIR)$(S)gssapi.h
+ $(INSTALL_DATA) $(srcdir)/krad.h $(DESTDIR)$(KRB5_INCDIR)/krad.h
+
+depend: krb5/krb5.h $(BUILT_HEADERS)
diff --git a/src/include/adm_proto.h b/src/include/adm_proto.h
new file mode 100644
index 000000000000..e99a84d6f86b
--- /dev/null
+++ b/src/include/adm_proto.h
@@ -0,0 +1,92 @@
+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/* include/adm_proto.h */
+/*
+ * Copyright 1995, 2007,2008,2009 by the Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ * require a specific license from the United States Government.
+ * It is the responsibility of any person or organization contemplating
+ * export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission. Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose. It is provided "as is" without express
+ * or implied warranty.
+ */
+
+#ifndef KRB5_ADM_PROTO_H__
+#define KRB5_ADM_PROTO_H__
+
+/*
+ * This is ugly, but avoids having to include k5-int or kdb.h for this.
+ */
+#ifndef KRB5_KDB5__
+struct _krb5_db_entry;
+typedef struct _krb5_db_entry krb5_db_entry;
+#endif /* KRB5_KDB5__ */
+
+/* Ditto for admin.h */
+
+#ifndef KRB5_KDB5__
+struct ___krb5_key_salt_tuple;
+typedef struct ___krb5_key_salt_tuple krb5_key_salt_tuple;
+#endif /* KRB5_KDB5__ */
+
+/*
+ * Function prototypes.
+ */
+
+/* logger.c */
+krb5_error_code krb5_klog_init(krb5_context, char *, char *, krb5_boolean);
+void krb5_klog_close(krb5_context);
+int krb5_klog_syslog(int, const char *, ...)
+#if !defined(__cplusplus) && (__GNUC__ > 2)
+ __attribute__((__format__(__printf__, 2, 3)))
+#endif
+ ;
+void krb5_klog_reopen (krb5_context);
+
+/* alt_prof.c */
+krb5_error_code krb5_aprof_init(char *, char *, krb5_pointer *);
+krb5_error_code krb5_aprof_getvals(krb5_pointer, const char **, char ***);
+krb5_error_code krb5_aprof_get_boolean(krb5_pointer, const char **, int,
+ krb5_boolean *);
+krb5_error_code krb5_aprof_get_deltat(krb5_pointer, const char **,
+ krb5_boolean, krb5_deltat *);
+krb5_error_code krb5_aprof_get_string(krb5_pointer, const char **,
+ krb5_boolean, char **);
+krb5_error_code krb5_aprof_get_string_all(krb5_pointer, const char **,
+ char **);
+krb5_error_code krb5_aprof_get_int32(krb5_pointer, const char **,
+ krb5_boolean, krb5_int32 *);
+krb5_error_code krb5_aprof_finish(krb5_pointer);
+
+/* str_conv.c */
+krb5_error_code krb5_flagspec_to_mask(const char *,
+ krb5_flags *, krb5_flags *);
+krb5_error_code krb5_flagnum_to_string(int, char **);
+krb5_error_code krb5_flags_to_strings(krb5_int32, char ***);
+
+/* keysalt.c */
+krb5_boolean krb5_keysalt_is_present(krb5_key_salt_tuple *, krb5_int32,
+ krb5_enctype, krb5_int32);
+krb5_error_code krb5_keysalt_iterate(krb5_key_salt_tuple *, krb5_int32,
+ krb5_boolean,
+ krb5_error_code (*)(krb5_key_salt_tuple *,
+ krb5_pointer),
+ krb5_pointer);
+
+krb5_error_code krb5_string_to_keysalts(const char *, const char *,
+ const char *, krb5_boolean,
+ krb5_key_salt_tuple **, krb5_int32 *);
+#endif /* KRB5_ADM_PROTO_H__ */
diff --git a/src/include/autoconf.h.in b/src/include/autoconf.h.in
new file mode 100644
index 000000000000..b33c5222325e
--- /dev/null
+++ b/src/include/autoconf.h.in
@@ -0,0 +1,770 @@
+/* include/autoconf.h.in. Generated from configure.in by autoheader. */
+
+
+#ifndef KRB5_AUTOCONF_H
+#define KRB5_AUTOCONF_H
+
+
+/* Define if AES-NI support is enabled */
+#undef AESNI
+
+/* Define if socket can't be bound to 0.0.0.0 */
+#undef BROKEN_STREAMS_SOCKETS
+
+/* Define if va_list objects can be simply copied by assignment. */
+#undef CAN_COPY_VA_LIST
+
+/* Define to reduce code size even if it means more cpu usage */
+#undef CONFIG_SMALL
+
+/* Define if __attribute__((constructor)) works */
+#undef CONSTRUCTOR_ATTR_WORKS
+
+/* Define to default ccache name */
+#undef DEFCCNAME
+
+/* Define to default client keytab name */
+#undef DEFCKTNAME
+
+/* Define to default keytab name */
+#undef DEFKTNAME
+
+/* Define if library initialization should be delayed until first use */
+#undef DELAY_INITIALIZER
+
+/* Define if __attribute__((destructor)) works */
+#undef DESTRUCTOR_ATTR_WORKS
+
+/* Define to disable PKINIT plugin support */
+#undef DISABLE_PKINIT
+
+/* Define if LDAP KDB support within the Kerberos library (mainly ASN.1 code)
+ should be enabled. */
+#undef ENABLE_LDAP
+
+/* Define if translation functions should be used. */
+#undef ENABLE_NLS
+
+/* Define if thread support enabled */
+#undef ENABLE_THREADS
+
+/* Define as return type of endrpcent */
+#undef ENDRPCENT_TYPE
+
+/* Define if Fortuna PRNG is selected */
+#undef FORTUNA
+
+/* Define to the type of elements in the array set by `getgroups'. Usually
+ this is either `int' or `gid_t'. */
+#undef GETGROUPS_T
+
+/* Define if gethostbyname_r returns int rather than struct hostent * */
+#undef GETHOSTBYNAME_R_RETURNS_INT
+
+/* Type of getpeername second argument. */
+#undef GETPEERNAME_ARG2_TYPE
+
+/* Type of getpeername second argument. */
+#undef GETPEERNAME_ARG3_TYPE
+
+/* Define if getpwnam_r exists but takes only 4 arguments (e.g., POSIX draft 6
+ implementations like some Solaris releases). */
+#undef GETPWNAM_R_4_ARGS
+
+/* Define if getpwnam_r returns an int */
+#undef GETPWNAM_R_RETURNS_INT
+
+/* Define if getpwuid_r exists but takes only 4 arguments (e.g., POSIX draft 6
+ implementations like some Solaris releases). */
+#undef GETPWUID_R_4_ARGS
+
+/* Define if getservbyname_r returns int rather than struct servent * */
+#undef GETSERVBYNAME_R_RETURNS_INT
+
+/* Type of pointer target for argument 2 to getsockname */
+#undef GETSOCKNAME_ARG2_TYPE
+
+/* Type of pointer target for argument 3 to getsockname */
+#undef GETSOCKNAME_ARG3_TYPE
+
+/* Define if gmtime_r returns int instead of struct tm pointer, as on old
+ HP-UX systems. */
+#undef GMTIME_R_RETURNS_INT
+
+/* Define if va_copy macro or function is available. */
+#undef HAS_VA_COPY
+
+/* Define to 1 if you have the `access' function. */
+#undef HAVE_ACCESS
+
+/* Define to 1 if you have the <alloca.h> header file. */
+#undef HAVE_ALLOCA_H
+
+/* Define to 1 if you have the <arpa/inet.h> header file. */
+#undef HAVE_ARPA_INET_H
+
+/* Define to 1 if you have the `bswap16' function. */
+#undef HAVE_BSWAP16
+
+/* Define to 1 if you have the `bswap64' function. */
+#undef HAVE_BSWAP64
+
+/* Define to 1 if bswap_16 is available via byteswap.h */
+#undef HAVE_BSWAP_16
+
+/* Define to 1 if bswap_64 is available via byteswap.h */
+#undef HAVE_BSWAP_64
+
+/* Define if bt_rseq is available, for recursive btree traversal. */
+#undef HAVE_BT_RSEQ
+
+/* Define to 1 if you have the <byteswap.h> header file. */
+#undef HAVE_BYTESWAP_H
+
+/* Define to 1 if you have the `chmod' function. */
+#undef HAVE_CHMOD
+
+/* Define to 1 if you have the `compile' function. */
+#undef HAVE_COMPILE
+
+/* Define if com_err has compatible gettext support */
+#undef HAVE_COM_ERR_INTL
+
+/* Define to 1 if you have the <cpuid.h> header file. */
+#undef HAVE_CPUID_H
+
+/* Define to 1 if you have the `daemon' function. */
+#undef HAVE_DAEMON
+
+/* Define to 1 if you have the declaration of `strerror_r', and to 0 if you
+ don't. */
+#undef HAVE_DECL_STRERROR_R
+
+/* Define to 1 if you have the <dirent.h> header file, and it defines `DIR'.
+ */
+#undef HAVE_DIRENT_H
+
+/* Define to 1 if you have the <dlfcn.h> header file. */
+#undef HAVE_DLFCN_H
+
+/* Define to 1 if you have the `dn_skipname' function. */
+#undef HAVE_DN_SKIPNAME
+
+/* Define to 1 if you have the <endian.h> header file. */
+#undef HAVE_ENDIAN_H
+
+/* Define to 1 if you have the <errno.h> header file. */
+#undef HAVE_ERRNO_H
+
+/* Define to 1 if you have the `fchmod' function. */
+#undef HAVE_FCHMOD
+
+/* Define to 1 if you have the <fcntl.h> header file. */
+#undef HAVE_FCNTL_H
+
+/* Define to 1 if you have the `flock' function. */
+#undef HAVE_FLOCK
+
+/* Define to 1 if you have the `fnmatch' function. */
+#undef HAVE_FNMATCH
+
+/* Define to 1 if you have the <fnmatch.h> header file. */
+#undef HAVE_FNMATCH_H
+
+/* Define if you have the getaddrinfo function */
+#undef HAVE_GETADDRINFO
+
+/* Define to 1 if you have the `getcwd' function. */
+#undef HAVE_GETCWD
+
+/* Define to 1 if you have the `getenv' function. */
+#undef HAVE_GETENV
+
+/* Define to 1 if you have the `geteuid' function. */
+#undef HAVE_GETEUID
+
+/* Define if gethostbyname_r exists and its return type is known */
+#undef HAVE_GETHOSTBYNAME_R
+
+/* Define to 1 if you have the `getnameinfo' function. */
+#undef HAVE_GETNAMEINFO
+
+/* Define if system getopt should be used. */
+#undef HAVE_GETOPT
+
+/* Define if system getopt_long should be used. */
+#undef HAVE_GETOPT_LONG
+
+/* Define if getpwnam_r is available and useful. */
+#undef HAVE_GETPWNAM_R
+
+/* Define if getpwuid_r is available and useful. */
+#undef HAVE_GETPWUID_R
+
+/* Define if getservbyname_r exists and its return type is known */
+#undef HAVE_GETSERVBYNAME_R
+
+/* Have the gettimeofday function */
+#undef HAVE_GETTIMEOFDAY
+
+/* Define to 1 if you have the `getusershell' function. */
+#undef HAVE_GETUSERSHELL
+
+/* Define to 1 if you have the `gmtime_r' function. */
+#undef HAVE_GMTIME_R
+
+/* Define to 1 if you have the <ifaddrs.h> header file. */
+#undef HAVE_IFADDRS_H
+
+/* Define to 1 if you have the `inet_ntop' function. */
+#undef HAVE_INET_NTOP
+
+/* Define to 1 if you have the `inet_pton' function. */
+#undef HAVE_INET_PTON
+
+/* Define to 1 if the system has the type `int16_t'. */
+#undef HAVE_INT16_T
+
+/* Define to 1 if the system has the type `int32_t'. */
+#undef HAVE_INT32_T
+
+/* Define to 1 if the system has the type `int8_t'. */
+#undef HAVE_INT8_T
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#undef HAVE_INTTYPES_H
+
+/* Define to 1 if you have the <keyutils.h> header file. */
+#undef HAVE_KEYUTILS_H
+
+/* Define to 1 if you have the <lber.h> header file. */
+#undef HAVE_LBER_H
+
+/* Define to 1 if you have the `ldap_explode_dn' function. */
+#undef HAVE_LDAP_EXPLODE_DN
+
+/* Define to 1 if you have the <ldap.h> header file. */
+#undef HAVE_LDAP_H
+
+/* Define to 1 if you have the `ldap_initialize' function. */
+#undef HAVE_LDAP_INITIALIZE
+
+/* Define to 1 if you have the `ldap_str2dn' function. */
+#undef HAVE_LDAP_STR2DN
+
+/* Define to 1 if you have the `ldap_unbind_ext_s' function. */
+#undef HAVE_LDAP_UNBIND_EXT_S
+
+/* Define to 1 if you have the `ldap_url_parse_nodn' function. */
+#undef HAVE_LDAP_URL_PARSE_NODN
+
+/* Define to 1 if you have the `crypto' library (-lcrypto). */
+#undef HAVE_LIBCRYPTO
+
+/* Define if building with libedit. */
+#undef HAVE_LIBEDIT
+
+/* Define to 1 if you have the `nsl' library (-lnsl). */
+#undef HAVE_LIBNSL
+
+/* Define to 1 if you have the `resolv' library (-lresolv). */
+#undef HAVE_LIBRESOLV
+
+/* Define to 1 if you have the `socket' library (-lsocket). */
+#undef HAVE_LIBSOCKET
+
+/* Define if the util library is available */
+#undef HAVE_LIBUTIL
+
+/* Define to 1 if you have the <limits.h> header file. */
+#undef HAVE_LIMITS_H
+
+/* Define to 1 if you have the `localtime_r' function. */
+#undef HAVE_LOCALTIME_R
+
+/* Define to 1 if you have the <machine/byte_order.h> header file. */
+#undef HAVE_MACHINE_BYTE_ORDER_H
+
+/* Define to 1 if you have the <machine/endian.h> header file. */
+#undef HAVE_MACHINE_ENDIAN_H
+
+/* Define to 1 if you have the <memory.h> header file. */
+#undef HAVE_MEMORY_H
+
+/* Define to 1 if you have the `mkstemp' function. */
+#undef HAVE_MKSTEMP
+
+/* Define to 1 if you have the <ndir.h> header file, and it defines `DIR'. */
+#undef HAVE_NDIR_H
+
+/* Define to 1 if you have the <netdb.h> header file. */
+#undef HAVE_NETDB_H
+
+/* Define if netdb.h declares h_errno */
+#undef HAVE_NETDB_H_H_ERRNO
+
+/* Define to 1 if you have the <netinet/in.h> header file. */
+#undef HAVE_NETINET_IN_H
+
+/* Define to 1 if you have the `ns_initparse' function. */
+#undef HAVE_NS_INITPARSE
+
+/* Define to 1 if you have the `ns_name_uncompress' function. */
+#undef HAVE_NS_NAME_UNCOMPRESS
+
+/* Define if OpenSSL supports cms. */
+#undef HAVE_OPENSSL_CMS
+
+/* Define to 1 if you have the <paths.h> header file. */
+#undef HAVE_PATHS_H
+
+/* Define if persistent keyrings are supported */
+#undef HAVE_PERSISTENT_KEYRING
+
+/* Define to 1 if you have the <poll.h> header file. */
+#undef HAVE_POLL_H
+
+/* Define if #pragma weak references work */
+#undef HAVE_PRAGMA_WEAK_REF
+
+/* Define if you have POSIX threads libraries and header files. */
+#undef HAVE_PTHREAD
+
+/* Define to 1 if you have the `pthread_once' function. */
+#undef HAVE_PTHREAD_ONCE
+
+/* Define to 1 if you have the `pthread_rwlock_init' function. */
+#undef HAVE_PTHREAD_RWLOCK_INIT
+
+/* Define if pthread_rwlock_init is provided in the thread library. */
+#undef HAVE_PTHREAD_RWLOCK_INIT_IN_THREAD_LIB
+
+/* Define to 1 if you have the <pwd.h> header file. */
+#undef HAVE_PWD_H
+
+/* Define if building with GNU Readline. */
+#undef HAVE_READLINE
+
+/* Define if regcomp exists and functions */
+#undef HAVE_REGCOMP
+
+/* Define to 1 if you have the `regexec' function. */
+#undef HAVE_REGEXEC
+
+/* Define to 1 if you have the <regexpr.h> header file. */
+#undef HAVE_REGEXPR_H
+
+/* Define to 1 if you have the <regex.h> header file. */
+#undef HAVE_REGEX_H
+
+/* Define to 1 if you have the `res_nclose' function. */
+#undef HAVE_RES_NCLOSE
+
+/* Define to 1 if you have the `res_ndestroy' function. */
+#undef HAVE_RES_NDESTROY
+
+/* Define to 1 if you have the `res_ninit' function. */
+#undef HAVE_RES_NINIT
+
+/* Define to 1 if you have the `res_nsearch' function. */
+#undef HAVE_RES_NSEARCH
+
+/* Define to 1 if you have the `res_search' function */
+#undef HAVE_RES_SEARCH
+
+/* Define to 1 if you have the `re_comp' function. */
+#undef HAVE_RE_COMP
+
+/* Define to 1 if you have the `re_exec' function. */
+#undef HAVE_RE_EXEC
+
+/* Define to 1 if you have the <sasl/sasl.h> header file. */
+#undef HAVE_SASL_SASL_H
+
+/* Define if struct sockaddr contains sa_len */
+#undef HAVE_SA_LEN
+
+/* Define to 1 if you have the `setegid' function. */
+#undef HAVE_SETEGID
+
+/* Define to 1 if you have the `setenv' function. */
+#undef HAVE_SETENV
+
+/* Define to 1 if you have the `seteuid' function. */
+#undef HAVE_SETEUID
+
+/* Define if setluid provided in OSF/1 security library */
+#undef HAVE_SETLUID
+
+/* Define to 1 if you have the `setregid' function. */
+#undef HAVE_SETREGID
+
+/* Define to 1 if you have the `setresgid' function. */
+#undef HAVE_SETRESGID
+
+/* Define to 1 if you have the `setresuid' function. */
+#undef HAVE_SETRESUID
+
+/* Define to 1 if you have the `setreuid' function. */
+#undef HAVE_SETREUID
+
+/* Define to 1 if you have the `setsid' function. */
+#undef HAVE_SETSID
+
+/* Define to 1 if you have the `setvbuf' function. */
+#undef HAVE_SETVBUF
+
+/* Define if there is a socklen_t type. If not, probably use size_t */
+#undef HAVE_SOCKLEN_T
+
+/* Define to 1 if you have the `srand' function. */
+#undef HAVE_SRAND
+
+/* Define to 1 if you have the `srand48' function. */
+#undef HAVE_SRAND48
+
+/* Define to 1 if you have the `srandom' function. */
+#undef HAVE_SRANDOM
+
+/* Define to 1 if the system has the type `ssize_t'. */
+#undef HAVE_SSIZE_T
+
+/* Define to 1 if you have the `stat' function. */
+#undef HAVE_STAT
+
+/* Define to 1 if you have the <stddef.h> header file. */
+#undef HAVE_STDDEF_H
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#undef HAVE_STDINT_H
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#undef HAVE_STDLIB_H
+
+/* Define to 1 if you have the `step' function. */
+#undef HAVE_STEP
+
+/* Define to 1 if you have the `strchr' function. */
+#undef HAVE_STRCHR
+
+/* Define to 1 if you have the `strdup' function. */
+#undef HAVE_STRDUP
+
+/* Define to 1 if you have the `strerror' function. */
+#undef HAVE_STRERROR
+
+/* Define to 1 if you have the `strerror_r' function. */
+#undef HAVE_STRERROR_R
+
+/* Define to 1 if you have the `strftime' function. */
+#undef HAVE_STRFTIME
+
+/* Define to 1 if you have the <strings.h> header file. */
+#undef HAVE_STRINGS_H
+
+/* Define to 1 if you have the <string.h> header file. */
+#undef HAVE_STRING_H
+
+/* Define to 1 if you have the `strlcpy' function. */
+#undef HAVE_STRLCPY
+
+/* Define to 1 if you have the `strptime' function. */
+#undef HAVE_STRPTIME
+
+/* Define to 1 if the system has the type `struct cmsghdr'. */
+#undef HAVE_STRUCT_CMSGHDR
+
+/* Define if there is a struct if_laddrconf. */
+#undef HAVE_STRUCT_IF_LADDRCONF
+
+/* Define to 1 if the system has the type `struct in6_pktinfo'. */
+#undef HAVE_STRUCT_IN6_PKTINFO
+
+/* Define to 1 if the system has the type `struct in_pktinfo'. */
+#undef HAVE_STRUCT_IN_PKTINFO
+
+/* Define if there is a struct lifconf. */
+#undef HAVE_STRUCT_LIFCONF
+
+/* Define to 1 if the system has the type `struct rt_msghdr'. */
+#undef HAVE_STRUCT_RT_MSGHDR
+
+/* Define to 1 if the system has the type `struct sockaddr_storage'. */
+#undef HAVE_STRUCT_SOCKADDR_STORAGE
+
+/* Define to 1 if `st_mtimensec' is a member of `struct stat'. */
+#undef HAVE_STRUCT_STAT_ST_MTIMENSEC
+
+/* Define to 1 if `st_mtimespec.tv_nsec' is a member of `struct stat'. */
+#undef HAVE_STRUCT_STAT_ST_MTIMESPEC_TV_NSEC
+
+/* Define to 1 if `st_mtim.tv_nsec' is a member of `struct stat'. */
+#undef HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC
+
+/* Define to 1 if you have the <sys/bswap.h> header file. */
+#undef HAVE_SYS_BSWAP_H
+
+/* Define to 1 if you have the <sys/dir.h> header file, and it defines `DIR'.
+ */
+#undef HAVE_SYS_DIR_H
+
+/* Define if sys_errlist in libc */
+#undef HAVE_SYS_ERRLIST
+
+/* Define to 1 if you have the <sys/file.h> header file. */
+#undef HAVE_SYS_FILE_H
+
+/* Define to 1 if you have the <sys/filio.h> header file. */
+#undef HAVE_SYS_FILIO_H
+
+/* Define to 1 if you have the <sys/ndir.h> header file, and it defines `DIR'.
+ */
+#undef HAVE_SYS_NDIR_H
+
+/* Define to 1 if you have the <sys/param.h> header file. */
+#undef HAVE_SYS_PARAM_H
+
+/* Define to 1 if you have the <sys/select.h> header file. */
+#undef HAVE_SYS_SELECT_H
+
+/* Define to 1 if you have the <sys/socket.h> header file. */
+#undef HAVE_SYS_SOCKET_H
+
+/* Define to 1 if you have the <sys/sockio.h> header file. */
+#undef HAVE_SYS_SOCKIO_H
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#undef HAVE_SYS_STAT_H
+
+/* Define to 1 if you have the <sys/time.h> header file. */
+#undef HAVE_SYS_TIME_H
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#undef HAVE_SYS_TYPES_H
+
+/* Define to 1 if you have the <sys/uio.h> header file. */
+#undef HAVE_SYS_UIO_H
+
+/* Define if tcl.h found */
+#undef HAVE_TCL_H
+
+/* Define if tcl/tcl.h found */
+#undef HAVE_TCL_TCL_H
+
+/* Define to 1 if you have the `timegm' function. */
+#undef HAVE_TIMEGM
+
+/* Define to 1 if you have the <time.h> header file. */
+#undef HAVE_TIME_H
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#undef HAVE_UNISTD_H
+
+/* Define to 1 if you have the `unsetenv' function. */
+#undef HAVE_UNSETENV
+
+/* Define to 1 if the system has the type `u_char'. */
+#undef HAVE_U_CHAR
+
+/* Define to 1 if the system has the type `u_int'. */
+#undef HAVE_U_INT
+
+/* Define to 1 if the system has the type `u_int16_t'. */
+#undef HAVE_U_INT16_T
+
+/* Define to 1 if the system has the type `u_int32_t'. */
+#undef HAVE_U_INT32_T
+
+/* Define to 1 if the system has the type `u_int8_t'. */
+#undef HAVE_U_INT8_T
+
+/* Define to 1 if the system has the type `u_long'. */
+#undef HAVE_U_LONG
+
+/* Define to 1 if you have the `vasprintf' function. */
+#undef HAVE_VASPRINTF
+
+/* Define to 1 if you have the `vsnprintf' function. */
+#undef HAVE_VSNPRINTF
+
+/* Define to 1 if you have the `vsprintf' function. */
+#undef HAVE_VSPRINTF
+
+/* Define if errno.h declares perror */
+#undef HDR_HAS_PERROR
+
+/* May need to be defined to enable IPv6 support, for example on IRIX */
+#undef INET6
+
+/* Define if MIT Project Athena default configuration should be used */
+#undef KRB5_ATHENA_COMPAT
+
+/* Define for DNS support of locating realms and KDCs */
+#undef KRB5_DNS_LOOKUP
+
+/* Define to enable DNS lookups of Kerberos realm names */
+#undef KRB5_DNS_LOOKUP_REALM
+
+/* Define if the KDC should return only vague error codes to clients */
+#undef KRBCONF_VAGUE_ERRORS
+
+/* define if the system header files are missing prototype for daemon() */
+#undef NEED_DAEMON_PROTO
+
+/* Define if in6addr_any is not defined in libc */
+#undef NEED_INSIXADDR_ANY
+
+/* define if the system header files are missing prototype for
+ ss_execute_command() */
+#undef NEED_SS_EXECUTE_COMMAND_PROTO
+
+/* define if the system header files are missing prototype for strptime() */
+#undef NEED_STRPTIME_PROTO
+
+/* define if the system header files are missing prototype for swab() */
+#undef NEED_SWAB_PROTO
+
+/* Define if need to declare sys_errlist */
+#undef NEED_SYS_ERRLIST
+
+/* define if the system header files are missing prototype for vasprintf() */
+#undef NEED_VASPRINTF_PROTO
+
+/* Define if the KDC should use no lookaside cache */
+#undef NOCACHE
+
+/* Define if references to pthread routines should be non-weak. */
+#undef NO_WEAK_PTHREADS
+
+/* Define if lex produes code with yylineno */
+#undef NO_YYLINENO
+
+/* Define to the address where bug reports for this package should be sent. */
+#undef PACKAGE_BUGREPORT
+
+/* Define to the full name of this package. */
+#undef PACKAGE_NAME
+
+/* Define to the full name and version of this package. */
+#undef PACKAGE_STRING
+
+/* Define to the one symbol short name of this package. */
+#undef PACKAGE_TARNAME
+
+/* Define to the home page for this package. */
+#undef PACKAGE_URL
+
+/* Define to the version of this package. */
+#undef PACKAGE_VERSION
+
+/* Define if pkinit crypto implementation is NSS */
+#undef PKINIT_CRYPTO_IMPL_NSS
+
+/* Define if setjmp indicates POSIX interface */
+#undef POSIX_SETJMP
+
+/* Define if POSIX signal handling is used */
+#undef POSIX_SIGNALS
+
+/* Define if POSIX signal handlers are used */
+#undef POSIX_SIGTYPE
+
+/* Define if termios.h exists and tcsetattr exists */
+#undef POSIX_TERMIOS
+
+/* Define to the necessary symbol if this constant uses a non-standard name on
+ your system. */
+#undef PTHREAD_CREATE_JOINABLE
+
+/* Define as the return type of signal handlers (`int' or `void'). */
+#undef RETSIGTYPE
+
+/* Define as return type of setrpcent */
+#undef SETRPCENT_TYPE
+
+/* Define for static plugin linkage */
+#undef STATIC_PLUGINS
+
+/* Define to 1 if you have the ANSI C header files. */
+#undef STDC_HEADERS
+
+/* Define to 1 if strerror_r returns char *. */
+#undef STRERROR_R_CHAR_P
+
+/* Define if sys_errlist is defined in errno.h */
+#undef SYS_ERRLIST_DECLARED
+
+/* Define to 1 if you can safely include both <sys/time.h> and <time.h>. */
+#undef TIME_WITH_SYS_TIME
+
+/* Define if no TLS implementation is selected */
+#undef TLS_IMPL_NONE
+
+/* Define if TLS implementation is OpenSSL */
+#undef TLS_IMPL_OPENSSL
+
+/* Define if you have dirent.h functionality */
+#undef USE_DIRENT_H
+
+/* Define if dlopen should be used */
+#undef USE_DLOPEN
+
+/* Define if the keyring ccache should be enabled */
+#undef USE_KEYRING_CCACHE
+
+/* Define if link-time options for library finalization will be used */
+#undef USE_LINKER_FINI_OPTION
+
+/* Define if link-time options for library initialization will be used */
+#undef USE_LINKER_INIT_OPTION
+
+/* Define if sigprocmask should be used */
+#undef USE_SIGPROCMASK
+
+/* Define if wait takes int as a argument */
+#undef WAIT_USES_INT
+
+/* Define to 1 if `lex' declares `yytext' as a `char *' by default, not a
+ `char[]'. */
+#undef YYTEXT_POINTER
+
+/* Define to enable extensions in glibc */
+#undef _GNU_SOURCE
+
+/* Define to enable C11 extensions */
+#undef __STDC_WANT_LIB_EXT1__
+
+/* Define to empty if `const' does not conform to ANSI C. */
+#undef const
+
+/* Define to `int' if <sys/types.h> doesn't define. */
+#undef gid_t
+
+/* Define to `__inline__' or `__inline' if that's what the C compiler
+ calls it, or to nothing if 'inline' is not supported under any name. */
+#ifndef __cplusplus
+#undef inline
+#endif
+
+/* Define krb5_sigtype to type of signal handler */
+#undef krb5_sigtype
+
+/* Define to `int' if <sys/types.h> does not define. */
+#undef mode_t
+
+/* Define to `long int' if <sys/types.h> does not define. */
+#undef off_t
+
+/* Define to `long' if <sys/types.h> does not define. */
+#undef time_t
+
+/* Define to `int' if <sys/types.h> doesn't define. */
+#undef uid_t
+
+
+#if defined(__GNUC__) && !defined(inline)
+/* Silence gcc pedantic warnings about ANSI C. */
+# define inline __inline__
+#endif
+#endif /* KRB5_AUTOCONF_H */
+
diff --git a/src/include/copyright.h b/src/include/copyright.h
new file mode 100644
index 000000000000..705e0a757e78
--- /dev/null
+++ b/src/include/copyright.h
@@ -0,0 +1,41 @@
+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/*
+ * Copyright (C) 1989-1994 by the Massachusetts Institute of Technology,
+ * Cambridge, MA, USA. All Rights Reserved.
+ *
+ * This software is being provided to you, the LICENSEE, by the
+ * Massachusetts Institute of Technology (M.I.T.) under the following
+ * license. By obtaining, using and/or copying this software, you agree
+ * that you have read, understood, and will comply with these terms and
+ * conditions:
+ *
+ * Export of this software from the United States of America may
+ * require a specific license from the United States Government.
+ * It is the responsibility of any person or organization contemplating
+ * export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify and distribute
+ * this software and its documentation for any purpose and without fee or
+ * royalty is hereby granted, provided that you agree to comply with the
+ * following copyright notice and statements, including the disclaimer, and
+ * that the same appear on ALL copies of the software and documentation,
+ * including modifications that you make for internal use or for
+ * distribution:
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS", AND M.I.T. MAKES NO REPRESENTATIONS
+ * OR WARRANTIES, EXPRESS OR IMPLIED. By way of example, but not
+ * limitation, M.I.T. MAKES NO REPRESENTATIONS OR WARRANTIES OF
+ * MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF
+ * THE LICENSED SOFTWARE OR DOCUMENTATION WILL NOT INFRINGE ANY THIRD PARTY
+ * PATENTS, COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS.
+ *
+ * The name of the Massachusetts Institute of Technology or M.I.T. may NOT
+ * be used in advertising or publicity pertaining to distribution of the
+ * software. Title to copyright in this software and any associated
+ * documentation shall at all times remain with M.I.T., and USER agrees to
+ * preserve same.
+ *
+ * Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ */
diff --git a/src/include/deps b/src/include/deps
new file mode 100644
index 000000000000..2feac3c9d388
--- /dev/null
+++ b/src/include/deps
@@ -0,0 +1 @@
+# No dependencies here.
diff --git a/src/include/fake-addrinfo.h b/src/include/fake-addrinfo.h
new file mode 100644
index 000000000000..03666a0aaaa7
--- /dev/null
+++ b/src/include/fake-addrinfo.h
@@ -0,0 +1,234 @@
+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/*
+ * Copyright (C) 2001,2002,2003,2004 by the Massachusetts Institute of Technology,
+ * Cambridge, MA, USA. All Rights Reserved.
+ *
+ * This software is being provided to you, the LICENSEE, by the
+ * Massachusetts Institute of Technology (M.I.T.) under the following
+ * license. By obtaining, using and/or copying this software, you agree
+ * that you have read, understood, and will comply with these terms and
+ * conditions:
+ *
+ * Export of this software from the United States of America may
+ * require a specific license from the United States Government.
+ * It is the responsibility of any person or organization contemplating
+ * export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify and distribute
+ * this software and its documentation for any purpose and without fee or
+ * royalty is hereby granted, provided that you agree to comply with the
+ * following copyright notice and statements, including the disclaimer, and
+ * that the same appear on ALL copies of the software and documentation,
+ * including modifications that you make for internal use or for
+ * distribution:
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS", AND M.I.T. MAKES NO REPRESENTATIONS
+ * OR WARRANTIES, EXPRESS OR IMPLIED. By way of example, but not
+ * limitation, M.I.T. MAKES NO REPRESENTATIONS OR WARRANTIES OF
+ * MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF
+ * THE LICENSED SOFTWARE OR DOCUMENTATION WILL NOT INFRINGE ANY THIRD PARTY
+ * PATENTS, COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS.
+ *
+ * The name of the Massachusetts Institute of Technology or M.I.T. may NOT
+ * be used in advertising or publicity pertaining to distribution of the
+ * software. Title to copyright in this software and any associated
+ * documentation shall at all times remain with M.I.T., and USER agrees to
+ * preserve same.
+ *
+ * Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ */
+
+/* Approach overview:
+
+ If a system version is available but buggy, save handles to it (via
+ inline functions in a support library), redefine the names to refer
+ to library functions, and in those functions, call the system
+ versions and fix up the returned data. Use the native data
+ structures and flag values.
+
+ If no system version exists, use gethostby* and fake it. Define
+ the data structures and flag values locally.
+
+
+ On Mac OS X, getaddrinfo results aren't cached (though
+ gethostbyname results are), so we need to build a cache here. Now
+ things are getting really messy. Because the cache is in use, we
+ use getservbyname, and throw away thread safety. (Not that the
+ cache is thread safe, but when we get locking support, that'll be
+ dealt with.) This code needs tearing down and rebuilding, soon.
+
+
+ Note that recent Windows developers' code has an interesting hack:
+ When you include the right header files, with the right set of
+ macros indicating system versions, you'll get an inline function
+ that looks for getaddrinfo (or whatever) in the system library, and
+ calls it if it's there. If it's not there, it fakes it with
+ gethostby* calls.
+
+ We're taking a simpler approach: A system provides these routines or
+ it does not.
+
+ Someday, we may want to take into account different versions (say,
+ different revs of GNU libc) where some are broken in one way, and
+ some work or are broken in another way. Cross that bridge when we
+ come to it. */
+
+/* To do, maybe:
+
+ + For AIX 4.3.3, using the RFC 2133 definition: Implement
+ AI_NUMERICHOST. It's not defined in the header file.
+
+ For certain (old?) versions of GNU libc, AI_NUMERICHOST is
+ defined but not implemented.
+
+ + Use gethostbyname2, inet_aton and other IPv6 or thread-safe
+ functions if available. But, see
+ http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=135182 for one
+ gethostbyname2 problem on Linux. And besides, if a platform is
+ supporting IPv6 at all, they really should be doing getaddrinfo
+ by now.
+
+ + inet_ntop, inet_pton
+
+ + Conditionally export/import the function definitions, so a
+ library can have a single copy instead of multiple.
+
+ + Upgrade host requirements to include working implementations of
+ these functions, and throw all this away. Pleeease? :-) */
+
+#ifndef FAI_DEFINED
+#define FAI_DEFINED
+#include "port-sockets.h"
+#include "socket-utils.h"
+
+#if !defined (HAVE_GETADDRINFO)
+
+#undef addrinfo
+#define addrinfo my_fake_addrinfo
+
+struct addrinfo {
+ int ai_family; /* PF_foo */
+ int ai_socktype; /* SOCK_foo */
+ int ai_protocol; /* 0, IPPROTO_foo */
+ int ai_flags; /* AI_PASSIVE etc */
+ size_t ai_addrlen; /* real length of socket address */
+ char *ai_canonname; /* canonical name of host */
+ struct sockaddr *ai_addr; /* pointer to variable-size address */
+ struct addrinfo *ai_next; /* next in linked list */
+};
+
+#undef AI_PASSIVE
+#define AI_PASSIVE 0x01
+#undef AI_CANONNAME
+#define AI_CANONNAME 0x02
+#undef AI_NUMERICHOST
+#define AI_NUMERICHOST 0x04
+/* RFC 2553 says these are part of the interface for getipnodebyname,
+ not for getaddrinfo. RFC 3493 says they're part of the interface
+ for getaddrinfo, and getipnodeby* are deprecated. Our fake
+ getaddrinfo implementation here does IPv4 only anyways. */
+#undef AI_V4MAPPED
+#define AI_V4MAPPED 0
+#undef AI_ADDRCONFIG
+#define AI_ADDRCONFIG 0
+#undef AI_ALL
+#define AI_ALL 0
+#undef AI_DEFAULT
+#define AI_DEFAULT (AI_V4MAPPED|AI_ADDRCONFIG)
+
+#ifndef NI_MAXHOST
+#define NI_MAXHOST 1025
+#endif
+#ifndef NI_MAXSERV
+#define NI_MAXSERV 32
+#endif
+
+#undef NI_NUMERICHOST
+#define NI_NUMERICHOST 0x01
+#undef NI_NUMERICSERV
+#define NI_NUMERICSERV 0x02
+#undef NI_NAMEREQD
+#define NI_NAMEREQD 0x04
+#undef NI_DGRAM
+#define NI_DGRAM 0x08
+#undef NI_NOFQDN
+#define NI_NOFQDN 0x10
+
+
+#undef EAI_ADDRFAMILY
+#define EAI_ADDRFAMILY 1
+#undef EAI_AGAIN
+#define EAI_AGAIN 2
+#undef EAI_BADFLAGS
+#define EAI_BADFLAGS 3
+#undef EAI_FAIL
+#define EAI_FAIL 4
+#undef EAI_FAMILY
+#define EAI_FAMILY 5
+#undef EAI_MEMORY
+#define EAI_MEMORY 6
+#undef EAI_NODATA
+#define EAI_NODATA 7
+#undef EAI_NONAME
+#define EAI_NONAME 8
+#undef EAI_SERVICE
+#define EAI_SERVICE 9
+#undef EAI_SOCKTYPE
+#define EAI_SOCKTYPE 10
+#undef EAI_SYSTEM
+#define EAI_SYSTEM 11
+
+#endif /* ! HAVE_GETADDRINFO */
+
+/* Fudge things on older gai implementations. */
+/* AIX 4.3.3 is based on RFC 2133; no AI_NUMERICHOST. */
+#ifndef AI_NUMERICHOST
+# define AI_NUMERICHOST 0
+#endif
+/* Partial RFC 2553 implementations may not have AI_ADDRCONFIG and
+ friends, which RFC 3493 says are now part of the getaddrinfo
+ interface, and we'll want to use. */
+#ifndef AI_ADDRCONFIG
+# define AI_ADDRCONFIG 0
+#endif
+#ifndef AI_V4MAPPED
+# define AI_V4MAPPED 0
+#endif
+#ifndef AI_ALL
+# define AI_ALL 0
+#endif
+#ifndef AI_DEFAULT
+# define AI_DEFAULT (AI_ADDRCONFIG|AI_V4MAPPED)
+#endif
+
+#if defined(NEED_INSIXADDR_ANY)
+/* If compiling with IPv6 support and C library does not define in6addr_any */
+extern const struct in6_addr krb5int_in6addr_any;
+#undef in6addr_any
+#define in6addr_any krb5int_in6addr_any
+#endif
+
+/* Call out to stuff defined in libkrb5support. */
+extern int krb5int_getaddrinfo (const char *node, const char *service,
+ const struct addrinfo *hints,
+ struct addrinfo **aip);
+extern void krb5int_freeaddrinfo (struct addrinfo *ai);
+extern const char *krb5int_gai_strerror(int err);
+extern int krb5int_getnameinfo (const struct sockaddr *sa, socklen_t salen,
+ char *hbuf, size_t hbuflen,
+ char *sbuf, size_t sbuflen,
+ int flags);
+#ifndef IMPLEMENT_FAKE_GETADDRINFO
+#undef getaddrinfo
+#define getaddrinfo krb5int_getaddrinfo
+#undef freeaddrinfo
+#define freeaddrinfo krb5int_freeaddrinfo
+#undef gai_strerror
+#define gai_strerror krb5int_gai_strerror
+#undef getnameinfo
+#define getnameinfo krb5int_getnameinfo
+#endif
+
+#endif /* FAI_DEFINED */
diff --git a/src/include/foreachaddr.h b/src/include/foreachaddr.h
new file mode 100644
index 000000000000..9ed35eab9ef3
--- /dev/null
+++ b/src/include/foreachaddr.h
@@ -0,0 +1,66 @@
+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/* include/foreachaddr.h */
+/*
+ * Copyright 1990,1991,2000,2001,2002,2004 by the Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ * require a specific license from the United States Government.
+ * It is the responsibility of any person or organization contemplating
+ * export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission. Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose. It is provided "as is" without express
+ * or implied warranty.
+ */
+
+/*
+ *
+ * Iterate over the protocol addresses supported by this host, invoking
+ * a callback function or three supplied by the caller.
+ *
+ * XNS support is untested, but "should just work". (Hah!)
+ */
+
+/* This function iterates over all the addresses it can find for the
+ local system, in one or two passes. In each pass, and between the
+ two, it can invoke callback functions supplied by the caller. The
+ two passes should operate on the same information, though not
+ necessarily in the same order each time. Duplicate and local
+ addresses should be eliminated. Storage passed to callback
+ functions should not be assumed to be valid after foreach_localaddr
+ returns.
+
+ The int return value is an errno value (XXX or krb5_error_code
+ returned for a socket error) if something internal to
+ foreach_localaddr fails. If one of the callback functions wants to
+ indicate an error, it should store something via the 'data' handle.
+ If any callback function returns a non-zero value,
+ foreach_localaddr will clean up and return immediately.
+
+ Multiple definitions are provided below, dependent on various
+ system facilities for extracting the necessary information. */
+
+extern int
+krb5int_foreach_localaddr (/*@null@*/ void *data,
+ int (*pass1fn) (/*@null@*/ void *,
+ struct sockaddr *) /*@*/,
+ /*@null@*/ int (*betweenfn) (/*@null@*/ void *) /*@*/,
+ /*@null@*/ int (*pass2fn) (/*@null@*/ void *,
+ struct sockaddr *) /*@*/)
+#if defined(DEBUG) || defined(TEST)
+/*@modifies fileSystem@*/
+#endif
+ ;
+
+#define foreach_localaddr krb5int_foreach_localaddr
diff --git a/src/include/gssapi.h b/src/include/gssapi.h
new file mode 100644
index 000000000000..9383dabdc0d0
--- /dev/null
+++ b/src/include/gssapi.h
@@ -0,0 +1,6 @@
+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/*
+ * Wrapper so that #include <gssapi.h> will work without special include
+ * paths.
+ */
+#include <gssapi/gssapi.h>
diff --git a/src/include/gssrpc/auth.h b/src/include/gssrpc/auth.h
new file mode 100644
index 000000000000..0f653fcc7638
--- /dev/null
+++ b/src/include/gssrpc/auth.h
@@ -0,0 +1,221 @@
+/* @(#)auth.h 2.3 88/08/07 4.0 RPCSRC; from 1.17 88/02/08 SMI */
+/*
+ * Copyright (c) 2010, Oracle America, Inc.
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * * Neither the name of the "Oracle America, Inc." nor the names of
+ * its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * auth.h, Authentication interface.
+ *
+ * The data structures are completely opaque to the client. The client
+ * is required to pass a AUTH * to routines that create rpc
+ * "sessions".
+ */
+#ifndef GSSRPC_AUTH_H
+#define GSSRPC_AUTH_H
+
+#include <gssrpc/xdr.h>
+
+GSSRPC__BEGIN_DECLS
+
+#define MAX_AUTH_BYTES 400
+#define MAXNETNAMELEN 255 /* maximum length of network user's name */
+
+/*
+ * Status returned from authentication check
+ */
+enum auth_stat {
+ AUTH_OK=0,
+ /*
+ * failed at remote end
+ */
+ AUTH_BADCRED=1, /* bogus credentials (seal broken) */
+ AUTH_REJECTEDCRED=2, /* client should begin new session */
+ AUTH_BADVERF=3, /* bogus verifier (seal broken) */
+ AUTH_REJECTEDVERF=4, /* verifier expired or was replayed */
+ AUTH_TOOWEAK=5, /* rejected due to security reasons */
+ /*
+ * failed locally
+ */
+ AUTH_INVALIDRESP=6, /* bogus response verifier */
+ AUTH_FAILED=7, /* some unknown reason */
+ /*
+ * RPCSEC_GSS errors
+ */
+ RPCSEC_GSS_CREDPROBLEM = 13,
+ RPCSEC_GSS_CTXPROBLEM = 14
+};
+
+union des_block {
+#if 0 /* XXX nothing uses this, anyway */
+ struct {
+ uint32_t high;
+ uint32_t low;
+ } key;
+#endif
+ char c[8];
+};
+typedef union des_block des_block;
+extern bool_t xdr_des_block(XDR *, des_block *);
+
+/*
+ * Authentication info. Opaque to client.
+ */
+struct opaque_auth {
+ enum_t oa_flavor; /* flavor of auth */
+ caddr_t oa_base; /* address of more auth stuff */
+ u_int oa_length; /* not to exceed MAX_AUTH_BYTES */
+};
+
+
+/*
+ * Auth handle, interface to client side authenticators.
+ */
+struct rpc_msg;
+
+typedef struct AUTH {
+ struct opaque_auth ah_cred;
+ struct opaque_auth ah_verf;
+ union des_block ah_key;
+ struct auth_ops {
+ void (*ah_nextverf)(struct AUTH *);
+ /* nextverf & serialize */
+ int (*ah_marshal)(struct AUTH *, XDR *);
+ /* validate varifier */
+ int (*ah_validate)(struct AUTH *,
+ struct opaque_auth *);
+ /* refresh credentials */
+ int (*ah_refresh)(struct AUTH *, struct rpc_msg *);
+ /* destroy this structure */
+ void (*ah_destroy)(struct AUTH *);
+ /* encode data for wire */
+ int (*ah_wrap)(struct AUTH *, XDR *,
+ xdrproc_t, caddr_t);
+ /* decode data from wire */
+ int (*ah_unwrap)(struct AUTH *, XDR *,
+ xdrproc_t, caddr_t);
+ } *ah_ops;
+ void *ah_private;
+} AUTH;
+
+
+/*
+ * Authentication ops.
+ * The ops and the auth handle provide the interface to the authenticators.
+ *
+ * AUTH *auth;
+ * XDR *xdrs;
+ * struct opaque_auth verf;
+ */
+#define AUTH_NEXTVERF(auth) \
+ ((*((auth)->ah_ops->ah_nextverf))(auth))
+#define auth_nextverf(auth) \
+ ((*((auth)->ah_ops->ah_nextverf))(auth))
+
+#define AUTH_MARSHALL(auth, xdrs) \
+ ((*((auth)->ah_ops->ah_marshal))(auth, xdrs))
+#define auth_marshall(auth, xdrs) \
+ ((*((auth)->ah_ops->ah_marshal))(auth, xdrs))
+
+#define AUTH_VALIDATE(auth, verfp) \
+ ((*((auth)->ah_ops->ah_validate))((auth), verfp))
+#define auth_validate(auth, verfp) \
+ ((*((auth)->ah_ops->ah_validate))((auth), verfp))
+
+#define AUTH_REFRESH(auth, msg) \
+ ((*((auth)->ah_ops->ah_refresh))(auth, msg))
+#define auth_refresh(auth, msg) \
+ ((*((auth)->ah_ops->ah_refresh))(auth, msg))
+
+#define AUTH_WRAP(auth, xdrs, xfunc, xwhere) \
+ ((*((auth)->ah_ops->ah_wrap))(auth, xdrs, \
+ xfunc, xwhere))
+#define auth_wrap(auth, xdrs, xfunc, xwhere) \
+ ((*((auth)->ah_ops->ah_wrap))(auth, xdrs, \
+ xfunc, xwhere))
+#define AUTH_UNWRAP(auth, xdrs, xfunc, xwhere) \
+ ((*((auth)->ah_ops->ah_unwrap))(auth, xdrs, \
+ xfunc, xwhere))
+#define auth_unwrap(auth, xdrs, xfunc, xwhere) \
+ ((*((auth)->ah_ops->ah_unwrap))(auth, xdrs, \
+ xfunc, xwhere))
+
+#define AUTH_DESTROY(auth) \
+ ((*((auth)->ah_ops->ah_destroy))(auth))
+#define auth_destroy(auth) \
+ ((*((auth)->ah_ops->ah_destroy))(auth))
+
+
+#ifdef GSSRPC__IMPL
+/* RENAMED: should be _null_auth if we can use reserved namespace. */
+extern struct opaque_auth gssrpc__null_auth;
+#endif
+
+/*
+ * These are the various implementations of client side authenticators.
+ */
+
+/*
+ * Unix style authentication
+ * AUTH *authunix_create(machname, uid, gid, len, aup_gids)
+ * char *machname;
+ * int uid;
+ * int gid;
+ * int len;
+ * int *aup_gids;
+ */
+extern AUTH *authunix_create(char *machname, int uid, int gid, int len,
+ int *aup_gids);
+extern AUTH *authunix_create_default(void); /* takes no parameters */
+extern AUTH *authnone_create(void); /* takes no parameters */
+extern AUTH *authdes_create();
+extern bool_t xdr_opaque_auth(XDR *, struct opaque_auth *);
+
+#define AUTH_NONE 0 /* no authentication */
+#define AUTH_NULL 0 /* backward compatibility */
+#define AUTH_UNIX 1 /* unix style (uid, gids) */
+#define AUTH_SHORT 2 /* short hand unix style */
+#define AUTH_DES 3 /* des style (encrypted timestamps) */
+#define AUTH_GSSAPI 300001 /* GSS-API style */
+#define RPCSEC_GSS 6 /* RPCSEC_GSS */
+
+#if 0
+/*
+ * BACKWARDS COMPATIBILIY! OpenV*Secure 1.0 had AUTH_GSSAPI == 4. We
+ * need to accept this value until 1.0 is dead.
+ */
+/* This conflicts with AUTH_KERB (Solaris). */
+#define AUTH_GSSAPI_COMPAT 4
+#endif
+
+GSSRPC__END_DECLS
+
+#endif /* !defined(GSSRPC_AUTH_H) */
diff --git a/src/include/gssrpc/auth_gss.h b/src/include/gssrpc/auth_gss.h
new file mode 100644
index 000000000000..9fa87742fe80
--- /dev/null
+++ b/src/include/gssrpc/auth_gss.h
@@ -0,0 +1,148 @@
+/* include/gssrpc/auth_gss.h */
+/*
+ Copyright (c) 2000 The Regents of the University of Michigan.
+ All rights reserved.
+
+ Copyright (c) 2000 Dug Song <dugsong@UMICH.EDU>.
+ All rights reserved, all wrongs reversed.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ 3. Neither the name of the University nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ Id: auth_gss.h,v 1.13 2002/05/08 16:54:33 andros Exp
+*/
+
+#ifndef GSSRPC_AUTH_GSS_H
+#define GSSRPC_AUTH_GSS_H
+
+#include <gssrpc/rpc.h>
+#include <gssrpc/clnt.h>
+#ifdef HAVE_HEIMDAL
+#include <gssapi.h>
+#else
+#include <gssapi/gssapi.h>
+#endif
+
+GSSRPC__BEGIN_DECLS
+
+/* RPCSEC_GSS control procedures. */
+typedef enum {
+ RPCSEC_GSS_DATA = 0,
+ RPCSEC_GSS_INIT = 1,
+ RPCSEC_GSS_CONTINUE_INIT = 2,
+ RPCSEC_GSS_DESTROY = 3
+} rpc_gss_proc_t;
+
+/* RPCSEC_GSS services. */
+typedef enum {
+ RPCSEC_GSS_SVC_NONE = 1,
+ RPCSEC_GSS_SVC_INTEGRITY = 2,
+ RPCSEC_GSS_SVC_PRIVACY = 3
+} rpc_gss_svc_t;
+
+#define RPCSEC_GSS_VERSION 1
+
+/* RPCSEC_GSS security triple. */
+struct rpc_gss_sec {
+ gss_OID mech; /* mechanism */
+ gss_qop_t qop; /* quality of protection */
+ rpc_gss_svc_t svc; /* service */
+ gss_cred_id_t cred; /* cred handle */
+ uint32_t req_flags; /* req flags for init_sec_context */
+};
+
+/* Private data required for kernel implementation */
+struct authgss_private_data {
+ gss_ctx_id_t pd_ctx; /* Session context handle */
+ gss_buffer_desc pd_ctx_hndl; /* Credentials context handle */
+ uint32_t pd_seq_win; /* Sequence window */
+};
+
+/* Krb 5 default mechanism
+#define KRB5OID "1.2.840.113554.1.2.2"
+
+gss_OID_desc krb5oid = {
+ 20, KRB5OID
+};
+ */
+
+/*
+struct rpc_gss_sec krb5mech = {
+ (gss_OID)&krb5oid,
+ GSS_QOP_DEFAULT,
+ RPCSEC_GSS_SVC_NONE
+};
+*/
+
+/* Credentials. */
+struct rpc_gss_cred {
+ u_int gc_v; /* version */
+ rpc_gss_proc_t gc_proc; /* control procedure */
+ uint32_t gc_seq; /* sequence number */
+ rpc_gss_svc_t gc_svc; /* service */
+ gss_buffer_desc gc_ctx; /* context handle */
+};
+
+/* Context creation response. */
+struct rpc_gss_init_res {
+ gss_buffer_desc gr_ctx; /* context handle */
+ uint32_t gr_major; /* major status */
+ uint32_t gr_minor; /* minor status */
+ uint32_t gr_win; /* sequence window */
+ gss_buffer_desc gr_token; /* token */
+};
+
+/* Maximum sequence number value. */
+#define MAXSEQ 0x80000000
+
+/* Prototypes. */
+bool_t xdr_rpc_gss_buf (XDR *xdrs, gss_buffer_t, u_int maxsize);
+bool_t xdr_rpc_gss_cred (XDR *xdrs, struct rpc_gss_cred *p);
+bool_t xdr_rpc_gss_init_args (XDR *xdrs, gss_buffer_desc *p);
+bool_t xdr_rpc_gss_init_res (XDR *xdrs, struct rpc_gss_init_res *p);
+bool_t xdr_rpc_gss_data (XDR *xdrs, xdrproc_t xdr_func,
+ caddr_t xdr_ptr, gss_ctx_id_t ctx,
+ gss_qop_t qop, rpc_gss_svc_t svc,
+ uint32_t seq);
+bool_t xdr_rpc_gss_wrap_data (XDR *xdrs, xdrproc_t xdr_func, caddr_t
+ xdr_ptr, gss_ctx_id_t ctx, gss_qop_t qop,
+ rpc_gss_svc_t svc, uint32_t seq);
+bool_t xdr_rpc_gss_unwrap_data (XDR *xdrs, xdrproc_t xdr_func, caddr_t
+ xdr_ptr, gss_ctx_id_t ctx, gss_qop_t qop,
+ rpc_gss_svc_t svc, uint32_t seq);
+
+AUTH *authgss_create (CLIENT *, gss_name_t, struct rpc_gss_sec *);
+AUTH *authgss_create_default (CLIENT *, char *, struct rpc_gss_sec *);
+bool_t authgss_service (AUTH *auth, int svc);
+bool_t authgss_get_private_data (AUTH *auth, struct authgss_private_data *);
+
+#ifdef GSSRPC__IMPL
+void log_debug (const char *fmt, ...);
+void log_status (char *m, OM_uint32 major, OM_uint32 minor);
+void log_hexdump (const u_char *buf, int len, int offset);
+#endif
+
+GSSRPC__END_DECLS
+#endif /* !defined(GSSRPC_AUTH_GSS_H) */
diff --git a/src/include/gssrpc/auth_gssapi.h b/src/include/gssrpc/auth_gssapi.h
new file mode 100644
index 000000000000..9d94853228ef
--- /dev/null
+++ b/src/include/gssrpc/auth_gssapi.h
@@ -0,0 +1,162 @@
+/* include/gssrpc/auth_gssapi.h - GSS-API style auth parameters for RPC */
+/*
+ * Copyright 1993 OpenVision Technologies, Inc., All Rights Reserved.
+ */
+
+#ifndef GSSRPC_AUTH_GSSAPI_H
+#define GSSRPC_AUTH_GSSAPI_H
+
+GSSRPC__BEGIN_DECLS
+
+#define AUTH_GSSAPI_EXIT 0
+#define AUTH_GSSAPI_INIT 1
+#define AUTH_GSSAPI_CONTINUE_INIT 2
+#define AUTH_GSSAPI_MSG 3
+#define AUTH_GSSAPI_DESTROY 4
+
+/*
+ * Yuck. Some sys/types.h files leak symbols
+ */
+#ifdef major
+#undef major
+#endif
+#ifdef minor
+#undef minor
+#endif
+
+typedef struct _auth_gssapi_name {
+ char *name;
+ gss_OID type;
+} auth_gssapi_name;
+
+typedef struct _auth_gssapi_creds {
+ uint32_t version;
+ bool_t auth_msg;
+ gss_buffer_desc client_handle;
+} auth_gssapi_creds;
+
+typedef struct _auth_gssapi_init_arg {
+ uint32_t version;
+ gss_buffer_desc token;
+} auth_gssapi_init_arg;
+
+typedef struct _auth_gssapi_init_res {
+ uint32_t version;
+ gss_buffer_desc client_handle;
+ OM_uint32 gss_major, gss_minor;
+ gss_buffer_desc token;
+ gss_buffer_desc signed_isn;
+} auth_gssapi_init_res;
+
+typedef void (*auth_gssapi_log_badauth_func)
+ (OM_uint32 major,
+ OM_uint32 minor,
+ struct sockaddr_in *raddr,
+ caddr_t data);
+
+/* auth_gssapi_log_badauth_func is IPv4-specific; this version gives the
+ * transport handle so the fd can be used to get the address. */
+typedef void (*auth_gssapi_log_badauth2_func)
+ (OM_uint32 major,
+ OM_uint32 minor,
+ SVCXPRT *xprt,
+ caddr_t data);
+
+typedef void (*auth_gssapi_log_badverf_func)
+ (gss_name_t client,
+ gss_name_t server,
+ struct svc_req *rqst,
+ struct rpc_msg *msg,
+ caddr_t data);
+
+typedef void (*auth_gssapi_log_miscerr_func)
+ (struct svc_req *rqst,
+ struct rpc_msg *msg,
+ char *error,
+ caddr_t data);
+
+bool_t xdr_gss_buf(XDR *, gss_buffer_t);
+bool_t xdr_authgssapi_creds(XDR *, auth_gssapi_creds *);
+bool_t xdr_authgssapi_init_arg(XDR *, auth_gssapi_init_arg *);
+bool_t xdr_authgssapi_init_res(XDR *, auth_gssapi_init_res *);
+
+bool_t auth_gssapi_wrap_data
+(OM_uint32 *major, OM_uint32 *minor,
+ gss_ctx_id_t context, uint32_t seq_num, XDR
+ *out_xdrs, bool_t (*xdr_func)(), caddr_t
+ xdr_ptr);
+bool_t auth_gssapi_unwrap_data
+(OM_uint32 *major, OM_uint32 *minor,
+ gss_ctx_id_t context, uint32_t seq_num, XDR
+ *in_xdrs, bool_t (*xdr_func)(), caddr_t
+ xdr_ptr);
+
+AUTH *auth_gssapi_create
+(CLIENT *clnt,
+ OM_uint32 *major_status,
+ OM_uint32 *minor_status,
+ gss_cred_id_t claimant_cred_handle,
+ gss_name_t target_name,
+ gss_OID mech_type,
+ OM_uint32 req_flags,
+ OM_uint32 time_req,
+ gss_OID *actual_mech_type,
+ OM_uint32 *ret_flags,
+ OM_uint32 *time_rec);
+
+AUTH *auth_gssapi_create_default
+(CLIENT *clnt, char *service_name);
+
+void auth_gssapi_display_status
+(char *msg, OM_uint32 major,
+ OM_uint32 minor);
+
+bool_t auth_gssapi_seal_seq
+(gss_ctx_id_t context, uint32_t seq_num, gss_buffer_t out_buf);
+
+bool_t auth_gssapi_unseal_seq
+(gss_ctx_id_t context, gss_buffer_t in_buf, uint32_t *seq_num);
+
+bool_t svcauth_gssapi_set_names
+(auth_gssapi_name *names, int num);
+void svcauth_gssapi_unset_names
+(void);
+
+void svcauth_gssapi_set_log_badauth_func
+(auth_gssapi_log_badauth_func func,
+ caddr_t data);
+void svcauth_gssapi_set_log_badauth2_func
+(auth_gssapi_log_badauth2_func func,
+ caddr_t data);
+void svcauth_gssapi_set_log_badverf_func
+(auth_gssapi_log_badverf_func func,
+ caddr_t data);
+void svcauth_gssapi_set_log_miscerr_func
+(auth_gssapi_log_miscerr_func func,
+ caddr_t data);
+
+void svcauth_gss_set_log_badauth_func(auth_gssapi_log_badauth_func,
+ caddr_t);
+void svcauth_gss_set_log_badauth2_func(auth_gssapi_log_badauth2_func,
+ caddr_t);
+void svcauth_gss_set_log_badverf_func(auth_gssapi_log_badverf_func,
+ caddr_t);
+void svcauth_gss_set_log_miscerr_func(auth_gssapi_log_miscerr_func,
+ caddr_t data);
+
+#define GSS_COPY_BUFFER(dest, src) { \
+ (dest).length = (src).length; \
+ (dest).value = (src).value; }
+
+#define GSS_DUP_BUFFER(dest, src) { \
+ (dest).length = (src).length; \
+ (dest).value = (void *) malloc((dest).length); \
+ memcpy((dest).value, (src).value, (dest).length); }
+
+#define GSS_BUFFERS_EQUAL(b1, b2) (((b1).length == (b2).length) && \
+ !memcmp((b1).value,(b2).value,(b1.length)))
+
+
+GSSRPC__END_DECLS
+
+#endif /* !defined(GSSRPC_AUTH_GSSAPI_H) */
diff --git a/src/include/gssrpc/auth_unix.h b/src/include/gssrpc/auth_unix.h
new file mode 100644
index 000000000000..6dda1af5cc4c
--- /dev/null
+++ b/src/include/gssrpc/auth_unix.h
@@ -0,0 +1,82 @@
+/* @(#)auth_unix.h 2.2 88/07/29 4.0 RPCSRC; from 1.8 88/02/08 SMI */
+/*
+ * Copyright (c) 2010, Oracle America, Inc.
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * * Neither the name of the "Oracle America, Inc." nor the names of
+ * its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/* @(#)auth_unix.h 1.5 86/07/16 SMI */
+
+/*
+ * auth_unix.h, Protocol for UNIX style authentication parameters for RPC
+ */
+
+#ifndef GSSRPC_AUTH_UNIX_H
+#define GSSRPC_AUTH_UNIX_H
+
+GSSRPC__BEGIN_DECLS
+/*
+ * The system is very weak. The client uses no encryption for it
+ * credentials and only sends null verifiers. The server sends backs
+ * null verifiers or optionally a verifier that suggests a new short hand
+ * for the credentials.
+ */
+
+/* The machine name is part of a credential; it may not exceed 255 bytes */
+#define MAX_MACHINE_NAME 255
+
+/* gids compose part of a credential; there may not be more than 16 of them */
+#define NGRPS 16
+
+/*
+ * Unix style credentials.
+ */
+struct authunix_parms {
+ uint32_t aup_time;
+ char *aup_machname;
+ int aup_uid;
+ int aup_gid;
+ u_int aup_len;
+ int *aup_gids;
+};
+
+extern bool_t xdr_authunix_parms(XDR *, struct authunix_parms *);
+
+/*
+ * If a response verifier has flavor AUTH_SHORT,
+ * then the body of the response verifier encapsulates the following structure;
+ * again it is serialized in the obvious fashion.
+ */
+struct short_hand_verf {
+ struct opaque_auth new_cred;
+};
+
+GSSRPC__END_DECLS
+
+#endif /* !defined(GSSRPC_AUTH_UNIX_H) */
diff --git a/src/include/gssrpc/clnt.h b/src/include/gssrpc/clnt.h
new file mode 100644
index 000000000000..40f7c69a46ef
--- /dev/null
+++ b/src/include/gssrpc/clnt.h
@@ -0,0 +1,346 @@
+/* @(#)clnt.h 2.1 88/07/29 4.0 RPCSRC; from 1.31 88/02/08 SMI*/
+/*
+ * Copyright (c) 2010, Oracle America, Inc.
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * * Neither the name of the "Oracle America, Inc." nor the names of
+ * its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * clnt.h - Client side remote procedure call interface.
+ */
+
+#ifndef GSSRPC_CLNT_H
+#define GSSRPC_CLNT_H
+
+GSSRPC__BEGIN_DECLS
+/*
+ * Rpc calls return an enum clnt_stat. This should be looked at more,
+ * since each implementation is required to live with this (implementation
+ * independent) list of errors.
+ */
+enum clnt_stat {
+ RPC_SUCCESS=0, /* call succeeded */
+ /*
+ * local errors
+ */
+ RPC_CANTENCODEARGS=1, /* can't encode arguments */
+ RPC_CANTDECODERES=2, /* can't decode results */
+ RPC_CANTSEND=3, /* failure in sending call */
+ RPC_CANTRECV=4, /* failure in receiving result */
+ RPC_TIMEDOUT=5, /* call timed out */
+ /*
+ * remote errors
+ */
+ RPC_VERSMISMATCH=6, /* rpc versions not compatible */
+ RPC_AUTHERROR=7, /* authentication error */
+ RPC_PROGUNAVAIL=8, /* program not available */
+ RPC_PROGVERSMISMATCH=9, /* program version mismatched */
+ RPC_PROCUNAVAIL=10, /* procedure unavailable */
+ RPC_CANTDECODEARGS=11, /* decode arguments error */
+ RPC_SYSTEMERROR=12, /* generic "other problem" */
+
+ /*
+ * callrpc & clnt_create errors
+ */
+ RPC_UNKNOWNHOST=13, /* unknown host name */
+ RPC_UNKNOWNPROTO=17, /* unkown protocol */
+
+ /*
+ * _ create errors
+ */
+ RPC_PMAPFAILURE=14, /* the pmapper failed in its call */
+ RPC_PROGNOTREGISTERED=15, /* remote program is not registered */
+ /*
+ * unspecified error
+ */
+ RPC_FAILED=16
+};
+
+
+/*
+ * Error info.
+ */
+struct rpc_err {
+ enum clnt_stat re_status;
+ union {
+ int RE_errno; /* realated system error */
+ enum auth_stat RE_why; /* why the auth error occurred */
+ struct {
+ rpcvers_t low; /* lowest verion supported */
+ rpcvers_t high; /* highest verion supported */
+ } RE_vers;
+ struct { /* maybe meaningful if RPC_FAILED */
+ int32_t s1;
+ int32_t s2;
+ } RE_lb; /* life boot & debugging only */
+ } ru;
+#define re_errno ru.RE_errno
+#define re_why ru.RE_why
+#define re_vers ru.RE_vers
+#define re_lb ru.RE_lb
+};
+
+
+/*
+ * Client rpc handle.
+ * Created by individual implementations, see e.g. rpc_udp.c.
+ * Client is responsible for initializing auth, see e.g. auth_none.c.
+ */
+typedef struct CLIENT {
+ AUTH *cl_auth; /* authenticator */
+ struct clnt_ops {
+ /* call remote procedure */
+ enum clnt_stat (*cl_call)(struct CLIENT *,
+ rpcproc_t, xdrproc_t, void *,
+ xdrproc_t, void *,
+ struct timeval);
+ /* abort a call */
+ void (*cl_abort)(struct CLIENT *);
+ /* get specific error code */
+ void (*cl_geterr)(struct CLIENT *,
+ struct rpc_err *);
+ /* frees results */
+ bool_t (*cl_freeres)(struct CLIENT *,
+ xdrproc_t, void *);
+ /* destroy this structure */
+ void (*cl_destroy)(struct CLIENT *);
+ /* the ioctl() of rpc */
+ /* XXX CITI makes 2nd arg take u_int */
+ bool_t (*cl_control)(struct CLIENT *, int,
+ void *);
+ } *cl_ops;
+ void *cl_private; /* private stuff */
+} CLIENT;
+
+
+/*
+ * client side rpc interface ops
+ *
+ * Parameter types are:
+ *
+ */
+
+/*
+ * enum clnt_stat
+ * CLNT_CALL(rh, proc, xargs, argsp, xres, resp, timeout)
+ * CLIENT *rh;
+ * rpcproc_t proc;
+ * xdrproc_t xargs;
+ * caddr_t argsp;
+ * xdrproc_t xres;
+ * caddr_t resp;
+ * struct timeval timeout;
+ */
+#define CLNT_CALL(rh, proc, xargs, argsp, xres, resp, secs) \
+ ((*(rh)->cl_ops->cl_call)(rh, proc, xargs, argsp, xres, resp, secs))
+#define clnt_call(rh, proc, xargs, argsp, xres, resp, secs) \
+ ((*(rh)->cl_ops->cl_call)(rh, proc, xargs, argsp, xres, resp, secs))
+
+/*
+ * void
+ * CLNT_ABORT(rh);
+ * CLIENT *rh;
+ */
+#define CLNT_ABORT(rh) ((*(rh)->cl_ops->cl_abort)(rh))
+#define clnt_abort(rh) ((*(rh)->cl_ops->cl_abort)(rh))
+
+/*
+ * struct rpc_err
+ * CLNT_GETERR(rh);
+ * CLIENT *rh;
+ */
+#define CLNT_GETERR(rh,errp) ((*(rh)->cl_ops->cl_geterr)(rh, errp))
+#define clnt_geterr(rh,errp) ((*(rh)->cl_ops->cl_geterr)(rh, errp))
+
+
+/*
+ * bool_t
+ * CLNT_FREERES(rh, xres, resp);
+ * CLIENT *rh;
+ * xdrproc_t xres;
+ * caddr_t resp;
+ */
+#define CLNT_FREERES(rh,xres,resp) ((*(rh)->cl_ops->cl_freeres)(rh,xres,resp))
+#define clnt_freeres(rh,xres,resp) ((*(rh)->cl_ops->cl_freeres)(rh,xres,resp))
+
+/*
+ * bool_t
+ * CLNT_CONTROL(cl, request, info)
+ * CLIENT *cl;
+ * u_int request;
+ * char *info;
+ */
+#define CLNT_CONTROL(cl,rq,in) ((*(cl)->cl_ops->cl_control)(cl,rq,in))
+#define clnt_control(cl,rq,in) ((*(cl)->cl_ops->cl_control)(cl,rq,in))
+
+/*
+ * control operations that apply to both udp and tcp transports
+ */
+#define CLSET_TIMEOUT 1 /* set timeout (timeval) */
+#define CLGET_TIMEOUT 2 /* get timeout (timeval) */
+#define CLGET_SERVER_ADDR 3 /* get server's address (sockaddr) */
+/*
+ * udp only control operations
+ */
+#define CLSET_RETRY_TIMEOUT 4 /* set retry timeout (timeval) */
+#define CLGET_RETRY_TIMEOUT 5 /* get retry timeout (timeval) */
+/*
+ * new control operations
+ */
+#define CLGET_LOCAL_ADDR 6 /* get local address (sockaddr, getsockname)*/
+
+/*
+ * void
+ * CLNT_DESTROY(rh);
+ * CLIENT *rh;
+ */
+#define CLNT_DESTROY(rh) ((*(rh)->cl_ops->cl_destroy)(rh))
+#define clnt_destroy(rh) ((*(rh)->cl_ops->cl_destroy)(rh))
+
+
+/*
+ * RPCTEST is a test program which is accessable on every rpc
+ * transport/port. It is used for testing, performance evaluation,
+ * and network administration.
+ */
+
+#define RPCTEST_PROGRAM ((rpcprog_t)1)
+#define RPCTEST_VERSION ((rpcvers_t)1)
+#define RPCTEST_NULL_PROC ((rpcproc_t)2)
+#define RPCTEST_NULL_BATCH_PROC ((rpcproc_t)3)
+
+/*
+ * By convention, procedure 0 takes null arguments and returns them
+ */
+
+#define NULLPROC ((rpcproc_t)0)
+
+/*
+ * Below are the client handle creation routines for the various
+ * implementations of client side rpc. They can return NULL if a
+ * creation failure occurs.
+ */
+
+/*
+ * Memory based rpc (for speed check and testing)
+ * CLIENT *
+ * clntraw_create(prog, vers)
+ * rpcprog_t prog;
+ * rpcvers_t vers;
+ */
+extern CLIENT *clntraw_create(rpcprog_t, rpcvers_t);
+
+/*
+ * Generic client creation routine. Supported protocols are "udp" and "tcp"
+ */
+extern CLIENT *clnt_create(char *, rpcprog_t, rpcvers_t, char *);
+
+
+/*
+ * TCP based rpc
+ * CLIENT *
+ * clnttcp_create(raddr, prog, vers, sockp, sendsz, recvsz)
+ * struct sockaddr_in *raddr;
+ * rpcprog_t prog;
+ * rpcvers_t version;
+ * register int *sockp;
+ * u_int sendsz;
+ * u_int recvsz;
+ */
+extern CLIENT *clnttcp_create(struct sockaddr_in *, rpcprog_t, rpcvers_t,
+ int *, u_int, u_int);
+
+/*
+ * UDP based rpc.
+ * CLIENT *
+ * clntudp_create(raddr, program, version, wait, sockp)
+ * struct sockaddr_in *raddr;
+ * rpcprog_t program;
+ * rpcvers_t version;
+ * struct timeval wait;
+ * int *sockp;
+ *
+ * Same as above, but you specify max packet sizes.
+ * CLIENT *
+ * clntudp_bufcreate(raddr, program, version, wait, sockp, sendsz, recvsz)
+ * struct sockaddr_in *raddr;
+ * rpcprog_t program;
+ * rpcvers_t version;
+ * struct timeval wait;
+ * int *sockp;
+ * u_int sendsz;
+ * u_int recvsz;
+ */
+extern CLIENT *clntudp_create(struct sockaddr_in *, rpcprog_t,
+ rpcvers_t, struct timeval, int *);
+extern CLIENT *clntudp_bufcreate(struct sockaddr_in *, rpcprog_t,
+ rpcvers_t, struct timeval, int *,
+ u_int, u_int);
+
+/*
+ * Print why creation failed
+ */
+void clnt_pcreateerror(char *); /* stderr */
+char *clnt_spcreateerror(char *); /* string */
+
+/*
+ * Like clnt_perror(), but is more verbose in its output
+ */
+void clnt_perrno(enum clnt_stat); /* stderr */
+
+/*
+ * Print an English error message, given the client error code
+ */
+void clnt_perror(CLIENT *, char *); /* stderr */
+char *clnt_sperror(CLIENT *, char *); /* string */
+
+/*
+ * If a creation fails, the following allows the user to figure out why.
+ */
+struct rpc_createerr {
+ enum clnt_stat cf_stat;
+ struct rpc_err cf_error; /* useful when cf_stat == RPC_PMAPFAILURE */
+};
+
+extern struct rpc_createerr rpc_createerr;
+
+
+
+/*
+ * Copy error message to buffer.
+ */
+char *clnt_sperrno(enum clnt_stat num); /* string */
+
+#define UDPMSGSIZE 8800 /* rpc imposed limit on udp msg size */
+#define RPCSMALLMSGSIZE 400 /* a more reasonable packet size */
+
+GSSRPC__END_DECLS
+
+#endif /* !defined(GSSRPC_CLNT_H) */
diff --git a/src/include/gssrpc/netdb.h b/src/include/gssrpc/netdb.h
new file mode 100644
index 000000000000..f933fbb7b479
--- /dev/null
+++ b/src/include/gssrpc/netdb.h
@@ -0,0 +1,58 @@
+/* include/gssrpc/netdb.h */
+/*
+ * Copyright (c) 2010, Oracle America, Inc.
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * * Neither the name of the "Oracle America, Inc." nor the names of
+ * its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/* @(#)netdb.h 2.1 88/07/29 3.9 RPCSRC */
+/* @(#)rpc.h 1.8 87/07/24 SMI */
+
+#ifndef RPC_NETDB_H
+#define RPC_NETDB_H
+
+#include <gssrpc/types.h>
+/* since the gssrpc library requires that any application using it be
+built with these header files, I am making the decision that any app
+which uses the rpcent routines must use this header file, or something
+compatible (which most <netdb.h> are) --marc */
+
+/* Really belongs in <netdb.h> */
+#ifdef STRUCT_RPCENT_IN_RPC_NETDB_H
+struct rpcent {
+ char *r_name; /* name of server for this rpc program */
+ char **r_aliases; /* alias list */
+ int r_number; /* rpc program number */
+};
+#endif /*STRUCT_RPCENT_IN_RPC_NETDB_H*/
+
+struct rpcent *getrpcbyname(), *getrpcbynumber(), *getrpcent();
+
+#endif
diff --git a/src/include/gssrpc/pmap_clnt.h b/src/include/gssrpc/pmap_clnt.h
new file mode 100644
index 000000000000..993bce27cd94
--- /dev/null
+++ b/src/include/gssrpc/pmap_clnt.h
@@ -0,0 +1,83 @@
+/* @(#)pmap_clnt.h 2.1 88/07/29 4.0 RPCSRC; from 1.11 88/02/08 SMI */
+/*
+ * Copyright (c) 2010, Oracle America, Inc.
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * * Neither the name of the "Oracle America, Inc." nor the names of
+ * its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * pmap_clnt.h
+ * Supplies C routines to get to portmap services.
+ */
+
+#ifndef GSSRPC_PMAP_CLNT_H
+#define GSSRPC_PMAP_CLNT_H
+
+/*
+ * Usage:
+ * success = pmap_set(program, version, protocol, port);
+ * success = pmap_unset(program, version);
+ * port = pmap_getport(address, program, version, protocol);
+ * head = pmap_getmaps(address);
+ * clnt_stat = pmap_rmtcall(address, program, version, procedure,
+ * xdrargs, argsp, xdrres, resp, tout, port_ptr)
+ * (works for udp only.)
+ * clnt_stat = clnt_broadcast(program, version, procedure,
+ * xdrargs, argsp, xdrres, resp, eachresult)
+ * (like pmap_rmtcall, except the call is broadcasted to all
+ * locally connected nets. For each valid response received,
+ * the procedure eachresult is called. Its form is:
+ * done = eachresult(resp, raddr)
+ * bool_t done;
+ * caddr_t resp;
+ * struct sockaddr_in raddr;
+ * where resp points to the results of the call and raddr is the
+ * address if the responder to the broadcast.
+ */
+
+GSSRPC__BEGIN_DECLS
+extern bool_t pmap_set(rpcprog_t, rpcvers_t, rpcprot_t, u_int);
+extern bool_t pmap_unset(rpcprog_t, rpcvers_t);
+extern struct pmaplist *pmap_getmaps(struct sockaddr_in *);
+enum clnt_stat pmap_rmtcall(struct sockaddr_in *, rpcprog_t,
+ rpcvers_t, rpcproc_t, xdrproc_t,
+ caddr_t, xdrproc_t, caddr_t,
+ struct timeval, rpcport_t *);
+
+typedef bool_t (*resultproc_t)(caddr_t, struct sockaddr_in *);
+
+enum clnt_stat clnt_broadcast(rpcprog_t, rpcvers_t, rpcproc_t,
+ xdrproc_t, caddr_t, xdrproc_t,
+ caddr_t, resultproc_t);
+extern u_short pmap_getport(struct sockaddr_in *,
+ rpcprog_t,
+ rpcvers_t, rpcprot_t);
+GSSRPC__END_DECLS
+#endif /* !defined(GSSRPC_PMAP_CLNT_H) */
diff --git a/src/include/gssrpc/pmap_prot.h b/src/include/gssrpc/pmap_prot.h
new file mode 100644
index 000000000000..0e35d6b9fbd7
--- /dev/null
+++ b/src/include/gssrpc/pmap_prot.h
@@ -0,0 +1,103 @@
+/* @(#)pmap_prot.h 2.1 88/07/29 4.0 RPCSRC; from 1.14 88/02/08 SMI */
+/*
+ * Copyright (c) 2010, Oracle America, Inc.
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * * Neither the name of the "Oracle America, Inc." nor the names of
+ * its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * pmap_prot.h
+ * Protocol for the local binder service, or pmap.
+ *
+ * The following procedures are supported by the protocol:
+ *
+ * PMAPPROC_NULL() returns ()
+ * takes nothing, returns nothing
+ *
+ * PMAPPROC_SET(struct pmap) returns (bool_t)
+ * TRUE is success, FALSE is failure. Registers the tuple
+ * [prog, vers, prot, port].
+ *
+ * PMAPPROC_UNSET(struct pmap) returns (bool_t)
+ * TRUE is success, FALSE is failure. Un-registers pair
+ * [prog, vers]. prot and port are ignored.
+ *
+ * PMAPPROC_GETPORT(struct pmap) returns (u_short).
+ * 0 is failure. Otherwise returns the port number where the pair
+ * [prog, vers] is registered. It may lie!
+ *
+ * PMAPPROC_DUMP() RETURNS (struct pmaplist *)
+ *
+ * PMAPPROC_CALLIT(rpcprog_t, rpcvers_t, rpcproc_t, string<>)
+ * RETURNS (port, string<>);
+ * usage: encapsulatedresults = PMAPPROC_CALLIT(prog, vers, proc, encapsulatedargs);
+ * Calls the procedure on the local machine. If it is not registered,
+ * this procedure is quite; ie it does not return error information!!!
+ * This procedure only is supported on rpc/udp and calls via
+ * rpc/udp. This routine only passes null authentication parameters.
+ * This file has no interface to xdr routines for PMAPPROC_CALLIT.
+ *
+ * The service supports remote procedure calls on udp/ip or tcp/ip socket 111.
+ */
+
+#ifndef GSSRPC_PMAP_PROT_H
+#define GSSRPC_PMAP_PROT_H
+GSSRPC__BEGIN_DECLS
+
+#define PMAPPORT ((u_short)111)
+#define PMAPPROG ((rpcprog_t)100000)
+#define PMAPVERS ((rpcvers_t)2)
+#define PMAPVERS_PROTO ((rpcprot_t)2)
+#define PMAPVERS_ORIG ((rpcvers_t)1)
+#define PMAPPROC_NULL ((rpcproc_t)0)
+#define PMAPPROC_SET ((rpcproc_t)1)
+#define PMAPPROC_UNSET ((rpcproc_t)2)
+#define PMAPPROC_GETPORT ((rpcproc_t)3)
+#define PMAPPROC_DUMP ((rpcproc_t)4)
+#define PMAPPROC_CALLIT ((rpcproc_t)5)
+
+struct pmap {
+ rpcprog_t pm_prog;
+ rpcvers_t pm_vers;
+ rpcprot_t pm_prot;
+ rpcport_t pm_port;
+};
+
+extern bool_t xdr_pmap(XDR *, struct pmap *);
+
+struct pmaplist {
+ struct pmap pml_map;
+ struct pmaplist *pml_next;
+};
+
+extern bool_t xdr_pmaplist(XDR *, struct pmaplist **);
+
+GSSRPC__END_DECLS
+#endif /* !defined(GSSRPC_PMAP_PROT_H) */
diff --git a/src/include/gssrpc/pmap_rmt.h b/src/include/gssrpc/pmap_rmt.h
new file mode 100644
index 000000000000..e978a8ee8c5b
--- /dev/null
+++ b/src/include/gssrpc/pmap_rmt.h
@@ -0,0 +1,65 @@
+/* @(#)pmap_rmt.h 2.1 88/07/29 4.0 RPCSRC; from 1.2 88/02/08 SMI */
+/*
+ * Copyright (c) 2010, Oracle America, Inc.
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * * Neither the name of the "Oracle America, Inc." nor the names of
+ * its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Structures and XDR routines for parameters to and replies from
+ * the portmapper remote-call-service.
+ */
+
+#ifndef GSSRPC_PMAP_RMT_H
+#define GSSRPC_PMAP_RMT_H
+GSSRPC__BEGIN_DECLS
+
+struct rmtcallargs {
+ rpcprog_t prog;
+ rpcvers_t vers;
+ rpcproc_t proc;
+ uint32_t arglen;
+ caddr_t args_ptr;
+ xdrproc_t xdr_args;
+};
+
+bool_t xdr_rmtcall_args(XDR *, struct rmtcallargs *);
+
+struct rmtcallres {
+ rpcport_t *port_ptr;
+ uint32_t resultslen;
+ caddr_t results_ptr;
+ xdrproc_t xdr_results;
+};
+
+bool_t xdr_rmtcallres(XDR *, struct rmtcallres *);
+
+GSSRPC__END_DECLS
+#endif /* !defined(GSSRPC_PMAP_RMT_H) */
diff --git a/src/include/gssrpc/rename.h b/src/include/gssrpc/rename.h
new file mode 100644
index 000000000000..669a0580c931
--- /dev/null
+++ b/src/include/gssrpc/rename.h
@@ -0,0 +1,311 @@
+/* include/gssrpc/rename.h */
+/*
+ * Copyright (C) 2004 by the Massachusetts Institute of Technology.
+ * All rights reserved.
+ *
+ * Export of this software from the United States of America may
+ * require a specific license from the United States Government.
+ * It is the responsibility of any person or organization contemplating
+ * export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission. Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose. It is provided "as is" without express
+ * or implied warranty.
+ */
+
+/*
+ *
+ * Namespace mangling for various purposes.
+ *
+ * Symbols in the object code need to be renamed to not conflict with
+ * an OS-provided RPC implementation. Without renaming, the conflicts
+ * can cause problems with things like RPC-enabled NSS
+ * implementations.
+ *
+ * Symbols in headers should not conflict with implementation-reserved
+ * namespace (prefixes "_[A-Z_]" for any purpose; prefix "_"
+ * for file scope identifiers and tag names), or unnecessarily impinge
+ * on user namespace.
+ *
+ * The renaming of the header directory is done to avoid problems when
+ * the OS header files include <rpc/foo.h> and might get ours instead.
+ * OS vendors should replace all the <gssrpc/foo.h> inclusions with
+ * <rpc/foo.h> inclusions, as appropriate. Additionally, vendors
+ * should probably put some symbols into the implementation namespace.
+ *
+ * For example, inclusion protection should change from "GSSRPC_*_H"
+ * to "_RPC_*_H", struct tags should get "__" prefixes, etc.
+ *
+ * This implementation reserves the object code prefix "gssrpc_".
+ * External names in the RPC API not beginning with "_" get renamed
+ * with the prefix "gssrpc_" via #define, e.g., "foo" -> "gssrpc_foo".
+ * External names in the RPC API beginning with "_" get textually
+ * rewritten, with "#if 0"-disabled #defines mapping them back to
+ * their original forms, e.g., "_foo" is rewrittten to "gssrpc__foo"
+ * in the original files, with an unused "#define gssrpc__foo _foo"
+ * here.
+ */
+
+#ifndef GSSRPC_RENAME_H
+#define GSSRPC_RENAME_H
+
+/* auth.h */
+
+#define xdr_des_block gssrpc_xdr_des_block
+
+#define authany_wrap gssrpc_authany_wrap
+#define authany_unwrap gssrpc_authany_unwrap
+
+#define authunix_create gssrpc_authunix_create
+#define authunix_create_default gssrpc_authunix_create_default
+#define authnone_create gssrpc_authnone_create
+#define authdes_create gssrpc_authdes_create
+#define xdr_opaque_auth gssrpc_xdr_opaque_auth
+
+#if 0
+#define gssrpc__null_auth _null_auth
+#endif
+
+/* auth_gss.c */
+
+#define auth_debug_gss gssrpc_auth_debug_gss
+#define misc_debug_gss gssrpc_misc_debug_gss
+
+/* auth_gss.h */
+
+#define xdr_rpc_gss_buf gssrpc_xdr_rpc_gss_buf
+#define xdr_rpc_gss_cred gssrpc_xdr_rpc_gss_cred
+#define xdr_rpc_gss_init_args gssrpc_xdr_rpc_gss_init_args
+#define xdr_rpc_gss_init_res gssrpc_xdr_rpc_gss_init_res
+#define xdr_rpc_gss_data gssrpc_xdr_rpc_gss_data
+#define xdr_rpc_gss_wrap_data gssrpc_xdr_rpc_gss_wrap_data
+#define xdr_rpc_gss_unwrap_data gssrpc_xdr_rpc_gss_unwrap_data
+
+#define authgss_create gssrpc_authgss_create
+#define authgss_create_default gssrpc_authgss_create_default
+#define authgss_get_private_data gssrpc_authgss_get_private_data
+#define authgss_service gssrpc_authgss_service
+
+#ifdef GSSRPC__IMPL
+#define log_debug gssrpc_log_debug
+#define log_status gssrpc_log_status
+#define log_hexdump gssrpc_log_hexdump
+#endif
+
+/* auth_gssapi.c */
+
+#define auth_debug_gssapi gssrpc_auth_debug_gssapi
+#define misc_debug_gssapi gssrpc_misc_debug_gssapi
+
+/* auth_gssapi.h */
+
+#define xdr_gss_buf gssrpc_xdr_gss_buf
+#define xdr_authgssapi_creds gssrpc_xdr_authgssapi_creds
+#define xdr_authgssapi_init_arg gssrpc_xdr_authgssapi_init_arg
+#define xdr_authgssapi_init_res gssrpc_xdr_authgssapi_init_res
+
+#define auth_gssapi_wrap_data gssrpc_auth_gssapi_wrap_data
+#define auth_gssapi_unwrap_data gssrpc_auth_gssapi_unwrap_data
+#define auth_gssapi_create gssrpc_auth_gssapi_create
+#define auth_gssapi_create_default gssrpc_auth_gssapi_create_default
+#define auth_gssapi_display_status gssrpc_auth_gssapi_display_status
+#define auth_gssapi_seal_seq gssrpc_auth_gssapi_seal_seq
+#define auth_gssapi_unseal_seq gssrpc_auth_gssapi_unseal_seq
+
+#define svcauth_gssapi_set_names gssrpc_svcauth_gssapi_set_names
+#define svcauth_gssapi_unset_names gssrpc_svcauth_gssapi_unset_names
+#define svcauth_gssapi_set_log_badauth_func gssrpc_svcauth_gssapi_set_log_badauth_func
+#define svcauth_gssapi_set_log_badauth2_func gssrpc_svcauth_gssapi_set_log_badauth2_func
+#define svcauth_gssapi_set_log_badverf_func gssrpc_svcauth_gssapi_set_log_badverf_func
+#define svcauth_gssapi_set_log_miscerr_func gssrpc_svcauth_gssapi_set_log_miscerr_func
+
+#define svcauth_gss_set_log_badauth_func gssrpc_svcauth_gss_set_log_badauth_func
+#define svcauth_gss_set_log_badauth2_func gssrpc_svcauth_gss_set_log_badauth2_func
+#define svcauth_gss_set_log_badverf_func gssrpc_svcauth_gss_set_log_badverf_func
+#define svcauth_gss_set_log_miscerr_func gssrpc_svcauth_gss_set_log_miscerr_func
+
+/* auth_unix.h */
+
+#define xdr_authunix_parms gssrpc_xdr_authunix_parms
+
+/* clnt.h */
+
+#define clntraw_create gssrpc_clntraw_create
+#define clnt_create gssrpc_clnt_create
+#define clnttcp_create gssrpc_clnttcp_create
+#define clntudp_create gssrpc_clntudp_create
+#define clntudp_bufcreate gssrpc_clntudp_bufcreate
+#define clnt_pcreateerror gssrpc_clnt_pcreateerror
+#define clnt_spcreateerror gssrpc_clnt_spcreateerror
+#define clnt_perrno gssrpc_clnt_perrno
+#define clnt_perror gssrpc_clnt_perror
+#define clnt_sperror gssrpc_clnt_sperror
+/* XXX do we need to rename the struct? */
+#define rpc_createerr gssrpc_rpc_createrr
+#define clnt_sperrno gssrpc_clnt_sperrno
+
+/* pmap_clnt.h */
+
+#define pmap_set gssrpc_pmap_set
+#define pmap_unset gssrpc_pmap_unset
+#define pmap_getmaps gssrpc_pmap_getmaps
+#define pmap_rmtcall gssrpc_pmap_rmtcall
+#define clnt_broadcast gssrpc_clnt_broadcast
+#define pmap_getport gssrpc_pmap_getport
+
+/* pmap_prot.h */
+
+#define xdr_pmap gssrpc_xdr_pmap
+#define xdr_pmaplist gssrpc_xdr_pmaplist
+
+/* pmap_rmt.h */
+
+#define xdr_rmtcall_args gssrpc_xdr_rmtcall_args
+#define xdr_rmtcallres gssrpc_xdr_rmtcallres
+
+/* rpc.h */
+
+#define get_myaddress gssrpc_get_myaddress
+#define bindresvport gssrpc_bindresvport
+#define bindresvport_sa gssrpc_bindresvport_sa
+#define callrpc gssrpc_callrpc
+#define getrpcport gssrpc_getrpcport
+
+#if 0
+#define gssrpc__rpc_getdtablesize _rpc_getdtablesize
+#endif
+
+/* rpc_msg.h */
+
+#define xdr_callmsg gssrpc_xdr_callmsg
+#define xdr_callhdr gssrpc_xdr_callhdr
+#define xdr_replymsg gssrpc_xdr_replymsg
+#define xdr_accepted_reply gssrpc_xdr_accepted_reply
+#define xdr_rejected_reply gssrpc_xdr_rejected_reply
+
+#if 0
+#define gssrpc__seterr_reply _seterr_reply
+#endif
+
+/* svc.h */
+
+#define svc_register gssrpc_svc_register
+#define registerrpc gssrpc_registerrpc
+#define svc_unregister gssrpc_svc_unregister
+#define xprt_register gssrpc_xprt_register
+#define xprt_unregister gssrpc_xprt_unregister
+
+#define svc_sendreply gssrpc_svc_sendreply
+#define svcerr_decode gssrpc_svcerr_decode
+#define svcerr_weakauth gssrpc_svcerr_weakauth
+#define svcerr_noproc gssrpc_svcerr_noproc
+#define svcerr_progvers gssrpc_svcerr_progvers
+#define svcerr_auth gssrpc_svcerr_auth
+#define svcerr_noprog gssrpc_svcerr_noprog
+#define svcerr_systemerr gssrpc_svcerr_systemerr
+
+#define svc_maxfd gssrpc_svc_maxfd
+#define svc_fdset gssrpc_svc_fdset
+#define svc_fds gssrpc_svc_fds
+
+#define rpctest_service gssrpc_rpctest_service
+
+#define svc_getreq gssrpc_svc_getreq
+#define svc_getreqset gssrpc_svc_getreqset
+#define svc_getreqset2 gssrpc_svc_getreqset2
+#define svc_run gssrpc_svc_run
+
+#define svcraw_create gssrpc_svcraw_create
+
+#define svcudp_create gssrpc_svcudp_create
+#define svcudp_bufcreate gssrpc_svcudp_bufcreate
+#define svcudp_enablecache gssrpc_svcudp_enablecache
+
+#define svctcp_create gssrpc_svctcp_create
+
+#define svcfd_create gssrpc_svcfd_create
+
+/* svc_auth.h */
+
+#define svc_auth_none_ops gssrpc_svc_auth_none_ops
+#define svc_auth_gssapi_ops gssrpc_svc_auth_gssapi_ops
+#define svc_auth_gss_ops gssrpc_svc_auth_gss_ops
+
+#define svcauth_gss_set_svc_name gssrpc_svcauth_gss_set_svc_name
+#define svcauth_gss_get_principal gssrpc_svcauth_gss_get_principal
+
+#if 0
+#define gssrpc__authenticate _authenticate
+#define gssrpc__svcauth_none _svcauth_none
+#define gssrpc__svcauth_unix _svcauth_unix
+#define gssrpc__svcauth_short _svcauth_short
+#define gssrpc__svcauth_gssapi _svcauth_gssapi
+#define gssrpc__svcauth_gss _svcauth_gss
+#endif
+
+/* svc_auth_gss.c */
+
+#define svc_debug_gss gssrpc_svc_debug_gss
+
+/* svc_auth_gssapi.c */
+
+#define svc_debug_gssapi gssrpc_svc_debug_gssapi
+
+/* svc_auth_none.c */
+
+#define svc_auth_none gssrpc_svc_auth_none
+
+/* xdr.h */
+
+#define xdr_void gssrpc_xdr_void
+#define xdr_int gssrpc_xdr_int
+#define xdr_u_int gssrpc_xdr_u_int
+#define xdr_long gssrpc_xdr_long
+#define xdr_u_long gssrpc_xdr_u_long
+#define xdr_short gssrpc_xdr_short
+#define xdr_u_short gssrpc_xdr_u_short
+#define xdr_bool gssrpc_xdr_bool
+#define xdr_enum gssrpc_xdr_enum
+#define xdr_array gssrpc_xdr_array
+#define xdr_bytes gssrpc_xdr_bytes
+#define xdr_opaque gssrpc_xdr_opaque
+#define xdr_string gssrpc_xdr_string
+#define xdr_union gssrpc_xdr_union
+#define xdr_char gssrpc_xdr_char
+#define xdr_u_char gssrpc_xdr_u_char
+#define xdr_vector gssrpc_xdr_vector
+#define xdr_float gssrpc_xdr_float
+#define xdr_double gssrpc_xdr_double
+#define xdr_reference gssrpc_xdr_reference
+#define xdr_pointer gssrpc_xdr_pointer
+#define xdr_wrapstring gssrpc_xdr_wrapstring
+#define xdr_free gssrpc_xdr_free
+
+#define xdr_sizeof gssrpc_xdr_sizeof
+
+#define xdr_netobj gssrpc_xdr_netobj
+#define xdr_int32 gssrpc_xdr_int32
+#define xdr_u_int32 gssrpc_xdr_u_int32
+
+#define xdralloc_create gssrpc_xdralloc_create
+#define xdralloc_release gssrpc_xdralloc_release
+#define xdralloc_getdata gssrpc_xdralloc_getdata
+
+#define xdrmem_create gssrpc_xdrmem_create
+#define xdrstdio_create gssrpc_xdrstdio_create
+#define xdrrec_create gssrpc_xdrrec_create
+#define xdrrec_endofrecord gssrpc_xdrrec_endofrecord
+#define xdrrec_skiprecord gssrpc_xdrrec_skiprecord
+#define xdrrec_eof gssrpc_xdrrec_eof
+
+#endif /* !defined(GSSRPC_RENAME_H) */
diff --git a/src/include/gssrpc/rpc.h b/src/include/gssrpc/rpc.h
new file mode 100644
index 000000000000..2d94a7fe9e2e
--- /dev/null
+++ b/src/include/gssrpc/rpc.h
@@ -0,0 +1,102 @@
+/* @(#)rpc.h 2.3 88/08/10 4.0 RPCSRC; from 1.9 88/02/08 SMI */
+/*
+ * Copyright (c) 2010, Oracle America, Inc.
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * * Neither the name of the "Oracle America, Inc." nor the names of
+ * its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * rpc.h, Just includes the billions of rpc header files necessary to
+ * do remote procedure calling.
+ */
+#ifndef GSSRPC_RPC_H
+#define GSSRPC_RPC_H
+
+#include <gssrpc/types.h> /* some typedefs */
+#include <netinet/in.h>
+
+/* external data representation interfaces */
+#include <gssrpc/xdr.h> /* generic (de)serializer */
+
+/* Client side only authentication */
+#include <gssrpc/auth.h> /* generic authenticator (client side) */
+
+/* Client side (mostly) remote procedure call */
+#include <gssrpc/clnt.h> /* generic rpc stuff */
+
+/* semi-private protocol headers */
+#include <gssrpc/rpc_msg.h> /* protocol for rpc messages */
+#include <gssrpc/auth_unix.h> /* protocol for unix style cred */
+#include <gssrpc/auth_gss.h> /* RPCSEC_GSS */
+/*
+ * Uncomment-out the next line if you are building the rpc library with
+ * DES Authentication (see the README file in the secure_rpc/ directory).
+ */
+#if 0
+#include <gssrpc/auth_des.h> protocol for des style cred
+#endif
+
+/* Server side only remote procedure callee */
+#include <gssrpc/svc_auth.h> /* service side authenticator */
+#include <gssrpc/svc.h> /* service manager and multiplexer */
+
+/*
+ * Punt the rpc/netdb.h everywhere because it just makes things much more
+ * difficult. We don't use the *rpcent functions anyway.
+ */
+#if 0
+/*
+ * COMMENT OUT THE NEXT INCLUDE IF RUNNING ON SUN OS OR ON A VERSION
+ * OF UNIX BASED ON NFSSRC. These systems will already have the structures
+ * defined by <rpc/netdb.h> included in <netdb.h>.
+ */
+/* routines for parsing /etc/rpc */
+#if 0 /* netdb.h already included in rpc/types.h */
+#include <netdb.h>
+#endif
+
+#include <gssrpc/netdb.h> /* structures and routines to parse /etc/rpc */
+#endif
+
+/*
+ * get the local host's IP address without consulting
+ * name service library functions
+ */
+GSSRPC__BEGIN_DECLS
+extern int get_myaddress(struct sockaddr_in *);
+extern int bindresvport(int, struct sockaddr_in *);
+extern int bindresvport_sa(int, struct sockaddr *);
+extern int callrpc(char *, rpcprog_t, rpcvers_t, rpcproc_t, xdrproc_t,
+ char *, xdrproc_t , char *);
+extern int getrpcport(char *, rpcprog_t, rpcvers_t, rpcprot_t);
+extern int gssrpc__rpc_dtablesize(void);
+GSSRPC__END_DECLS
+
+#endif /* !defined(GSSRPC_RPC_H) */
diff --git a/src/include/gssrpc/rpc_msg.h b/src/include/gssrpc/rpc_msg.h
new file mode 100644
index 000000000000..107020283e2b
--- /dev/null
+++ b/src/include/gssrpc/rpc_msg.h
@@ -0,0 +1,207 @@
+/* @(#)rpc_msg.h 2.1 88/07/29 4.0 RPCSRC */
+/*
+ * Copyright (c) 2010, Oracle America, Inc.
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * * Neither the name of the "Oracle America, Inc." nor the names of
+ * its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/* @(#)rpc_msg.h 1.7 86/07/16 SMI */
+
+/*
+ * rpc_msg.h
+ * rpc message definition
+ */
+
+#ifndef GSSRPC_RPC_MSG_H
+#define GSSRPC_RPC_MSG_H
+
+GSSRPC__BEGIN_DECLS
+
+#define RPC_MSG_VERSION ((uint32_t) 2)
+#define RPC_SERVICE_PORT ((u_short) 2048)
+
+/*
+ * Bottom up definition of an rpc message.
+ * NOTE: call and reply use the same overall stuct but
+ * different parts of unions within it.
+ */
+
+enum msg_type {
+ CALL=0,
+ REPLY=1
+};
+
+enum reply_stat {
+ MSG_ACCEPTED=0,
+ MSG_DENIED=1
+};
+
+enum accept_stat {
+ SUCCESS=0,
+ PROG_UNAVAIL=1,
+ PROG_MISMATCH=2,
+ PROC_UNAVAIL=3,
+ GARBAGE_ARGS=4,
+ SYSTEM_ERR=5
+};
+
+enum reject_stat {
+ RPC_MISMATCH=0,
+ AUTH_ERROR=1
+};
+
+/*
+ * Reply part of an rpc exchange
+ */
+
+/*
+ * Reply to an rpc request that was accepted by the server.
+ * Note: there could be an error even though the request was
+ * accepted.
+ */
+struct accepted_reply {
+ struct opaque_auth ar_verf;
+ enum accept_stat ar_stat;
+ union {
+ struct {
+ rpcvers_t low;
+ rpcvers_t high;
+ } AR_versions;
+ struct {
+ caddr_t where;
+ xdrproc_t proc;
+ } AR_results;
+ /* and many other null cases */
+ } ru;
+#define ar_results ru.AR_results
+#define ar_vers ru.AR_versions
+};
+
+/*
+ * Reply to an rpc request that was rejected by the server.
+ */
+struct rejected_reply {
+ enum reject_stat rj_stat;
+ union {
+ struct {
+ rpcvers_t low;
+ rpcvers_t high;
+ } RJ_versions;
+ enum auth_stat RJ_why; /* why authentication did not work */
+ } ru;
+#define rj_vers ru.RJ_versions
+#define rj_why ru.RJ_why
+};
+
+/*
+ * Body of a reply to an rpc request.
+ */
+struct reply_body {
+ enum reply_stat rp_stat;
+ union {
+ struct accepted_reply RP_ar;
+ struct rejected_reply RP_dr;
+ } ru;
+#define rp_acpt ru.RP_ar
+#define rp_rjct ru.RP_dr
+};
+
+/*
+ * Body of an rpc request call.
+ */
+struct call_body {
+ rpcvers_t cb_rpcvers; /* must be equal to two */
+ rpcprog_t cb_prog;
+ rpcvers_t cb_vers;
+ rpcproc_t cb_proc;
+ struct opaque_auth cb_cred;
+ struct opaque_auth cb_verf; /* protocol specific - provided by client */
+};
+
+/*
+ * The rpc message
+ */
+struct rpc_msg {
+ uint32_t rm_xid;
+ enum msg_type rm_direction;
+ union {
+ struct call_body RM_cmb;
+ struct reply_body RM_rmb;
+ } ru;
+#define rm_call ru.RM_cmb
+#define rm_reply ru.RM_rmb
+};
+#define acpted_rply ru.RM_rmb.ru.RP_ar
+#define rjcted_rply ru.RM_rmb.ru.RP_dr
+
+
+/*
+ * XDR routine to handle a rpc message.
+ * xdr_callmsg(xdrs, cmsg)
+ * XDR *xdrs;
+ * struct rpc_msg *cmsg;
+ */
+extern bool_t xdr_callmsg(XDR *, struct rpc_msg *);
+
+/*
+ * XDR routine to pre-serialize the static part of a rpc message.
+ * xdr_callhdr(xdrs, cmsg)
+ * XDR *xdrs;
+ * struct rpc_msg *cmsg;
+ */
+extern bool_t xdr_callhdr(XDR *, struct rpc_msg *);
+
+/*
+ * XDR routine to handle a rpc reply.
+ * xdr_replymsg(xdrs, rmsg)
+ * XDR *xdrs;
+ * struct rpc_msg *rmsg;
+ */
+extern bool_t xdr_replymsg(XDR *, struct rpc_msg *);
+
+/*
+ * Fills in the error part of a reply message.
+ * _seterr_reply(msg, error)
+ * struct rpc_msg *msg;
+ * struct rpc_err *error;
+ */
+/*
+ * RENAMED: should be _seterr_reply or __seterr_reply if we can use
+ * reserved namespace.
+ */
+extern void gssrpc__seterr_reply(struct rpc_msg *, struct rpc_err *);
+
+/* XDR the MSG_ACCEPTED part of a reply message union */
+extern bool_t xdr_accepted_reply(XDR *, struct accepted_reply *);
+
+/* XDR the MSG_DENIED part of a reply message union */
+extern bool_t xdr_rejected_reply(XDR *, struct rejected_reply *);
+GSSRPC__END_DECLS
+
+#endif /* !defined(GSSRPC_RPC_MSG_H) */
diff --git a/src/include/gssrpc/svc.h b/src/include/gssrpc/svc.h
new file mode 100644
index 000000000000..1bb8dd97a160
--- /dev/null
+++ b/src/include/gssrpc/svc.h
@@ -0,0 +1,343 @@
+/* @(#)svc.h 2.2 88/07/29 4.0 RPCSRC; from 1.20 88/02/08 SMI */
+/*
+ * Copyright (c) 2010, Oracle America, Inc.
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * * Neither the name of the "Oracle America, Inc." nor the names of
+ * its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * svc.h, Server-side remote procedure call interface.
+ */
+
+#ifndef GSSRPC_SVC_H
+#define GSSRPC_SVC_H
+
+#include <gssrpc/svc_auth.h>
+
+GSSRPC__BEGIN_DECLS
+/*
+ * This interface must manage two items concerning remote procedure calling:
+ *
+ * 1) An arbitrary number of transport connections upon which rpc requests
+ * are received. The two most notable transports are TCP and UDP; they are
+ * created and registered by routines in svc_tcp.c and svc_udp.c, respectively;
+ * they in turn call xprt_register and xprt_unregister.
+ *
+ * 2) An arbitrary number of locally registered services. Services are
+ * described by the following four data: program number, version number,
+ * "service dispatch" function, a transport handle, and a boolean that
+ * indicates whether or not the exported program should be registered with a
+ * local binder service; if true the program's number and version and the
+ * port number from the transport handle are registered with the binder.
+ * These data are registered with the rpc svc system via svc_register.
+ *
+ * A service's dispatch function is called whenever an rpc request comes in
+ * on a transport. The request's program and version numbers must match
+ * those of the registered service. The dispatch function is passed two
+ * parameters, struct svc_req * and SVCXPRT *, defined below.
+ */
+
+enum xprt_stat {
+ XPRT_DIED,
+ XPRT_MOREREQS,
+ XPRT_IDLE
+};
+
+/*
+ * Server side transport handle
+ */
+typedef struct SVCXPRT {
+#ifdef _WIN32
+ SOCKET xp_sock;
+#else
+ int xp_sock;
+#endif
+ u_short xp_port; /* associated port number */
+ struct xp_ops {
+ /* receive incomming requests */
+ bool_t (*xp_recv)(struct SVCXPRT *, struct rpc_msg *);
+ /* get transport status */
+ enum xprt_stat (*xp_stat)(struct SVCXPRT *);
+ /* get arguments */
+ bool_t (*xp_getargs)(struct SVCXPRT *, xdrproc_t,
+ void *);
+ /* send reply */
+ bool_t (*xp_reply)(struct SVCXPRT *,
+ struct rpc_msg *);
+ /* free mem allocated for args */
+ bool_t (*xp_freeargs)(struct SVCXPRT *, xdrproc_t,
+ void *);
+ /* destroy this struct */
+ void (*xp_destroy)(struct SVCXPRT *);
+ } *xp_ops;
+ int xp_addrlen; /* length of remote address */
+ struct sockaddr_in xp_raddr; /* remote address */
+ struct opaque_auth xp_verf; /* raw response verifier */
+ SVCAUTH *xp_auth; /* auth flavor of current req */
+ void *xp_p1; /* private */
+ void *xp_p2; /* private */
+ int xp_laddrlen; /* lenght of local address */
+ struct sockaddr_in xp_laddr; /* local address */
+} SVCXPRT;
+
+/*
+ * Approved way of getting address of caller
+ */
+#define svc_getcaller(x) (&(x)->xp_raddr)
+
+/*
+ * Operations defined on an SVCXPRT handle
+ *
+ * SVCXPRT *xprt;
+ * struct rpc_msg *msg;
+ * xdrproc_t xargs;
+ * caddr_t argsp;
+ */
+#define SVC_RECV(xprt, msg) \
+ (*(xprt)->xp_ops->xp_recv)((xprt), (msg))
+#define svc_recv(xprt, msg) \
+ (*(xprt)->xp_ops->xp_recv)((xprt), (msg))
+
+#define SVC_STAT(xprt) \
+ (*(xprt)->xp_ops->xp_stat)(xprt)
+#define svc_stat(xprt) \
+ (*(xprt)->xp_ops->xp_stat)(xprt)
+
+#define SVC_GETARGS(xprt, xargs, argsp) \
+ (*(xprt)->xp_ops->xp_getargs)((xprt), (xargs), (argsp))
+#define svc_getargs(xprt, xargs, argsp) \
+ (*(xprt)->xp_ops->xp_getargs)((xprt), (xargs), (argsp))
+
+#define SVC_GETARGS_REQ(xprt, req, xargs, argsp) \
+ (*(xprt)->xp_ops->xp_getargs_req)((xprt), (req), (xargs), (argsp))
+#define svc_getargs_req(xprt, req, xargs, argsp) \
+ (*(xprt)->xp_ops->xp_getargs_req)((xprt), (req), (xargs), (argsp))
+
+#define SVC_REPLY(xprt, msg) \
+ (*(xprt)->xp_ops->xp_reply) ((xprt), (msg))
+#define svc_reply(xprt, msg) \
+ (*(xprt)->xp_ops->xp_reply) ((xprt), (msg))
+
+#define SVC_REPLY_REQ(xprt, req, msg) \
+ (*(xprt)->xp_ops->xp_reply_req) ((xprt), (req), (msg))
+#define svc_reply_req(xprt, msg) \
+ (*(xprt)->xp_ops->xp_reply_req) ((xprt), (req), (msg))
+
+#define SVC_FREEARGS(xprt, xargs, argsp) \
+ (*(xprt)->xp_ops->xp_freeargs)((xprt), (xargs), (argsp))
+#define svc_freeargs(xprt, xargs, argsp) \
+ (*(xprt)->xp_ops->xp_freeargs)((xprt), (xargs), (argsp))
+
+#define SVC_DESTROY(xprt) \
+ (*(xprt)->xp_ops->xp_destroy)(xprt)
+#define svc_destroy(xprt) \
+ (*(xprt)->xp_ops->xp_destroy)(xprt)
+
+
+/*
+ * Service request
+ */
+struct svc_req {
+ rpcprog_t rq_prog; /* service program number */
+ rpcvers_t rq_vers; /* service protocol version */
+ rpcproc_t rq_proc; /* the desired procedure */
+ struct opaque_auth rq_cred; /* raw creds from the wire */
+ void * rq_clntcred; /* read only cooked client cred */
+ void * rq_svccred; /* read only svc cred/context */
+ void * rq_clntname; /* read only client name */
+ SVCXPRT *rq_xprt; /* associated transport */
+ /* The request's auth flavor *should* be here, but the svc_req */
+ /* isn't passed around everywhere it is necessary. The */
+ /* transport *is* passed around, so the auth flavor it stored */
+ /* there. This means that the transport must be single */
+ /* threaded, but other parts of SunRPC already require that. */
+ /*SVCAUTH *rq_auth; associated auth flavor */
+};
+
+
+/*
+ * Service registration
+ *
+ * svc_register(xprt, prog, vers, dispatch, protocol)
+ * SVCXPRT *xprt;
+ * rpcprog_t prog;
+ * rpcvers_t vers;
+ * void (*dispatch)();
+ * int protocol; like IPPROTO_TCP or _UDP; zero means do not register
+ *
+ * registerrpc(prog, vers, proc, routine, inproc, outproc)
+ * returns 0 upon success, -1 if error.
+ */
+extern bool_t svc_register(SVCXPRT *, rpcprog_t, rpcvers_t,
+ void (*)(struct svc_req *, SVCXPRT *), int);
+
+extern int registerrpc(rpcprog_t, rpcvers_t, rpcproc_t,
+ char *(*)(void *),
+ xdrproc_t, xdrproc_t);
+
+/*
+ * Service un-registration
+ *
+ * svc_unregister(prog, vers)
+ * rpcprog_t prog;
+ * rpcvers_t vers;
+ */
+extern void svc_unregister(rpcprog_t, rpcvers_t);
+
+/*
+ * Transport registration.
+ *
+ * xprt_register(xprt)
+ * SVCXPRT *xprt;
+ */
+extern void xprt_register(SVCXPRT *);
+
+/*
+ * Transport un-register
+ *
+ * xprt_unregister(xprt)
+ * SVCXPRT *xprt;
+ */
+extern void xprt_unregister(SVCXPRT *);
+
+
+/*
+ * When the service routine is called, it must first check to see if
+ * it knows about the procedure; if not, it should call svcerr_noproc
+ * and return. If so, it should deserialize its arguments via
+ * SVC_GETARGS or the new SVC_GETARGS_REQ (both defined above). If
+ * the deserialization does not work, svcerr_decode should be called
+ * followed by a return. Successful decoding of the arguments should
+ * be followed the execution of the procedure's code and a call to
+ * svc_sendreply or the new svc_sendreply_req.
+ *
+ * Also, if the service refuses to execute the procedure due to too-
+ * weak authentication parameters, svcerr_weakauth should be called.
+ * Note: do not confuse access-control failure with weak authentication!
+ *
+ * NB: In pure implementations of rpc, the caller always waits for a reply
+ * msg. This message is sent when svc_sendreply is called.
+ * Therefore pure service implementations should always call
+ * svc_sendreply even if the function logically returns void; use
+ * xdr.h - xdr_void for the xdr routine. HOWEVER, tcp based rpc allows
+ * for the abuse of pure rpc via batched calling or pipelining. In the
+ * case of a batched call, svc_sendreply should NOT be called since
+ * this would send a return message, which is what batching tries to avoid.
+ * It is the service/protocol writer's responsibility to know which calls are
+ * batched and which are not. Warning: responding to batch calls may
+ * deadlock the caller and server processes!
+ */
+
+extern bool_t svc_sendreply(SVCXPRT *, xdrproc_t, caddr_t);
+extern void svcerr_decode(SVCXPRT *);
+extern void svcerr_weakauth(SVCXPRT *);
+extern void svcerr_noproc(SVCXPRT *);
+extern void svcerr_progvers(SVCXPRT *, rpcvers_t, rpcvers_t);
+extern void svcerr_auth(SVCXPRT *, enum auth_stat);
+extern void svcerr_noprog(SVCXPRT *);
+extern void svcerr_systemerr(SVCXPRT *);
+
+/*
+ * Lowest level dispatching -OR- who owns this process anyway.
+ * Somebody has to wait for incoming requests and then call the correct
+ * service routine. The routine svc_run does infinite waiting; i.e.,
+ * svc_run never returns.
+ * Since another (co-existant) package may wish to selectively wait for
+ * incoming calls or other events outside of the rpc architecture, the
+ * routine svc_getreq is provided. It must be passed readfds, the
+ * "in-place" results of a select system call (see select, section 2).
+ */
+
+/*
+ * Global keeper of rpc service descriptors in use
+ * dynamic; must be inspected before each call to select
+ */
+extern int svc_maxfd;
+#ifdef FD_SETSIZE
+extern fd_set svc_fdset;
+/* RENAMED */
+#define gssrpc_svc_fds gsssrpc_svc_fdset.fds_bits[0] /* compatibility */
+#else
+extern int svc_fds;
+#endif /* def FD_SETSIZE */
+extern int svc_maxfd;
+
+/*
+ * a small program implemented by the svc_rpc implementation itself;
+ * also see clnt.h for protocol numbers.
+ */
+extern void rpctest_service();
+
+extern void svc_getreq(int);
+#ifdef FD_SETSIZE
+extern void svc_getreqset(fd_set *);/* takes fdset instead of int */
+extern void svc_getreqset2(fd_set *, int);
+#else
+extern void svc_getreqset(int *);
+#endif
+extern void svc_run(void); /* never returns */
+
+/*
+ * Socket to use on svcxxx_create call to get default socket
+ */
+#define RPC_ANYSOCK -1
+
+/*
+ * These are the existing service side transport implementations
+ */
+
+/*
+ * Memory based rpc for testing and timing.
+ */
+extern SVCXPRT *svcraw_create(void);
+
+/*
+ * Udp based rpc.
+ */
+extern SVCXPRT *svcudp_create(int);
+extern SVCXPRT *svcudp_bufcreate(int, u_int, u_int);
+extern int svcudp_enablecache(SVCXPRT *, uint32_t);
+
+/*
+ * Tcp based rpc.
+ */
+extern SVCXPRT *svctcp_create(int, u_int, u_int);
+
+/*
+ * Like svtcp_create(), except the routine takes any *open* UNIX file
+ * descriptor as its first input.
+ */
+extern SVCXPRT *svcfd_create(int, u_int, u_int);
+
+/* XXX add auth_gsapi_log_*? */
+
+GSSRPC__END_DECLS
+
+#endif /* !defined(GSSRPC_SVC_H) */
diff --git a/src/include/gssrpc/svc_auth.h b/src/include/gssrpc/svc_auth.h
new file mode 100644
index 000000000000..ceb13b746f9f
--- /dev/null
+++ b/src/include/gssrpc/svc_auth.h
@@ -0,0 +1,119 @@
+/* @(#)svc_auth.h 2.1 88/07/29 4.0 RPCSRC */
+/*
+ * Copyright (c) 2010, Oracle America, Inc.
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * * Neither the name of the "Oracle America, Inc." nor the names of
+ * its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/* @(#)svc_auth.h 1.6 86/07/16 SMI */
+
+/*
+ * svc_auth.h, Service side of rpc authentication.
+ */
+
+/*
+ * Interface to server-side authentication flavors.
+ */
+
+#ifndef GSSRPC_SVC_AUTH_H
+#define GSSRPC_SVC_AUTH_H
+
+#include <gssapi/gssapi.h>
+
+GSSRPC__BEGIN_DECLS
+
+struct svc_req;
+
+typedef struct SVCAUTH {
+ struct svc_auth_ops {
+ int (*svc_ah_wrap)(struct SVCAUTH *, XDR *, xdrproc_t,
+ caddr_t);
+ int (*svc_ah_unwrap)(struct SVCAUTH *, XDR *, xdrproc_t,
+ caddr_t);
+ int (*svc_ah_destroy)(struct SVCAUTH *);
+ } *svc_ah_ops;
+ void * svc_ah_private;
+} SVCAUTH;
+
+#ifdef GSSRPC__IMPL
+
+extern SVCAUTH svc_auth_none;
+
+extern struct svc_auth_ops svc_auth_none_ops;
+extern struct svc_auth_ops svc_auth_gssapi_ops;
+extern struct svc_auth_ops svc_auth_gss_ops;
+
+/*
+ * Server side authenticator
+ */
+/* RENAMED: should be _authenticate. */
+extern enum auth_stat gssrpc__authenticate(struct svc_req *rqst,
+ struct rpc_msg *msg, bool_t *no_dispatch);
+
+#define SVCAUTH_WRAP(auth, xdrs, xfunc, xwhere) \
+ ((*((auth)->svc_ah_ops->svc_ah_wrap))(auth, xdrs, xfunc, xwhere))
+#define SVCAUTH_UNWRAP(auth, xdrs, xfunc, xwhere) \
+ ((*((auth)->svc_ah_ops->svc_ah_unwrap))(auth, xdrs, xfunc, xwhere))
+#define SVCAUTH_DESTROY(auth) \
+ ((*((auth)->svc_ah_ops->svc_ah_destroy))(auth))
+
+/* no authentication */
+/* RENAMED: should be _svcauth_none. */
+enum auth_stat gssrpc__svcauth_none(struct svc_req *,
+ struct rpc_msg *, bool_t *);
+/* unix style (uid, gids) */
+/* RENAMED: shoudl be _svcauth_unix. */
+enum auth_stat gssrpc__svcauth_unix(struct svc_req *,
+ struct rpc_msg *, bool_t *);
+/* short hand unix style */
+/* RENAMED: should be _svcauth_short. */
+enum auth_stat gssrpc__svcauth_short(struct svc_req *,
+ struct rpc_msg *, bool_t *);
+/* GSS-API style */
+/* RENAMED: should be _svcauth_gssapi. */
+enum auth_stat gssrpc__svcauth_gssapi(struct svc_req *,
+ struct rpc_msg *, bool_t *);
+/* RPCSEC_GSS */
+enum auth_stat gssrpc__svcauth_gss(struct svc_req *,
+ struct rpc_msg *, bool_t *);
+
+#endif /* defined(GSSRPC__IMPL) */
+
+/*
+ * Approved way of getting principal of caller
+ */
+char *svcauth_gss_get_principal(SVCAUTH *auth);
+/*
+ * Approved way of setting server principal
+ */
+bool_t svcauth_gss_set_svc_name(gss_name_t name);
+
+GSSRPC__END_DECLS
+
+#endif /* !defined(GSSRPC_SVC_AUTH_H) */
diff --git a/src/include/gssrpc/types.hin b/src/include/gssrpc/types.hin
new file mode 100644
index 000000000000..022ab4fa90a7
--- /dev/null
+++ b/src/include/gssrpc/types.hin
@@ -0,0 +1,137 @@
+/* @(#)types.h 2.3 88/08/15 4.0 RPCSRC */
+/*
+ * Copyright (c) 2010, Oracle America, Inc.
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * * Neither the name of the “Oracle America, Inc.” nor the names of
+ * its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/* @(#)types.h 1.18 87/07/24 SMI */
+
+/*
+ * Rpc additions to <sys/types.h>
+ */
+#ifndef GSSRPC_TYPES_H
+#define GSSRPC_TYPES_H
+
+#include <sys/types.h>
+
+@GSSRPC__SYS_SELECT_H@
+@GSSRPC__SYS_TIME_H@
+@GSSRPC__UNISTD_H@
+
+/*
+ * Try to get MAXHOSTNAMELEN from somewhere.
+ */
+@GSSRPC__SYS_PARAM_H@
+@GSSRPC__NETDB_H@
+
+/* Get htonl(), ntohl(), etc. */
+#include <netinet/in.h>
+
+#include <stdlib.h>
+#include <stdint.h>
+#include <limits.h>
+
+#ifndef GSSRPC__BEGIN_DECLS
+#ifdef __cplusplus
+#define GSSRPC__BEGIN_DECLS extern "C" {
+#define GSSRPC__END_DECLS }
+#else
+#define GSSRPC__BEGIN_DECLS
+#define GSSRPC__END_DECLS
+#endif
+#endif
+
+GSSRPC__BEGIN_DECLS
+
+#if defined(CHAR_BIT) && CHAR_BIT != 8
+#error "Bytes must be exactly 8 bits."
+#endif
+
+/* Define if we need to fake up some BSD type aliases. */
+#ifndef GSSRPC__BSD_TYPEALIASES /* Allow application to override. */
+@GSSRPC__BSD_TYPEALIASES@
+#endif
+#if GSSRPC__BSD_TYPEALIASES
+typedef unsigned char u_char;
+typedef unsigned short u_short;
+typedef unsigned int u_int;
+typedef unsigned long u_long;
+#endif
+
+typedef uint32_t rpcprog_t;
+typedef uint32_t rpcvers_t;
+typedef uint32_t rpcprot_t;
+typedef uint32_t rpcproc_t;
+typedef uint32_t rpcport_t;
+typedef int32_t rpc_inline_t;
+
+/* This is for rpc/netdb.h */
+@rpcent_define@
+
+#define bool_t int
+#define enum_t int
+#ifndef FALSE
+# define FALSE (0)
+#endif
+#ifndef TRUE
+# define TRUE (1)
+#endif
+/* XXX namespace */
+#define __dontcare__ -1
+#ifndef NULL
+# define NULL 0
+#endif
+
+/*
+ * The below should probably be internal-only, but seem to be
+ * traditionally exported in RPC implementations.
+ */
+#define mem_alloc(bsize) malloc(bsize)
+#define mem_free(ptr, bsize) free(ptr)
+
+#if 0
+#include <netdb.h> /* XXX This should not have to be here.
+ * I got sick of seeing the warnings for MAXHOSTNAMELEN
+ * and the two values were different. -- shanzer
+ */
+#endif
+
+#ifndef INADDR_LOOPBACK
+#define INADDR_LOOPBACK (uint32_t)0x7F000001
+#endif
+#ifndef MAXHOSTNAMELEN
+#define MAXHOSTNAMELEN 64
+#endif
+
+GSSRPC__END_DECLS
+
+#include <gssrpc/rename.h>
+
+#endif /* !defined(GSSRPC_TYPES_H) */
diff --git a/src/include/gssrpc/xdr.h b/src/include/gssrpc/xdr.h
new file mode 100644
index 000000000000..c66ae6951431
--- /dev/null
+++ b/src/include/gssrpc/xdr.h
@@ -0,0 +1,338 @@
+/* @(#)xdr.h 2.2 88/07/29 4.0 RPCSRC */
+/*
+ * Copyright (c) 2010, Oracle America, Inc.
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * * Neither the name of the "Oracle America, Inc." nor the names of
+ * its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/* @(#)xdr.h 1.19 87/04/22 SMI */
+
+/*
+ * xdr.h, External Data Representation Serialization Routines.
+ */
+
+#ifndef GSSRPC_XDR_H
+#define GSSRPC_XDR_H
+
+#include <stdio.h> /* for FILE */
+
+GSSRPC__BEGIN_DECLS
+/*
+ * XDR provides a conventional way for converting between C data
+ * types and an external bit-string representation. Library supplied
+ * routines provide for the conversion on built-in C data types. These
+ * routines and utility routines defined here are used to help implement
+ * a type encode/decode routine for each user-defined type.
+ *
+ * Each data type provides a single procedure which takes two arguments:
+ *
+ * bool_t
+ * xdrproc(xdrs, argresp)
+ * XDR *xdrs;
+ * <type> *argresp;
+ *
+ * xdrs is an instance of a XDR handle, to which or from which the data
+ * type is to be converted. argresp is a pointer to the structure to be
+ * converted. The XDR handle contains an operation field which indicates
+ * which of the operations (ENCODE, DECODE * or FREE) is to be performed.
+ *
+ * XDR_DECODE may allocate space if the pointer argresp is null. This
+ * data can be freed with the XDR_FREE operation.
+ *
+ * We write only one procedure per data type to make it easy
+ * to keep the encode and decode procedures for a data type consistent.
+ * In many cases the same code performs all operations on a user defined type,
+ * because all the hard work is done in the component type routines.
+ * decode as a series of calls on the nested data types.
+ */
+
+/*
+ * Xdr operations. XDR_ENCODE causes the type to be encoded into the
+ * stream. XDR_DECODE causes the type to be extracted from the stream.
+ * XDR_FREE can be used to release the space allocated by an XDR_DECODE
+ * request.
+ */
+enum xdr_op {
+ XDR_ENCODE=0,
+ XDR_DECODE=1,
+ XDR_FREE=2
+};
+
+/*
+ * This is the number of bytes per unit of external data.
+ */
+#define BYTES_PER_XDR_UNIT (4)
+#define RNDUP(x) ((((x) + BYTES_PER_XDR_UNIT - 1) / BYTES_PER_XDR_UNIT) \
+ * BYTES_PER_XDR_UNIT)
+
+/*
+ * A xdrproc_t exists for each data type which is to be encoded or decoded.
+ *
+ * The second argument to the xdrproc_t is a pointer to an opaque pointer.
+ * The opaque pointer generally points to a structure of the data type
+ * to be decoded. If this pointer is 0, then the type routines should
+ * allocate dynamic storage of the appropriate size and return it.
+ * bool_t (*xdrproc_t)(XDR *, caddr_t *);
+ *
+ * XXX can't actually prototype it, because some take three args!!!
+ */
+typedef bool_t (*xdrproc_t)();
+
+/*
+ * The XDR handle.
+ * Contains operation which is being applied to the stream,
+ * an operations vector for the paticular implementation (e.g. see xdr_mem.c),
+ * and two private fields for the use of the particular impelementation.
+ */
+typedef struct XDR {
+ enum xdr_op x_op; /* operation; fast additional param */
+ struct xdr_ops {
+ /* get a long from underlying stream */
+ bool_t (*x_getlong)(struct XDR *, long *);
+
+ /* put a long to underlying stream */
+ bool_t (*x_putlong)(struct XDR *, long *);
+
+ /* get some bytes from underlying stream */
+ bool_t (*x_getbytes)(struct XDR *, caddr_t, u_int);
+
+ /* put some bytes to underlying stream */
+ bool_t (*x_putbytes)(struct XDR *, caddr_t, u_int);
+
+ /* returns bytes off from beginning */
+ u_int (*x_getpostn)(struct XDR *);
+
+ /* lets you reposition the stream */
+ bool_t (*x_setpostn)(struct XDR *, u_int);
+
+ /* buf quick ptr to buffered data */
+ rpc_inline_t *(*x_inline)(struct XDR *, int);
+
+ /* free privates of this xdr_stream */
+ void (*x_destroy)(struct XDR *);
+ } *x_ops;
+ caddr_t x_public; /* users' data */
+ void * x_private; /* pointer to private data */
+ caddr_t x_base; /* private used for position info */
+ int x_handy; /* extra private word */
+} XDR;
+
+/*
+ * Operations defined on a XDR handle
+ *
+ * XDR *xdrs;
+ * int32_t *longp;
+ * caddr_t addr;
+ * u_int len;
+ * u_int pos;
+ */
+#define XDR_GETLONG(xdrs, longp) \
+ (*(xdrs)->x_ops->x_getlong)(xdrs, longp)
+#define xdr_getlong(xdrs, longp) \
+ (*(xdrs)->x_ops->x_getlong)(xdrs, longp)
+
+#define XDR_PUTLONG(xdrs, longp) \
+ (*(xdrs)->x_ops->x_putlong)(xdrs, longp)
+#define xdr_putlong(xdrs, longp) \
+ (*(xdrs)->x_ops->x_putlong)(xdrs, longp)
+
+#define XDR_GETBYTES(xdrs, addr, len) \
+ (*(xdrs)->x_ops->x_getbytes)(xdrs, addr, len)
+#define xdr_getbytes(xdrs, addr, len) \
+ (*(xdrs)->x_ops->x_getbytes)(xdrs, addr, len)
+
+#define XDR_PUTBYTES(xdrs, addr, len) \
+ (*(xdrs)->x_ops->x_putbytes)(xdrs, addr, len)
+#define xdr_putbytes(xdrs, addr, len) \
+ (*(xdrs)->x_ops->x_putbytes)(xdrs, addr, len)
+
+#define XDR_GETPOS(xdrs) \
+ (*(xdrs)->x_ops->x_getpostn)(xdrs)
+#define xdr_getpos(xdrs) \
+ (*(xdrs)->x_ops->x_getpostn)(xdrs)
+
+#define XDR_SETPOS(xdrs, pos) \
+ (*(xdrs)->x_ops->x_setpostn)(xdrs, pos)
+#define xdr_setpos(xdrs, pos) \
+ (*(xdrs)->x_ops->x_setpostn)(xdrs, pos)
+
+#define XDR_INLINE(xdrs, len) \
+ (*(xdrs)->x_ops->x_inline)(xdrs, len)
+#define xdr_inline(xdrs, len) \
+ (*(xdrs)->x_ops->x_inline)(xdrs, len)
+
+#define XDR_DESTROY(xdrs) \
+ if ((xdrs)->x_ops->x_destroy) \
+ (*(xdrs)->x_ops->x_destroy)(xdrs)
+#define xdr_destroy(xdrs) \
+ if ((xdrs)->x_ops->x_destroy) \
+ (*(xdrs)->x_ops->x_destroy)(xdrs)
+
+/*
+ * Support struct for discriminated unions.
+ * You create an array of xdrdiscrim structures, terminated with
+ * a entry with a null procedure pointer. The xdr_union routine gets
+ * the discriminant value and then searches the array of structures
+ * for a matching value. If a match is found the associated xdr routine
+ * is called to handle that part of the union. If there is
+ * no match, then a default routine may be called.
+ * If there is no match and no default routine it is an error.
+ */
+#define NULL_xdrproc_t ((xdrproc_t)0)
+struct xdr_discrim {
+ int value;
+ xdrproc_t proc;
+};
+
+/*
+ * In-line routines for fast encode/decode of primitve data types.
+ * Caveat emptor: these use single memory cycles to get the
+ * data from the underlying buffer, and will fail to operate
+ * properly if the data is not aligned. The standard way to use these
+ * is to say:
+ * if ((buf = XDR_INLINE(xdrs, count)) == NULL)
+ * return (FALSE);
+ * <<< macro calls >>>
+ * where ``count'' is the number of bytes of data occupied
+ * by the primitive data types.
+ *
+ * N.B. and frozen for all time: each data type here uses 4 bytes
+ * of external representation.
+ */
+#define IXDR_GET_INT32(buf) ((int32_t)IXDR_GET_U_INT32(buf))
+#define IXDR_PUT_INT32(buf, v) IXDR_PUT_U_INT32((buf),((uint32_t)(v)))
+#define IXDR_GET_U_INT32(buf) (ntohl((uint32_t)*(buf)++))
+#define IXDR_PUT_U_INT32(buf, v) (*(buf)++ = (int32_t)htonl((v)))
+
+#define IXDR_GET_LONG(buf) ((long)IXDR_GET_INT32(buf))
+#define IXDR_PUT_LONG(buf, v) IXDR_PUT_U_INT32((buf),((uint32_t)(v)))
+
+#define IXDR_GET_BOOL(buf) ((bool_t)IXDR_GET_LONG(buf))
+#define IXDR_GET_ENUM(buf, t) ((t)IXDR_GET_INT32(buf))
+#define IXDR_GET_U_LONG(buf) ((u_long)IXDR_GET_U_INT32(buf))
+#define IXDR_GET_SHORT(buf) ((short)IXDR_GET_INT32(buf))
+#define IXDR_GET_U_SHORT(buf) ((u_short)IXDR_GET_U_INT32(buf))
+
+#define IXDR_PUT_BOOL(buf, v) IXDR_PUT_INT32((buf),((int32_t)(v)))
+#define IXDR_PUT_ENUM(buf, v) IXDR_PUT_INT32((buf),((int32_t)(v)))
+#define IXDR_PUT_U_LONG(buf, v) IXDR_PUT_U_INT32((buf),((uint32_t)(v)))
+#define IXDR_PUT_SHORT(buf, v) IXDR_PUT_INT32((buf),((int32_t)(v)))
+#define IXDR_PUT_U_SHORT(buf, v) IXDR_PUT_U_INT32((buf),((uint32_t)(v)))
+
+/*
+ * These are the "generic" xdr routines.
+ */
+extern bool_t xdr_void(XDR *, void *);
+extern bool_t xdr_int(XDR *, int *);
+extern bool_t xdr_u_int(XDR *, u_int *);
+extern bool_t xdr_long(XDR *, long *);
+extern bool_t xdr_u_long(XDR *, u_long *);
+extern bool_t xdr_short(XDR *, short *);
+extern bool_t xdr_u_short(XDR *, u_short *);
+extern bool_t xdr_bool(XDR *, bool_t *);
+extern bool_t xdr_enum(XDR *, enum_t *);
+extern bool_t xdr_array(XDR *, caddr_t *, u_int *,
+ u_int, u_int, xdrproc_t);
+extern bool_t xdr_bytes(XDR *, char **, u_int *, u_int);
+extern bool_t xdr_opaque(XDR *, caddr_t, u_int);
+extern bool_t xdr_string(XDR *, char **, u_int);
+extern bool_t xdr_union(XDR *, enum_t *, char *, struct xdr_discrim *,
+ xdrproc_t);
+extern bool_t xdr_char(XDR *, char *);
+extern bool_t xdr_u_char(XDR *, u_char *);
+extern bool_t xdr_vector(XDR *, char *, u_int, u_int, xdrproc_t);
+extern bool_t xdr_float(XDR *, float *);
+extern bool_t xdr_double(XDR *, double *);
+extern bool_t xdr_reference(XDR *, caddr_t *, u_int, xdrproc_t);
+extern bool_t xdr_pointer(XDR *, char **, u_int, xdrproc_t);
+extern bool_t xdr_wrapstring(XDR *, char **);
+
+extern unsigned long xdr_sizeof(xdrproc_t, void *);
+
+#define xdr_rpcprog xdr_u_int32
+#define xdr_rpcvers xdr_u_int32
+#define xdr_rpcprot xdr_u_int32
+#define xdr_rpcproc xdr_u_int32
+#define xdr_rpcport xdr_u_int32
+
+/*
+ * Common opaque bytes objects used by many rpc protocols;
+ * declared here due to commonality.
+ */
+#define MAX_NETOBJ_SZ 2048
+struct netobj {
+ u_int n_len;
+ char *n_bytes;
+};
+typedef struct netobj netobj;
+
+extern bool_t xdr_netobj(XDR *, struct netobj *);
+
+extern bool_t xdr_int32(XDR *, int32_t *);
+extern bool_t xdr_u_int32(XDR *, uint32_t *);
+
+/*
+ * These are the public routines for the various implementations of
+ * xdr streams.
+ */
+
+/* XDR allocating memory buffer */
+extern void xdralloc_create(XDR *, enum xdr_op);
+
+/* destroy xdralloc, save buf */
+extern void xdralloc_release(XDR *);
+
+/* get buffer from xdralloc */
+extern caddr_t xdralloc_getdata(XDR *);
+
+/* XDR using memory buffers */
+extern void xdrmem_create(XDR *, caddr_t, u_int, enum xdr_op);
+
+/* XDR using stdio library */
+extern void xdrstdio_create(XDR *, FILE *, enum xdr_op);
+
+/* XDR pseudo records for tcp */
+extern void xdrrec_create(XDR *xdrs, u_int, u_int, caddr_t,
+ int (*) (caddr_t, caddr_t, int),
+ int (*) (caddr_t, caddr_t, int));
+
+/* make end of xdr record */
+extern bool_t xdrrec_endofrecord(XDR *, bool_t);
+
+/* move to beginning of next record */
+extern bool_t xdrrec_skiprecord (XDR *xdrs);
+
+/* true if no more input */
+extern bool_t xdrrec_eof (XDR *xdrs);
+
+/* free memory buffers for xdr */
+extern void xdr_free (xdrproc_t, void *);
+GSSRPC__END_DECLS
+
+#endif /* !defined(GSSRPC_XDR_H) */
diff --git a/src/include/iprop.h b/src/include/iprop.h
new file mode 100644
index 000000000000..7367666e2c5a
--- /dev/null
+++ b/src/include/iprop.h
@@ -0,0 +1,275 @@
+/*
+ * Please do not edit this file.
+ * It was generated using rpcgen.
+ */
+
+#ifndef _IPROP_H_RPCGEN
+#define _IPROP_H_RPCGEN
+
+#include <gssrpc/rpc.h>
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+typedef struct {
+ u_int utf8str_t_len;
+ char *utf8str_t_val;
+} utf8str_t;
+
+typedef uint32_t kdb_sno_t;
+
+struct kdbe_time_t {
+ uint32_t seconds;
+ uint32_t useconds;
+};
+typedef struct kdbe_time_t kdbe_time_t;
+
+struct kdbe_key_t {
+ int32_t k_ver;
+ int32_t k_kvno;
+ struct {
+ u_int k_enctype_len;
+ int32_t *k_enctype_val;
+ } k_enctype;
+ struct {
+ u_int k_contents_len;
+ utf8str_t *k_contents_val;
+ } k_contents;
+};
+typedef struct kdbe_key_t kdbe_key_t;
+
+struct kdbe_data_t {
+ int32_t k_magic;
+ utf8str_t k_data;
+};
+typedef struct kdbe_data_t kdbe_data_t;
+
+struct kdbe_princ_t {
+ utf8str_t k_realm;
+ struct {
+ u_int k_components_len;
+ kdbe_data_t *k_components_val;
+ } k_components;
+ int32_t k_nametype;
+};
+typedef struct kdbe_princ_t kdbe_princ_t;
+
+struct kdbe_tl_t {
+ int16_t tl_type;
+ struct {
+ u_int tl_data_len;
+ char *tl_data_val;
+ } tl_data;
+};
+typedef struct kdbe_tl_t kdbe_tl_t;
+
+typedef struct {
+ u_int kdbe_pw_hist_t_len;
+ kdbe_key_t *kdbe_pw_hist_t_val;
+} kdbe_pw_hist_t;
+
+enum kdbe_attr_type_t {
+ AT_ATTRFLAGS = 0,
+ AT_MAX_LIFE = 1,
+ AT_MAX_RENEW_LIFE = 2,
+ AT_EXP = 3,
+ AT_PW_EXP = 4,
+ AT_LAST_SUCCESS = 5,
+ AT_LAST_FAILED = 6,
+ AT_FAIL_AUTH_COUNT = 7,
+ AT_PRINC = 8,
+ AT_KEYDATA = 9,
+ AT_TL_DATA = 10,
+ AT_LEN = 11,
+ AT_MOD_PRINC = 12,
+ AT_MOD_TIME = 13,
+ AT_MOD_WHERE = 14,
+ AT_PW_LAST_CHANGE = 15,
+ AT_PW_POLICY = 16,
+ AT_PW_POLICY_SWITCH = 17,
+ AT_PW_HIST_KVNO = 18,
+ AT_PW_HIST = 19
+};
+typedef enum kdbe_attr_type_t kdbe_attr_type_t;
+
+struct kdbe_val_t {
+ kdbe_attr_type_t av_type;
+ union {
+ uint32_t av_attrflags;
+ uint32_t av_max_life;
+ uint32_t av_max_renew_life;
+ uint32_t av_exp;
+ uint32_t av_pw_exp;
+ uint32_t av_last_success;
+ uint32_t av_last_failed;
+ uint32_t av_fail_auth_count;
+ kdbe_princ_t av_princ;
+ struct {
+ u_int av_keydata_len;
+ kdbe_key_t *av_keydata_val;
+ } av_keydata;
+ struct {
+ u_int av_tldata_len;
+ kdbe_tl_t *av_tldata_val;
+ } av_tldata;
+ int16_t av_len;
+ uint32_t av_pw_last_change;
+ kdbe_princ_t av_mod_princ;
+ uint32_t av_mod_time;
+ utf8str_t av_mod_where;
+ utf8str_t av_pw_policy;
+ bool_t av_pw_policy_switch;
+ uint32_t av_pw_hist_kvno;
+ struct {
+ u_int av_pw_hist_len;
+ kdbe_pw_hist_t *av_pw_hist_val;
+ } av_pw_hist;
+ struct {
+ u_int av_extension_len;
+ char *av_extension_val;
+ } av_extension;
+ } kdbe_val_t_u;
+};
+typedef struct kdbe_val_t kdbe_val_t;
+
+typedef struct {
+ u_int kdbe_t_len;
+ kdbe_val_t *kdbe_t_val;
+} kdbe_t;
+
+struct kdb_incr_update_t {
+ utf8str_t kdb_princ_name;
+ kdb_sno_t kdb_entry_sno;
+ kdbe_time_t kdb_time;
+ kdbe_t kdb_update;
+ bool_t kdb_deleted;
+ bool_t kdb_commit;
+ struct {
+ u_int kdb_kdcs_seen_by_len;
+ utf8str_t *kdb_kdcs_seen_by_val;
+ } kdb_kdcs_seen_by;
+ struct {
+ u_int kdb_futures_len;
+ char *kdb_futures_val;
+ } kdb_futures;
+};
+typedef struct kdb_incr_update_t kdb_incr_update_t;
+
+typedef struct {
+ u_int kdb_ulog_t_len;
+ kdb_incr_update_t *kdb_ulog_t_val;
+} kdb_ulog_t;
+
+enum update_status_t {
+ UPDATE_OK = 0,
+ UPDATE_ERROR = 1,
+ UPDATE_FULL_RESYNC_NEEDED = 2,
+ UPDATE_BUSY = 3,
+ UPDATE_NIL = 4,
+ UPDATE_PERM_DENIED = 5
+};
+typedef enum update_status_t update_status_t;
+
+struct kdb_last_t {
+ kdb_sno_t last_sno;
+ kdbe_time_t last_time;
+};
+typedef struct kdb_last_t kdb_last_t;
+
+struct kdb_incr_result_t {
+ kdb_last_t lastentry;
+ kdb_ulog_t updates;
+ update_status_t ret;
+};
+typedef struct kdb_incr_result_t kdb_incr_result_t;
+
+struct kdb_fullresync_result_t {
+ kdb_last_t lastentry;
+ update_status_t ret;
+};
+typedef struct kdb_fullresync_result_t kdb_fullresync_result_t;
+
+#define KRB5_IPROP_PROG 100423
+#define KRB5_IPROP_VERS 1
+
+#if defined(__STDC__) || defined(__cplusplus)
+#define IPROP_NULL 0
+extern void * iprop_null_1(void *, CLIENT *);
+extern void * iprop_null_1_svc(void *, struct svc_req *);
+#define IPROP_GET_UPDATES 1
+extern kdb_incr_result_t * iprop_get_updates_1(kdb_last_t *, CLIENT *);
+extern kdb_incr_result_t * iprop_get_updates_1_svc(kdb_last_t *, struct svc_req *);
+#define IPROP_FULL_RESYNC 2
+extern kdb_fullresync_result_t * iprop_full_resync_1(void *, CLIENT *);
+extern kdb_fullresync_result_t * iprop_full_resync_1_svc(void *, struct svc_req *);
+#define IPROP_FULL_RESYNC_EXT 3
+extern kdb_fullresync_result_t * iprop_full_resync_ext_1(uint32_t *, CLIENT *);
+extern kdb_fullresync_result_t * iprop_full_resync_ext_1_svc(uint32_t *, struct svc_req *);
+extern int krb5_iprop_prog_1_freeresult (SVCXPRT *, xdrproc_t, caddr_t);
+
+#else /* K&R C */
+#define IPROP_NULL 0
+extern void * iprop_null_1();
+extern void * iprop_null_1_svc();
+#define IPROP_GET_UPDATES 1
+extern kdb_incr_result_t * iprop_get_updates_1();
+extern kdb_incr_result_t * iprop_get_updates_1_svc();
+#define IPROP_FULL_RESYNC 2
+extern kdb_fullresync_result_t * iprop_full_resync_1();
+extern kdb_fullresync_result_t * iprop_full_resync_1_svc();
+#define IPROP_FULL_RESYNC_EXT 3
+extern kdb_fullresync_result_t * iprop_full_resync_ext_1(uint32_t *, CLIENT *);
+extern kdb_fullresync_result_t * iprop_full_resync_ext_1_svc(uint32_t *, struct svc_req *);
+extern int krb5_iprop_prog_1_freeresult ();
+#endif /* K&R C */
+
+/* the xdr functions */
+
+#if defined(__STDC__) || defined(__cplusplus)
+extern bool_t xdr_utf8str_t (XDR *, utf8str_t*);
+extern bool_t xdr_kdb_sno_t (XDR *, kdb_sno_t*);
+extern bool_t xdr_kdbe_time_t (XDR *, kdbe_time_t*);
+extern bool_t xdr_kdbe_key_t (XDR *, kdbe_key_t*);
+extern bool_t xdr_kdbe_data_t (XDR *, kdbe_data_t*);
+extern bool_t xdr_kdbe_princ_t (XDR *, kdbe_princ_t*);
+extern bool_t xdr_kdbe_tl_t (XDR *, kdbe_tl_t*);
+extern bool_t xdr_kdbe_pw_hist_t (XDR *, kdbe_pw_hist_t*);
+extern bool_t xdr_kdbe_attr_type_t (XDR *, kdbe_attr_type_t*);
+extern bool_t xdr_kdbe_val_t (XDR *, kdbe_val_t*);
+extern bool_t xdr_kdbe_t (XDR *, kdbe_t*);
+extern bool_t xdr_kdb_incr_update_t (XDR *, kdb_incr_update_t*);
+extern bool_t xdr_kdb_ulog_t (XDR *, kdb_ulog_t*);
+extern bool_t xdr_update_status_t (XDR *, update_status_t*);
+extern bool_t xdr_kdb_last_t (XDR *, kdb_last_t*);
+extern bool_t xdr_kdb_incr_result_t (XDR *, kdb_incr_result_t*);
+extern bool_t xdr_kdb_fullresync_result_t (XDR *, kdb_fullresync_result_t*);
+
+#else /* K&R C */
+extern bool_t xdr_utf8str_t ();
+extern bool_t xdr_kdb_sno_t ();
+extern bool_t xdr_kdbe_time_t ();
+extern bool_t xdr_kdbe_key_t ();
+extern bool_t xdr_kdbe_data_t ();
+extern bool_t xdr_kdbe_princ_t ();
+extern bool_t xdr_kdbe_tl_t ();
+extern bool_t xdr_kdbe_pw_hist_t ();
+extern bool_t xdr_kdbe_attr_type_t ();
+extern bool_t xdr_kdbe_val_t ();
+extern bool_t xdr_kdbe_t ();
+extern bool_t xdr_kdb_incr_update_t ();
+extern bool_t xdr_kdb_ulog_t ();
+extern bool_t xdr_update_status_t ();
+extern bool_t xdr_kdb_last_t ();
+extern bool_t xdr_kdb_incr_result_t ();
+extern bool_t xdr_kdb_fullresync_result_t ();
+
+#endif /* K&R C */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* !_IPROP_H_RPCGEN */
diff --git a/src/include/iprop_hdr.h b/src/include/iprop_hdr.h
new file mode 100644
index 000000000000..9027c76cf928
--- /dev/null
+++ b/src/include/iprop_hdr.h
@@ -0,0 +1,50 @@
+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/*
+ * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+
+#ifndef _IPROP_HDR_H
+#define _IPROP_HDR_H
+
+/* #pragma ident "@(#)iprop_hdr.h 1.1 04/02/20 SMI" */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * This file has some defines common to the iprop client and
+ * server routines.
+ */
+
+/*
+ * Maximum size for each ulog entry is 2KB and maximum
+ * possible attribute-value pairs for each ulog entry is 20
+ */
+#define MAXENTRY_SIZE 2048
+#define MAXATTRS_SIZE 20
+
+#define KIPROP_SVC_NAME "kiprop"
+#define MAX_BACKOFF 300 /* Backoff for a maximum for 5 mts */
+
+enum iprop_role {
+ IPROP_NULL = 0,
+ IPROP_MASTER = 1,
+ IPROP_SLAVE = 2
+};
+typedef enum iprop_role iprop_role;
+
+/*
+ * Full resync dump versioning
+ */
+#define IPROPX_VERSION_0 0
+#define IPROPX_VERSION_1 1
+#define IPROPX_VERSION IPROPX_VERSION_1
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* !_IPROP_HDR_H */
diff --git a/src/include/k5-base64.h b/src/include/k5-base64.h
new file mode 100644
index 000000000000..a7cc48fb52d0
--- /dev/null
+++ b/src/include/k5-base64.h
@@ -0,0 +1,52 @@
+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/* include/k5-base64.h - base64 declarations */
+/*
+ * Copyright (c) 1995, 1996, 1997 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef K5_BASE64_H
+#define K5_BASE64_H
+
+#include <stddef.h>
+
+/* base64-encode data and return it in an allocated buffer. Return NULL if out
+ * of memory. */
+char *k5_base64_encode(const void *data, size_t len);
+
+/*
+ * Decode str as base64 and return the result in an allocated buffer, setting
+ * *len_out to the length. Return NULL and *len_out == 0 if out of memory,
+ * NULL and *len_out == SIZE_MAX on invalid input.
+ */
+void *k5_base64_decode(const char *str, size_t *len_out);
+
+#endif /* K5_BASE64_H */
diff --git a/src/include/k5-buf.h b/src/include/k5-buf.h
new file mode 100644
index 000000000000..f3207bd09afd
--- /dev/null
+++ b/src/include/k5-buf.h
@@ -0,0 +1,99 @@
+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/* include/k5-buf.h - k5buf interface declarations */
+/*
+ * Copyright 2008 Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ * require a specific license from the United States Government.
+ * It is the responsibility of any person or organization contemplating
+ * export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission. Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose. It is provided "as is" without express
+ * or implied warranty.
+ */
+
+#ifndef K5_BUF_H
+#define K5_BUF_H
+
+#include <stdarg.h>
+#include <string.h>
+
+/*
+ * The k5buf module is intended to allow multi-step string construction in a
+ * fixed or dynamic buffer without the need to check for a failure at each step
+ * (and without aborting on malloc failure). If an allocation failure occurs
+ * or the fixed buffer runs out of room, the buffer will be set to an error
+ * state which can be detected with k5_buf_status. Data in a buffer is
+ * terminated with a zero byte so that it can be used as a C string.
+ *
+ * k5buf structures are usually stack-allocated. Do not put k5buf structure
+ * pointers into public APIs. It is okay to reference the data and len fields
+ * of a buffer (they will be NULL/0 if the buffer is in an error state), but do
+ * not change them.
+ */
+
+/* Buffer type values */
+enum k5buftype { K5BUF_ERROR, K5BUF_FIXED, K5BUF_DYNAMIC };
+
+struct k5buf {
+ enum k5buftype buftype;
+ void *data;
+ size_t space;
+ size_t len;
+};
+
+#define EMPTY_K5BUF { K5BUF_ERROR }
+
+/* Initialize a k5buf using a fixed-sized, existing buffer. SPACE must be
+ * more than zero, or an assertion failure will result. */
+void k5_buf_init_fixed(struct k5buf *buf, char *data, size_t space);
+
+/* Initialize a k5buf using an internally allocated dynamic buffer. */
+void k5_buf_init_dynamic(struct k5buf *buf);
+
+/* Add a C string to BUF. */
+void k5_buf_add(struct k5buf *buf, const char *data);
+
+/* Add a counted series of bytes to BUF. */
+void k5_buf_add_len(struct k5buf *buf, const void *data, size_t len);
+
+/* Add sprintf-style formatted data to BUF. */
+void k5_buf_add_fmt(struct k5buf *buf, const char *fmt, ...)
+#if !defined(__cplusplus) && (__GNUC__ > 2)
+ __attribute__((__format__(__printf__, 2, 3)))
+#endif
+ ;
+
+/* Extend the length of buf by len and return a pointer to the reserved space,
+ * to be filled in by the caller. Return NULL on error. */
+void *k5_buf_get_space(struct k5buf *buf, size_t len);
+
+/* Truncate BUF. LEN must be between 0 and the existing buffer
+ * length, or an assertion failure will result. */
+void k5_buf_truncate(struct k5buf *buf, size_t len);
+
+/* Return ENOMEM if buf is in an error state, 0 otherwise. */
+int k5_buf_status(struct k5buf *buf);
+
+/*
+ * Free the storage used in the dynamic buffer BUF. The caller may choose to
+ * take responsibility for freeing the data pointer instead of using this
+ * function. If BUF is a fixed buffer, an assertion failure will result.
+ * Freeing a buffer in the error state, a buffer initialized with EMPTY_K5BUF,
+ * or a zeroed k5buf structure is a no-op.
+ */
+void k5_buf_free(struct k5buf *buf);
+
+#endif /* K5_BUF_H */
diff --git a/src/include/k5-err.h b/src/include/k5-err.h
new file mode 100644
index 000000000000..d92920764e6d
--- /dev/null
+++ b/src/include/k5-err.h
@@ -0,0 +1,69 @@
+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/* include/k5-err.h */
+/*
+ * Copyright 2006, 2007 Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ * require a specific license from the United States Government.
+ * It is the responsibility of any person or organization contemplating
+ * export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission. Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose. It is provided "as is" without express
+ * or implied warranty.
+ */
+
+/*
+ *
+ * Error-message handling
+ */
+
+#ifndef K5_ERR_H
+#define K5_ERR_H
+
+#if defined(_MSDOS) || defined(_WIN32)
+#include <win-mac.h>
+#endif
+#ifndef KRB5_CALLCONV
+#define KRB5_CALLCONV
+#define KRB5_CALLCONV_C
+#endif
+
+#include <stdarg.h>
+
+struct errinfo {
+ long code;
+ char *msg;
+};
+#define EMPTY_ERRINFO { 0, NULL }
+
+void k5_set_error(struct errinfo *ep, long code, const char *fmt, ...)
+#if !defined(__cplusplus) && (__GNUC__ > 2)
+ __attribute__((__format__(__printf__, 3, 4)))
+#endif
+ ;
+
+void k5_vset_error(struct errinfo *ep, long code, const char *fmt,
+ va_list args)
+#if !defined(__cplusplus) && (__GNUC__ > 2)
+ __attribute__((__format__(__printf__, 3, 0)))
+#endif
+ ;
+
+const char *k5_get_error(struct errinfo *ep, long code);
+void k5_free_error(struct errinfo *ep, const char *msg);
+void k5_clear_error(struct errinfo *ep);
+void k5_set_error_info_callout_fn(const char *(KRB5_CALLCONV *f)(long));
+
+#endif /* K5_ERR_H */
diff --git a/src/include/k5-gmt_mktime.h b/src/include/k5-gmt_mktime.h
new file mode 100644
index 000000000000..795e46ce5e2a
--- /dev/null
+++ b/src/include/k5-gmt_mktime.h
@@ -0,0 +1,53 @@
+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/* include/k5-gmt_mktime.h */
+/*
+ * Copyright 2008 Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ * require a specific license from the United States Government.
+ * It is the responsibility of any person or organization contemplating
+ * export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission. Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose. It is provided "as is" without express
+ * or implied warranty.
+ */
+
+/*
+ *
+ * GMT struct tm conversion
+ *
+ * Because of ordering of things in the UNIX build, we can't just keep
+ * the declaration in k5-int.h and include it in
+ * util/support/gmt_mktime.c, since k5-int.h includes krb5.h which
+ * hasn't been built when gmt_mktime.c gets compiled. Hence this
+ * silly little helper header.
+ */
+
+#ifndef K5_GMT_MKTIME_H
+#define K5_GMT_MKTIME_H
+
+#include "autoconf.h"
+#ifdef HAVE_SYS_TIME_H
+#include <sys/time.h>
+#ifdef TIME_WITH_SYS_TIME
+#include <time.h>
+#endif
+#else
+#include <time.h>
+#endif
+
+time_t krb5int_gmt_mktime (struct tm *);
+
+#endif /* K5_GMT_MKTIME_H */
diff --git a/src/include/k5-input.h b/src/include/k5-input.h
new file mode 100644
index 000000000000..d42ebce8f271
--- /dev/null
+++ b/src/include/k5-input.h
@@ -0,0 +1,143 @@
+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/* include/k5-input.h - k5input helper functions */
+/*
+ * Copyright (C) 2014 by the Massachusetts Institute of Technology.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef K5_INPUT_H
+#define K5_INPUT_H
+
+#include "k5-int.h"
+
+/*
+ * The k5input module defines helpers for safely consuming a fixed-sized block
+ * of memory. If an overrun or allocation failure occurs at any step,
+ * subsequent functions will return default values until the error is detected
+ * by looking at the status field.
+ */
+
+struct k5input {
+ const unsigned char *ptr;
+ size_t len;
+ krb5_error_code status;
+};
+
+static inline void
+k5_input_init(struct k5input *in, const void *ptr, size_t len)
+{
+ in->ptr = ptr;
+ in->len = len;
+ in->status = 0;
+}
+
+/* Only set the status value of in if it hasn't already been set, so status
+ * reflects the first thing to go wrong. */
+static inline void
+k5_input_set_status(struct k5input *in, krb5_error_code status)
+{
+ if (!in->status)
+ in->status = status;
+}
+
+static inline const unsigned char *
+k5_input_get_bytes(struct k5input *in, size_t len)
+{
+ if (in->len < len)
+ k5_input_set_status(in, EINVAL);
+ if (in->status)
+ return NULL;
+ in->len -= len;
+ in->ptr += len;
+ return in->ptr - len;
+}
+
+static inline unsigned char
+k5_input_get_byte(struct k5input *in)
+{
+ const unsigned char *ptr = k5_input_get_bytes(in, 1);
+ return (ptr == NULL) ? '\0' : *ptr;
+}
+
+static inline uint16_t
+k5_input_get_uint16_be(struct k5input *in)
+{
+ const unsigned char *ptr = k5_input_get_bytes(in, 2);
+ return (ptr == NULL) ? 0 : load_16_be(ptr);
+}
+
+static inline uint16_t
+k5_input_get_uint16_le(struct k5input *in)
+{
+ const unsigned char *ptr = k5_input_get_bytes(in, 2);
+ return (ptr == NULL) ? 0 : load_16_le(ptr);
+}
+
+static inline uint16_t
+k5_input_get_uint16_n(struct k5input *in)
+{
+ const unsigned char *ptr = k5_input_get_bytes(in, 2);
+ return (ptr == NULL) ? 0 : load_16_n(ptr);
+}
+
+static inline uint32_t
+k5_input_get_uint32_be(struct k5input *in)
+{
+ const unsigned char *ptr = k5_input_get_bytes(in, 4);
+ return (ptr == NULL) ? 0 : load_32_be(ptr);
+}
+
+static inline uint32_t
+k5_input_get_uint32_le(struct k5input *in)
+{
+ const unsigned char *ptr = k5_input_get_bytes(in, 4);
+ return (ptr == NULL) ? 0 : load_32_le(ptr);
+}
+
+static inline uint32_t
+k5_input_get_uint32_n(struct k5input *in)
+{
+ const unsigned char *ptr = k5_input_get_bytes(in, 4);
+ return (ptr == NULL) ? 0 : load_32_n(ptr);
+}
+
+static inline uint64_t
+k5_input_get_uint64_be(struct k5input *in)
+{
+ const unsigned char *ptr = k5_input_get_bytes(in, 8);
+ return (ptr == NULL) ? 0 : load_64_be(ptr);
+}
+
+static inline uint64_t
+k5_input_get_uint64_le(struct k5input *in)
+{
+ const unsigned char *ptr = k5_input_get_bytes(in, 8);
+ return (ptr == NULL) ? 0 : load_64_le(ptr);
+}
+
+#endif /* K5_BUF_H */
diff --git a/src/include/k5-int-pkinit.h b/src/include/k5-int-pkinit.h
new file mode 100644
index 000000000000..7b2f595cbb99
--- /dev/null
+++ b/src/include/k5-int-pkinit.h
@@ -0,0 +1,283 @@
+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/*
+ * COPYRIGHT (C) 2006
+ * THE REGENTS OF THE UNIVERSITY OF MICHIGAN
+ * ALL RIGHTS RESERVED
+ *
+ * Permission is granted to use, copy, create derivative works
+ * and redistribute this software and such derivative works
+ * for any purpose, so long as the name of The University of
+ * Michigan is not used in any advertising or publicity
+ * pertaining to the use of distribution of this software
+ * without specific, written prior authorization. If the
+ * above copyright notice or any other identification of the
+ * University of Michigan is included in any copy of any
+ * portion of this software, then the disclaimer below must
+ * also be included.
+ *
+ * THIS SOFTWARE IS PROVIDED AS IS, WITHOUT REPRESENTATION
+ * FROM THE UNIVERSITY OF MICHIGAN AS TO ITS FITNESS FOR ANY
+ * PURPOSE, AND WITHOUT WARRANTY BY THE UNIVERSITY OF
+ * MICHIGAN OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING
+ * WITHOUT LIMITATION THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE
+ * REGENTS OF THE UNIVERSITY OF MICHIGAN SHALL NOT BE LIABLE
+ * FOR ANY DAMAGES, INCLUDING SPECIAL, INDIRECT, INCIDENTAL, OR
+ * CONSEQUENTIAL DAMAGES, WITH RESPECT TO ANY CLAIM ARISING
+ * OUT OF OR IN CONNECTION WITH THE USE OF THE SOFTWARE, EVEN
+ * IF IT HAS BEEN OR IS HEREAFTER ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGES.
+ */
+
+#ifndef _KRB5_INT_PKINIT_H
+#define _KRB5_INT_PKINIT_H
+
+/*
+ * pkinit structures
+ */
+
+/* PKAuthenticator */
+typedef struct _krb5_pk_authenticator {
+ krb5_int32 cusec; /* (0..999999) */
+ krb5_timestamp ctime;
+ krb5_int32 nonce; /* (0..4294967295) */
+ krb5_checksum paChecksum;
+} krb5_pk_authenticator;
+
+/* PKAuthenticator draft9 */
+typedef struct _krb5_pk_authenticator_draft9 {
+ krb5_principal kdcName;
+ krb5_int32 cusec; /* (0..999999) */
+ krb5_timestamp ctime;
+ krb5_int32 nonce; /* (0..4294967295) */
+} krb5_pk_authenticator_draft9;
+
+/* AlgorithmIdentifier */
+typedef struct _krb5_algorithm_identifier {
+ krb5_data algorithm; /* OID */
+ krb5_data parameters; /* Optional */
+} krb5_algorithm_identifier;
+
+/* SubjectPublicKeyInfo */
+typedef struct _krb5_subject_pk_info {
+ krb5_algorithm_identifier algorithm;
+ krb5_data subjectPublicKey; /* BIT STRING */
+} krb5_subject_pk_info;
+
+/** AuthPack from RFC 4556*/
+typedef struct _krb5_auth_pack {
+ krb5_pk_authenticator pkAuthenticator;
+ krb5_subject_pk_info *clientPublicValue; /* Optional */
+ krb5_algorithm_identifier **supportedCMSTypes; /* Optional */
+ krb5_data clientDHNonce; /* Optional */
+ krb5_data **supportedKDFs; /* OIDs of KDFs; OPTIONAL */
+} krb5_auth_pack;
+
+/* AuthPack draft9 */
+typedef struct _krb5_auth_pack_draft9 {
+ krb5_pk_authenticator_draft9 pkAuthenticator;
+ krb5_subject_pk_info *clientPublicValue; /* Optional */
+} krb5_auth_pack_draft9;
+
+/* ExternalPrincipalIdentifier */
+typedef struct _krb5_external_principal_identifier {
+ krb5_data subjectName; /* Optional */
+ krb5_data issuerAndSerialNumber; /* Optional */
+ krb5_data subjectKeyIdentifier; /* Optional */
+} krb5_external_principal_identifier;
+
+/* PA-PK-AS-REQ (Draft 9 -- PA TYPE 14) */
+/* This has four fields, but we only care about the first and third for
+ * encoding, and the only about the first for decoding. */
+typedef struct _krb5_pa_pk_as_req_draft9 {
+ krb5_data signedAuthPack;
+ krb5_data kdcCert; /* Optional */
+} krb5_pa_pk_as_req_draft9;
+
+/* PA-PK-AS-REQ (rfc4556 -- PA TYPE 16) */
+typedef struct _krb5_pa_pk_as_req {
+ krb5_data signedAuthPack;
+ krb5_external_principal_identifier **trustedCertifiers; /* Optional array */
+ krb5_data kdcPkId; /* Optional */
+} krb5_pa_pk_as_req;
+
+/** Pkinit DHRepInfo */
+typedef struct _krb5_dh_rep_info {
+ krb5_data dhSignedData;
+ krb5_data serverDHNonce; /* Optional */
+ krb5_data *kdfID; /* OID of selected KDF OPTIONAL */
+} krb5_dh_rep_info;
+
+/* KDCDHKeyInfo */
+typedef struct _krb5_kdc_dh_key_info {
+ krb5_data subjectPublicKey; /* BIT STRING */
+ krb5_int32 nonce; /* (0..4294967295) */
+ krb5_timestamp dhKeyExpiration; /* Optional */
+} krb5_kdc_dh_key_info;
+
+/* KDCDHKeyInfo draft9*/
+typedef struct _krb5_kdc_dh_key_info_draft9 {
+ krb5_data subjectPublicKey; /* BIT STRING */
+ krb5_int32 nonce; /* (0..4294967295) */
+} krb5_kdc_dh_key_info_draft9;
+
+/* ReplyKeyPack */
+typedef struct _krb5_reply_key_pack {
+ krb5_keyblock replyKey;
+ krb5_checksum asChecksum;
+} krb5_reply_key_pack;
+
+/* ReplyKeyPack */
+typedef struct _krb5_reply_key_pack_draft9 {
+ krb5_keyblock replyKey;
+ krb5_int32 nonce;
+} krb5_reply_key_pack_draft9;
+
+/* PA-PK-AS-REP (Draft 9 -- PA TYPE 15) */
+typedef struct _krb5_pa_pk_as_rep_draft9 {
+ enum krb5_pa_pk_as_rep_draft9_selection {
+ choice_pa_pk_as_rep_draft9_UNKNOWN = -1,
+ choice_pa_pk_as_rep_draft9_dhSignedData = 0,
+ choice_pa_pk_as_rep_draft9_encKeyPack = 1
+ } choice;
+ union krb5_pa_pk_as_rep_draft9_choices {
+ krb5_data dhSignedData;
+ krb5_data encKeyPack;
+ } u;
+} krb5_pa_pk_as_rep_draft9;
+
+/* PA-PK-AS-REP (rfc4556 -- PA TYPE 17) */
+typedef struct _krb5_pa_pk_as_rep {
+ enum krb5_pa_pk_as_rep_selection {
+ choice_pa_pk_as_rep_UNKNOWN = -1,
+ choice_pa_pk_as_rep_dhInfo = 0,
+ choice_pa_pk_as_rep_encKeyPack = 1
+ } choice;
+ union krb5_pa_pk_as_rep_choices {
+ krb5_dh_rep_info dh_Info;
+ krb5_data encKeyPack;
+ } u;
+} krb5_pa_pk_as_rep;
+
+/* SP80056A OtherInfo, for pkinit algorithm agility */
+typedef struct _krb5_sp80056a_other_info {
+ krb5_algorithm_identifier algorithm_identifier;
+ krb5_principal party_u_info;
+ krb5_principal party_v_info;
+ krb5_data supp_pub_info;
+} krb5_sp80056a_other_info;
+
+/* PkinitSuppPubInfo, for pkinit algorithm agility */
+typedef struct _krb5_pkinit_supp_pub_info {
+ krb5_enctype enctype;
+ krb5_data as_req;
+ krb5_data pk_as_rep;
+} krb5_pkinit_supp_pub_info;
+
+/*
+ * Begin "asn1.h"
+ */
+
+/*************************************************************************
+ * Prototypes for pkinit asn.1 encode routines
+ *************************************************************************/
+
+krb5_error_code
+encode_krb5_pa_pk_as_req(const krb5_pa_pk_as_req *rep, krb5_data **code);
+
+krb5_error_code
+encode_krb5_pa_pk_as_req_draft9(const krb5_pa_pk_as_req_draft9 *rep,
+ krb5_data **code);
+
+krb5_error_code
+encode_krb5_pa_pk_as_rep(const krb5_pa_pk_as_rep *rep, krb5_data **code);
+
+krb5_error_code
+encode_krb5_pa_pk_as_rep_draft9(const krb5_pa_pk_as_rep_draft9 *rep,
+ krb5_data **code);
+
+krb5_error_code
+encode_krb5_auth_pack(const krb5_auth_pack *rep, krb5_data **code);
+
+krb5_error_code
+encode_krb5_auth_pack_draft9(const krb5_auth_pack_draft9 *rep,
+ krb5_data **code);
+
+krb5_error_code
+encode_krb5_kdc_dh_key_info(const krb5_kdc_dh_key_info *rep, krb5_data **code);
+
+krb5_error_code
+encode_krb5_reply_key_pack(const krb5_reply_key_pack *, krb5_data **code);
+
+krb5_error_code
+encode_krb5_reply_key_pack_draft9(const krb5_reply_key_pack_draft9 *,
+ krb5_data **code);
+
+krb5_error_code
+encode_krb5_td_trusted_certifiers(krb5_external_principal_identifier *const *,
+ krb5_data **code);
+
+krb5_error_code
+encode_krb5_td_dh_parameters(krb5_algorithm_identifier *const *,
+ krb5_data **code);
+
+krb5_error_code
+encode_krb5_sp80056a_other_info(const krb5_sp80056a_other_info *,
+ krb5_data **);
+
+krb5_error_code
+encode_krb5_pkinit_supp_pub_info(const krb5_pkinit_supp_pub_info *,
+ krb5_data **);
+
+/*************************************************************************
+ * Prototypes for pkinit asn.1 decode routines
+ *************************************************************************/
+
+krb5_error_code
+decode_krb5_pa_pk_as_req(const krb5_data *, krb5_pa_pk_as_req **);
+
+krb5_error_code
+decode_krb5_pa_pk_as_req_draft9(const krb5_data *,
+ krb5_pa_pk_as_req_draft9 **);
+
+krb5_error_code
+decode_krb5_pa_pk_as_rep(const krb5_data *, krb5_pa_pk_as_rep **);
+
+krb5_error_code
+decode_krb5_auth_pack(const krb5_data *, krb5_auth_pack **);
+
+krb5_error_code
+decode_krb5_auth_pack_draft9(const krb5_data *, krb5_auth_pack_draft9 **);
+
+krb5_error_code
+decode_krb5_kdc_dh_key_info(const krb5_data *, krb5_kdc_dh_key_info **);
+
+krb5_error_code
+decode_krb5_principal_name(const krb5_data *, krb5_principal_data **);
+
+krb5_error_code
+decode_krb5_reply_key_pack(const krb5_data *, krb5_reply_key_pack **);
+
+krb5_error_code
+decode_krb5_reply_key_pack_draft9(const krb5_data *,
+ krb5_reply_key_pack_draft9 **);
+
+krb5_error_code
+decode_krb5_td_trusted_certifiers(const krb5_data *,
+ krb5_external_principal_identifier ***);
+
+krb5_error_code
+decode_krb5_td_dh_parameters(const krb5_data *, krb5_algorithm_identifier ***);
+
+krb5_error_code
+encode_krb5_enc_data(const krb5_enc_data *, krb5_data **);
+
+krb5_error_code
+encode_krb5_encryption_key(const krb5_keyblock *rep, krb5_data **code);
+
+krb5_error_code
+krb5_encrypt_helper(krb5_context context, const krb5_keyblock *key,
+ krb5_keyusage keyusage, const krb5_data *plain,
+ krb5_enc_data *cipher);
+
+#endif /* _KRB5_INT_PKINIT_H */
diff --git a/src/include/k5-int.h b/src/include/k5-int.h
new file mode 100644
index 000000000000..64991738a3e2
--- /dev/null
+++ b/src/include/k5-int.h
@@ -0,0 +1,2389 @@
+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/*
+ * Copyright (C) 1989,1990,1991,1992,1993,1994,1995,2000,2001,
+ * 2003,2006,2007,2008,2009 by the Massachusetts Institute of Technology,
+ * Cambridge, MA, USA. All Rights Reserved.
+ *
+ * This software is being provided to you, the LICENSEE, by the
+ * Massachusetts Institute of Technology (M.I.T.) under the following
+ * license. By obtaining, using and/or copying this software, you agree
+ * that you have read, understood, and will comply with these terms and
+ * conditions:
+ *
+ * Export of this software from the United States of America may
+ * require a specific license from the United States Government.
+ * It is the responsibility of any person or organization contemplating
+ * export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify and distribute
+ * this software and its documentation for any purpose and without fee or
+ * royalty is hereby granted, provided that you agree to comply with the
+ * following copyright notice and statements, including the disclaimer, and
+ * that the same appear on ALL copies of the software and documentation,
+ * including modifications that you make for internal use or for
+ * distribution:
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS", AND M.I.T. MAKES NO REPRESENTATIONS
+ * OR WARRANTIES, EXPRESS OR IMPLIED. By way of example, but not
+ * limitation, M.I.T. MAKES NO REPRESENTATIONS OR WARRANTIES OF
+ * MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF
+ * THE LICENSED SOFTWARE OR DOCUMENTATION WILL NOT INFRINGE ANY THIRD PARTY
+ * PATENTS, COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS.
+ *
+ * The name of the Massachusetts Institute of Technology or M.I.T. may NOT
+ * be used in advertising or publicity pertaining to distribution of the
+ * software. Title to copyright in this software and any associated
+ * documentation shall at all times remain with M.I.T., and USER agrees to
+ * preserve same.
+ *
+ * Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ */
+/*
+ * Copyright (C) 1998 by the FundsXpress, INC.
+ *
+ * All rights reserved.
+ *
+ * Export of this software from the United States of America may require
+ * a specific license from the United States Government. It is the
+ * responsibility of any person or organization contemplating export to
+ * obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of FundsXpress. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission. FundsXpress makes no representations about the suitability of
+ * this software for any purpose. It is provided "as is" without express
+ * or implied warranty.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+/*
+ * This prototype for k5-int.h (Krb5 internals include file)
+ * includes the user-visible definitions from krb5.h and then
+ * includes other definitions that are not user-visible but are
+ * required for compiling Kerberos internal routines.
+ *
+ * John Gilmore, Cygnus Support, Sat Jan 21 22:45:52 PST 1995
+ */
+
+#ifndef _KRB5_INT_H
+#define _KRB5_INT_H
+
+#ifdef KRB5_GENERAL__
+#error krb5.h included before k5-int.h
+#endif /* KRB5_GENERAL__ */
+
+#include "osconf.h"
+
+#if defined(__MACH__) && defined(__APPLE__)
+# include <TargetConditionals.h>
+# if TARGET_RT_MAC_CFM
+# error "Use KfM 4.0 SDK headers for CFM compilation."
+# endif
+#endif
+
+/*
+ * Begin "k5-config.h"
+ */
+#ifndef KRB5_CONFIG__
+#define KRB5_CONFIG__
+
+/*
+ * Machine-type definitions: PC Clone 386 running Microloss Windows
+ */
+
+#if defined(_MSDOS) || defined(_WIN32)
+#include "win-mac.h"
+
+/* Kerberos Windows initialization file */
+#define KERBEROS_INI "kerberos.ini"
+#define INI_FILES "Files"
+#define INI_KRB_CCACHE "krb5cc" /* Location of the ccache */
+#define INI_KRB5_CONF "krb5.ini" /* Location of krb5.conf file */
+#endif
+
+#include "autoconf.h"
+
+#ifndef KRB5_SYSTYPES__
+#define KRB5_SYSTYPES__
+
+#ifdef HAVE_SYS_TYPES_H /* From autoconf.h */
+#include <sys/types.h>
+#else /* HAVE_SYS_TYPES_H */
+typedef unsigned long u_long;
+typedef unsigned int u_int;
+typedef unsigned short u_short;
+typedef unsigned char u_char;
+#endif /* HAVE_SYS_TYPES_H */
+#endif /* KRB5_SYSTYPES__ */
+
+
+#include "k5-platform.h"
+
+#define KRB5_KDB_MAX_LIFE (60*60*24) /* one day */
+#define KRB5_KDB_MAX_RLIFE (60*60*24*7) /* one week */
+#define KRB5_KDB_EXPIRATION 2145830400 /* Thu Jan 1 00:00:00 2038 UTC */
+
+/*
+ * Windows requires a different api interface to each function. Here
+ * just define it as NULL.
+ */
+#ifndef KRB5_CALLCONV
+#define KRB5_CALLCONV
+#define KRB5_CALLCONV_C
+#endif
+#ifndef O_BINARY
+#define O_BINARY 0
+#endif
+
+/* #define KRB5_OLD_CRYPTO is done in krb5.h */
+
+#endif /* KRB5_CONFIG__ */
+
+/*
+ * End "k5-config.h"
+ */
+
+/*
+ * After loading the configuration definitions, load the Kerberos definitions.
+ */
+#include <errno.h>
+#include "krb5.h"
+#include <krb5/plugin.h>
+#include "profile.h"
+
+#include "port-sockets.h"
+#include "socket-utils.h"
+
+/* Get mutex support; currently used only for the replay cache. */
+#include "k5-thread.h"
+
+/* Get error info support. */
+#include "k5-err.h"
+
+/* Get string buffer support. */
+#include "k5-buf.h"
+
+/* Define tracing macros. */
+#include "k5-trace.h"
+
+/* Profile variables. Constants are named KRB5_CONF_STRING, where STRING
+ * matches the variable name. Keep these alphabetized. */
+#define KRB5_CONF_ACL_FILE "acl_file"
+#define KRB5_CONF_ADMIN_SERVER "admin_server"
+#define KRB5_CONF_ALLOW_WEAK_CRYPTO "allow_weak_crypto"
+#define KRB5_CONF_AP_REQ_CHECKSUM_TYPE "ap_req_checksum_type"
+#define KRB5_CONF_AUTH_TO_LOCAL "auth_to_local"
+#define KRB5_CONF_AUTH_TO_LOCAL_NAMES "auth_to_local_names"
+#define KRB5_CONF_CANONICALIZE "canonicalize"
+#define KRB5_CONF_CCACHE_TYPE "ccache_type"
+#define KRB5_CONF_CLOCKSKEW "clockskew"
+#define KRB5_CONF_DATABASE_NAME "database_name"
+#define KRB5_CONF_DB_MODULE_DIR "db_module_dir"
+#define KRB5_CONF_DEBUG "debug"
+#define KRB5_CONF_DEFAULT "default"
+#define KRB5_CONF_DEFAULT_CCACHE_NAME "default_ccache_name"
+#define KRB5_CONF_DEFAULT_CLIENT_KEYTAB_NAME "default_client_keytab_name"
+#define KRB5_CONF_DEFAULT_DOMAIN "default_domain"
+#define KRB5_CONF_DEFAULT_KEYTAB_NAME "default_keytab_name"
+#define KRB5_CONF_DEFAULT_PRINCIPAL_EXPIRATION "default_principal_expiration"
+#define KRB5_CONF_DEFAULT_PRINCIPAL_FLAGS "default_principal_flags"
+#define KRB5_CONF_DEFAULT_REALM "default_realm"
+#define KRB5_CONF_DEFAULT_TGS_ENCTYPES "default_tgs_enctypes"
+#define KRB5_CONF_DEFAULT_TKT_ENCTYPES "default_tkt_enctypes"
+#define KRB5_CONF_DES_CRC_SESSION_SUPPORTED "des_crc_session_supported"
+#define KRB5_CONF_DICT_FILE "dict_file"
+#define KRB5_CONF_DISABLE "disable"
+#define KRB5_CONF_DISABLE_LAST_SUCCESS "disable_last_success"
+#define KRB5_CONF_DISABLE_LOCKOUT "disable_lockout"
+#define KRB5_CONF_DNS_CANONICALIZE_HOSTNAME "dns_canonicalize_hostname"
+#define KRB5_CONF_DNS_FALLBACK "dns_fallback"
+#define KRB5_CONF_DNS_LOOKUP_KDC "dns_lookup_kdc"
+#define KRB5_CONF_DNS_LOOKUP_REALM "dns_lookup_realm"
+#define KRB5_CONF_DNS_URI_LOOKUP "dns_uri_lookup"
+#define KRB5_CONF_DOMAIN_REALM "domain_realm"
+#define KRB5_CONF_ENABLE_ONLY "enable_only"
+#define KRB5_CONF_ERR_FMT "err_fmt"
+#define KRB5_CONF_EXTRA_ADDRESSES "extra_addresses"
+#define KRB5_CONF_FORWARDABLE "forwardable"
+#define KRB5_CONF_HOST_BASED_SERVICES "host_based_services"
+#define KRB5_CONF_HTTP_ANCHORS "http_anchors"
+#define KRB5_CONF_IGNORE_ACCEPTOR_HOSTNAME "ignore_acceptor_hostname"
+#define KRB5_CONF_IPROP_ENABLE "iprop_enable"
+#define KRB5_CONF_IPROP_LISTEN "iprop_listen"
+#define KRB5_CONF_IPROP_LOGFILE "iprop_logfile"
+#define KRB5_CONF_IPROP_MASTER_ULOGSIZE "iprop_master_ulogsize"
+#define KRB5_CONF_IPROP_PORT "iprop_port"
+#define KRB5_CONF_IPROP_RESYNC_TIMEOUT "iprop_resync_timeout"
+#define KRB5_CONF_IPROP_SLAVE_POLL "iprop_slave_poll"
+#define KRB5_CONF_K5LOGIN_AUTHORITATIVE "k5login_authoritative"
+#define KRB5_CONF_K5LOGIN_DIRECTORY "k5login_directory"
+#define KRB5_CONF_KADMIND_LISTEN "kadmind_listen"
+#define KRB5_CONF_KADMIND_PORT "kadmind_port"
+#define KRB5_CONF_KCM_MACH_SERVICE "kcm_mach_service"
+#define KRB5_CONF_KCM_SOCKET "kcm_socket"
+#define KRB5_CONF_KDC "kdc"
+#define KRB5_CONF_KDCDEFAULTS "kdcdefaults"
+#define KRB5_CONF_KDC_DEFAULT_OPTIONS "kdc_default_options"
+#define KRB5_CONF_KDC_LISTEN "kdc_listen"
+#define KRB5_CONF_KDC_MAX_DGRAM_REPLY_SIZE "kdc_max_dgram_reply_size"
+#define KRB5_CONF_KDC_PORTS "kdc_ports"
+#define KRB5_CONF_KDC_REQ_CHECKSUM_TYPE "kdc_req_checksum_type"
+#define KRB5_CONF_KDC_TCP_PORTS "kdc_tcp_ports"
+#define KRB5_CONF_KDC_TCP_LISTEN "kdc_tcp_listen"
+#define KRB5_CONF_KDC_TCP_LISTEN_BACKLOG "kdc_tcp_listen_backlog"
+#define KRB5_CONF_KDC_TIMESYNC "kdc_timesync"
+#define KRB5_CONF_KEY_STASH_FILE "key_stash_file"
+#define KRB5_CONF_KPASSWD_LISTEN "kpasswd_listen"
+#define KRB5_CONF_KPASSWD_PORT "kpasswd_port"
+#define KRB5_CONF_KPASSWD_SERVER "kpasswd_server"
+#define KRB5_CONF_KRB524_SERVER "krb524_server"
+#define KRB5_CONF_LDAP_CONNS_PER_SERVER "ldap_conns_per_server"
+#define KRB5_CONF_LDAP_KADMIND_DN "ldap_kadmind_dn"
+#define KRB5_CONF_LDAP_KADMIND_SASL_AUTHCID "ldap_kadmind_sasl_authcid"
+#define KRB5_CONF_LDAP_KADMIND_SASL_AUTHZID "ldap_kadmind_sasl_authzid"
+#define KRB5_CONF_LDAP_KADMIND_SASL_MECH "ldap_kadmind_sasl_mech"
+#define KRB5_CONF_LDAP_KADMIND_SASL_REALM "ldap_kadmind_sasl_realm"
+#define KRB5_CONF_LDAP_KDC_DN "ldap_kdc_dn"
+#define KRB5_CONF_LDAP_KDC_SASL_AUTHCID "ldap_kdc_sasl_authcid"
+#define KRB5_CONF_LDAP_KDC_SASL_AUTHZID "ldap_kdc_sasl_authzid"
+#define KRB5_CONF_LDAP_KDC_SASL_MECH "ldap_kdc_sasl_mech"
+#define KRB5_CONF_LDAP_KDC_SASL_REALM "ldap_kdc_sasl_realm"
+#define KRB5_CONF_LDAP_KERBEROS_CONTAINER_DN "ldap_kerberos_container_dn"
+#define KRB5_CONF_LDAP_SERVERS "ldap_servers"
+#define KRB5_CONF_LDAP_SERVICE_PASSWORD_FILE "ldap_service_password_file"
+#define KRB5_CONF_LIBDEFAULTS "libdefaults"
+#define KRB5_CONF_LOGGING "logging"
+#define KRB5_CONF_MASTER_KDC "master_kdc"
+#define KRB5_CONF_MASTER_KEY_NAME "master_key_name"
+#define KRB5_CONF_MASTER_KEY_TYPE "master_key_type"
+#define KRB5_CONF_MAX_LIFE "max_life"
+#define KRB5_CONF_MAX_RENEWABLE_LIFE "max_renewable_life"
+#define KRB5_CONF_MODULE "module"
+#define KRB5_CONF_NOADDRESSES "noaddresses"
+#define KRB5_CONF_NO_HOST_REFERRAL "no_host_referral"
+#define KRB5_CONF_PERMITTED_ENCTYPES "permitted_enctypes"
+#define KRB5_CONF_PLUGINS "plugins"
+#define KRB5_CONF_PLUGIN_BASE_DIR "plugin_base_dir"
+#define KRB5_CONF_PREFERRED_PREAUTH_TYPES "preferred_preauth_types"
+#define KRB5_CONF_PROXIABLE "proxiable"
+#define KRB5_CONF_RDNS "rdns"
+#define KRB5_CONF_REALMS "realms"
+#define KRB5_CONF_REALM_TRY_DOMAINS "realm_try_domains"
+#define KRB5_CONF_REJECT_BAD_TRANSIT "reject_bad_transit"
+#define KRB5_CONF_RENEW_LIFETIME "renew_lifetime"
+#define KRB5_CONF_RESTRICT_ANONYMOUS_TO_TGT "restrict_anonymous_to_tgt"
+#define KRB5_CONF_SAFE_CHECKSUM_TYPE "safe_checksum_type"
+#define KRB5_CONF_SUPPORTED_ENCTYPES "supported_enctypes"
+#define KRB5_CONF_TICKET_LIFETIME "ticket_lifetime"
+#define KRB5_CONF_UDP_PREFERENCE_LIMIT "udp_preference_limit"
+#define KRB5_CONF_UNLOCKITER "unlockiter"
+#define KRB5_CONF_V4_INSTANCE_CONVERT "v4_instance_convert"
+#define KRB5_CONF_V4_REALM "v4_realm"
+#define KRB5_CONF_VERIFY_AP_REQ_NOFAIL "verify_ap_req_nofail"
+
+/* Cache configuration variables */
+#define KRB5_CC_CONF_FAST_AVAIL "fast_avail"
+#define KRB5_CC_CONF_PA_CONFIG_DATA "pa_config_data"
+#define KRB5_CC_CONF_PA_TYPE "pa_type"
+#define KRB5_CC_CONF_PROXY_IMPERSONATOR "proxy_impersonator"
+#define KRB5_CC_CONF_REFRESH_TIME "refresh_time"
+
+/* Error codes used in KRB_ERROR protocol messages.
+ Return values of library routines are based on a different error table
+ (which allows non-ambiguous error codes between subsystems) */
+
+/* KDC errors */
+#define KDC_ERR_NONE 0 /* No error */
+#define KDC_ERR_NAME_EXP 1 /* Client's entry in DB expired */
+#define KDC_ERR_SERVICE_EXP 2 /* Server's entry in DB expired */
+#define KDC_ERR_BAD_PVNO 3 /* Requested pvno not supported */
+#define KDC_ERR_C_OLD_MAST_KVNO 4 /* C's key encrypted in old master */
+#define KDC_ERR_S_OLD_MAST_KVNO 5 /* S's key encrypted in old master */
+#define KDC_ERR_C_PRINCIPAL_UNKNOWN 6 /* Client not found in Kerberos DB */
+#define KDC_ERR_S_PRINCIPAL_UNKNOWN 7 /* Server not found in Kerberos DB */
+#define KDC_ERR_PRINCIPAL_NOT_UNIQUE 8 /* Multiple entries in Kerberos DB */
+#define KDC_ERR_NULL_KEY 9 /* The C or S has a null key */
+#define KDC_ERR_CANNOT_POSTDATE 10 /* Tkt ineligible for postdating */
+#define KDC_ERR_NEVER_VALID 11 /* Requested starttime > endtime */
+#define KDC_ERR_POLICY 12 /* KDC policy rejects request */
+#define KDC_ERR_BADOPTION 13 /* KDC can't do requested opt. */
+#define KDC_ERR_ENCTYPE_NOSUPP 14 /* No support for encryption type */
+#define KDC_ERR_SUMTYPE_NOSUPP 15 /* No support for checksum type */
+#define KDC_ERR_PADATA_TYPE_NOSUPP 16 /* No support for padata type */
+#define KDC_ERR_TRTYPE_NOSUPP 17 /* No support for transited type */
+#define KDC_ERR_CLIENT_REVOKED 18 /* C's creds have been revoked */
+#define KDC_ERR_SERVICE_REVOKED 19 /* S's creds have been revoked */
+#define KDC_ERR_TGT_REVOKED 20 /* TGT has been revoked */
+#define KDC_ERR_CLIENT_NOTYET 21 /* C not yet valid */
+#define KDC_ERR_SERVICE_NOTYET 22 /* S not yet valid */
+#define KDC_ERR_KEY_EXP 23 /* Password has expired */
+#define KDC_ERR_PREAUTH_FAILED 24 /* Preauthentication failed */
+#define KDC_ERR_PREAUTH_REQUIRED 25 /* Additional preauthentication */
+ /* required */
+#define KDC_ERR_SERVER_NOMATCH 26 /* Requested server and */
+ /* ticket don't match*/
+#define KDC_ERR_MUST_USE_USER2USER 27 /* Server principal valid for */
+ /* user2user only */
+#define KDC_ERR_PATH_NOT_ACCEPTED 28 /* KDC policy rejected transited */
+ /* path */
+#define KDC_ERR_SVC_UNAVAILABLE 29 /* A service is not
+ * available that is
+ * required to process the
+ * request */
+/* Application errors */
+#define KRB_AP_ERR_BAD_INTEGRITY 31 /* Decrypt integrity check failed */
+#define KRB_AP_ERR_TKT_EXPIRED 32 /* Ticket expired */
+#define KRB_AP_ERR_TKT_NYV 33 /* Ticket not yet valid */
+#define KRB_AP_ERR_REPEAT 34 /* Request is a replay */
+#define KRB_AP_ERR_NOT_US 35 /* The ticket isn't for us */
+#define KRB_AP_ERR_BADMATCH 36 /* Ticket/authenticator don't match */
+#define KRB_AP_ERR_SKEW 37 /* Clock skew too great */
+#define KRB_AP_ERR_BADADDR 38 /* Incorrect net address */
+#define KRB_AP_ERR_BADVERSION 39 /* Protocol version mismatch */
+#define KRB_AP_ERR_MSG_TYPE 40 /* Invalid message type */
+#define KRB_AP_ERR_MODIFIED 41 /* Message stream modified */
+#define KRB_AP_ERR_BADORDER 42 /* Message out of order */
+#define KRB_AP_ERR_BADKEYVER 44 /* Key version is not available */
+#define KRB_AP_ERR_NOKEY 45 /* Service key not available */
+#define KRB_AP_ERR_MUT_FAIL 46 /* Mutual authentication failed */
+#define KRB_AP_ERR_BADDIRECTION 47 /* Incorrect message direction */
+#define KRB_AP_ERR_METHOD 48 /* Alternative authentication */
+ /* method required */
+#define KRB_AP_ERR_BADSEQ 49 /* Incorrect sequence numnber */
+ /* in message */
+#define KRB_AP_ERR_INAPP_CKSUM 50 /* Inappropriate type of */
+ /* checksum in message */
+#define KRB_AP_PATH_NOT_ACCEPTED 51 /* Policy rejects transited path */
+#define KRB_ERR_RESPONSE_TOO_BIG 52 /* Response too big for UDP, */
+ /* retry with TCP */
+
+/* other errors */
+#define KRB_ERR_GENERIC 60 /* Generic error (description */
+ /* in e-text) */
+#define KRB_ERR_FIELD_TOOLONG 61 /* Field is too long for impl. */
+
+/* PKINIT server-reported errors */
+#define KDC_ERR_CLIENT_NOT_TRUSTED 62 /* client cert not trusted */
+#define KDC_ERR_KDC_NOT_TRUSTED 63
+#define KDC_ERR_INVALID_SIG 64 /* client signature verify failed */
+#define KDC_ERR_DH_KEY_PARAMETERS_NOT_ACCEPTED 65 /* invalid Diffie-Hellman parameters */
+#define KDC_ERR_CERTIFICATE_MISMATCH 66
+#define KRB_AP_ERR_NO_TGT 67
+#define KDC_ERR_WRONG_REALM 68
+#define KRB_AP_ERR_USER_TO_USER_REQUIRED 69
+#define KDC_ERR_CANT_VERIFY_CERTIFICATE 70 /* client cert not verifiable to */
+ /* trusted root cert */
+#define KDC_ERR_INVALID_CERTIFICATE 71 /* client cert had invalid signature */
+#define KDC_ERR_REVOKED_CERTIFICATE 72 /* client cert was revoked */
+#define KDC_ERR_REVOCATION_STATUS_UNKNOWN 73 /* client cert revoked, reason unknown */
+#define KDC_ERR_REVOCATION_STATUS_UNAVAILABLE 74
+#define KDC_ERR_CLIENT_NAME_MISMATCH 75 /* mismatch between client cert and */
+ /* principal name */
+#define KDC_ERR_INCONSISTENT_KEY_PURPOSE 77 /* bad extended key use */
+#define KDC_ERR_DIGEST_IN_CERT_NOT_ACCEPTED 78 /* bad digest algorithm in client cert */
+#define KDC_ERR_PA_CHECKSUM_MUST_BE_INCLUDED 79 /* missing paChecksum in PA-PK-AS-REQ */
+#define KDC_ERR_DIGEST_IN_SIGNED_DATA_NOT_ACCEPTED 80 /* bad digest algorithm in SignedData */
+#define KDC_ERR_PUBLIC_KEY_ENCRYPTION_NOT_SUPPORTED 81
+#define KRB_AP_ERR_IAKERB_KDC_NOT_FOUND 85 /* The IAKERB proxy could
+ not find a KDC */
+#define KRB_AP_ERR_IAKERB_KDC_NO_RESPONSE 86 /* The KDC did not respond
+ to the IAKERB proxy */
+#define KDC_ERR_PREAUTH_EXPIRED 90 /* RFC 6113 */
+#define KDC_ERR_MORE_PREAUTH_DATA_REQUIRED 91 /* RFC 6113 */
+#define KRB_ERR_MAX 127 /* err table base max offset for protocol err codes */
+
+/*
+ * A null-terminated array of this structure is returned by the KDC as
+ * the data part of the ETYPE_INFO preauth type. It informs the
+ * client which encryption types are supported.
+ * The same data structure is used by both etype-info and etype-info2
+ * but s2kparams must be null when encoding etype-info.
+ */
+typedef struct _krb5_etype_info_entry {
+ krb5_magic magic;
+ krb5_enctype etype;
+ unsigned int length;
+ krb5_octet *salt;
+ krb5_data s2kparams;
+} krb5_etype_info_entry;
+
+/*
+ * This is essentially -1 without sign extension which can screw up
+ * comparisons on 64 bit machines. If the length is this value, then
+ * the salt data is not present. This is to distinguish between not
+ * being set and being of 0 length.
+ */
+#define KRB5_ETYPE_NO_SALT VALID_UINT_BITS
+
+typedef krb5_etype_info_entry ** krb5_etype_info;
+
+/* RFC 4537 */
+typedef struct _krb5_etype_list {
+ int length;
+ krb5_enctype *etypes;
+} krb5_etype_list;
+
+/* sam_type values -- informational only */
+#define PA_SAM_TYPE_ENIGMA 1 /* Enigma Logic */
+#define PA_SAM_TYPE_DIGI_PATH 2 /* Digital Pathways */
+#define PA_SAM_TYPE_SKEY_K0 3 /* S/key where KDC has key 0 */
+#define PA_SAM_TYPE_SKEY 4 /* Traditional S/Key */
+#define PA_SAM_TYPE_SECURID 5 /* Security Dynamics */
+#define PA_SAM_TYPE_CRYPTOCARD 6 /* CRYPTOCard */
+#if 1 /* XXX need to figure out who has which numbers assigned */
+#define PA_SAM_TYPE_ACTIVCARD_DEC 6 /* ActivCard decimal mode */
+#define PA_SAM_TYPE_ACTIVCARD_HEX 7 /* ActivCard hex mode */
+#define PA_SAM_TYPE_DIGI_PATH_HEX 8 /* Digital Pathways hex mode */
+#endif
+#define PA_SAM_TYPE_EXP_BASE 128 /* experimental */
+#define PA_SAM_TYPE_GRAIL (PA_SAM_TYPE_EXP_BASE+0) /* testing */
+#define PA_SAM_TYPE_SECURID_PREDICT (PA_SAM_TYPE_EXP_BASE+1) /* special */
+
+typedef struct _krb5_sam_challenge_2 {
+ krb5_data sam_challenge_2_body;
+ krb5_checksum **sam_cksum; /* Array of checksums */
+} krb5_sam_challenge_2;
+
+typedef struct _krb5_sam_challenge_2_body {
+ krb5_magic magic;
+ krb5_int32 sam_type; /* information */
+ krb5_flags sam_flags; /* KRB5_SAM_* values */
+ krb5_data sam_type_name;
+ krb5_data sam_track_id;
+ krb5_data sam_challenge_label;
+ krb5_data sam_challenge;
+ krb5_data sam_response_prompt;
+ krb5_data sam_pk_for_sad;
+ krb5_int32 sam_nonce;
+ krb5_enctype sam_etype;
+} krb5_sam_challenge_2_body;
+
+typedef struct _krb5_sam_response_2 {
+ krb5_magic magic;
+ krb5_int32 sam_type; /* informational */
+ krb5_flags sam_flags; /* KRB5_SAM_* values */
+ krb5_data sam_track_id; /* copied */
+ krb5_enc_data sam_enc_nonce_or_sad; /* krb5_enc_sam_response_enc */
+ krb5_int32 sam_nonce;
+} krb5_sam_response_2;
+
+typedef struct _krb5_enc_sam_response_enc_2 {
+ krb5_magic magic;
+ krb5_int32 sam_nonce;
+ krb5_data sam_sad;
+} krb5_enc_sam_response_enc_2;
+
+/*
+ * Keep the pkinit definitions in a separate file so that the plugin
+ * only has to include k5-int-pkinit.h rather than k5-int.h
+ */
+
+#include "k5-int-pkinit.h"
+
+#define KRB5_OTP_FLAG_NEXTOTP 0x40000000
+#define KRB5_OTP_FLAG_COMBINE 0x20000000
+#define KRB5_OTP_FLAG_COLLECT_PIN 0x10000000
+#define KRB5_OTP_FLAG_NO_COLLECT_PIN 0x08000000
+#define KRB5_OTP_FLAG_ENCRYPT_NONCE 0x04000000
+#define KRB5_OTP_FLAG_SEPARATE_PIN 0x02000000
+#define KRB5_OTP_FLAG_CHECK_DIGIT 0x01000000
+
+#define KRB5_OTP_FORMAT_DECIMAL 0x00000000
+#define KRB5_OTP_FORMAT_HEXADECIMAL 0x00000001
+#define KRB5_OTP_FORMAT_ALPHANUMERIC 0x00000002
+#define KRB5_OTP_FORMAT_BINARY 0x00000003
+#define KRB5_OTP_FORMAT_BASE64 0x00000004
+
+typedef struct _krb5_otp_tokeninfo {
+ krb5_flags flags;
+ krb5_data vendor;
+ krb5_data challenge;
+ krb5_int32 length; /* -1 for unspecified */
+ krb5_int32 format; /* -1 for unspecified */
+ krb5_data token_id;
+ krb5_data alg_id;
+ krb5_algorithm_identifier **supported_hash_alg;
+ krb5_int32 iteration_count; /* -1 for unspecified */
+} krb5_otp_tokeninfo;
+
+typedef struct _krb5_pa_otp_challenge {
+ krb5_data nonce;
+ krb5_data service;
+ krb5_otp_tokeninfo **tokeninfo;
+ krb5_data salt;
+ krb5_data s2kparams;
+} krb5_pa_otp_challenge;
+
+typedef struct _krb5_pa_otp_req {
+ krb5_int32 flags;
+ krb5_data nonce;
+ krb5_enc_data enc_data;
+ krb5_algorithm_identifier *hash_alg;
+ krb5_int32 iteration_count; /* -1 for unspecified */
+ krb5_data otp_value;
+ krb5_data pin;
+ krb5_data challenge;
+ krb5_timestamp time;
+ krb5_data counter;
+ krb5_int32 format; /* -1 for unspecified */
+ krb5_data token_id;
+ krb5_data alg_id;
+ krb5_data vendor;
+} krb5_pa_otp_req;
+
+typedef struct _krb5_kkdcp_message {
+ krb5_data kerb_message;
+ krb5_data target_domain;
+ krb5_int32 dclocator_hint;
+} krb5_kkdcp_message;
+
+/* Plain text of an encrypted PA-FX-COOKIE value produced by the KDC. */
+typedef struct _krb5_secure_cookie {
+ time_t time;
+ krb5_pa_data **data;
+} krb5_secure_cookie;
+
+#include <stdlib.h>
+#include <string.h>
+
+#ifndef HAVE_STRDUP
+extern char *strdup (const char *);
+#endif
+
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#ifdef HAVE_SYS_TIME_H
+#include <sys/time.h>
+#ifdef TIME_WITH_SYS_TIME
+#include <time.h>
+#endif
+#else
+#include <time.h>
+#endif
+
+#ifdef HAVE_SYS_STAT_H
+#include <sys/stat.h> /* struct stat, stat() */
+#endif
+
+#ifdef HAVE_SYS_PARAM_H
+#include <sys/param.h> /* MAXPATHLEN */
+#endif
+
+#ifdef HAVE_SYS_FILE_H
+#include <sys/file.h> /* prototypes for file-related
+ syscalls; flags for open &
+ friends */
+#endif
+
+#ifdef HAVE_FCNTL_H
+#include <fcntl.h>
+#endif
+
+#include <stdio.h>
+
+#include "k5-gmt_mktime.h"
+
+/* libos.spec */
+krb5_error_code krb5_lock_file(krb5_context, int, int);
+krb5_error_code krb5_unlock_file(krb5_context, int);
+krb5_error_code krb5_sendto_kdc(krb5_context, const krb5_data *,
+ const krb5_data *, krb5_data *, int *, int);
+
+krb5_error_code krb5int_init_context_kdc(krb5_context *);
+
+struct derived_key {
+ krb5_data constant;
+ krb5_key dkey;
+ struct derived_key *next;
+};
+
+/* Internal structure of an opaque key identifier */
+struct krb5_key_st {
+ krb5_keyblock keyblock;
+ int refcount;
+ struct derived_key *derived;
+ /*
+ * Cache of data private to the cipher implementation, which we
+ * don't want to have to recompute for every operation. This may
+ * include key schedules, iteration counts, etc.
+ *
+ * The cipher implementation is responsible for setting this up
+ * whenever needed, and the enc_provider key_cleanup method must
+ * then be provided to dispose of it.
+ */
+ void *cache;
+};
+
+krb5_error_code
+krb5int_arcfour_gsscrypt(const krb5_keyblock *keyblock, krb5_keyusage usage,
+ const krb5_data *kd_data, krb5_crypto_iov *data,
+ size_t num_data);
+
+#define K5_SHA256_HASHLEN (256 / 8)
+
+/* Write the SHA-256 hash of in to out. */
+krb5_error_code
+k5_sha256(const krb5_data *in, uint8_t out[K5_SHA256_HASHLEN]);
+
+/*
+ * Attempt to zero memory in a way that compilers won't optimize out.
+ *
+ * This mechanism should work even for heap storage about to be freed,
+ * or automatic storage right before we return from a function.
+ *
+ * Then, even if we leak uninitialized memory someplace, or UNIX
+ * "core" files get created with world-read access, some of the most
+ * sensitive data in the process memory will already be safely wiped.
+ *
+ * We're not going so far -- yet -- as to try to protect key data that
+ * may have been written into swap space....
+ */
+#ifdef _WIN32
+# define zap(ptr, len) SecureZeroMemory(ptr, len)
+#elif defined(__STDC_LIB_EXT1__)
+/*
+ * Use memset_s() which cannot be optimized out. Avoid memset_s(NULL, 0, 0, 0)
+ * which would cause a runtime constraint violation.
+ */
+static inline void zap(void *ptr, size_t len)
+{
+ if (len > 0)
+ memset_s(ptr, len, 0, len);
+}
+#elif defined(__GNUC__) || defined(__clang__)
+/*
+ * Use an asm statement which declares a memory clobber to force the memset to
+ * be carried out. Avoid memset(NULL, 0, 0) which has undefined behavior.
+ */
+static inline void zap(void *ptr, size_t len)
+{
+ if (len > 0)
+ memset(ptr, 0, len);
+ __asm__ __volatile__("" : : "r" (ptr) : "memory");
+}
+#else
+/*
+ * Use a function from libkrb5support to defeat inlining unless link-time
+ * optimization is used. The function uses a volatile pointer, which prevents
+ * current compilers from optimizing out the memset.
+ */
+# define zap(ptr, len) krb5int_zap(ptr, len)
+#endif
+
+/* Convenience function: zap and free ptr if it is non-NULL. */
+static inline void
+zapfree(void *ptr, size_t len)
+{
+ if (ptr != NULL) {
+ zap(ptr, len);
+ free(ptr);
+ }
+}
+
+/* Convenience function: zap and free zero-terminated str if it is non-NULL. */
+static inline void
+zapfreestr(void *str)
+{
+ if (str != NULL) {
+ zap(str, strlen((char *)str));
+ free(str);
+ }
+}
+
+/*
+ * Combine two keys (normally used by the hardware preauth mechanism)
+ */
+krb5_error_code
+krb5int_c_combine_keys(krb5_context context, krb5_keyblock *key1,
+ krb5_keyblock *key2, krb5_keyblock *outkey);
+
+void krb5int_c_free_keyblock(krb5_context, krb5_keyblock *key);
+void krb5int_c_free_keyblock_contents(krb5_context, krb5_keyblock *);
+krb5_error_code krb5int_c_init_keyblock(krb5_context, krb5_enctype enctype,
+ size_t length, krb5_keyblock **out);
+krb5_error_code krb5int_c_copy_keyblock(krb5_context context,
+ const krb5_keyblock *from,
+ krb5_keyblock **to);
+krb5_error_code krb5int_c_copy_keyblock_contents(krb5_context context,
+ const krb5_keyblock *from,
+ krb5_keyblock *to);
+
+krb5_error_code krb5_crypto_us_timeofday(krb5_int32 *, krb5_int32 *);
+
+/*
+ * End "los-proto.h"
+ */
+
+typedef struct _krb5_os_context {
+ krb5_magic magic;
+ krb5_int32 time_offset;
+ krb5_int32 usec_offset;
+ krb5_int32 os_flags;
+ char * default_ccname;
+} *krb5_os_context;
+
+/*
+ * Flags for the os_flags field
+ *
+ * KRB5_OS_TOFFSET_VALID means that the time offset fields are valid.
+ * The intention is that this facility to correct the system clocks so
+ * that they reflect the "real" time, for systems where for some
+ * reason we can't set the system clock. Instead we calculate the
+ * offset between the system time and real time, and store the offset
+ * in the os context so that we can correct the system clock as necessary.
+ *
+ * KRB5_OS_TOFFSET_TIME means that the time offset fields should be
+ * returned as the time by the krb5 time routines. This should only
+ * be used for testing purposes (obviously!)
+ */
+#define KRB5_OS_TOFFSET_VALID 1
+#define KRB5_OS_TOFFSET_TIME 2
+
+/* lock mode flags */
+#define KRB5_LOCKMODE_SHARED 0x0001
+#define KRB5_LOCKMODE_EXCLUSIVE 0x0002
+#define KRB5_LOCKMODE_DONTBLOCK 0x0004
+#define KRB5_LOCKMODE_UNLOCK 0x0008
+
+/*
+ * Begin "preauth.h"
+ *
+ * (Originally written by Glen Machin at Sandia Labs.)
+ */
+/*
+ * Sandia National Laboratories also makes no representations about the
+ * suitability of the modifications, or additions to this software for
+ * any purpose. It is provided "as is" without express or implied warranty.
+ */
+#ifndef KRB5_PREAUTH__
+#define KRB5_PREAUTH__
+
+typedef struct _krb5_pa_enc_ts {
+ krb5_timestamp patimestamp;
+ krb5_int32 pausec;
+} krb5_pa_enc_ts;
+
+typedef struct _krb5_pa_for_user {
+ krb5_principal user;
+ krb5_checksum cksum;
+ krb5_data auth_package;
+} krb5_pa_for_user;
+
+typedef struct _krb5_s4u_userid {
+ krb5_int32 nonce;
+ krb5_principal user;
+ krb5_data subject_cert;
+ krb5_flags options;
+} krb5_s4u_userid;
+
+#define KRB5_S4U_OPTS_CHECK_LOGON_HOURS 0x40000000 /* check logon hour restrictions */
+#define KRB5_S4U_OPTS_USE_REPLY_KEY_USAGE 0x20000000 /* sign with usage 27 instead of 26 */
+
+typedef struct _krb5_pa_s4u_x509_user {
+ krb5_s4u_userid user_id;
+ krb5_checksum cksum;
+} krb5_pa_s4u_x509_user;
+
+enum {
+ KRB5_FAST_ARMOR_AP_REQUEST = 0x1
+};
+
+typedef struct _krb5_fast_armor {
+ krb5_int32 armor_type;
+ krb5_data armor_value;
+} krb5_fast_armor;
+typedef struct _krb5_fast_armored_req {
+ krb5_magic magic;
+ krb5_fast_armor *armor;
+ krb5_checksum req_checksum;
+ krb5_enc_data enc_part;
+} krb5_fast_armored_req;
+
+typedef struct _krb5_fast_req {
+ krb5_magic magic;
+ krb5_flags fast_options;
+ /* padata from req_body is used*/
+ krb5_kdc_req *req_body;
+} krb5_fast_req;
+
+/* Bits 0-15 are critical in FAST options (RFC 6113 section 7.3). */
+#define UNSUPPORTED_CRITICAL_FAST_OPTIONS 0xbfff0000
+#define KRB5_FAST_OPTION_HIDE_CLIENT_NAMES 0x40000000
+
+typedef struct _krb5_fast_finished {
+ krb5_timestamp timestamp;
+ krb5_int32 usec;
+ krb5_principal client;
+ krb5_checksum ticket_checksum;
+} krb5_fast_finished;
+
+typedef struct _krb5_fast_response {
+ krb5_magic magic;
+ krb5_pa_data **padata;
+ krb5_keyblock *strengthen_key;
+ krb5_fast_finished *finished;
+ krb5_int32 nonce;
+} krb5_fast_response;
+
+typedef struct _krb5_ad_kdcissued {
+ krb5_checksum ad_checksum;
+ krb5_principal i_principal;
+ krb5_authdata **elements;
+} krb5_ad_kdcissued;
+
+typedef struct _krb5_ad_signedpath_data {
+ krb5_principal client;
+ krb5_timestamp authtime;
+ krb5_principal *delegated;
+ krb5_pa_data **method_data;
+ krb5_authdata **authorization_data;
+} krb5_ad_signedpath_data;
+
+typedef struct _krb5_ad_signedpath {
+ krb5_enctype enctype;
+ krb5_checksum checksum;
+ krb5_principal *delegated;
+ krb5_pa_data **method_data;
+} krb5_ad_signedpath;
+
+typedef struct _krb5_iakerb_header {
+ krb5_data target_realm;
+ krb5_data *cookie;
+} krb5_iakerb_header;
+
+typedef struct _krb5_iakerb_finished {
+ krb5_checksum checksum;
+} krb5_iakerb_finished;
+
+typedef struct _krb5_verifier_mac {
+ krb5_principal princ;
+ krb5_kvno kvno;
+ krb5_enctype enctype;
+ krb5_checksum checksum;
+} krb5_verifier_mac;
+
+/*
+ * AD-CAMMAC's other-verifiers field is a sequence of Verifier, which is an
+ * extensible choice with only one selection, Verifier-MAC. For the time being
+ * we will represent this field directly as an array of krb5_verifier_mac.
+ * That will have to change if other selections are added.
+ */
+typedef struct _krb5_cammac {
+ krb5_authdata **elements;
+ krb5_verifier_mac *kdc_verifier;
+ krb5_verifier_mac *svc_verifier;
+ krb5_verifier_mac **other_verifiers;
+} krb5_cammac;
+
+krb5_pa_data *
+krb5int_find_pa_data(krb5_context, krb5_pa_data *const *, krb5_preauthtype);
+/* Does not return a copy; original padata sequence responsible for freeing*/
+
+void krb5_free_etype_info(krb5_context, krb5_etype_info);
+
+#endif /* KRB5_PREAUTH__ */
+/*
+ * End "preauth.h"
+ */
+
+krb5_error_code
+krb5int_copy_data_contents(krb5_context, const krb5_data *, krb5_data *);
+
+krb5_error_code
+krb5int_copy_data_contents_add0(krb5_context, const krb5_data *, krb5_data *);
+
+void KRB5_CALLCONV
+krb5_free_sam_challenge_2(krb5_context, krb5_sam_challenge_2 *);
+
+void KRB5_CALLCONV
+krb5_free_sam_challenge_2_body(krb5_context, krb5_sam_challenge_2_body *);
+
+void KRB5_CALLCONV
+krb5_free_sam_response_2(krb5_context, krb5_sam_response_2 *);
+
+void KRB5_CALLCONV
+krb5_free_enc_sam_response_enc_2(krb5_context, krb5_enc_sam_response_enc_2 *);
+
+void KRB5_CALLCONV
+krb5_free_sam_challenge_2_contents(krb5_context, krb5_sam_challenge_2 *);
+
+void KRB5_CALLCONV
+krb5_free_sam_challenge_2_body_contents(krb5_context,
+ krb5_sam_challenge_2_body *);
+
+void KRB5_CALLCONV
+krb5_free_sam_response_2_contents(krb5_context, krb5_sam_response_2 *);
+
+void KRB5_CALLCONV
+krb5_free_enc_sam_response_enc_2_contents(krb5_context,
+ krb5_enc_sam_response_enc_2 * );
+
+void KRB5_CALLCONV
+krb5_free_pa_enc_ts(krb5_context, krb5_pa_enc_ts *);
+
+void KRB5_CALLCONV
+krb5_free_pa_for_user(krb5_context, krb5_pa_for_user *);
+
+void KRB5_CALLCONV
+krb5_free_s4u_userid_contents(krb5_context, krb5_s4u_userid *);
+
+void KRB5_CALLCONV
+krb5_free_pa_s4u_x509_user(krb5_context, krb5_pa_s4u_x509_user *);
+
+void KRB5_CALLCONV
+krb5_free_pa_pac_req(krb5_context, krb5_pa_pac_req * );
+
+void KRB5_CALLCONV krb5_free_fast_armor(krb5_context, krb5_fast_armor *);
+void KRB5_CALLCONV krb5_free_fast_armored_req(krb5_context,
+ krb5_fast_armored_req *);
+void KRB5_CALLCONV krb5_free_fast_req(krb5_context, krb5_fast_req *);
+void KRB5_CALLCONV krb5_free_fast_finished(krb5_context, krb5_fast_finished *);
+void KRB5_CALLCONV krb5_free_fast_response(krb5_context, krb5_fast_response *);
+void KRB5_CALLCONV krb5_free_ad_kdcissued(krb5_context, krb5_ad_kdcissued *);
+void KRB5_CALLCONV krb5_free_ad_signedpath(krb5_context, krb5_ad_signedpath *);
+void KRB5_CALLCONV krb5_free_iakerb_header(krb5_context, krb5_iakerb_header *);
+void KRB5_CALLCONV krb5_free_iakerb_finished(krb5_context,
+ krb5_iakerb_finished *);
+void k5_free_algorithm_identifier(krb5_context context,
+ krb5_algorithm_identifier *val);
+void k5_free_otp_tokeninfo(krb5_context context, krb5_otp_tokeninfo *val);
+void k5_free_pa_otp_challenge(krb5_context context,
+ krb5_pa_otp_challenge *val);
+void k5_free_pa_otp_req(krb5_context context, krb5_pa_otp_req *val);
+void k5_free_kkdcp_message(krb5_context context, krb5_kkdcp_message *val);
+void k5_free_cammac(krb5_context context, krb5_cammac *val);
+void k5_free_secure_cookie(krb5_context context, krb5_secure_cookie *val);
+
+krb5_error_code
+k5_unwrap_cammac_svc(krb5_context context, const krb5_authdata *ad,
+ const krb5_keyblock *key, krb5_authdata ***adata_out);
+krb5_error_code
+k5_authind_decode(const krb5_authdata *ad, krb5_data ***indicators);
+
+/* #include "krb5/wordsize.h" -- comes in through base-defs.h. */
+#include "com_err.h"
+#include "k5-plugin.h"
+
+#include <krb5/authdata_plugin.h>
+
+struct _krb5_authdata_context {
+ krb5_magic magic;
+ int n_modules;
+ struct _krb5_authdata_context_module {
+ krb5_authdatatype ad_type;
+ void *plugin_context;
+ authdata_client_plugin_fini_proc client_fini;
+ krb5_flags flags;
+ krb5plugin_authdata_client_ftable_v0 *ftable;
+ authdata_client_request_init_proc client_req_init;
+ authdata_client_request_fini_proc client_req_fini;
+ const char *name;
+ void *request_context;
+ void **request_context_pp;
+ } *modules;
+ struct plugin_dir_handle plugins;
+};
+
+typedef struct _krb5_authdata_context *krb5_authdata_context;
+
+void
+k5_free_data_ptr_list(krb5_data **list);
+
+void
+k5_zapfree_pa_data(krb5_pa_data **val);
+
+void KRB5_CALLCONV
+krb5int_free_data_list(krb5_context context, krb5_data *data);
+
+krb5_error_code KRB5_CALLCONV
+krb5_authdata_context_init(krb5_context kcontext,
+ krb5_authdata_context *pcontext);
+
+void KRB5_CALLCONV
+krb5_authdata_context_free(krb5_context kcontext,
+ krb5_authdata_context context);
+
+krb5_error_code KRB5_CALLCONV
+krb5_authdata_export_authdata(krb5_context kcontext,
+ krb5_authdata_context context, krb5_flags usage,
+ krb5_authdata ***pauthdata);
+
+krb5_error_code KRB5_CALLCONV
+krb5_authdata_get_attribute_types(krb5_context kcontext,
+ krb5_authdata_context context,
+ krb5_data **attrs);
+
+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);
+
+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);
+
+krb5_error_code KRB5_CALLCONV
+krb5_authdata_delete_attribute(krb5_context kcontext,
+ krb5_authdata_context context,
+ const krb5_data *attribute);
+
+krb5_error_code KRB5_CALLCONV
+krb5_authdata_import_attributes(krb5_context kcontext,
+ krb5_authdata_context context,
+ krb5_flags usage, const krb5_data *attributes);
+
+krb5_error_code KRB5_CALLCONV
+krb5_authdata_export_attributes(krb5_context kcontext,
+ krb5_authdata_context context,
+ krb5_flags usage, krb5_data **pattributes);
+
+krb5_error_code KRB5_CALLCONV
+krb5_authdata_export_internal(krb5_context kcontext,
+ krb5_authdata_context context,
+ krb5_boolean restrict_authenticated,
+ const char *module, void **ptr);
+
+krb5_error_code KRB5_CALLCONV
+krb5_authdata_context_copy(krb5_context kcontext, krb5_authdata_context src,
+ krb5_authdata_context *dst);
+
+krb5_error_code KRB5_CALLCONV
+krb5_authdata_free_internal(krb5_context kcontext,
+ krb5_authdata_context context, const char *module,
+ void *ptr);
+
+/*** Plugin framework ***/
+
+/*
+ * This framework can be used to create pluggable interfaces. Not all existing
+ * pluggable interface use this framework, but new ones should. A new
+ * pluggable interface entails:
+ *
+ * - An interface ID definition in the list of #defines below.
+ *
+ * - A name in the interface_names array in lib/krb5/krb/plugins.c.
+ *
+ * - An installed public header file in include/krb5. The public header should
+ * include <krb5/plugin.h> and should declare a vtable structure for each
+ * supported major version of the interface.
+ *
+ * - A consumer API implementation, located within the code unit which makes
+ * use of the pluggable interface. The consumer API should consist of:
+ *
+ * . An interface-specific handle type which contains a vtable structure for
+ * the module (or a union of several such structures, if there are multiple
+ * supported major versions) and, optionally, resource data bound to the
+ * handle.
+ *
+ * . An interface-specific loader function which creates a handle or list of
+ * handles. A list of handles would be created if the interface is a
+ * one-to-many interface where the consumer wants to consult all available
+ * modules; a single handle would be created for an interface where the
+ * consumer wants to consult a specific module. The loader function should
+ * use k5_plugin_load or k5_plugin_load_all to produce one or a list of
+ * vtable initializer functions, and should use those functions to fill in
+ * the vtable structure for the module (if necessary, trying each supported
+ * major version starting from the most recent). The loader function can
+ * also bind resource data into the handle based on caller arguments, if
+ * appropriate.
+ *
+ * . For each plugin method, a wrapper function which accepts a krb5_context,
+ * a plugin handle, and the method arguments. Wrapper functions should
+ * invoke the method function contained in the handle's vtable.
+ *
+ * - Possibly, built-in implementations of the interface, also located within
+ * the code unit which makes use of the interface. Built-in implementations
+ * must be registered with k5_plugin_register before the first call to
+ * k5_plugin_load or k5_plugin_load_all.
+ *
+ * A pluggable interface should have one or more currently supported major
+ * versions, starting at 1. Each major version should have a current minor
+ * version, also starting at 1. If new methods are added to a vtable, the
+ * minor version should be incremented and the vtable stucture should document
+ * where each minor vtable version ends. If method signatures for a vtable are
+ * changed, the major version should be incremented.
+ *
+ * Plugin module implementations (either built-in or dynamically loaded) should
+ * define a function named <interfacename>_<modulename>_initvt, matching the
+ * signature of krb5_plugin_initvt_fn as declared in include/krb5/plugin.h.
+ * The initvt function should check the given maj_ver argument against its own
+ * supported major versions, cast the vtable pointer to the appropriate
+ * interface-specific vtable type, and fill in the vtable methods, stopping as
+ * appropriate for the given min_ver. Memory for the vtable structure is
+ * allocated by the caller, not by the module.
+ *
+ * Dynamic plugin modules are registered with the framework through the
+ * [plugins] section of the profile, as described in the admin documentation
+ * and krb5.conf man page.
+ */
+
+struct plugin_mapping;
+
+/* Holds krb5_context information about each pluggable interface. */
+struct plugin_interface {
+ struct plugin_mapping **modules;
+ krb5_boolean configured;
+};
+
+/* A list of plugin interface IDs. Make sure to increment
+ * PLUGIN_NUM_INTERFACES when a new interface is added, and add an entry to the
+ * interface_names table in lib/krb5/krb/plugin.c. */
+#define PLUGIN_INTERFACE_PWQUAL 0
+#define PLUGIN_INTERFACE_KADM5_HOOK 1
+#define PLUGIN_INTERFACE_CLPREAUTH 2
+#define PLUGIN_INTERFACE_KDCPREAUTH 3
+#define PLUGIN_INTERFACE_CCSELECT 4
+#define PLUGIN_INTERFACE_LOCALAUTH 5
+#define PLUGIN_INTERFACE_HOSTREALM 6
+#define PLUGIN_INTERFACE_AUDIT 7
+#define PLUGIN_INTERFACE_TLS 8
+#define PLUGIN_INTERFACE_KDCAUTHDATA 9
+#define PLUGIN_NUM_INTERFACES 10
+
+/* Retrieve the plugin module of type interface_id and name modname,
+ * storing the result into module. */
+krb5_error_code
+k5_plugin_load(krb5_context context, int interface_id, const char *modname,
+ krb5_plugin_initvt_fn *module);
+
+/* Retrieve all plugin modules of type interface_id, storing the result
+ * into modules. Free the result with k5_plugin_free_handles. */
+krb5_error_code
+k5_plugin_load_all(krb5_context context, int interface_id,
+ krb5_plugin_initvt_fn **modules);
+
+/* Release a module list allocated by k5_plugin_load_all. */
+void
+k5_plugin_free_modules(krb5_context context, krb5_plugin_initvt_fn *modules);
+
+/* Register a plugin module of type interface_id and name modname. */
+krb5_error_code
+k5_plugin_register(krb5_context context, int interface_id, const char *modname,
+ krb5_plugin_initvt_fn module);
+
+/*
+ * Register a plugin module which is part of the krb5 tree but is built as a
+ * dynamic plugin. Look for the module in modsubdir relative to the
+ * context->base_plugin_dir.
+ */
+krb5_error_code
+k5_plugin_register_dyn(krb5_context context, int interface_id,
+ const char *modname, const char *modsubdir);
+
+/* Destroy the module state within context; used by krb5_free_context. */
+void
+k5_plugin_free_context(krb5_context context);
+
+struct _kdb5_dal_handle; /* private, in kdb5.h */
+typedef struct _kdb5_dal_handle kdb5_dal_handle;
+struct _kdb_log_context;
+typedef struct krb5_preauth_context_st krb5_preauth_context;
+struct ccselect_module_handle;
+struct localauth_module_handle;
+struct hostrealm_module_handle;
+struct k5_tls_vtable_st;
+struct _krb5_context {
+ krb5_magic magic;
+ krb5_enctype *in_tkt_etypes;
+ krb5_enctype *tgs_etypes;
+ struct _krb5_os_context os_context;
+ char *default_realm;
+ profile_t profile;
+ kdb5_dal_handle *dal_handle;
+ int ser_ctx_count;
+ void *ser_ctx;
+ /* allowable clock skew */
+ krb5_deltat clockskew;
+ krb5_cksumtype kdc_req_sumtype;
+ krb5_cksumtype default_ap_req_sumtype;
+ krb5_cksumtype default_safe_sumtype;
+ krb5_flags kdc_default_options;
+ krb5_flags library_options;
+ krb5_boolean profile_secure;
+ int fcc_default_format;
+ krb5_prompt_type *prompt_types;
+ /* Message size above which we'll try TCP first in send-to-kdc
+ type code. Aside from the 2**16 size limit, we put no
+ absolute limit on the UDP packet size. */
+ int udp_pref_limit;
+
+ /* Use the config-file ktypes instead of app-specified? */
+ krb5_boolean use_conf_ktypes;
+
+ /* locate_kdc module stuff */
+ struct plugin_dir_handle libkrb5_plugins;
+
+ /* preauth module stuff */
+ krb5_preauth_context *preauth_context;
+
+ /* cache module stuff */
+ struct ccselect_module_handle **ccselect_handles;
+
+ /* localauth module stuff */
+ struct localauth_module_handle **localauth_handles;
+
+ /* hostrealm module stuff */
+ struct hostrealm_module_handle **hostrealm_handles;
+
+ /* TLS module vtable (if loaded) */
+ struct k5_tls_vtable_st *tls;
+
+ /* error detail info */
+ struct errinfo err;
+ char *err_fmt;
+
+ /* For Sun iprop code; does this really have to be here? */
+ struct _kdb_log_context *kdblog_context;
+
+ krb5_boolean allow_weak_crypto;
+ krb5_boolean ignore_acceptor_hostname;
+ krb5_boolean dns_canonicalize_hostname;
+
+ krb5_trace_callback trace_callback;
+ void *trace_callback_data;
+
+ krb5_pre_send_fn kdc_send_hook;
+ void *kdc_send_hook_data;
+
+ krb5_post_recv_fn kdc_recv_hook;
+ void *kdc_recv_hook_data;
+
+ struct plugin_interface plugins[PLUGIN_NUM_INTERFACES];
+ char *plugin_base_dir;
+};
+
+/* could be used in a table to find an etype and initialize a block */
+
+
+#define KRB5_LIBOPT_SYNC_KDCTIME 0x0001
+
+/* internal message representations */
+
+typedef struct _krb5_safe {
+ krb5_magic magic;
+ krb5_data user_data; /* user data */
+ krb5_timestamp timestamp; /* client time, optional */
+ krb5_int32 usec; /* microsecond portion of time,
+ optional */
+ krb5_ui_4 seq_number; /* sequence #, optional */
+ krb5_address *s_address; /* sender address */
+ krb5_address *r_address; /* recipient address, optional */
+ krb5_checksum *checksum; /* data integrity checksum */
+} krb5_safe;
+
+typedef struct _krb5_priv {
+ krb5_magic magic;
+ krb5_enc_data enc_part; /* encrypted part */
+} krb5_priv;
+
+typedef struct _krb5_priv_enc_part {
+ krb5_magic magic;
+ krb5_data user_data; /* user data */
+ krb5_timestamp timestamp; /* client time, optional */
+ krb5_int32 usec; /* microsecond portion of time, opt. */
+ krb5_ui_4 seq_number; /* sequence #, optional */
+ krb5_address *s_address; /* sender address */
+ krb5_address *r_address; /* recipient address, optional */
+} krb5_priv_enc_part;
+
+void KRB5_CALLCONV krb5_free_safe(krb5_context, krb5_safe *);
+void KRB5_CALLCONV krb5_free_priv(krb5_context, krb5_priv *);
+void KRB5_CALLCONV krb5_free_priv_enc_part(krb5_context, krb5_priv_enc_part *);
+
+/*
+ * Begin "asn1.h"
+ */
+#ifndef KRB5_ASN1__
+#define KRB5_ASN1__
+
+/* ASN.1 encoding knowledge; KEEP IN SYNC WITH ASN.1 defs! */
+/* here we use some knowledge of ASN.1 encodings */
+/*
+ Ticket is APPLICATION 1.
+ Authenticator is APPLICATION 2.
+ AS_REQ is APPLICATION 10.
+ AS_REP is APPLICATION 11.
+ TGS_REQ is APPLICATION 12.
+ TGS_REP is APPLICATION 13.
+ AP_REQ is APPLICATION 14.
+ AP_REP is APPLICATION 15.
+ KRB_SAFE is APPLICATION 20.
+ KRB_PRIV is APPLICATION 21.
+ KRB_CRED is APPLICATION 22.
+ EncASRepPart is APPLICATION 25.
+ EncTGSRepPart is APPLICATION 26.
+ EncAPRepPart is APPLICATION 27.
+ EncKrbPrivPart is APPLICATION 28.
+ EncKrbCredPart is APPLICATION 29.
+ KRB_ERROR is APPLICATION 30.
+*/
+/* allow either constructed or primitive encoding, so check for bit 6
+ set or reset */
+#define krb5int_is_app_tag(dat,tag) \
+ ((dat != NULL) && (dat)->length && \
+ ((((dat)->data[0] & ~0x20) == ((tag) | 0x40))))
+#define krb5_is_krb_ticket(dat) krb5int_is_app_tag(dat, 1)
+#define krb5_is_krb_authenticator(dat) krb5int_is_app_tag(dat, 2)
+#define krb5_is_as_req(dat) krb5int_is_app_tag(dat, 10)
+#define krb5_is_as_rep(dat) krb5int_is_app_tag(dat, 11)
+#define krb5_is_tgs_req(dat) krb5int_is_app_tag(dat, 12)
+#define krb5_is_tgs_rep(dat) krb5int_is_app_tag(dat, 13)
+#define krb5_is_ap_req(dat) krb5int_is_app_tag(dat, 14)
+#define krb5_is_ap_rep(dat) krb5int_is_app_tag(dat, 15)
+#define krb5_is_krb_safe(dat) krb5int_is_app_tag(dat, 20)
+#define krb5_is_krb_priv(dat) krb5int_is_app_tag(dat, 21)
+#define krb5_is_krb_cred(dat) krb5int_is_app_tag(dat, 22)
+#define krb5_is_krb_enc_as_rep_part(dat) krb5int_is_app_tag(dat, 25)
+#define krb5_is_krb_enc_tgs_rep_part(dat) krb5int_is_app_tag(dat, 26)
+#define krb5_is_krb_enc_ap_rep_part(dat) krb5int_is_app_tag(dat, 27)
+#define krb5_is_krb_enc_krb_priv_part(dat) krb5int_is_app_tag(dat, 28)
+#define krb5_is_krb_enc_krb_cred_part(dat) krb5int_is_app_tag(dat, 29)
+#define krb5_is_krb_error(dat) krb5int_is_app_tag(dat, 30)
+
+/*************************************************************************
+ * Prototypes for krb5_encode.c
+ *************************************************************************/
+
+/*
+ krb5_error_code encode_krb5_structure(const krb5_structure *rep,
+ krb5_data **code);
+ modifies *code
+ effects Returns the ASN.1 encoding of *rep in **code.
+ Returns ASN1_MISSING_FIELD if a required field is emtpy in *rep.
+ Returns ENOMEM if memory runs out.
+*/
+
+krb5_error_code
+encode_krb5_authenticator(const krb5_authenticator *rep, krb5_data **code);
+
+krb5_error_code
+encode_krb5_ticket(const krb5_ticket *rep, krb5_data **code);
+
+krb5_error_code
+encode_krb5_enc_tkt_part(const krb5_enc_tkt_part *rep, krb5_data **code);
+
+krb5_error_code
+encode_krb5_enc_kdc_rep_part(const krb5_enc_kdc_rep_part *rep,
+ krb5_data **code);
+
+/* yes, the translation is identical to that used for KDC__REP */
+krb5_error_code
+encode_krb5_as_rep(const krb5_kdc_rep *rep, krb5_data **code);
+
+/* yes, the translation is identical to that used for KDC__REP */
+krb5_error_code
+encode_krb5_tgs_rep(const krb5_kdc_rep *rep, krb5_data **code);
+
+krb5_error_code
+encode_krb5_ap_req(const krb5_ap_req *rep, krb5_data **code);
+
+krb5_error_code
+encode_krb5_ap_rep(const krb5_ap_rep *rep, krb5_data **code);
+
+krb5_error_code
+encode_krb5_ap_rep_enc_part(const krb5_ap_rep_enc_part *rep, krb5_data **code);
+
+krb5_error_code
+encode_krb5_as_req(const krb5_kdc_req *rep, krb5_data **code);
+
+krb5_error_code
+encode_krb5_tgs_req(const krb5_kdc_req *rep, krb5_data **code);
+
+krb5_error_code
+encode_krb5_kdc_req_body(const krb5_kdc_req *rep, krb5_data **code);
+
+krb5_error_code
+encode_krb5_safe(const krb5_safe *rep, krb5_data **code);
+
+struct krb5_safe_with_body {
+ krb5_safe *safe;
+ krb5_data *body;
+};
+krb5_error_code
+encode_krb5_safe_with_body(const struct krb5_safe_with_body *rep,
+ krb5_data **code);
+
+krb5_error_code
+encode_krb5_priv(const krb5_priv *rep, krb5_data **code);
+
+krb5_error_code
+encode_krb5_enc_priv_part(const krb5_priv_enc_part *rep, krb5_data **code);
+
+krb5_error_code
+encode_krb5_cred(const krb5_cred *rep, krb5_data **code);
+krb5_error_code
+encode_krb5_checksum(const krb5_checksum *, krb5_data **);
+
+krb5_error_code
+encode_krb5_enc_cred_part(const krb5_cred_enc_part *rep, krb5_data **code);
+
+krb5_error_code
+encode_krb5_error(const krb5_error *rep, krb5_data **code);
+
+krb5_error_code
+encode_krb5_authdata(krb5_authdata *const *rep, krb5_data **code);
+
+krb5_error_code
+encode_krb5_padata_sequence(krb5_pa_data *const *rep, krb5_data **code);
+
+krb5_error_code
+encode_krb5_typed_data(krb5_pa_data *const *rep, krb5_data **code);
+
+krb5_error_code
+encode_krb5_etype_info(krb5_etype_info_entry *const *, krb5_data **code);
+
+krb5_error_code
+encode_krb5_etype_info2(krb5_etype_info_entry *const *, krb5_data **code);
+
+krb5_error_code
+encode_krb5_pa_enc_ts(const krb5_pa_enc_ts *, krb5_data **);
+
+krb5_error_code
+encode_krb5_sam_challenge_2(const krb5_sam_challenge_2 * , krb5_data **);
+
+krb5_error_code
+encode_krb5_sam_challenge_2_body(const krb5_sam_challenge_2_body *,
+ krb5_data **);
+
+krb5_error_code
+encode_krb5_enc_sam_response_enc_2(const krb5_enc_sam_response_enc_2 *,
+ krb5_data **);
+
+krb5_error_code
+encode_krb5_sam_response_2(const krb5_sam_response_2 * , krb5_data **);
+
+struct krb5_setpw_req {
+ krb5_principal target;
+ krb5_data password;
+};
+krb5_error_code
+encode_krb5_setpw_req(const struct krb5_setpw_req *rep, krb5_data **code);
+
+krb5_error_code
+encode_krb5_pa_for_user(const krb5_pa_for_user *, krb5_data **);
+
+krb5_error_code
+encode_krb5_s4u_userid(const krb5_s4u_userid *, krb5_data **);
+
+krb5_error_code
+encode_krb5_pa_s4u_x509_user(const krb5_pa_s4u_x509_user *, krb5_data **);
+
+krb5_error_code
+encode_krb5_pa_pac_req(const krb5_pa_pac_req *, krb5_data **);
+
+krb5_error_code
+encode_krb5_etype_list(const krb5_etype_list * , krb5_data **);
+
+krb5_error_code
+encode_krb5_pa_fx_fast_request(const krb5_fast_armored_req *, krb5_data **);
+
+krb5_error_code
+encode_krb5_fast_req(const krb5_fast_req *, krb5_data **);
+
+krb5_error_code
+encode_krb5_pa_fx_fast_reply(const krb5_enc_data *, krb5_data **);
+
+krb5_error_code
+encode_krb5_iakerb_header(const krb5_iakerb_header *, krb5_data **);
+
+krb5_error_code
+encode_krb5_iakerb_finished(const krb5_iakerb_finished *, krb5_data **);
+
+krb5_error_code
+encode_krb5_fast_response(const krb5_fast_response *, krb5_data **);
+
+krb5_error_code
+encode_krb5_ad_kdcissued(const krb5_ad_kdcissued *, krb5_data **);
+
+krb5_error_code
+encode_krb5_ad_signedpath(const krb5_ad_signedpath *, krb5_data **);
+
+krb5_error_code
+encode_krb5_ad_signedpath_data(const krb5_ad_signedpath_data *, krb5_data **);
+
+krb5_error_code
+encode_krb5_otp_tokeninfo(const krb5_otp_tokeninfo *, krb5_data **);
+
+krb5_error_code
+encode_krb5_pa_otp_challenge(const krb5_pa_otp_challenge *, krb5_data **);
+
+krb5_error_code
+encode_krb5_pa_otp_req(const krb5_pa_otp_req *, krb5_data **);
+
+krb5_error_code
+encode_krb5_pa_otp_enc_req(const krb5_data *, krb5_data **);
+
+krb5_error_code
+encode_krb5_kkdcp_message(const krb5_kkdcp_message *, krb5_data **);
+
+krb5_error_code
+encode_krb5_cammac(const krb5_cammac *, krb5_data **);
+
+krb5_error_code
+encode_utf8_strings(krb5_data *const *ut8fstrings, krb5_data **);
+
+krb5_error_code
+encode_krb5_secure_cookie(const krb5_secure_cookie *, krb5_data **);
+
+/*************************************************************************
+ * End of prototypes for krb5_encode.c
+ *************************************************************************/
+
+krb5_error_code
+decode_krb5_sam_challenge_2(const krb5_data *, krb5_sam_challenge_2 **);
+
+krb5_error_code
+decode_krb5_sam_challenge_2_body(const krb5_data *,
+ krb5_sam_challenge_2_body **);
+
+krb5_error_code
+decode_krb5_enc_sam_response_enc_2(const krb5_data *,
+ krb5_enc_sam_response_enc_2 **);
+
+krb5_error_code
+decode_krb5_sam_response_2(const krb5_data *, krb5_sam_response_2 **);
+
+
+/*************************************************************************
+ * Prototypes for krb5_decode.c
+ *************************************************************************/
+/*
+ krb5_error_code decode_krb5_structure(const krb5_data *code,
+ krb5_structure **rep);
+
+ requires Expects **rep to not have been allocated;
+ a new *rep is allocated regardless of the old value.
+ effects Decodes *code into **rep.
+ Returns ENOMEM if memory is exhausted.
+ Returns asn1 and krb5 errors.
+*/
+
+krb5_error_code
+decode_krb5_authenticator(const krb5_data *code, krb5_authenticator **rep);
+
+krb5_error_code
+decode_krb5_ticket(const krb5_data *code, krb5_ticket **rep);
+
+krb5_error_code
+decode_krb5_encryption_key(const krb5_data *output, krb5_keyblock **rep);
+
+krb5_error_code
+decode_krb5_enc_tkt_part(const krb5_data *output, krb5_enc_tkt_part **rep);
+
+krb5_error_code
+decode_krb5_enc_kdc_rep_part(const krb5_data *output,
+ krb5_enc_kdc_rep_part **rep);
+
+krb5_error_code
+decode_krb5_as_rep(const krb5_data *output, krb5_kdc_rep **rep);
+
+krb5_error_code
+decode_krb5_tgs_rep(const krb5_data *output, krb5_kdc_rep **rep);
+
+krb5_error_code
+decode_krb5_ap_req(const krb5_data *output, krb5_ap_req **rep);
+
+krb5_error_code
+decode_krb5_ap_rep(const krb5_data *output, krb5_ap_rep **rep);
+
+krb5_error_code
+decode_krb5_ap_rep_enc_part(const krb5_data *output,
+ krb5_ap_rep_enc_part **rep);
+
+krb5_error_code
+decode_krb5_as_req(const krb5_data *output, krb5_kdc_req **rep);
+
+krb5_error_code
+decode_krb5_tgs_req(const krb5_data *output, krb5_kdc_req **rep);
+
+krb5_error_code
+decode_krb5_kdc_req_body(const krb5_data *output, krb5_kdc_req **rep);
+
+krb5_error_code
+decode_krb5_safe(const krb5_data *output, krb5_safe **rep);
+
+krb5_error_code
+decode_krb5_safe_with_body(const krb5_data *output, krb5_safe **rep,
+ krb5_data **body);
+
+krb5_error_code
+decode_krb5_priv(const krb5_data *output, krb5_priv **rep);
+
+krb5_error_code
+decode_krb5_enc_priv_part(const krb5_data *output, krb5_priv_enc_part **rep);
+krb5_error_code
+decode_krb5_checksum(const krb5_data *, krb5_checksum **);
+
+krb5_error_code
+decode_krb5_cred(const krb5_data *output, krb5_cred **rep);
+
+krb5_error_code
+decode_krb5_enc_cred_part(const krb5_data *output, krb5_cred_enc_part **rep);
+
+krb5_error_code
+decode_krb5_error(const krb5_data *output, krb5_error **rep);
+
+krb5_error_code
+decode_krb5_authdata(const krb5_data *output, krb5_authdata ***rep);
+
+krb5_error_code
+decode_krb5_padata_sequence(const krb5_data *output, krb5_pa_data ***rep);
+
+krb5_error_code
+decode_krb5_typed_data(const krb5_data *, krb5_pa_data ***);
+
+krb5_error_code
+decode_krb5_etype_info(const krb5_data *output, krb5_etype_info_entry ***rep);
+
+krb5_error_code
+decode_krb5_etype_info2(const krb5_data *output, krb5_etype_info_entry ***rep);
+
+krb5_error_code
+decode_krb5_enc_data(const krb5_data *output, krb5_enc_data **rep);
+
+krb5_error_code
+decode_krb5_pa_enc_ts(const krb5_data *output, krb5_pa_enc_ts **rep);
+
+krb5_error_code
+decode_krb5_setpw_req(const krb5_data *, krb5_data **, krb5_principal *);
+
+krb5_error_code
+decode_krb5_pa_for_user(const krb5_data *, krb5_pa_for_user **);
+
+krb5_error_code
+decode_krb5_pa_s4u_x509_user(const krb5_data *, krb5_pa_s4u_x509_user **);
+
+krb5_error_code
+decode_krb5_pa_pac_req(const krb5_data *, krb5_pa_pac_req **);
+
+krb5_error_code
+decode_krb5_etype_list(const krb5_data *, krb5_etype_list **);
+
+krb5_error_code
+decode_krb5_pa_fx_fast_request(const krb5_data *, krb5_fast_armored_req **);
+
+krb5_error_code
+decode_krb5_fast_req(const krb5_data *, krb5_fast_req **);
+
+krb5_error_code
+decode_krb5_pa_fx_fast_reply(const krb5_data *, krb5_enc_data **);
+
+krb5_error_code
+decode_krb5_fast_response(const krb5_data *, krb5_fast_response **);
+
+krb5_error_code
+decode_krb5_ad_kdcissued(const krb5_data *, krb5_ad_kdcissued **);
+
+krb5_error_code
+decode_krb5_ad_signedpath(const krb5_data *, krb5_ad_signedpath **);
+
+krb5_error_code
+decode_krb5_iakerb_header(const krb5_data *, krb5_iakerb_header **);
+
+krb5_error_code
+decode_krb5_iakerb_finished(const krb5_data *, krb5_iakerb_finished **);
+
+krb5_error_code
+decode_krb5_otp_tokeninfo(const krb5_data *, krb5_otp_tokeninfo **);
+
+krb5_error_code
+decode_krb5_pa_otp_challenge(const krb5_data *, krb5_pa_otp_challenge **);
+
+krb5_error_code
+decode_krb5_pa_otp_req(const krb5_data *, krb5_pa_otp_req **);
+
+krb5_error_code
+decode_krb5_pa_otp_enc_req(const krb5_data *, krb5_data **);
+
+krb5_error_code
+decode_krb5_kkdcp_message(const krb5_data *, krb5_kkdcp_message **);
+
+krb5_error_code
+decode_krb5_cammac(const krb5_data *, krb5_cammac **);
+
+krb5_error_code
+decode_utf8_strings(const krb5_data *, krb5_data ***);
+
+krb5_error_code
+decode_krb5_secure_cookie(const krb5_data *, krb5_secure_cookie **);
+
+struct _krb5_key_data; /* kdb.h */
+
+struct ldap_seqof_key_data {
+ krb5_int32 mkvno; /* Master key version number */
+ krb5_ui_2 kvno; /* kvno of key_data elements (all the same) */
+ struct _krb5_key_data *key_data;
+ krb5_int16 n_key_data;
+};
+typedef struct ldap_seqof_key_data ldap_seqof_key_data;
+
+krb5_error_code
+krb5int_ldap_encode_sequence_of_keys(const ldap_seqof_key_data *val,
+ krb5_data **code);
+
+krb5_error_code
+krb5int_ldap_decode_sequence_of_keys(const krb5_data *in,
+ ldap_seqof_key_data **rep);
+
+/*************************************************************************
+ * End of prototypes for krb5_decode.c
+ *************************************************************************/
+
+#endif /* KRB5_ASN1__ */
+/*
+ * End "asn1.h"
+ */
+
+
+/*
+ * Internal krb5 library routines
+ */
+krb5_error_code
+krb5_encrypt_tkt_part(krb5_context, const krb5_keyblock *, krb5_ticket *);
+
+krb5_error_code
+krb5_encode_kdc_rep(krb5_context, krb5_msgtype, const krb5_enc_kdc_rep_part *,
+ int using_subkey, const krb5_keyblock *, krb5_kdc_rep *,
+ krb5_data ** );
+
+/* Return true if s is non-empty and composed solely of digits. */
+krb5_boolean
+k5_is_string_numeric(const char *s);
+
+krb5_error_code
+k5_parse_host_string(const char *address, int default_port, char **host_out,
+ int *port_out);
+
+/*
+ * [De]Serialization Handle and operations.
+ */
+struct __krb5_serializer {
+ krb5_magic odtype;
+ krb5_error_code (*sizer) (krb5_context,
+ krb5_pointer,
+ size_t *);
+ krb5_error_code (*externalizer) (krb5_context,
+ krb5_pointer,
+ krb5_octet **,
+ size_t *);
+ krb5_error_code (*internalizer) (krb5_context,
+ krb5_pointer *,
+ krb5_octet **,
+ size_t *);
+};
+typedef const struct __krb5_serializer * krb5_ser_handle;
+typedef struct __krb5_serializer krb5_ser_entry;
+
+krb5_ser_handle krb5_find_serializer(krb5_context, krb5_magic);
+krb5_error_code krb5_register_serializer(krb5_context, const krb5_ser_entry *);
+
+/* Determine the external size of a particular opaque structure */
+krb5_error_code KRB5_CALLCONV
+krb5_size_opaque(krb5_context, krb5_magic, krb5_pointer, size_t *);
+
+/* Serialize the structure into a buffer */
+krb5_error_code KRB5_CALLCONV
+krb5_externalize_opaque(krb5_context, krb5_magic, krb5_pointer, krb5_octet **,
+ size_t *);
+
+/* Deserialize the structure from a buffer */
+krb5_error_code KRB5_CALLCONV
+krb5_internalize_opaque(krb5_context, krb5_magic, krb5_pointer *,
+ krb5_octet **, size_t *);
+
+/* Serialize data into a buffer */
+krb5_error_code
+krb5_externalize_data(krb5_context, krb5_pointer, krb5_octet **, size_t *);
+/*
+ * Initialization routines.
+ */
+
+/* Initialize serialization for krb5_[os_]context */
+krb5_error_code KRB5_CALLCONV krb5_ser_context_init(krb5_context);
+
+/* Initialize serialization for krb5_auth_context */
+krb5_error_code KRB5_CALLCONV krb5_ser_auth_context_init(krb5_context);
+
+/* Initialize serialization for krb5_keytab */
+krb5_error_code KRB5_CALLCONV krb5_ser_keytab_init(krb5_context);
+
+/* Initialize serialization for krb5_ccache */
+krb5_error_code KRB5_CALLCONV krb5_ser_ccache_init(krb5_context);
+
+/* Initialize serialization for krb5_rcache */
+krb5_error_code KRB5_CALLCONV krb5_ser_rcache_init(krb5_context);
+
+/* [De]serialize 4-byte integer */
+krb5_error_code KRB5_CALLCONV
+krb5_ser_pack_int32(krb5_int32, krb5_octet **, size_t *);
+
+krb5_error_code KRB5_CALLCONV
+krb5_ser_unpack_int32(krb5_int32 *, krb5_octet **, size_t *);
+
+/* [De]serialize 8-byte integer */
+krb5_error_code KRB5_CALLCONV
+krb5_ser_pack_int64(int64_t, krb5_octet **, size_t *);
+
+krb5_error_code KRB5_CALLCONV
+krb5_ser_unpack_int64(int64_t *, krb5_octet **, size_t *);
+
+/* [De]serialize byte string */
+krb5_error_code KRB5_CALLCONV
+krb5_ser_pack_bytes(krb5_octet *, size_t, krb5_octet **, size_t *);
+
+krb5_error_code KRB5_CALLCONV
+krb5_ser_unpack_bytes(krb5_octet *, size_t, krb5_octet **, size_t *);
+
+krb5_error_code KRB5_CALLCONV
+krb5int_cc_default(krb5_context, krb5_ccache *);
+
+/* Fill in the buffer with random alpha-numeric data. */
+krb5_error_code
+krb5int_random_string(krb5_context, char *string, unsigned int length);
+
+/* value to use when requesting a keytab entry and KVNO doesn't matter */
+#define IGNORE_VNO 0
+/* value to use when requesting a keytab entry and enctype doesn't matter */
+#define IGNORE_ENCTYPE 0
+
+/* To keep happy libraries which are (for now) accessing internal stuff */
+
+/* Make sure to increment by one when changing the struct */
+#define KRB5INT_ACCESS_STRUCT_VERSION 21
+
+typedef struct _krb5int_access {
+ krb5_error_code (*auth_con_get_subkey_enctype)(krb5_context,
+ krb5_auth_context,
+ krb5_enctype *);
+
+ krb5_error_code (*clean_hostname)(krb5_context, const char *, char *,
+ size_t);
+
+ krb5_error_code (*mandatory_cksumtype)(krb5_context, krb5_enctype,
+ krb5_cksumtype *);
+ krb5_error_code (KRB5_CALLCONV *ser_pack_int64)(int64_t, krb5_octet **,
+ size_t *);
+ krb5_error_code (KRB5_CALLCONV *ser_unpack_int64)(int64_t *, krb5_octet **,
+ size_t *);
+
+ /* Used for KDB LDAP back end. */
+ krb5_error_code
+ (*asn1_ldap_encode_sequence_of_keys)(const ldap_seqof_key_data *val,
+ krb5_data **code);
+
+ krb5_error_code
+ (*asn1_ldap_decode_sequence_of_keys)(const krb5_data *in,
+ ldap_seqof_key_data **);
+
+ /*
+ * pkinit asn.1 encode/decode functions
+ */
+ krb5_error_code
+ (*encode_krb5_auth_pack)(const krb5_auth_pack *rep, krb5_data **code);
+
+ krb5_error_code
+ (*encode_krb5_auth_pack_draft9)(const krb5_auth_pack_draft9 *rep,
+ krb5_data **code);
+
+ krb5_error_code
+ (*encode_krb5_kdc_dh_key_info)(const krb5_kdc_dh_key_info *rep,
+ krb5_data **code);
+
+ krb5_error_code
+ (*encode_krb5_pa_pk_as_rep)(const krb5_pa_pk_as_rep *rep,
+ krb5_data **code);
+
+ krb5_error_code
+ (*encode_krb5_pa_pk_as_rep_draft9)(const krb5_pa_pk_as_rep_draft9 *rep,
+ krb5_data **code);
+
+ krb5_error_code
+ (*encode_krb5_pa_pk_as_req)(const krb5_pa_pk_as_req *rep,
+ krb5_data **code);
+
+ krb5_error_code
+ (*encode_krb5_pa_pk_as_req_draft9)(const krb5_pa_pk_as_req_draft9 *rep,
+ krb5_data **code);
+
+ krb5_error_code
+ (*encode_krb5_reply_key_pack)(const krb5_reply_key_pack *,
+ krb5_data **code);
+
+ krb5_error_code
+ (*encode_krb5_reply_key_pack_draft9)(const krb5_reply_key_pack_draft9 *,
+ krb5_data **code);
+
+ krb5_error_code
+ (*encode_krb5_td_dh_parameters)(krb5_algorithm_identifier *const *,
+ krb5_data **code);
+
+ krb5_error_code
+ (*encode_krb5_td_trusted_certifiers)(krb5_external_principal_identifier *
+ const *, krb5_data **code);
+
+ krb5_error_code
+ (*decode_krb5_auth_pack)(const krb5_data *, krb5_auth_pack **);
+
+ krb5_error_code
+ (*decode_krb5_auth_pack_draft9)(const krb5_data *,
+ krb5_auth_pack_draft9 **);
+
+ krb5_error_code
+ (*decode_krb5_pa_pk_as_req)(const krb5_data *, krb5_pa_pk_as_req **);
+
+ krb5_error_code
+ (*decode_krb5_pa_pk_as_req_draft9)(const krb5_data *,
+ krb5_pa_pk_as_req_draft9 **);
+
+ krb5_error_code
+ (*decode_krb5_pa_pk_as_rep)(const krb5_data *, krb5_pa_pk_as_rep **);
+
+ krb5_error_code
+ (*decode_krb5_kdc_dh_key_info)(const krb5_data *, krb5_kdc_dh_key_info **);
+
+ krb5_error_code
+ (*decode_krb5_principal_name)(const krb5_data *, krb5_principal_data **);
+
+ krb5_error_code
+ (*decode_krb5_reply_key_pack)(const krb5_data *, krb5_reply_key_pack **);
+
+ krb5_error_code
+ (*decode_krb5_reply_key_pack_draft9)(const krb5_data *,
+ krb5_reply_key_pack_draft9 **);
+
+ krb5_error_code
+ (*decode_krb5_td_dh_parameters)(const krb5_data *,
+ krb5_algorithm_identifier ***);
+
+ krb5_error_code
+ (*decode_krb5_td_trusted_certifiers)(const krb5_data *,
+ krb5_external_principal_identifier
+ ***);
+
+ krb5_error_code
+ (*encode_krb5_kdc_req_body)(const krb5_kdc_req *rep, krb5_data **code);
+
+ void
+ (KRB5_CALLCONV *free_kdc_req)(krb5_context, krb5_kdc_req * );
+ void
+ (*set_prompt_types)(krb5_context, krb5_prompt_type *);
+} krb5int_access;
+
+#define KRB5INT_ACCESS_VERSION \
+ (((krb5_int32)((sizeof(krb5int_access) & 0xFFFF) | \
+ (KRB5INT_ACCESS_STRUCT_VERSION << 16))) & 0xFFFFFFFF)
+
+krb5_error_code KRB5_CALLCONV
+krb5int_accessor(krb5int_access*, krb5_int32);
+
+typedef struct _krb5_donot_replay {
+ krb5_magic magic;
+ krb5_ui_4 hash;
+ char *server; /* null-terminated */
+ char *client; /* null-terminated */
+ char *msghash; /* null-terminated */
+ krb5_int32 cusec;
+ krb5_timestamp ctime;
+} krb5_donot_replay;
+
+krb5_error_code KRB5_CALLCONV
+krb5int_cc_user_set_default_name(krb5_context context, const char *name);
+
+krb5_error_code krb5_rc_default(krb5_context, krb5_rcache *);
+krb5_error_code krb5_rc_resolve_type(krb5_context, krb5_rcache *,
+ const char *);
+krb5_error_code krb5_rc_resolve_full(krb5_context, krb5_rcache *,
+ const char *);
+char *krb5_rc_get_type(krb5_context, krb5_rcache);
+char *krb5_rc_default_type(krb5_context);
+char *krb5_rc_default_name(krb5_context);
+krb5_error_code krb5_auth_to_rep(krb5_context, krb5_tkt_authent *,
+ krb5_donot_replay *);
+krb5_error_code krb5_rc_hash_message(krb5_context context,
+ const krb5_data *message, char **out);
+
+krb5_error_code KRB5_CALLCONV
+krb5_rc_initialize(krb5_context, krb5_rcache, krb5_deltat);
+
+krb5_error_code KRB5_CALLCONV
+krb5_rc_recover_or_initialize(krb5_context, krb5_rcache,krb5_deltat);
+
+krb5_error_code KRB5_CALLCONV
+krb5_rc_recover(krb5_context, krb5_rcache);
+
+krb5_error_code KRB5_CALLCONV
+krb5_rc_destroy(krb5_context, krb5_rcache);
+
+krb5_error_code KRB5_CALLCONV
+krb5_rc_close(krb5_context, krb5_rcache);
+
+krb5_error_code KRB5_CALLCONV
+krb5_rc_store(krb5_context, krb5_rcache, krb5_donot_replay *);
+
+krb5_error_code KRB5_CALLCONV
+krb5_rc_expunge(krb5_context, krb5_rcache);
+
+krb5_error_code KRB5_CALLCONV
+krb5_rc_get_lifespan(krb5_context, krb5_rcache,krb5_deltat *);
+
+char *KRB5_CALLCONV
+krb5_rc_get_name(krb5_context, krb5_rcache);
+
+krb5_error_code KRB5_CALLCONV
+krb5_rc_resolve(krb5_context, krb5_rcache, char *);
+
+/*
+ * This structure was exposed and used in macros in krb5 1.2, so do not
+ * change its ABI.
+ */
+typedef struct _krb5_kt_ops {
+ krb5_magic magic;
+ char *prefix;
+
+ /* routines always present */
+ krb5_error_code (KRB5_CALLCONV *resolve)(krb5_context, const char *,
+ krb5_keytab *);
+ krb5_error_code (KRB5_CALLCONV *get_name)(krb5_context, krb5_keytab,
+ char *, unsigned int);
+ krb5_error_code (KRB5_CALLCONV *close)(krb5_context, krb5_keytab);
+ krb5_error_code (KRB5_CALLCONV *get)(krb5_context, krb5_keytab,
+ krb5_const_principal, krb5_kvno,
+ krb5_enctype, krb5_keytab_entry *);
+ krb5_error_code (KRB5_CALLCONV *start_seq_get)(krb5_context, krb5_keytab,
+ krb5_kt_cursor *);
+ krb5_error_code (KRB5_CALLCONV *get_next)(krb5_context, krb5_keytab,
+ krb5_keytab_entry *,
+ krb5_kt_cursor *);
+ krb5_error_code (KRB5_CALLCONV *end_get)(krb5_context, krb5_keytab,
+ krb5_kt_cursor *);
+ /* routines to be included on extended version (write routines) */
+ krb5_error_code (KRB5_CALLCONV *add)(krb5_context, krb5_keytab,
+ krb5_keytab_entry *);
+ krb5_error_code (KRB5_CALLCONV *remove)(krb5_context, krb5_keytab,
+ krb5_keytab_entry *);
+
+ /* Handle for serializer */
+ const krb5_ser_entry *serializer;
+} krb5_kt_ops;
+
+/* Not sure it's ready for exposure just yet. */
+extern krb5_error_code
+krb5int_c_mandatory_cksumtype(krb5_context, krb5_enctype, krb5_cksumtype *);
+
+/*
+ * Referral definitions and subfunctions.
+ */
+#define KRB5_REFERRAL_MAXHOPS 10
+
+struct _krb5_kt { /* should move into k5-int.h */
+ krb5_magic magic;
+ const struct _krb5_kt_ops *ops;
+ krb5_pointer data;
+};
+
+krb5_error_code krb5_set_default_in_tkt_ktypes(krb5_context,
+ const krb5_enctype *);
+
+krb5_error_code krb5_get_default_in_tkt_ktypes(krb5_context, krb5_enctype **);
+
+krb5_error_code krb5_set_default_tgs_ktypes(krb5_context,
+ const krb5_enctype *);
+
+krb5_error_code KRB5_CALLCONV
+krb5_get_tgs_ktypes(krb5_context, krb5_const_principal, krb5_enctype **);
+
+krb5_boolean krb5_is_permitted_enctype(krb5_context, krb5_enctype);
+
+krb5_boolean KRB5_CALLCONV krb5int_c_weak_enctype(krb5_enctype);
+
+krb5_error_code krb5_kdc_rep_decrypt_proc(krb5_context, const krb5_keyblock *,
+ krb5_const_pointer, krb5_kdc_rep *);
+krb5_error_code KRB5_CALLCONV krb5_decrypt_tkt_part(krb5_context,
+ const krb5_keyblock *,
+ krb5_ticket * );
+
+krb5_error_code krb5_get_cred_via_tkt(krb5_context, krb5_creds *, krb5_flags,
+ krb5_address *const *, krb5_creds *,
+ krb5_creds **);
+
+krb5_error_code KRB5_CALLCONV krb5_copy_addr(krb5_context,
+ const krb5_address *,
+ krb5_address **);
+
+void krb5_init_ets(krb5_context);
+void krb5_free_ets(krb5_context);
+krb5_error_code krb5_generate_subkey(krb5_context, const krb5_keyblock *,
+ krb5_keyblock **);
+krb5_error_code krb5_generate_subkey_extended(krb5_context,
+ const krb5_keyblock *,
+ krb5_enctype, krb5_keyblock **);
+krb5_error_code krb5_generate_seq_number(krb5_context, const krb5_keyblock *,
+ krb5_ui_4 *);
+
+krb5_error_code KRB5_CALLCONV krb5_kt_register(krb5_context,
+ const struct _krb5_kt_ops *);
+
+krb5_error_code k5_kt_get_principal(krb5_context context, krb5_keytab keytab,
+ krb5_principal *princ_out);
+
+krb5_error_code krb5_principal2salt_norealm(krb5_context, krb5_const_principal,
+ krb5_data *);
+
+unsigned int KRB5_CALLCONV krb5_get_notification_message(void);
+
+/* chk_trans.c */
+krb5_error_code krb5_check_transited_list(krb5_context, const krb5_data *trans,
+ const krb5_data *realm1,
+ const krb5_data *realm2);
+
+/* free_rtree.c */
+void krb5_free_realm_tree(krb5_context, krb5_principal *);
+
+void KRB5_CALLCONV krb5_free_authenticator_contents(krb5_context,
+ krb5_authenticator *);
+
+void KRB5_CALLCONV krb5_free_address(krb5_context, krb5_address *);
+
+void KRB5_CALLCONV krb5_free_enc_tkt_part(krb5_context, krb5_enc_tkt_part *);
+
+void KRB5_CALLCONV krb5_free_tickets(krb5_context, krb5_ticket **);
+void KRB5_CALLCONV krb5_free_kdc_req(krb5_context, krb5_kdc_req *);
+void KRB5_CALLCONV krb5_free_kdc_rep(krb5_context, krb5_kdc_rep *);
+void KRB5_CALLCONV krb5_free_last_req(krb5_context, krb5_last_req_entry **);
+void KRB5_CALLCONV krb5_free_enc_kdc_rep_part(krb5_context,
+ krb5_enc_kdc_rep_part *);
+void KRB5_CALLCONV krb5_free_ap_req(krb5_context, krb5_ap_req *);
+void KRB5_CALLCONV krb5_free_ap_rep(krb5_context, krb5_ap_rep *);
+void KRB5_CALLCONV krb5_free_cred(krb5_context, krb5_cred *);
+void KRB5_CALLCONV krb5_free_cred_enc_part(krb5_context, krb5_cred_enc_part *);
+void KRB5_CALLCONV krb5_free_pa_data(krb5_context, krb5_pa_data **);
+void KRB5_CALLCONV krb5_free_tkt_authent(krb5_context, krb5_tkt_authent *);
+void KRB5_CALLCONV krb5_free_enc_data(krb5_context, krb5_enc_data *);
+krb5_error_code krb5_set_config_files(krb5_context, const char **);
+
+krb5_error_code KRB5_CALLCONV krb5_get_default_config_files(char ***filenames);
+
+void KRB5_CALLCONV krb5_free_config_files(char **filenames);
+
+krb5_error_code krb5_rd_req_decoded(krb5_context, krb5_auth_context *,
+ const krb5_ap_req *, krb5_const_principal,
+ krb5_keytab, krb5_flags *, krb5_ticket **);
+
+krb5_error_code krb5_rd_req_decoded_anyflag(krb5_context, krb5_auth_context *,
+ const krb5_ap_req *,
+ krb5_const_principal, krb5_keytab,
+ krb5_flags *, krb5_ticket **);
+
+krb5_error_code KRB5_CALLCONV
+krb5_cc_register(krb5_context, const krb5_cc_ops *, krb5_boolean );
+
+krb5_error_code krb5_walk_realm_tree(krb5_context, const krb5_data *,
+ const krb5_data *, krb5_principal **,
+ int);
+
+krb5_error_code
+krb5_auth_con_set_safe_cksumtype(krb5_context, krb5_auth_context,
+ krb5_cksumtype);
+
+krb5_error_code krb5_auth_con_setivector(krb5_context, krb5_auth_context,
+ krb5_pointer);
+
+krb5_error_code krb5_auth_con_getivector(krb5_context, krb5_auth_context,
+ krb5_pointer *);
+
+krb5_error_code krb5_auth_con_setpermetypes(krb5_context, krb5_auth_context,
+ const krb5_enctype *);
+
+krb5_error_code krb5_auth_con_getpermetypes(krb5_context, krb5_auth_context,
+ krb5_enctype **);
+
+krb5_error_code krb5_auth_con_get_subkey_enctype(krb5_context context,
+ krb5_auth_context,
+ krb5_enctype *);
+
+krb5_error_code
+krb5_auth_con_get_authdata_context(krb5_context context,
+ krb5_auth_context auth_context,
+ krb5_authdata_context *ad_context);
+
+krb5_error_code
+krb5_auth_con_set_authdata_context(krb5_context context,
+ krb5_auth_context auth_context,
+ krb5_authdata_context ad_context);
+
+krb5_error_code krb5_read_message(krb5_context, krb5_pointer, krb5_data *);
+krb5_error_code krb5_write_message(krb5_context, krb5_pointer, krb5_data *);
+int krb5_net_read(krb5_context, int , char *, int);
+int krb5_net_write(krb5_context, int , const char *, int);
+
+krb5_error_code KRB5_CALLCONV krb5_get_realm_domain(krb5_context,
+ const char *, char ** );
+
+krb5_error_code krb5_gen_portaddr(krb5_context, const krb5_address *,
+ krb5_const_pointer, krb5_address **);
+
+krb5_error_code krb5_gen_replay_name(krb5_context, const krb5_address *,
+ const char *, char **);
+krb5_error_code krb5_make_fulladdr(krb5_context, krb5_address *,
+ krb5_address *, krb5_address *);
+
+krb5_error_code krb5_set_debugging_time(krb5_context, krb5_timestamp,
+ krb5_int32);
+krb5_error_code krb5_use_natural_time(krb5_context);
+krb5_error_code krb5_set_time_offsets(krb5_context, krb5_timestamp,
+ krb5_int32);
+
+/* Some data comparison and conversion functions. */
+static inline int
+data_eq(krb5_data d1, krb5_data d2)
+{
+ return (d1.length == d2.length && (d1.length == 0 ||
+ !memcmp(d1.data, d2.data, d1.length)));
+}
+
+static inline int
+data_eq_string (krb5_data d, const char *s)
+{
+ return (d.length == strlen(s) && (d.length == 0 ||
+ !memcmp(d.data, s, d.length)));
+}
+
+static inline krb5_data
+make_data(void *data, unsigned int len)
+{
+ krb5_data d;
+
+ d.magic = KV5M_DATA;
+ d.data = (char *) data;
+ d.length = len;
+ return d;
+}
+
+static inline krb5_data
+empty_data()
+{
+ return make_data(NULL, 0);
+}
+
+static inline krb5_data
+string2data(char *str)
+{
+ return make_data(str, strlen(str));
+}
+
+static inline krb5_error_code
+alloc_data(krb5_data *data, unsigned int len)
+{
+ /* Allocate at least one byte since zero-byte allocs may return NULL. */
+ char *ptr = (char *) calloc((len > 0) ? len : 1, 1);
+
+ if (ptr == NULL)
+ return ENOMEM;
+ data->magic = KV5M_DATA;
+ data->data = ptr;
+ data->length = len;
+ return 0;
+}
+
+static inline int
+authdata_eq(krb5_authdata a1, krb5_authdata a2)
+{
+ return (a1.ad_type == a2.ad_type && a1.length == a2.length &&
+ (a1.length == 0 || !memcmp(a1.contents, a2.contents, a1.length)));
+}
+
+/* Allocate zeroed memory; set *code to 0 on success or ENOMEM on failure. */
+static inline void *
+k5calloc(size_t nmemb, size_t size, krb5_error_code *code)
+{
+ void *ptr;
+
+ /* Allocate at least one byte since zero-byte allocs may return NULL. */
+ ptr = calloc(nmemb ? nmemb : 1, size ? size : 1);
+ *code = (ptr == NULL) ? ENOMEM : 0;
+ return ptr;
+}
+
+/* Allocate zeroed memory; set *code to 0 on success or ENOMEM on failure. */
+static inline void *
+k5alloc(size_t size, krb5_error_code *code)
+{
+ return k5calloc(1, size, code);
+}
+
+/* Return a copy of the len bytes of memory at in; set *code to 0 or ENOMEM. */
+static inline void *
+k5memdup(const void *in, size_t len, krb5_error_code *code)
+{
+ void *ptr = k5alloc(len, code);
+
+ if (ptr != NULL && len > 0)
+ memcpy(ptr, in, len);
+ return ptr;
+}
+
+/* Like k5memdup, but add a final null byte. */
+static inline void *
+k5memdup0(const void *in, size_t len, krb5_error_code *code)
+{
+ void *ptr = k5alloc(len + 1, code);
+
+ if (ptr != NULL && len > 0)
+ memcpy(ptr, in, len);
+ return ptr;
+}
+
+krb5_error_code KRB5_CALLCONV
+krb5_get_credentials_for_user(krb5_context context, krb5_flags options,
+ krb5_ccache ccache,
+ krb5_creds *in_creds,
+ krb5_data *cert,
+ krb5_creds **out_creds);
+
+krb5_error_code KRB5_CALLCONV
+krb5_get_credentials_for_proxy(krb5_context context,
+ krb5_flags options,
+ krb5_ccache ccache,
+ krb5_creds *in_creds,
+ krb5_ticket *evidence_tkt,
+ krb5_creds **out_creds);
+
+krb5_error_code KRB5_CALLCONV
+krb5int_get_authdata_containee_types(krb5_context context,
+ const krb5_authdata *container,
+ unsigned int *nad_types,
+ krb5_authdatatype **ad_types);
+
+krb5_error_code krb5int_parse_enctype_list(krb5_context context,
+ const char *profkey, char *profstr,
+ krb5_enctype *default_list,
+ krb5_enctype **result);
+
+krb5_boolean k5_etypes_contains(const krb5_enctype *list, krb5_enctype etype);
+
+void k5_change_error_message_code(krb5_context ctx, krb5_error_code oldcode,
+ krb5_error_code newcode);
+
+/* Define shorter internal names for setting error messages. */
+#define k5_setmsg krb5_set_error_message
+#define k5_prependmsg krb5_prepend_error_message
+#define k5_wrapmsg krb5_wrap_error_message
+
+#endif /* _KRB5_INT_H */
diff --git a/src/include/k5-ipc_stream.h b/src/include/k5-ipc_stream.h
new file mode 100644
index 000000000000..11f8bc7678f1
--- /dev/null
+++ b/src/include/k5-ipc_stream.h
@@ -0,0 +1,77 @@
+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/* include/k5-ipc_stream.h */
+/*
+ * Copyright 2006 Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ * require a specific license from the United States Government.
+ * It is the responsibility of any person or organization contemplating
+ * export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission. Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose. It is provided "as is" without express
+ * or implied warranty.
+ */
+
+#ifndef K5_IPC_STREAM_H
+#define K5_IPC_STREAM_H
+
+#include "k5-platform.h"
+
+struct k5_ipc_stream_s;
+typedef struct k5_ipc_stream_s *k5_ipc_stream;
+
+
+int32_t krb5int_ipc_stream_new (k5_ipc_stream *out_stream);
+
+uint32_t krb5int_ipc_stream_release (k5_ipc_stream io_stream);
+
+uint64_t krb5int_ipc_stream_size (k5_ipc_stream in_stream);
+
+const char *krb5int_ipc_stream_data (k5_ipc_stream in_stream);
+
+uint32_t krb5int_ipc_stream_read (k5_ipc_stream in_stream,
+ void *io_data,
+ uint64_t in_size);
+uint32_t krb5int_ipc_stream_write (k5_ipc_stream in_stream,
+ const void *in_data,
+ uint64_t in_size);
+
+uint32_t krb5int_ipc_stream_read_string (k5_ipc_stream io_stream,
+ char **out_string);
+uint32_t krb5int_ipc_stream_write_string (k5_ipc_stream io_stream,
+ const char *in_string);
+void krb5int_ipc_stream_free_string (char *in_string);
+
+uint32_t krb5int_ipc_stream_read_int32 (k5_ipc_stream io_stream,
+ int32_t *out_int32);
+uint32_t krb5int_ipc_stream_write_int32 (k5_ipc_stream io_stream,
+ int32_t in_int32);
+
+uint32_t krb5int_ipc_stream_read_uint32 (k5_ipc_stream io_stream,
+ uint32_t *out_uint32);
+uint32_t krb5int_ipc_stream_write_uint32 (k5_ipc_stream io_stream,
+ uint32_t in_uint32);
+
+uint32_t krb5int_ipc_stream_read_int64 (k5_ipc_stream io_stream,
+ int64_t *out_int64);
+uint32_t krb5int_ipc_stream_write_int64 (k5_ipc_stream io_stream,
+ int64_t in_int64);
+
+uint32_t krb5int_ipc_stream_read_uint64 (k5_ipc_stream io_stream,
+ uint64_t *out_uint64);
+uint32_t krb5int_ipc_stream_write_uint64 (k5_ipc_stream io_stream,
+ uint64_t in_uint64);
+
+#endif /* K5_IPC_STREAM_H */
diff --git a/src/include/k5-json.h b/src/include/k5-json.h
new file mode 100644
index 000000000000..8b22cd39d33d
--- /dev/null
+++ b/src/include/k5-json.h
@@ -0,0 +1,218 @@
+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/* include/k5-json.h - JSON declarations */
+/*
+ * Copyright (c) 2010 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * All rights reserved.
+ *
+ * Portions Copyright (c) 2010 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+/*
+ * Copyright (C) 2012 by the Massachusetts Institute of Technology.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef K5_JSON_H
+#define K5_JSON_H
+
+#include <stddef.h>
+
+#define K5_JSON_TID_NUMBER 0
+#define K5_JSON_TID_NULL 1
+#define K5_JSON_TID_BOOL 2
+#define K5_JSON_TID_MEMORY 128
+#define K5_JSON_TID_ARRAY 129
+#define K5_JSON_TID_OBJECT 130
+#define K5_JSON_TID_STRING 131
+
+/*
+ * The k5_json_value C type can represent any kind of JSON value. It has no
+ * static type safety since it is represented using a void pointer, so be
+ * careful with it. Its type can be checked dynamically with k5_json_get_tid()
+ * and the above constants.
+ */
+typedef void *k5_json_value;
+typedef unsigned int k5_json_tid;
+
+k5_json_tid k5_json_get_tid(k5_json_value val);
+
+/*
+ * k5_json_value objects are reference-counted. These functions increment and
+ * decrement the refcount, possibly freeing the value. k5_json_retain returns
+ * its argument and always succeeds. Both functions gracefully accept NULL.
+ */
+k5_json_value k5_json_retain(k5_json_value val);
+void k5_json_release(k5_json_value val);
+
+/*
+ * If a k5_json_* function can fail, it returns 0 on success and an errno value
+ * on failure.
+ */
+
+/*
+ * Null
+ */
+
+typedef struct k5_json_null_st *k5_json_null;
+
+int k5_json_null_create(k5_json_null *null_out);
+
+/* Create a null value as a k5_json_value, for polymorphic convenience. */
+int k5_json_null_create_val(k5_json_value *val_out);
+
+/*
+ * Boolean
+ */
+
+typedef struct k5_json_bool_st *k5_json_bool;
+
+int k5_json_bool_create(int truth, k5_json_bool *val_out);
+int k5_json_bool_value(k5_json_bool bval);
+
+/*
+ * Array
+ */
+
+typedef struct k5_json_array_st *k5_json_array;
+
+int k5_json_array_create(k5_json_array *val_out);
+size_t k5_json_array_length(k5_json_array array);
+
+/* Both of these functions increment the reference count on val. */
+int k5_json_array_add(k5_json_array array, k5_json_value val);
+void k5_json_array_set(k5_json_array array, size_t idx, k5_json_value val);
+
+/* Get an alias to the idx-th element of array, without incrementing the
+ * reference count. The caller must check idx against the array length. */
+k5_json_value k5_json_array_get(k5_json_array array, size_t idx);
+
+/*
+ * Create an array from a template and a variable argument list. template
+ * characters are:
+ * v: a k5_json_value argument is read, retained, and stored
+ * n: no argument is read; a null value is stored
+ * b: an int argument is read and stored as a boolean value
+ * i: an int argument is read and stored as a number value
+ * L: a long long argument is read and stored as a number value
+ * s: a const char * argument is read and stored as a null or string value
+ * B: const void * and size_t arguments are read and stored as a base64
+ * string value
+ */
+int
+k5_json_array_fmt(k5_json_array *array_out, const char *template, ...);
+
+/*
+ * Object
+ */
+
+typedef struct k5_json_object_st *k5_json_object;
+typedef void (*k5_json_object_iterator_fn)(void *arg, const char *key,
+ k5_json_value val);
+
+int k5_json_object_create(k5_json_object *val_out);
+void k5_json_object_iterate(k5_json_object obj,
+ k5_json_object_iterator_fn func, void *arg);
+
+/* Return the number of mappings in an object. */
+size_t k5_json_object_count(k5_json_object obj);
+
+/*
+ * Store val into object at key, incrementing val's reference count and
+ * releasing any previous value at key. If val is NULL, key is removed from
+ * obj if it exists, and obj remains unchanged if it does not.
+ */
+int k5_json_object_set(k5_json_object obj, const char *key, k5_json_value val);
+
+/* Get an alias to the object's value for key, without incrementing the
+ * reference count. Returns NULL if there is no value for key. */
+k5_json_value k5_json_object_get(k5_json_object obj, const char *key);
+
+/*
+ * String
+ */
+
+typedef struct k5_json_string_st *k5_json_string;
+
+int k5_json_string_create(const char *cstring, k5_json_string *val_out);
+int k5_json_string_create_len(const void *data, size_t len,
+ k5_json_string *val_out);
+const char *k5_json_string_utf8(k5_json_string string);
+
+
+/* Create a base64 string value from binary data. */
+int k5_json_string_create_base64(const void *data, size_t len,
+ k5_json_string *val_out);
+
+/* Decode the base64 contents of string. */
+int k5_json_string_unbase64(k5_json_string string, unsigned char **data_out,
+ size_t *len_out);
+
+/*
+ * Number
+ */
+
+typedef struct k5_json_number_st *k5_json_number;
+
+int k5_json_number_create(long long number, k5_json_number *val_out);
+long long k5_json_number_value(k5_json_number number);
+
+/*
+ * JSON encoding and decoding
+ */
+
+int k5_json_encode(k5_json_value val, char **json_out);
+int k5_json_decode(const char *str, k5_json_value *val_out);
+
+#endif /* K5_JSON_H */
diff --git a/src/include/k5-platform.h b/src/include/k5-platform.h
new file mode 100644
index 000000000000..994f46323cb0
--- /dev/null
+++ b/src/include/k5-platform.h
@@ -0,0 +1,1102 @@
+/* -*- mode: c; indent-tabs-mode: nil -*- */
+/* include/k5-platform.h */
+/*
+ * Copyright 2003, 2004, 2005, 2007, 2008, 2009 Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ * require a specific license from the United States Government.
+ * It is the responsibility of any person or organization contemplating
+ * export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission. Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose. It is provided "as is" without express
+ * or implied warranty.
+ */
+
+/*
+ * Some platform-dependent definitions to sync up the C support level.
+ * Some to a C99-ish level, some related utility code.
+ *
+ * Currently:
+ * + [u]int{8,16,32}_t types
+ * + 64-bit types and load/store code
+ * + SIZE_MAX
+ * + shared library init/fini hooks
+ * + consistent getpwnam/getpwuid interfaces
+ * + va_copy fudged if not provided
+ * + strlcpy/strlcat
+ * + fnmatch
+ * + [v]asprintf
+ * + strerror_r
+ * + mkstemp
+ * + zap (support function; macro is in k5-int.h)
+ * + constant time memory comparison
+ * + path manipulation
+ * + _, N_, dgettext, bindtextdomain (for localization)
+ */
+
+#ifndef K5_PLATFORM_H
+#define K5_PLATFORM_H
+
+#include "autoconf.h"
+#include <assert.h>
+#include <string.h>
+#include <stdarg.h>
+#include <stdint.h>
+#include <limits.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <errno.h>
+#ifdef HAVE_FNMATCH_H
+#include <fnmatch.h>
+#endif
+
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#ifdef _WIN32
+#define CAN_COPY_VA_LIST
+#endif
+
+#if defined(macintosh) || (defined(__MACH__) && defined(__APPLE__))
+#include <TargetConditionals.h>
+#endif
+
+/* Initialization and finalization function support for libraries.
+
+ At top level, before the functions are defined or even declared:
+ MAKE_INIT_FUNCTION(init_fn);
+ MAKE_FINI_FUNCTION(fini_fn);
+ Then:
+ int init_fn(void) { ... }
+ void fini_fn(void) { if (INITIALIZER_RAN(init_fn)) ... }
+ In code, in the same file:
+ err = CALL_INIT_FUNCTION(init_fn);
+
+ To trigger or verify the initializer invocation from another file,
+ a helper function must be created.
+
+ This model handles both the load-time execution (Windows) and
+ delayed execution (pthread_once) approaches, and should be able to
+ guarantee in both cases that the init function is run once, in one
+ thread, before other stuff in the library is done; furthermore, the
+ finalization code should only run if the initialization code did.
+ (Maybe I could've made the "if INITIALIZER_RAN" test implicit, via
+ another function hidden in macros, but this is hairy enough
+ already.)
+
+ The init_fn and fini_fn names should be chosen such that any
+ exported names staring with those names, and optionally followed by
+ additional characters, fits in with any namespace constraints on
+ the library in question.
+
+
+ There's also PROGRAM_EXITING() currently always defined as zero.
+ If there's some trivial way to find out if the fini function is
+ being called because the program that the library is linked into is
+ exiting, we can just skip all the work because the resources are
+ about to be freed up anyways. Generally this is likely to be the
+ same as distinguishing whether the library was loaded dynamically
+ while the program was running, or loaded as part of program
+ startup. On most platforms, I don't think we can distinguish these
+ cases easily, and it's probably not worth expending any significant
+ effort. (Note in particular that atexit() won't do, because if the
+ library is explicitly loaded and unloaded, it would have to be able
+ to deregister the atexit callback function. Also, the system limit
+ on atexit callbacks may be small.)
+
+
+ Implementation outline:
+
+ Windows: MAKE_FINI_FUNCTION creates a symbol with a magic name that
+ is sought at library build time, and code is added to invoke the
+ function when the library is unloaded. MAKE_INIT_FUNCTION does
+ likewise, but the function is invoked when the library is loaded,
+ and an extra variable is declared to hold an error code and a "yes
+ the initializer ran" flag. CALL_INIT_FUNCTION blows up if the flag
+ isn't set, otherwise returns the error code.
+
+ UNIX: MAKE_INIT_FUNCTION creates and initializes a variable with a
+ name derived from the function name, containing a k5_once_t
+ (pthread_once_t or int), an error code, and a pointer to the
+ function. The function itself is declared static, but the
+ associated variable has external linkage. CALL_INIT_FUNCTION
+ ensures thath the function is called exactly once (pthread_once or
+ just check the flag) and returns the stored error code (or the
+ pthread_once error).
+
+ (That's the basic idea. With some debugging assert() calls and
+ such, it's a bit more complicated. And we also need to handle
+ doing the pthread test at run time on systems where that works, so
+ we use the k5_once_t stuff instead.)
+
+ UNIX, with compiler support: MAKE_FINI_FUNCTION declares the
+ function as a destructor, and the run time linker support or
+ whatever will cause it to be invoked when the library is unloaded,
+ the program ends, etc.
+
+ UNIX, with linker support: MAKE_FINI_FUNCTION creates a symbol with
+ a magic name that is sought at library build time, and linker
+ options are used to mark it as a finalization function for the
+ library. The symbol must be exported.
+
+ UNIX, no library finalization support: The finalization function
+ never runs, and we leak memory. Tough.
+
+ DELAY_INITIALIZER will be defined by the configure script if we
+ want to use k5_once instead of load-time initialization. That'll
+ be the preferred method on most systems except Windows, where we
+ have to initialize some mutexes.
+
+
+
+
+ For maximum flexibility in defining the macros, the function name
+ parameter should be a simple name, not even a macro defined as
+ another name. The function should have a unique name, and should
+ conform to whatever namespace is used by the library in question.
+ (We do have export lists, but (1) they're not used for all
+ platforms, and (2) they're not used for static libraries.)
+
+ If the macro expansion needs the function to have been declared, it
+ must include a declaration. If it is not necessary for the symbol
+ name to be exported from the object file, the macro should declare
+ it as "static". Hence the signature must exactly match "void
+ foo(void)". (ANSI C allows a static declaration followed by a
+ non-static one; the result is internal linkage.) The macro
+ expansion has to come before the function, because gcc apparently
+ won't act on "__attribute__((constructor))" if it comes after the
+ function definition.
+
+ This is going to be compiler- and environment-specific, and may
+ require some support at library build time, and/or "asm"
+ statements. But through macro expansion and auxiliary functions,
+ we should be able to handle most things except #pragma.
+
+ It's okay for this code to require that the library be built
+ with the same compiler and compiler options throughout, but
+ we shouldn't require that the library and application use the
+ same compiler.
+
+ For static libraries, we don't really care about cleanup too much,
+ since it's all memory handling and mutex allocation which will all
+ be cleaned up when the program exits. Thus, it's okay if gcc-built
+ static libraries don't play nicely with cc-built executables when
+ it comes to static constructors, just as long as it doesn't cause
+ linking to fail.
+
+ For dynamic libraries on UNIX, we'll use pthread_once-type support
+ to do delayed initialization, so if finalization can't be made to
+ work, we'll only have memory leaks in a load/use/unload cycle. If
+ anyone (like, say, the OS vendor) complains about this, they can
+ tell us how to get a shared library finalization function invoked
+ automatically.
+
+ Currently there's --disable-delayed-initialization for preventing
+ the initialization from being delayed on UNIX, but that's mainly
+ just for testing the linker options for initialization, and will
+ probably be removed at some point. */
+
+/* Helper macros. */
+
+# define JOIN__2_2(A,B) A ## _ ## _ ## B
+# define JOIN__2(A,B) JOIN__2_2(A,B)
+
+/* XXX Should test USE_LINKER_INIT_OPTION early, and if it's set,
+ always provide a function by the expected name, even if we're
+ delaying initialization. */
+
+#if defined(DELAY_INITIALIZER)
+
+/* Run the initialization code during program execution, at the latest
+ possible moment. This means multiple threads may be active. */
+# include "k5-thread.h"
+typedef struct { k5_once_t once; int error, did_run; void (*fn)(void); } k5_init_t;
+# ifdef USE_LINKER_INIT_OPTION
+# define MAYBE_DUMMY_INIT(NAME) \
+ void JOIN__2(NAME, auxinit) () { }
+# else
+# define MAYBE_DUMMY_INIT(NAME)
+# endif
+# ifdef __GNUC__
+/* Do it in macro form so we get the file/line of the invocation if
+ the assertion fails. */
+# define k5_call_init_function(I) \
+ (__extension__ ({ \
+ k5_init_t *k5int_i = (I); \
+ int k5int_err = k5_once(&k5int_i->once, k5int_i->fn); \
+ (k5int_err \
+ ? k5int_err \
+ : (assert(k5int_i->did_run != 0), k5int_i->error)); \
+ }))
+# define MAYBE_DEFINE_CALLINIT_FUNCTION
+# else
+# define MAYBE_DEFINE_CALLINIT_FUNCTION \
+ static inline int k5_call_init_function(k5_init_t *i) \
+ { \
+ int err; \
+ err = k5_once(&i->once, i->fn); \
+ if (err) \
+ return err; \
+ assert (i->did_run != 0); \
+ return i->error; \
+ }
+# endif
+# define MAKE_INIT_FUNCTION(NAME) \
+ static int NAME(void); \
+ MAYBE_DUMMY_INIT(NAME) \
+ /* forward declaration for use in initializer */ \
+ static void JOIN__2(NAME, aux) (void); \
+ static k5_init_t JOIN__2(NAME, once) = \
+ { K5_ONCE_INIT, 0, 0, JOIN__2(NAME, aux) }; \
+ MAYBE_DEFINE_CALLINIT_FUNCTION \
+ static void JOIN__2(NAME, aux) (void) \
+ { \
+ JOIN__2(NAME, once).did_run = 1; \
+ JOIN__2(NAME, once).error = NAME(); \
+ } \
+ /* so ';' following macro use won't get error */ \
+ static int NAME(void)
+# define CALL_INIT_FUNCTION(NAME) \
+ k5_call_init_function(& JOIN__2(NAME, once))
+/* This should be called in finalization only, so we shouldn't have
+ multiple active threads mucking around in our library at this
+ point. So ignore the once_t object and just look at the flag.
+
+ XXX Could we have problems with memory coherence between processors
+ if we don't invoke mutex/once routines? Probably not, the
+ application code should already be coordinating things such that
+ the library code is not in use by this point, and memory
+ synchronization will be needed there. */
+# define INITIALIZER_RAN(NAME) \
+ (JOIN__2(NAME, once).did_run && JOIN__2(NAME, once).error == 0)
+
+# define PROGRAM_EXITING() (0)
+
+#elif defined(__GNUC__) && !defined(_WIN32) && defined(CONSTRUCTOR_ATTR_WORKS)
+
+/* Run initializer at load time, via GCC/C++ hook magic. */
+
+# ifdef USE_LINKER_INIT_OPTION
+ /* Both gcc and linker option?? Favor gcc. */
+# define MAYBE_DUMMY_INIT(NAME) \
+ void JOIN__2(NAME, auxinit) () { }
+# else
+# define MAYBE_DUMMY_INIT(NAME)
+# endif
+
+typedef struct { int error; unsigned char did_run; } k5_init_t;
+# define MAKE_INIT_FUNCTION(NAME) \
+ MAYBE_DUMMY_INIT(NAME) \
+ static k5_init_t JOIN__2(NAME, ran) \
+ = { 0, 2 }; \
+ static void JOIN__2(NAME, aux)(void) \
+ __attribute__((constructor)); \
+ static int NAME(void); \
+ static void JOIN__2(NAME, aux)(void) \
+ { \
+ JOIN__2(NAME, ran).error = NAME(); \
+ JOIN__2(NAME, ran).did_run = 3; \
+ } \
+ static int NAME(void)
+# define CALL_INIT_FUNCTION(NAME) \
+ (JOIN__2(NAME, ran).did_run == 3 \
+ ? JOIN__2(NAME, ran).error \
+ : (abort(),0))
+# define INITIALIZER_RAN(NAME) (JOIN__2(NAME,ran).did_run == 3 && JOIN__2(NAME, ran).error == 0)
+
+# define PROGRAM_EXITING() (0)
+
+#elif defined(USE_LINKER_INIT_OPTION) || defined(_WIN32)
+
+/* Run initializer at load time, via linker magic, or in the
+ case of WIN32, win_glue.c hard-coded knowledge. */
+typedef struct { int error; unsigned char did_run; } k5_init_t;
+# define MAKE_INIT_FUNCTION(NAME) \
+ static k5_init_t JOIN__2(NAME, ran) \
+ = { 0, 2 }; \
+ static int NAME(void); \
+ void JOIN__2(NAME, auxinit)() \
+ { \
+ JOIN__2(NAME, ran).error = NAME(); \
+ JOIN__2(NAME, ran).did_run = 3; \
+ } \
+ static int NAME(void)
+# define CALL_INIT_FUNCTION(NAME) \
+ (JOIN__2(NAME, ran).did_run == 3 \
+ ? JOIN__2(NAME, ran).error \
+ : (abort(),0))
+# define INITIALIZER_RAN(NAME) \
+ (JOIN__2(NAME, ran).error == 0)
+
+# define PROGRAM_EXITING() (0)
+
+#else
+
+# error "Don't know how to do load-time initializers for this configuration."
+
+# define PROGRAM_EXITING() (0)
+
+#endif
+
+
+
+#if !defined(SHARED) && !defined(_WIN32)
+
+/*
+ * In this case, we just don't care about finalization.
+ *
+ * The code will still define the function, but we won't do anything
+ * with it. Annoying: This may generate unused-function warnings.
+ */
+
+# define MAKE_FINI_FUNCTION(NAME) \
+ static void NAME(void)
+
+#elif defined(USE_LINKER_FINI_OPTION) || defined(_WIN32)
+/* If we're told the linker option will be used, it doesn't really
+ matter what compiler we're using. Do it the same way
+ regardless. */
+
+# ifdef __hpux
+
+ /* On HP-UX, we need this auxiliary function. At dynamic load or
+ unload time (but *not* program startup and termination for
+ link-time specified libraries), the linker-indicated function
+ is called with a handle on the library and a flag indicating
+ whether it's being loaded or unloaded.
+
+ The "real" fini function doesn't need to be exported, so
+ declare it static.
+
+ As usual, the final declaration is just for syntactic
+ convenience, so the top-level invocation of this macro can be
+ followed by a semicolon. */
+
+# include <dl.h>
+# define MAKE_FINI_FUNCTION(NAME) \
+ static void NAME(void); \
+ void JOIN__2(NAME, auxfini)(shl_t, int); /* silence gcc warnings */ \
+ void JOIN__2(NAME, auxfini)(shl_t h, int l) { if (!l) NAME(); } \
+ static void NAME(void)
+
+# else /* not hpux */
+
+# define MAKE_FINI_FUNCTION(NAME) \
+ void NAME(void)
+
+# endif
+
+#elif defined(__GNUC__) && defined(DESTRUCTOR_ATTR_WORKS)
+/* If we're using gcc, if the C++ support works, the compiler should
+ build executables and shared libraries that support the use of
+ static constructors and destructors. The C compiler supports a
+ function attribute that makes use of the same facility as C++.
+
+ XXX How do we know if the C++ support actually works? */
+# define MAKE_FINI_FUNCTION(NAME) \
+ static void NAME(void) __attribute__((destructor))
+
+#else
+
+# error "Don't know how to do unload-time finalization for this configuration."
+
+#endif
+
+#ifndef SIZE_MAX
+# define SIZE_MAX ((size_t)((size_t)0 - 1))
+#endif
+
+#ifdef _WIN32
+# define SSIZE_MAX ((ssize_t)(SIZE_MAX/2))
+#endif
+
+/* Read and write integer values as (unaligned) octet strings in
+ specific byte orders. Add per-platform optimizations as
+ needed. */
+
+#if HAVE_ENDIAN_H
+# include <endian.h>
+#elif HAVE_MACHINE_ENDIAN_H
+# include <machine/endian.h>
+#endif
+/* Check for BIG/LITTLE_ENDIAN macros. If exactly one is defined, use
+ it. If both are defined, then BYTE_ORDER should be defined and
+ match one of them. Try those symbols, then try again with an
+ underscore prefix. */
+#if defined(BIG_ENDIAN) && defined(LITTLE_ENDIAN)
+# if BYTE_ORDER == BIG_ENDIAN
+# define K5_BE
+# endif
+# if BYTE_ORDER == LITTLE_ENDIAN
+# define K5_LE
+# endif
+#elif defined(BIG_ENDIAN)
+# define K5_BE
+#elif defined(LITTLE_ENDIAN)
+# define K5_LE
+#elif defined(_BIG_ENDIAN) && defined(_LITTLE_ENDIAN)
+# if _BYTE_ORDER == _BIG_ENDIAN
+# define K5_BE
+# endif
+# if _BYTE_ORDER == _LITTLE_ENDIAN
+# define K5_LE
+# endif
+#elif defined(_BIG_ENDIAN)
+# define K5_BE
+#elif defined(_LITTLE_ENDIAN)
+# define K5_LE
+#elif defined(__BIG_ENDIAN__) && !defined(__LITTLE_ENDIAN__)
+# define K5_BE
+#elif defined(__LITTLE_ENDIAN__) && !defined(__BIG_ENDIAN__)
+# define K5_LE
+#endif
+#if !defined(K5_BE) && !defined(K5_LE)
+/* Look for some architectures we know about.
+
+ MIPS can use either byte order, but the preprocessor tells us which
+ mode we're compiling for. The GCC config files indicate that
+ variants of Alpha and IA64 might be out there with both byte
+ orders, but until we encounter the "wrong" ones in the real world,
+ just go with the default (unless there are cpp predefines to help
+ us there too).
+
+ As far as I know, only PDP11 and ARM (which we don't handle here)
+ have strange byte orders where an 8-byte value isn't laid out as
+ either 12345678 or 87654321. */
+# if defined(__i386__) || defined(_MIPSEL) || defined(__alpha__) || (defined(__ia64__) && !defined(__hpux))
+# define K5_LE
+# endif
+# if defined(__hppa__) || defined(__rs6000__) || defined(__sparc__) || defined(_MIPSEB) || defined(__m68k__) || defined(__sparc64__) || defined(__ppc__) || defined(__ppc64__) || (defined(__hpux) && defined(__ia64__))
+# define K5_BE
+# endif
+#endif
+#if defined(K5_BE) && defined(K5_LE)
+# error "oops, check the byte order macros"
+#endif
+
+/* Optimize for GCC on platforms with known byte orders.
+
+ GCC's packed structures can be written to with any alignment; the
+ compiler will use byte operations, unaligned-word operations, or
+ normal memory ops as appropriate for the architecture.
+
+ This assumes the availability of uint##_t types, which should work
+ on most of our platforms except Windows, where we're not using
+ GCC. */
+#ifdef __GNUC__
+# define PUT(SIZE,PTR,VAL) (((struct { uint##SIZE##_t i; } __attribute__((packed)) *)(PTR))->i = (VAL))
+# define GET(SIZE,PTR) (((const struct { uint##SIZE##_t i; } __attribute__((packed)) *)(PTR))->i)
+# define PUTSWAPPED(SIZE,PTR,VAL) PUT(SIZE,PTR,SWAP##SIZE(VAL))
+# define GETSWAPPED(SIZE,PTR) SWAP##SIZE(GET(SIZE,PTR))
+#endif
+/* To do: Define SWAP16, SWAP32, SWAP64 macros to byte-swap values
+ with the indicated numbers of bits.
+
+ Linux: byteswap.h, bswap_16 etc.
+ Solaris 10: none
+ Mac OS X: machine/endian.h or byte_order.h, NXSwap{Short,Int,LongLong}
+ NetBSD: sys/bswap.h, bswap16 etc. */
+
+#if defined(HAVE_BYTESWAP_H) && defined(HAVE_BSWAP_16)
+# include <byteswap.h>
+# define SWAP16 bswap_16
+# define SWAP32 bswap_32
+# ifdef HAVE_BSWAP_64
+# define SWAP64 bswap_64
+# endif
+#elif TARGET_OS_MAC
+# include <architecture/byte_order.h>
+# if 0 /* This causes compiler warnings. */
+# define SWAP16 OSSwapInt16
+# else
+# define SWAP16 k5_swap16
+static inline unsigned int k5_swap16 (unsigned int x) {
+ x &= 0xffff;
+ return (x >> 8) | ((x & 0xff) << 8);
+}
+# endif
+# define SWAP32 OSSwapInt32
+# define SWAP64 OSSwapInt64
+#elif defined(HAVE_SYS_BSWAP_H)
+/* XXX NetBSD/x86 5.0.1 defines bswap16 and bswap32 as inline
+ functions only, so autoconf doesn't pick up on their existence.
+ So, no feature macro test for them here. The 64-bit version isn't
+ inline at all, though, for whatever reason. */
+# include <sys/bswap.h>
+# define SWAP16 bswap16
+# define SWAP32 bswap32
+/* However, bswap64 causes lots of warnings about 'long long'
+ constants; probably only on 32-bit platforms. */
+# if LONG_MAX > 0x7fffffffL
+# define SWAP64 bswap64
+# endif
+#endif
+
+/* Note that on Windows at least this file can be included from C++
+ source, so casts *from* void* are required. */
+static inline void
+store_16_be (unsigned int val, void *vp)
+{
+ unsigned char *p = (unsigned char *) vp;
+#if defined(__GNUC__) && defined(K5_BE) && !defined(__cplusplus)
+ PUT(16,p,val);
+#elif defined(__GNUC__) && defined(K5_LE) && defined(SWAP16) && !defined(__cplusplus)
+ PUTSWAPPED(16,p,val);
+#else
+ p[0] = (val >> 8) & 0xff;
+ p[1] = (val ) & 0xff;
+#endif
+}
+static inline void
+store_32_be (unsigned int val, void *vp)
+{
+ unsigned char *p = (unsigned char *) vp;
+#if defined(__GNUC__) && defined(K5_BE) && !defined(__cplusplus)
+ PUT(32,p,val);
+#elif defined(__GNUC__) && defined(K5_LE) && defined(SWAP32) && !defined(__cplusplus)
+ PUTSWAPPED(32,p,val);
+#else
+ p[0] = (val >> 24) & 0xff;
+ p[1] = (val >> 16) & 0xff;
+ p[2] = (val >> 8) & 0xff;
+ p[3] = (val ) & 0xff;
+#endif
+}
+static inline void
+store_64_be (uint64_t val, void *vp)
+{
+ unsigned char *p = (unsigned char *) vp;
+#if defined(__GNUC__) && defined(K5_BE) && !defined(__cplusplus)
+ PUT(64,p,val);
+#elif defined(__GNUC__) && defined(K5_LE) && defined(SWAP64) && !defined(__cplusplus)
+ PUTSWAPPED(64,p,val);
+#else
+ p[0] = (unsigned char)((val >> 56) & 0xff);
+ p[1] = (unsigned char)((val >> 48) & 0xff);
+ p[2] = (unsigned char)((val >> 40) & 0xff);
+ p[3] = (unsigned char)((val >> 32) & 0xff);
+ p[4] = (unsigned char)((val >> 24) & 0xff);
+ p[5] = (unsigned char)((val >> 16) & 0xff);
+ p[6] = (unsigned char)((val >> 8) & 0xff);
+ p[7] = (unsigned char)((val ) & 0xff);
+#endif
+}
+static inline unsigned short
+load_16_be (const void *cvp)
+{
+ const unsigned char *p = (const unsigned char *) cvp;
+#if defined(__GNUC__) && defined(K5_BE) && !defined(__cplusplus)
+ return GET(16,p);
+#elif defined(__GNUC__) && defined(K5_LE) && defined(SWAP16) && !defined(__cplusplus)
+ return GETSWAPPED(16,p);
+#else
+ return (p[1] | (p[0] << 8));
+#endif
+}
+static inline unsigned int
+load_32_be (const void *cvp)
+{
+ const unsigned char *p = (const unsigned char *) cvp;
+#if defined(__GNUC__) && defined(K5_BE) && !defined(__cplusplus)
+ return GET(32,p);
+#elif defined(__GNUC__) && defined(K5_LE) && defined(SWAP32) && !defined(__cplusplus)
+ return GETSWAPPED(32,p);
+#else
+ return (p[3] | (p[2] << 8)
+ | ((uint32_t) p[1] << 16)
+ | ((uint32_t) p[0] << 24));
+#endif
+}
+static inline uint64_t
+load_64_be (const void *cvp)
+{
+ const unsigned char *p = (const unsigned char *) cvp;
+#if defined(__GNUC__) && defined(K5_BE) && !defined(__cplusplus)
+ return GET(64,p);
+#elif defined(__GNUC__) && defined(K5_LE) && defined(SWAP64) && !defined(__cplusplus)
+ return GETSWAPPED(64,p);
+#else
+ return ((uint64_t)load_32_be(p) << 32) | load_32_be(p+4);
+#endif
+}
+static inline void
+store_16_le (unsigned int val, void *vp)
+{
+ unsigned char *p = (unsigned char *) vp;
+#if defined(__GNUC__) && defined(K5_LE) && !defined(__cplusplus)
+ PUT(16,p,val);
+#elif defined(__GNUC__) && defined(K5_BE) && defined(SWAP16) && !defined(__cplusplus)
+ PUTSWAPPED(16,p,val);
+#else
+ p[1] = (val >> 8) & 0xff;
+ p[0] = (val ) & 0xff;
+#endif
+}
+static inline void
+store_32_le (unsigned int val, void *vp)
+{
+ unsigned char *p = (unsigned char *) vp;
+#if defined(__GNUC__) && defined(K5_LE) && !defined(__cplusplus)
+ PUT(32,p,val);
+#elif defined(__GNUC__) && defined(K5_BE) && defined(SWAP32) && !defined(__cplusplus)
+ PUTSWAPPED(32,p,val);
+#else
+ p[3] = (val >> 24) & 0xff;
+ p[2] = (val >> 16) & 0xff;
+ p[1] = (val >> 8) & 0xff;
+ p[0] = (val ) & 0xff;
+#endif
+}
+static inline void
+store_64_le (uint64_t val, void *vp)
+{
+ unsigned char *p = (unsigned char *) vp;
+#if defined(__GNUC__) && defined(K5_LE) && !defined(__cplusplus)
+ PUT(64,p,val);
+#elif defined(__GNUC__) && defined(K5_BE) && defined(SWAP64) && !defined(__cplusplus)
+ PUTSWAPPED(64,p,val);
+#else
+ p[7] = (unsigned char)((val >> 56) & 0xff);
+ p[6] = (unsigned char)((val >> 48) & 0xff);
+ p[5] = (unsigned char)((val >> 40) & 0xff);
+ p[4] = (unsigned char)((val >> 32) & 0xff);
+ p[3] = (unsigned char)((val >> 24) & 0xff);
+ p[2] = (unsigned char)((val >> 16) & 0xff);
+ p[1] = (unsigned char)((val >> 8) & 0xff);
+ p[0] = (unsigned char)((val ) & 0xff);
+#endif
+}
+static inline unsigned short
+load_16_le (const void *cvp)
+{
+ const unsigned char *p = (const unsigned char *) cvp;
+#if defined(__GNUC__) && defined(K5_LE) && !defined(__cplusplus)
+ return GET(16,p);
+#elif defined(__GNUC__) && defined(K5_BE) && defined(SWAP16) && !defined(__cplusplus)
+ return GETSWAPPED(16,p);
+#else
+ return (p[0] | (p[1] << 8));
+#endif
+}
+static inline unsigned int
+load_32_le (const void *cvp)
+{
+ const unsigned char *p = (const unsigned char *) cvp;
+#if defined(__GNUC__) && defined(K5_LE) && !defined(__cplusplus)
+ return GET(32,p);
+#elif defined(__GNUC__) && defined(K5_BE) && defined(SWAP32) && !defined(__cplusplus)
+ return GETSWAPPED(32,p);
+#else
+ return (p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24));
+#endif
+}
+static inline uint64_t
+load_64_le (const void *cvp)
+{
+ const unsigned char *p = (const unsigned char *) cvp;
+#if defined(__GNUC__) && defined(K5_LE) && !defined(__cplusplus)
+ return GET(64,p);
+#elif defined(__GNUC__) && defined(K5_BE) && defined(SWAP64) && !defined(__cplusplus)
+ return GETSWAPPED(64,p);
+#else
+ return ((uint64_t)load_32_le(p+4) << 32) | load_32_le(p);
+#endif
+}
+
+#define UINT16_TYPE uint16_t
+#define UINT32_TYPE uint32_t
+
+static inline void
+store_16_n (unsigned int val, void *vp)
+{
+ UINT16_TYPE n = val;
+ memcpy(vp, &n, 2);
+}
+static inline void
+store_32_n (unsigned int val, void *vp)
+{
+ UINT32_TYPE n = val;
+ memcpy(vp, &n, 4);
+}
+static inline void
+store_64_n (uint64_t val, void *vp)
+{
+ uint64_t n = val;
+ memcpy(vp, &n, 8);
+}
+static inline unsigned short
+load_16_n (const void *p)
+{
+ UINT16_TYPE n;
+ memcpy(&n, p, 2);
+ return n;
+}
+static inline unsigned int
+load_32_n (const void *p)
+{
+ UINT32_TYPE n;
+ memcpy(&n, p, 4);
+ return n;
+}
+static inline uint64_t
+load_64_n (const void *p)
+{
+ uint64_t n;
+ memcpy(&n, p, 8);
+ return n;
+}
+#undef UINT16_TYPE
+#undef UINT32_TYPE
+
+/* Assume for simplicity that these swaps are identical. */
+static inline uint64_t
+k5_htonll (uint64_t val)
+{
+#ifdef K5_BE
+ return val;
+#elif defined K5_LE && defined SWAP64
+ return SWAP64 (val);
+#else
+ return load_64_be ((unsigned char *)&val);
+#endif
+}
+static inline uint64_t
+k5_ntohll (uint64_t val)
+{
+ return k5_htonll (val);
+}
+
+/* Make the interfaces to getpwnam and getpwuid consistent.
+ Model the wrappers on the POSIX thread-safe versions, but
+ use the unsafe system versions if the safe ones don't exist
+ or we can't figure out their interfaces. */
+
+/* int k5_getpwnam_r(const char *, blah blah) */
+#ifdef HAVE_GETPWNAM_R
+# ifndef GETPWNAM_R_4_ARGS
+/* POSIX */
+# define k5_getpwnam_r(NAME, REC, BUF, BUFSIZE, OUT) \
+ (getpwnam_r(NAME,REC,BUF,BUFSIZE,OUT) == 0 \
+ ? (*(OUT) == NULL ? -1 : 0) : -1)
+# else
+/* POSIX drafts? */
+# ifdef GETPWNAM_R_RETURNS_INT
+# define k5_getpwnam_r(NAME, REC, BUF, BUFSIZE, OUT) \
+ (getpwnam_r(NAME,REC,BUF,BUFSIZE) == 0 \
+ ? (*(OUT) = REC, 0) \
+ : (*(OUT) = NULL, -1))
+# else
+# define k5_getpwnam_r(NAME, REC, BUF, BUFSIZE, OUT) \
+ (*(OUT) = getpwnam_r(NAME,REC,BUF,BUFSIZE), *(OUT) == NULL ? -1 : 0)
+# endif
+# endif
+#else /* no getpwnam_r, or can't figure out #args or return type */
+/* Will get warnings about unused variables. */
+# define k5_getpwnam_r(NAME, REC, BUF, BUFSIZE, OUT) \
+ (*(OUT) = getpwnam(NAME), *(OUT) == NULL ? -1 : 0)
+#endif
+
+/* int k5_getpwuid_r(uid_t, blah blah) */
+#ifdef HAVE_GETPWUID_R
+# ifndef GETPWUID_R_4_ARGS
+/* POSIX */
+# define k5_getpwuid_r(UID, REC, BUF, BUFSIZE, OUT) \
+ (getpwuid_r(UID,REC,BUF,BUFSIZE,OUT) == 0 \
+ ? (*(OUT) == NULL ? -1 : 0) : -1)
+# else
+/* POSIX drafts? Yes, I mean to test GETPWNAM... here. Less junk to
+ do at configure time. */
+# ifdef GETPWNAM_R_RETURNS_INT
+# define k5_getpwuid_r(UID, REC, BUF, BUFSIZE, OUT) \
+ (getpwuid_r(UID,REC,BUF,BUFSIZE) == 0 \
+ ? (*(OUT) = REC, 0) \
+ : (*(OUT) = NULL, -1))
+# else
+# define k5_getpwuid_r(UID, REC, BUF, BUFSIZE, OUT) \
+ (*(OUT) = getpwuid_r(UID,REC,BUF,BUFSIZE), *(OUT) == NULL ? -1 : 0)
+# endif
+# endif
+#else /* no getpwuid_r, or can't figure out #args or return type */
+/* Will get warnings about unused variables. */
+# define k5_getpwuid_r(UID, REC, BUF, BUFSIZE, OUT) \
+ (*(OUT) = getpwuid(UID), *(OUT) == NULL ? -1 : 0)
+#endif
+
+/* Ensure, if possible, that the indicated file descriptor won't be
+ kept open if we exec another process (e.g., launching a ccapi
+ server). If we don't know how to do it... well, just go about our
+ business. Probably most callers won't check the return status
+ anyways. */
+
+#if 0
+static inline void
+set_cloexec_fd(int fd)
+{
+#if defined(F_SETFD)
+# ifdef FD_CLOEXEC
+ (void)fcntl(fd, F_SETFD, FD_CLOEXEC);
+# else
+ (void)fcntl(fd, F_SETFD, 1);
+# endif
+#endif
+}
+
+static inline void
+set_cloexec_file(FILE *f)
+{
+ return set_cloexec_fd(fileno(f));
+}
+#else
+/* Macros make the Sun compiler happier, and all variants of this do a
+ single evaluation of the argument, and fcntl and fileno should
+ produce reasonable error messages on type mismatches, on any system
+ with F_SETFD. */
+#ifdef F_SETFD
+# ifdef FD_CLOEXEC
+# define set_cloexec_fd(FD) ((void)fcntl((FD), F_SETFD, FD_CLOEXEC))
+# else
+# define set_cloexec_fd(FD) ((void)fcntl((FD), F_SETFD, 1))
+# endif
+#else
+# define set_cloexec_fd(FD) ((void)(FD))
+#endif
+#define set_cloexec_file(F) set_cloexec_fd(fileno(F))
+#endif
+
+
+
+/* Since the original ANSI C spec left it undefined whether or
+ how you could copy around a va_list, C 99 added va_copy.
+ For old implementations, let's do our best to fake it.
+
+ XXX Doesn't yet handle implementations with __va_copy (early draft)
+ or GCC's __builtin_va_copy. */
+#if defined(HAS_VA_COPY) || defined(va_copy)
+/* Do nothing. */
+#elif defined(CAN_COPY_VA_LIST)
+#define va_copy(dest, src) ((dest) = (src))
+#else
+/* Assume array type, but still simply copyable.
+
+ There is, theoretically, the possibility that va_start will
+ allocate some storage pointed to by the va_list, and in that case
+ we'll just lose. If anyone cares, we could try to devise a test
+ for that case. */
+#define va_copy(dest, src) memcpy(dest, src, sizeof(va_list))
+#endif
+
+/* Provide strlcpy/strlcat interfaces. */
+#ifndef HAVE_STRLCPY
+#define strlcpy krb5int_strlcpy
+#define strlcat krb5int_strlcat
+extern size_t krb5int_strlcpy(char *dst, const char *src, size_t siz);
+extern size_t krb5int_strlcat(char *dst, const char *src, size_t siz);
+#endif
+
+/* Provide fnmatch interface. */
+#ifndef HAVE_FNMATCH
+#define fnmatch k5_fnmatch
+int k5_fnmatch(const char *pattern, const char *string, int flags);
+#define FNM_NOMATCH 1 /* Match failed. */
+#define FNM_NOSYS 2 /* Function not implemented. */
+#define FNM_NORES 3 /* Out of resources */
+#define FNM_NOESCAPE 0x01 /* Disable backslash escaping. */
+#define FNM_PATHNAME 0x02 /* Slash must be matched by slash. */
+#define FNM_PERIOD 0x04 /* Period must be matched by period. */
+#define FNM_CASEFOLD 0x08 /* Pattern is matched case-insensitive */
+#define FNM_LEADING_DIR 0x10 /* Ignore /<tail> after Imatch. */
+#endif
+
+/* Provide [v]asprintf interfaces. */
+#ifndef HAVE_VSNPRINTF
+#ifdef _WIN32
+static inline int
+vsnprintf(char *str, size_t size, const char *format, va_list args)
+{
+ va_list args_copy;
+ int length;
+
+ va_copy(args_copy, args);
+ length = _vscprintf(format, args_copy);
+ va_end(args_copy);
+ if (size > 0) {
+ _vsnprintf(str, size, format, args);
+ str[size - 1] = '\0';
+ }
+ return length;
+}
+static inline int
+snprintf(char *str, size_t size, const char *format, ...)
+{
+ va_list args;
+ int n;
+
+ va_start(args, format);
+ n = vsnprintf(str, size, format, args);
+ va_end(args);
+ return n;
+}
+#else /* not win32 */
+#error We need an implementation of vsnprintf.
+#endif /* win32? */
+#endif /* no vsnprintf */
+
+#ifndef HAVE_VASPRINTF
+
+extern int krb5int_vasprintf(char **, const char *, va_list)
+#if !defined(__cplusplus) && (__GNUC__ > 2)
+ __attribute__((__format__(__printf__, 2, 0)))
+#endif
+ ;
+extern int krb5int_asprintf(char **, const char *, ...)
+#if !defined(__cplusplus) && (__GNUC__ > 2)
+ __attribute__((__format__(__printf__, 2, 3)))
+#endif
+ ;
+
+#define vasprintf krb5int_vasprintf
+/* Assume HAVE_ASPRINTF iff HAVE_VASPRINTF. */
+#define asprintf krb5int_asprintf
+
+#elif defined(NEED_VASPRINTF_PROTO)
+
+extern int vasprintf(char **, const char *, va_list)
+#if !defined(__cplusplus) && (__GNUC__ > 2)
+ __attribute__((__format__(__printf__, 2, 0)))
+#endif
+ ;
+extern int asprintf(char **, const char *, ...)
+#if !defined(__cplusplus) && (__GNUC__ > 2)
+ __attribute__((__format__(__printf__, 2, 3)))
+#endif
+ ;
+
+#endif /* have vasprintf and prototype? */
+
+/* Return true if the snprintf return value RESULT reflects a buffer
+ overflow for the buffer size SIZE.
+
+ We cast the result to unsigned int for two reasons. First, old
+ implementations of snprintf (such as the one in Solaris 9 and
+ prior) return -1 on a buffer overflow. Casting the result to -1
+ will convert that value to UINT_MAX, which should compare larger
+ than any reasonable buffer size. Second, comparing signed and
+ unsigned integers will generate warnings with some compilers, and
+ can have unpredictable results, particularly when the relative
+ widths of the types is not known (size_t may be the same width as
+ int or larger).
+*/
+#define SNPRINTF_OVERFLOW(result, size) \
+ ((unsigned int)(result) >= (size_t)(size))
+
+#if defined(_WIN32) || !defined(HAVE_STRERROR_R) || defined(STRERROR_R_CHAR_P)
+#define strerror_r k5_strerror_r
+#endif
+extern int k5_strerror_r(int errnum, char *buf, size_t buflen);
+
+#ifndef HAVE_MKSTEMP
+extern int krb5int_mkstemp(char *);
+#define mkstemp krb5int_mkstemp
+#endif
+
+#ifndef HAVE_GETTIMEOFDAY
+extern int krb5int_gettimeofday(struct timeval *tp, void *ignore);
+#define gettimeofday krb5int_gettimeofday
+#endif
+
+extern void krb5int_zap(void *ptr, size_t len);
+
+/*
+ * Return 0 if the n-byte memory regions p1 and p2 are equal, and nonzero if
+ * they are not. The function is intended to take the same amount of time
+ * regardless of how many bytes of p1 and p2 are equal.
+ */
+int k5_bcmp(const void *p1, const void *p2, size_t n);
+
+/*
+ * Split a path into parent directory and basename. Either output parameter
+ * may be NULL if the caller doesn't need it. parent_out will be empty if path
+ * has no basename. basename_out will be empty if path ends with a path
+ * separator. Returns 0 on success or ENOMEM on allocation failure.
+ */
+long k5_path_split(const char *path, char **parent_out, char **basename_out);
+
+/*
+ * Compose two path components, inserting the platform-appropriate path
+ * separator if needed. If path2 is an absolute path, path1 will be discarded
+ * and path_out will be a copy of path2. Returns 0 on success or ENOMEM on
+ * allocation failure.
+ */
+long k5_path_join(const char *path1, const char *path2, char **path_out);
+
+/* Return 1 if path is absolute, 0 if it is relative. */
+int k5_path_isabs(const char *path);
+
+/*
+ * Localization macros. If we have gettext, define _ appropriately for
+ * translating a string. If we do not have gettext, define _ and
+ * bindtextdomain as no-ops. N_ is always a no-op; it marks a string for
+ * extraction to pot files but does not translate it.
+ */
+#ifdef ENABLE_NLS
+#include <libintl.h>
+#define KRB5_TEXTDOMAIN "mit-krb5"
+#define _(s) dgettext(KRB5_TEXTDOMAIN, s)
+#else
+#define _(s) s
+#define dgettext(d, m) m
+#define ngettext(m1, m2, n) (((n) == 1) ? m1 : m2)
+#define bindtextdomain(p, d)
+#endif
+#define N_(s) s
+
+#if !defined(HAVE_GETOPT) || !defined(HAVE_UNISTD_H)
+extern int k5_opterr;
+extern int k5_optind;
+extern int k5_optopt;
+extern char *k5_optarg;
+#define opterr k5_opterr
+#define optind k5_optind
+#define optopt k5_optopt
+#define optarg k5_optarg
+
+extern int k5_getopt(int nargc, char * const nargv[], const char *ostr);
+#define getopt k5_getopt
+#endif /* HAVE_GETOPT */
+
+#ifdef HAVE_GETOPT_LONG
+#include <getopt.h>
+#else
+
+struct option
+{
+ const char *name;
+ int has_arg;
+ int *flag;
+ int val;
+};
+
+#define no_argument 0
+#define required_argument 1
+#define optional_argument 2
+
+extern int k5_getopt_long(int nargc, char **nargv, char *options,
+ struct option *long_options, int *index);
+#define getopt_long k5_getopt_long
+#endif /* HAVE_GETOPT_LONG */
+
+#endif /* K5_PLATFORM_H */
diff --git a/src/include/k5-plugin.h b/src/include/k5-plugin.h
new file mode 100644
index 000000000000..90809e168e9f
--- /dev/null
+++ b/src/include/k5-plugin.h
@@ -0,0 +1,121 @@
+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/*
+ * Copyright (C) 2006 Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * This software is being provided to you, the LICENSEE, by the
+ * Massachusetts Institute of Technology (M.I.T.) under the following
+ * license. By obtaining, using and/or copying this software, you agree
+ * that you have read, understood, and will comply with these terms and
+ * conditions:
+ *
+ * Export of this software from the United States of America may
+ * require a specific license from the United States Government.
+ * It is the responsibility of any person or organization contemplating
+ * export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify and distribute
+ * this software and its documentation for any purpose and without fee or
+ * royalty is hereby granted, provided that you agree to comply with the
+ * following copyright notice and statements, including the disclaimer, and
+ * that the same appear on ALL copies of the software and documentation,
+ * including modifications that you make for internal use or for
+ * distribution:
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS", AND M.I.T. MAKES NO REPRESENTATIONS
+ * OR WARRANTIES, EXPRESS OR IMPLIED. By way of example, but not
+ * limitation, M.I.T. MAKES NO REPRESENTATIONS OR WARRANTIES OF
+ * MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF
+ * THE LICENSED SOFTWARE OR DOCUMENTATION WILL NOT INFRINGE ANY THIRD PARTY
+ * PATENTS, COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS.
+ *
+ * The name of the Massachusetts Institute of Technology or M.I.T. may NOT
+ * be used in advertising or publicity pertaining to distribution of the
+ * software. Title to copyright in this software and any associated
+ * documentation shall at all times remain with M.I.T., and USER agrees to
+ * preserve same.
+ *
+ * Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ */
+
+/* Just those definitions which are needed by util/support/plugins.c,
+ which gets compiled before util/et is built, which happens before
+ we can construct krb5.h, which is included by k5-int.h.
+
+ So, no krb5 types. */
+
+#ifndef K5_PLUGIN_H
+#define K5_PLUGIN_H
+
+#if defined(_MSDOS) || defined(_WIN32)
+#include "win-mac.h"
+#endif
+#include "autoconf.h"
+#ifndef KRB5_CALLCONV
+#define KRB5_CALLCONV
+#define KRB5_CALLCONV_C
+#endif
+
+#include "k5-err.h"
+
+/*
+ * Plugins normally export fixed symbol names, but when statically
+ * linking plugins, we need a different symbol name for each plugin.
+ * The first argument to PLUGIN_SYMBOL_NAME acts as the
+ * differentiator, and is only used for static plugin linking.
+ *
+ * Although this macro (and thus this header file) are used in plugins
+ * whose code lies inside the krb5 tree, plugins maintained separately
+ * from the krb5 tree do not need it; they can just use the fixed
+ * symbol name unconditionally.
+ */
+#ifdef STATIC_PLUGINS
+#define PLUGIN_SYMBOL_NAME(prefix, symbol) prefix ## _ ## symbol
+#else
+#define PLUGIN_SYMBOL_NAME(prefix, symbol) symbol
+#endif
+
+struct plugin_file_handle; /* opaque */
+
+struct plugin_dir_handle {
+ /* This points to a NULL-terminated list of pointers to plugin_file_handle structs */
+ struct plugin_file_handle **files;
+};
+#define PLUGIN_DIR_INIT(P) ((P)->files = NULL)
+#define PLUGIN_DIR_OPEN(P) ((P)->files != NULL)
+
+long KRB5_CALLCONV
+krb5int_open_plugin (const char *, struct plugin_file_handle **, struct errinfo *);
+void KRB5_CALLCONV
+krb5int_close_plugin (struct plugin_file_handle *);
+
+long KRB5_CALLCONV
+krb5int_get_plugin_data (struct plugin_file_handle *, const char *, void **,
+ struct errinfo *);
+
+long KRB5_CALLCONV
+krb5int_get_plugin_func (struct plugin_file_handle *, const char *,
+ void (**)(), struct errinfo *);
+
+
+long KRB5_CALLCONV
+krb5int_open_plugin_dirs (const char * const *, const char * const *,
+ struct plugin_dir_handle *, struct errinfo *);
+void KRB5_CALLCONV
+krb5int_close_plugin_dirs (struct plugin_dir_handle *);
+
+long KRB5_CALLCONV
+krb5int_get_plugin_dir_data (struct plugin_dir_handle *, const char *,
+ void ***, struct errinfo *);
+void KRB5_CALLCONV
+krb5int_free_plugin_dir_data (void **);
+
+long KRB5_CALLCONV
+krb5int_get_plugin_dir_func (struct plugin_dir_handle *, const char *,
+ void (***)(void), struct errinfo *);
+void KRB5_CALLCONV
+krb5int_free_plugin_dir_func (void (**)(void));
+
+#endif /* K5_PLUGIN_H */
diff --git a/src/include/k5-queue.h b/src/include/k5-queue.h
new file mode 100644
index 000000000000..ad6d866faa4e
--- /dev/null
+++ b/src/include/k5-queue.h
@@ -0,0 +1,637 @@
+/*
+ * This is a copy of NetBSD's sys/queue.h, edited to use a different symbol for
+ * multiple inclusion protection and to suppress the include of <sys/null.h>.
+ */
+
+/* $NetBSD: queue.h,v 1.53 2011/11/19 22:51:31 tls Exp $ */
+
+/*
+ * Copyright (c) 1991, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)queue.h 8.5 (Berkeley) 8/20/94
+ */
+
+#ifndef K5_QUEUE_H
+#define K5_QUEUE_H
+
+/* #include <sys/null.h> */
+
+/*
+ * This file defines five types of data structures: singly-linked lists,
+ * lists, simple queues, tail queues, and circular queues.
+ *
+ * A singly-linked list is headed by a single forward pointer. The
+ * elements are singly linked for minimum space and pointer manipulation
+ * overhead at the expense of O(n) removal for arbitrary elements. New
+ * elements can be added to the list after an existing element or at the
+ * head of the list. Elements being removed from the head of the list
+ * should use the explicit macro for this purpose for optimum
+ * efficiency. A singly-linked list may only be traversed in the forward
+ * direction. Singly-linked lists are ideal for applications with large
+ * datasets and few or no removals or for implementing a LIFO queue.
+ *
+ * A list is headed by a single forward pointer (or an array of forward
+ * pointers for a hash table header). The elements are doubly linked
+ * so that an arbitrary element can be removed without a need to
+ * traverse the list. New elements can be added to the list before
+ * or after an existing element or at the head of the list. A list
+ * may only be traversed in the forward direction.
+ *
+ * A simple queue is headed by a pair of pointers, one the head of the
+ * list and the other to the tail of the list. The elements are singly
+ * linked to save space, so elements can only be removed from the
+ * head of the list. New elements can be added to the list after
+ * an existing element, at the head of the list, or at the end of the
+ * list. A simple queue may only be traversed in the forward direction.
+ *
+ * A tail queue is headed by a pair of pointers, one to the head of the
+ * list and the other to the tail of the list. The elements are doubly
+ * linked so that an arbitrary element can be removed without a need to
+ * traverse the list. New elements can be added to the list before or
+ * after an existing element, at the head of the list, or at the end of
+ * the list. A tail queue may be traversed in either direction.
+ *
+ * A circle queue is headed by a pair of pointers, one to the head of the
+ * list and the other to the tail of the list. The elements are doubly
+ * linked so that an arbitrary element can be removed without a need to
+ * traverse the list. New elements can be added to the list before or after
+ * an existing element, at the head of the list, or at the end of the list.
+ * A circle queue may be traversed in either direction, but has a more
+ * complex end of list detection.
+ *
+ * For details on the use of these macros, see the queue(3) manual page.
+ */
+
+/*
+ * List definitions.
+ */
+#define K5_LIST_HEAD(name, type) \
+struct name { \
+ struct type *lh_first; /* first element */ \
+}
+
+#define K5_LIST_HEAD_INITIALIZER(head) \
+ { NULL }
+
+#define K5_LIST_ENTRY(type) \
+struct { \
+ struct type *le_next; /* next element */ \
+ struct type **le_prev; /* address of previous next element */ \
+}
+
+/*
+ * List functions.
+ */
+#define K5_LIST_INIT(head) do { \
+ (head)->lh_first = NULL; \
+} while (/*CONSTCOND*/0)
+
+#define K5_LIST_INSERT_AFTER(listelm, elm, field) do { \
+ if (((elm)->field.le_next = (listelm)->field.le_next) != NULL) \
+ (listelm)->field.le_next->field.le_prev = \
+ &(elm)->field.le_next; \
+ (listelm)->field.le_next = (elm); \
+ (elm)->field.le_prev = &(listelm)->field.le_next; \
+} while (/*CONSTCOND*/0)
+
+#define K5_LIST_INSERT_BEFORE(listelm, elm, field) do { \
+ (elm)->field.le_prev = (listelm)->field.le_prev; \
+ (elm)->field.le_next = (listelm); \
+ *(listelm)->field.le_prev = (elm); \
+ (listelm)->field.le_prev = &(elm)->field.le_next; \
+} while (/*CONSTCOND*/0)
+
+#define K5_LIST_INSERT_HEAD(head, elm, field) do { \
+ if (((elm)->field.le_next = (head)->lh_first) != NULL) \
+ (head)->lh_first->field.le_prev = &(elm)->field.le_next;\
+ (head)->lh_first = (elm); \
+ (elm)->field.le_prev = &(head)->lh_first; \
+} while (/*CONSTCOND*/0)
+
+#define K5_LIST_REMOVE(elm, field) do { \
+ if ((elm)->field.le_next != NULL) \
+ (elm)->field.le_next->field.le_prev = \
+ (elm)->field.le_prev; \
+ *(elm)->field.le_prev = (elm)->field.le_next; \
+} while (/*CONSTCOND*/0)
+
+#define K5_LIST_FOREACH(var, head, field) \
+ for ((var) = ((head)->lh_first); \
+ (var); \
+ (var) = ((var)->field.le_next))
+
+#define K5_LIST_FOREACH_SAFE(var, head, field, tvar) \
+ for ((var) = K5_LIST_FIRST((head)); \
+ (var) && ((tvar) = K5_LIST_NEXT((var), field), 1); \
+ (var) = (tvar))
+/*
+ * List access methods.
+ */
+#define K5_LIST_EMPTY(head) ((head)->lh_first == NULL)
+#define K5_LIST_FIRST(head) ((head)->lh_first)
+#define K5_LIST_NEXT(elm, field) ((elm)->field.le_next)
+
+
+/*
+ * Singly-linked List definitions.
+ */
+#define K5_SLIST_HEAD(name, type) \
+struct name { \
+ struct type *slh_first; /* first element */ \
+}
+
+#define K5_SLIST_HEAD_INITIALIZER(head) \
+ { NULL }
+
+#define K5_SLIST_ENTRY(type) \
+struct { \
+ struct type *sle_next; /* next element */ \
+}
+
+/*
+ * Singly-linked List functions.
+ */
+#define K5_SLIST_INIT(head) do { \
+ (head)->slh_first = NULL; \
+} while (/*CONSTCOND*/0)
+
+#define K5_SLIST_INSERT_AFTER(slistelm, elm, field) do { \
+ (elm)->field.sle_next = (slistelm)->field.sle_next; \
+ (slistelm)->field.sle_next = (elm); \
+} while (/*CONSTCOND*/0)
+
+#define K5_SLIST_INSERT_HEAD(head, elm, field) do { \
+ (elm)->field.sle_next = (head)->slh_first; \
+ (head)->slh_first = (elm); \
+} while (/*CONSTCOND*/0)
+
+#define K5_SLIST_REMOVE_HEAD(head, field) do { \
+ (head)->slh_first = (head)->slh_first->field.sle_next; \
+} while (/*CONSTCOND*/0)
+
+#define K5_SLIST_REMOVE(head, elm, type, field) do { \
+ if ((head)->slh_first == (elm)) { \
+ K5_SLIST_REMOVE_HEAD((head), field); \
+ } \
+ else { \
+ struct type *curelm = (head)->slh_first; \
+ while(curelm->field.sle_next != (elm)) \
+ curelm = curelm->field.sle_next; \
+ curelm->field.sle_next = \
+ curelm->field.sle_next->field.sle_next; \
+ } \
+} while (/*CONSTCOND*/0)
+
+#define K5_SLIST_REMOVE_AFTER(slistelm, field) do { \
+ (slistelm)->field.sle_next = \
+ K5_SLIST_NEXT(K5_SLIST_NEXT((slistelm), field), field); \
+} while (/*CONSTCOND*/0)
+
+#define K5_SLIST_FOREACH(var, head, field) \
+ for((var) = (head)->slh_first; (var); (var) = (var)->field.sle_next)
+
+#define K5_SLIST_FOREACH_SAFE(var, head, field, tvar) \
+ for ((var) = K5_SLIST_FIRST((head)); \
+ (var) && ((tvar) = K5_SLIST_NEXT((var), field), 1); \
+ (var) = (tvar))
+
+/*
+ * Singly-linked List access methods.
+ */
+#define K5_SLIST_EMPTY(head) ((head)->slh_first == NULL)
+#define K5_SLIST_FIRST(head) ((head)->slh_first)
+#define K5_SLIST_NEXT(elm, field) ((elm)->field.sle_next)
+
+
+/*
+ * Singly-linked Tail queue declarations.
+ */
+#define K5_STAILQ_HEAD(name, type) \
+struct name { \
+ struct type *stqh_first; /* first element */ \
+ struct type **stqh_last; /* addr of last next element */ \
+}
+
+#define K5_STAILQ_HEAD_INITIALIZER(head) \
+ { NULL, &(head).stqh_first }
+
+#define K5_STAILQ_ENTRY(type) \
+struct { \
+ struct type *stqe_next; /* next element */ \
+}
+
+/*
+ * Singly-linked Tail queue functions.
+ */
+#define K5_STAILQ_INIT(head) do { \
+ (head)->stqh_first = NULL; \
+ (head)->stqh_last = &(head)->stqh_first; \
+} while (/*CONSTCOND*/0)
+
+#define K5_STAILQ_INSERT_HEAD(head, elm, field) do { \
+ if (((elm)->field.stqe_next = (head)->stqh_first) == NULL) \
+ (head)->stqh_last = &(elm)->field.stqe_next; \
+ (head)->stqh_first = (elm); \
+} while (/*CONSTCOND*/0)
+
+#define K5_STAILQ_INSERT_TAIL(head, elm, field) do { \
+ (elm)->field.stqe_next = NULL; \
+ *(head)->stqh_last = (elm); \
+ (head)->stqh_last = &(elm)->field.stqe_next; \
+} while (/*CONSTCOND*/0)
+
+#define K5_STAILQ_INSERT_AFTER(head, listelm, elm, field) do { \
+ if (((elm)->field.stqe_next = (listelm)->field.stqe_next) == NULL)\
+ (head)->stqh_last = &(elm)->field.stqe_next; \
+ (listelm)->field.stqe_next = (elm); \
+} while (/*CONSTCOND*/0)
+
+#define K5_STAILQ_REMOVE_HEAD(head, field) do { \
+ if (((head)->stqh_first = (head)->stqh_first->field.stqe_next) == NULL) \
+ (head)->stqh_last = &(head)->stqh_first; \
+} while (/*CONSTCOND*/0)
+
+#define K5_STAILQ_REMOVE(head, elm, type, field) do { \
+ if ((head)->stqh_first == (elm)) { \
+ K5_STAILQ_REMOVE_HEAD((head), field); \
+ } else { \
+ struct type *curelm = (head)->stqh_first; \
+ while (curelm->field.stqe_next != (elm)) \
+ curelm = curelm->field.stqe_next; \
+ if ((curelm->field.stqe_next = \
+ curelm->field.stqe_next->field.stqe_next) == NULL) \
+ (head)->stqh_last = &(curelm)->field.stqe_next; \
+ } \
+} while (/*CONSTCOND*/0)
+
+#define K5_STAILQ_FOREACH(var, head, field) \
+ for ((var) = ((head)->stqh_first); \
+ (var); \
+ (var) = ((var)->field.stqe_next))
+
+#define K5_STAILQ_FOREACH_SAFE(var, head, field, tvar) \
+ for ((var) = K5_STAILQ_FIRST((head)); \
+ (var) && ((tvar) = K5_STAILQ_NEXT((var), field), 1); \
+ (var) = (tvar))
+
+#define K5_STAILQ_CONCAT(head1, head2) do { \
+ if (!K5_STAILQ_EMPTY((head2))) { \
+ *(head1)->stqh_last = (head2)->stqh_first; \
+ (head1)->stqh_last = (head2)->stqh_last; \
+ K5_STAILQ_INIT((head2)); \
+ } \
+} while (/*CONSTCOND*/0)
+
+#define K5_STAILQ_LAST(head, type, field) \
+ (K5_STAILQ_EMPTY((head)) ? \
+ NULL : \
+ ((struct type *)(void *) \
+ ((char *)((head)->stqh_last) - offsetof(struct type, field))))
+
+/*
+ * Singly-linked Tail queue access methods.
+ */
+#define K5_STAILQ_EMPTY(head) ((head)->stqh_first == NULL)
+#define K5_STAILQ_FIRST(head) ((head)->stqh_first)
+#define K5_STAILQ_NEXT(elm, field) ((elm)->field.stqe_next)
+
+
+/*
+ * Simple queue definitions.
+ */
+#define K5_SIMPLEQ_HEAD(name, type) \
+struct name { \
+ struct type *sqh_first; /* first element */ \
+ struct type **sqh_last; /* addr of last next element */ \
+}
+
+#define K5_SIMPLEQ_HEAD_INITIALIZER(head) \
+ { NULL, &(head).sqh_first }
+
+#define K5_SIMPLEQ_ENTRY(type) \
+struct { \
+ struct type *sqe_next; /* next element */ \
+}
+
+/*
+ * Simple queue functions.
+ */
+#define K5_SIMPLEQ_INIT(head) do { \
+ (head)->sqh_first = NULL; \
+ (head)->sqh_last = &(head)->sqh_first; \
+} while (/*CONSTCOND*/0)
+
+#define K5_SIMPLEQ_INSERT_HEAD(head, elm, field) do { \
+ if (((elm)->field.sqe_next = (head)->sqh_first) == NULL) \
+ (head)->sqh_last = &(elm)->field.sqe_next; \
+ (head)->sqh_first = (elm); \
+} while (/*CONSTCOND*/0)
+
+#define K5_SIMPLEQ_INSERT_TAIL(head, elm, field) do { \
+ (elm)->field.sqe_next = NULL; \
+ *(head)->sqh_last = (elm); \
+ (head)->sqh_last = &(elm)->field.sqe_next; \
+} while (/*CONSTCOND*/0)
+
+#define K5_SIMPLEQ_INSERT_AFTER(head, listelm, elm, field) do { \
+ if (((elm)->field.sqe_next = (listelm)->field.sqe_next) == NULL)\
+ (head)->sqh_last = &(elm)->field.sqe_next; \
+ (listelm)->field.sqe_next = (elm); \
+} while (/*CONSTCOND*/0)
+
+#define K5_SIMPLEQ_REMOVE_HEAD(head, field) do { \
+ if (((head)->sqh_first = (head)->sqh_first->field.sqe_next) == NULL) \
+ (head)->sqh_last = &(head)->sqh_first; \
+} while (/*CONSTCOND*/0)
+
+#define K5_SIMPLEQ_REMOVE(head, elm, type, field) do { \
+ if ((head)->sqh_first == (elm)) { \
+ K5_SIMPLEQ_REMOVE_HEAD((head), field); \
+ } else { \
+ struct type *curelm = (head)->sqh_first; \
+ while (curelm->field.sqe_next != (elm)) \
+ curelm = curelm->field.sqe_next; \
+ if ((curelm->field.sqe_next = \
+ curelm->field.sqe_next->field.sqe_next) == NULL) \
+ (head)->sqh_last = &(curelm)->field.sqe_next; \
+ } \
+} while (/*CONSTCOND*/0)
+
+#define K5_SIMPLEQ_FOREACH(var, head, field) \
+ for ((var) = ((head)->sqh_first); \
+ (var); \
+ (var) = ((var)->field.sqe_next))
+
+#define K5_SIMPLEQ_FOREACH_SAFE(var, head, field, next) \
+ for ((var) = ((head)->sqh_first); \
+ (var) && ((next = ((var)->field.sqe_next)), 1); \
+ (var) = (next))
+
+#define K5_SIMPLEQ_CONCAT(head1, head2) do { \
+ if (!K5_SIMPLEQ_EMPTY((head2))) { \
+ *(head1)->sqh_last = (head2)->sqh_first; \
+ (head1)->sqh_last = (head2)->sqh_last; \
+ K5_SIMPLEQ_INIT((head2)); \
+ } \
+} while (/*CONSTCOND*/0)
+
+#define K5_SIMPLEQ_LAST(head, type, field) \
+ (K5_SIMPLEQ_EMPTY((head)) ? \
+ NULL : \
+ ((struct type *)(void *) \
+ ((char *)((head)->sqh_last) - offsetof(struct type, field))))
+
+/*
+ * Simple queue access methods.
+ */
+#define K5_SIMPLEQ_EMPTY(head) ((head)->sqh_first == NULL)
+#define K5_SIMPLEQ_FIRST(head) ((head)->sqh_first)
+#define K5_SIMPLEQ_NEXT(elm, field) ((elm)->field.sqe_next)
+
+
+/*
+ * Tail queue definitions.
+ */
+#define _K5_TAILQ_HEAD(name, type, qual) \
+struct name { \
+ qual type *tqh_first; /* first element */ \
+ qual type *qual *tqh_last; /* addr of last next element */ \
+}
+#define K5_TAILQ_HEAD(name, type) _K5_TAILQ_HEAD(name, struct type,)
+
+#define K5_TAILQ_HEAD_INITIALIZER(head) \
+ { NULL, &(head).tqh_first }
+
+#define _K5_TAILQ_ENTRY(type, qual) \
+struct { \
+ qual type *tqe_next; /* next element */ \
+ qual type *qual *tqe_prev; /* address of previous next element */\
+}
+#define K5_TAILQ_ENTRY(type) _K5_TAILQ_ENTRY(struct type,)
+
+/*
+ * Tail queue functions.
+ */
+#define K5_TAILQ_INIT(head) do { \
+ (head)->tqh_first = NULL; \
+ (head)->tqh_last = &(head)->tqh_first; \
+} while (/*CONSTCOND*/0)
+
+#define K5_TAILQ_INSERT_HEAD(head, elm, field) do { \
+ if (((elm)->field.tqe_next = (head)->tqh_first) != NULL) \
+ (head)->tqh_first->field.tqe_prev = \
+ &(elm)->field.tqe_next; \
+ else \
+ (head)->tqh_last = &(elm)->field.tqe_next; \
+ (head)->tqh_first = (elm); \
+ (elm)->field.tqe_prev = &(head)->tqh_first; \
+} while (/*CONSTCOND*/0)
+
+#define K5_TAILQ_INSERT_TAIL(head, elm, field) do { \
+ (elm)->field.tqe_next = NULL; \
+ (elm)->field.tqe_prev = (head)->tqh_last; \
+ *(head)->tqh_last = (elm); \
+ (head)->tqh_last = &(elm)->field.tqe_next; \
+} while (/*CONSTCOND*/0)
+
+#define K5_TAILQ_INSERT_AFTER(head, listelm, elm, field) do { \
+ if (((elm)->field.tqe_next = (listelm)->field.tqe_next) != NULL)\
+ (elm)->field.tqe_next->field.tqe_prev = \
+ &(elm)->field.tqe_next; \
+ else \
+ (head)->tqh_last = &(elm)->field.tqe_next; \
+ (listelm)->field.tqe_next = (elm); \
+ (elm)->field.tqe_prev = &(listelm)->field.tqe_next; \
+} while (/*CONSTCOND*/0)
+
+#define K5_TAILQ_INSERT_BEFORE(listelm, elm, field) do { \
+ (elm)->field.tqe_prev = (listelm)->field.tqe_prev; \
+ (elm)->field.tqe_next = (listelm); \
+ *(listelm)->field.tqe_prev = (elm); \
+ (listelm)->field.tqe_prev = &(elm)->field.tqe_next; \
+} while (/*CONSTCOND*/0)
+
+#define K5_TAILQ_REMOVE(head, elm, field) do { \
+ if (((elm)->field.tqe_next) != NULL) \
+ (elm)->field.tqe_next->field.tqe_prev = \
+ (elm)->field.tqe_prev; \
+ else \
+ (head)->tqh_last = (elm)->field.tqe_prev; \
+ *(elm)->field.tqe_prev = (elm)->field.tqe_next; \
+} while (/*CONSTCOND*/0)
+
+#define K5_TAILQ_FOREACH(var, head, field) \
+ for ((var) = ((head)->tqh_first); \
+ (var); \
+ (var) = ((var)->field.tqe_next))
+
+#define K5_TAILQ_FOREACH_SAFE(var, head, field, next) \
+ for ((var) = ((head)->tqh_first); \
+ (var) != NULL && ((next) = K5_TAILQ_NEXT(var, field), 1); \
+ (var) = (next))
+
+#define K5_TAILQ_FOREACH_REVERSE(var, head, headname, field) \
+ for ((var) = (*(((struct headname *)((head)->tqh_last))->tqh_last)); \
+ (var); \
+ (var) = (*(((struct headname *)((var)->field.tqe_prev))->tqh_last)))
+
+#define K5_TAILQ_FOREACH_REVERSE_SAFE(var, head, headname, field, prev) \
+ for ((var) = K5_TAILQ_LAST((head), headname); \
+ (var) && ((prev) = K5_TAILQ_PREV((var), headname, field), 1);\
+ (var) = (prev))
+
+#define K5_TAILQ_CONCAT(head1, head2, field) do { \
+ if (!K5_TAILQ_EMPTY(head2)) { \
+ *(head1)->tqh_last = (head2)->tqh_first; \
+ (head2)->tqh_first->field.tqe_prev = (head1)->tqh_last; \
+ (head1)->tqh_last = (head2)->tqh_last; \
+ K5_TAILQ_INIT((head2)); \
+ } \
+} while (/*CONSTCOND*/0)
+
+/*
+ * Tail queue access methods.
+ */
+#define K5_TAILQ_EMPTY(head) ((head)->tqh_first == NULL)
+#define K5_TAILQ_FIRST(head) ((head)->tqh_first)
+#define K5_TAILQ_NEXT(elm, field) ((elm)->field.tqe_next)
+
+#define K5_TAILQ_LAST(head, headname) \
+ (*(((struct headname *)((head)->tqh_last))->tqh_last))
+#define K5_TAILQ_PREV(elm, headname, field) \
+ (*(((struct headname *)((elm)->field.tqe_prev))->tqh_last))
+
+
+/*
+ * Circular queue definitions.
+ */
+#define K5_CIRCLEQ_HEAD(name, type) \
+struct name { \
+ struct type *cqh_first; /* first element */ \
+ struct type *cqh_last; /* last element */ \
+}
+
+#define K5_CIRCLEQ_HEAD_INITIALIZER(head) \
+ { (void *)&head, (void *)&head }
+
+#define K5_CIRCLEQ_ENTRY(type) \
+struct { \
+ struct type *cqe_next; /* next element */ \
+ struct type *cqe_prev; /* previous element */ \
+}
+
+/*
+ * Circular queue functions.
+ */
+#define K5_CIRCLEQ_INIT(head) do { \
+ (head)->cqh_first = (void *)(head); \
+ (head)->cqh_last = (void *)(head); \
+} while (/*CONSTCOND*/0)
+
+#define K5_CIRCLEQ_INSERT_AFTER(head, listelm, elm, field) do { \
+ (elm)->field.cqe_next = (listelm)->field.cqe_next; \
+ (elm)->field.cqe_prev = (listelm); \
+ if ((listelm)->field.cqe_next == (void *)(head)) \
+ (head)->cqh_last = (elm); \
+ else \
+ (listelm)->field.cqe_next->field.cqe_prev = (elm); \
+ (listelm)->field.cqe_next = (elm); \
+} while (/*CONSTCOND*/0)
+
+#define K5_CIRCLEQ_INSERT_BEFORE(head, listelm, elm, field) do { \
+ (elm)->field.cqe_next = (listelm); \
+ (elm)->field.cqe_prev = (listelm)->field.cqe_prev; \
+ if ((listelm)->field.cqe_prev == (void *)(head)) \
+ (head)->cqh_first = (elm); \
+ else \
+ (listelm)->field.cqe_prev->field.cqe_next = (elm); \
+ (listelm)->field.cqe_prev = (elm); \
+} while (/*CONSTCOND*/0)
+
+#define K5_CIRCLEQ_INSERT_HEAD(head, elm, field) do { \
+ (elm)->field.cqe_next = (head)->cqh_first; \
+ (elm)->field.cqe_prev = (void *)(head); \
+ if ((head)->cqh_last == (void *)(head)) \
+ (head)->cqh_last = (elm); \
+ else \
+ (head)->cqh_first->field.cqe_prev = (elm); \
+ (head)->cqh_first = (elm); \
+} while (/*CONSTCOND*/0)
+
+#define K5_CIRCLEQ_INSERT_TAIL(head, elm, field) do { \
+ (elm)->field.cqe_next = (void *)(head); \
+ (elm)->field.cqe_prev = (head)->cqh_last; \
+ if ((head)->cqh_first == (void *)(head)) \
+ (head)->cqh_first = (elm); \
+ else \
+ (head)->cqh_last->field.cqe_next = (elm); \
+ (head)->cqh_last = (elm); \
+} while (/*CONSTCOND*/0)
+
+#define K5_CIRCLEQ_REMOVE(head, elm, field) do { \
+ if ((elm)->field.cqe_next == (void *)(head)) \
+ (head)->cqh_last = (elm)->field.cqe_prev; \
+ else \
+ (elm)->field.cqe_next->field.cqe_prev = \
+ (elm)->field.cqe_prev; \
+ if ((elm)->field.cqe_prev == (void *)(head)) \
+ (head)->cqh_first = (elm)->field.cqe_next; \
+ else \
+ (elm)->field.cqe_prev->field.cqe_next = \
+ (elm)->field.cqe_next; \
+} while (/*CONSTCOND*/0)
+
+#define K5_CIRCLEQ_FOREACH(var, head, field) \
+ for ((var) = ((head)->cqh_first); \
+ (var) != (const void *)(head); \
+ (var) = ((var)->field.cqe_next))
+
+#define K5_CIRCLEQ_FOREACH_REVERSE(var, head, field) \
+ for ((var) = ((head)->cqh_last); \
+ (var) != (const void *)(head); \
+ (var) = ((var)->field.cqe_prev))
+
+/*
+ * Circular queue access methods.
+ */
+#define K5_CIRCLEQ_EMPTY(head) ((head)->cqh_first == (void *)(head))
+#define K5_CIRCLEQ_FIRST(head) ((head)->cqh_first)
+#define K5_CIRCLEQ_LAST(head) ((head)->cqh_last)
+#define K5_CIRCLEQ_NEXT(elm, field) ((elm)->field.cqe_next)
+#define K5_CIRCLEQ_PREV(elm, field) ((elm)->field.cqe_prev)
+
+#define K5_CIRCLEQ_LOOP_NEXT(head, elm, field) \
+ (((elm)->field.cqe_next == (void *)(head)) \
+ ? ((head)->cqh_first) \
+ : (elm->field.cqe_next))
+#define K5_CIRCLEQ_LOOP_PREV(head, elm, field) \
+ (((elm)->field.cqe_prev == (void *)(head)) \
+ ? ((head)->cqh_last) \
+ : (elm->field.cqe_prev))
+
+#endif /* !K5_QUEUE_H */
diff --git a/src/include/k5-thread.h b/src/include/k5-thread.h
new file mode 100644
index 000000000000..3e3901d6e8fb
--- /dev/null
+++ b/src/include/k5-thread.h
@@ -0,0 +1,427 @@
+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/* include/k5-thread.h - Preliminary portable thread support */
+/*
+ * Copyright 2004,2005,2006,2007,2008 by the Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ * require a specific license from the United States Government.
+ * It is the responsibility of any person or organization contemplating
+ * export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission. Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose. It is provided "as is" without express
+ * or implied warranty.
+ */
+
+#ifndef K5_THREAD_H
+#define K5_THREAD_H
+
+#include "autoconf.h"
+#ifndef KRB5_CALLCONV
+# define KRB5_CALLCONV
+#endif
+#ifndef KRB5_CALLCONV_C
+# define KRB5_CALLCONV_C
+#endif
+
+/* Interface (tentative):
+
+ Mutex support:
+
+ // Between these two, we should be able to do pure compile-time
+ // and pure run-time initialization.
+ // POSIX: partial initializer is PTHREAD_MUTEX_INITIALIZER,
+ // finish does nothing
+ // Windows: partial initializer is an invalid handle,
+ // finish does the real initialization work
+ k5_mutex_t foo_mutex = K5_MUTEX_PARTIAL_INITIALIZER;
+ int k5_mutex_finish_init(k5_mutex_t *);
+ // for dynamic allocation
+ int k5_mutex_init(k5_mutex_t *);
+ // Must work for both kinds of alloc, even if it means adding flags.
+ int k5_mutex_destroy(k5_mutex_t *);
+
+ // As before.
+ int k5_mutex_lock(k5_mutex_t *);
+ int k5_mutex_unlock(k5_mutex_t *);
+
+ In each library, one new function to finish the static mutex init,
+ and any other library-wide initialization that might be desired.
+ On POSIX, this function would be called via the second support
+ function (see below). On Windows, it would be called at library
+ load time. These functions, or functions they calls, should be the
+ only places that k5_mutex_finish_init gets called.
+
+ A second function or macro called at various possible "first" entry
+ points which either calls pthread_once on the first function
+ (POSIX), or checks some flag set by the first function (Windows),
+ and possibly returns an error. (In the non-threaded case, a simple
+ flag can be used to avoid multiple invocations, and the mutexes
+ don't need run-time initialization anyways.)
+
+ A third function for library termination calls mutex_destroy on
+ each mutex for the library. This function would be called
+ automatically at library unload time. If it turns out to be needed
+ at exit time for libraries that don't get unloaded, perhaps we
+ should also use atexit(). Any static mutexes should be cleaned up
+ with k5_mutex_destroy here.
+
+ How does that second support function invoke the first support
+ function only once? Through something modelled on pthread_once
+ that I haven't written up yet. Probably:
+
+ k5_once_t foo_once = K5_ONCE_INIT;
+ k5_once(k5_once_t *, void (*)(void));
+
+ For POSIX: Map onto pthread_once facility.
+ For non-threaded case: A simple flag.
+ For Windows: Not needed; library init code takes care of it.
+
+ XXX: A general k5_once mechanism isn't possible for Windows,
+ without faking it through named mutexes or mutexes initialized at
+ startup. I was only using it in one place outside these headers,
+ so I'm dropping the general scheme. Eventually the existing uses
+ in k5-thread.h and k5-platform.h will be converted to pthread_once
+ or static variables.
+
+
+ Thread-specific data:
+
+ // TSD keys are limited in number in gssapi/krb5/com_err; enumerate
+ // them all. This allows support code init to allocate the
+ // necessary storage for pointers all at once, and avoids any
+ // possible error in key creation.
+ enum { ... } k5_key_t;
+ // Register destructor function. Called in library init code.
+ int k5_key_register(k5_key_t, void (*destructor)(void *));
+ // Returns NULL or data.
+ void *k5_getspecific(k5_key_t);
+ // Returns error if key out of bounds, or the pointer table can't
+ // be allocated. A call to k5_key_register must have happened first.
+ // This may trigger the calling of pthread_setspecific on POSIX.
+ int k5_setspecific(k5_key_t, void *);
+ // Called in library termination code.
+ // Trashes data in all threads, calling the registered destructor
+ // (but calling it from the current thread).
+ int k5_key_delete(k5_key_t);
+
+ For the non-threaded version, the support code will have a static
+ array indexed by k5_key_t values, and get/setspecific simply access
+ the array elements.
+
+ The TSD destructor table is global state, protected by a mutex if
+ threads are enabled.
+
+
+ Any actual external symbols will use the krb5int_ prefix. The k5_
+ names will be simple macros or inline functions to rename the
+ external symbols, or slightly more complex ones to expand the
+ implementation inline (e.g., map to POSIX versions and/or debug
+ code using __FILE__ and the like).
+
+
+ More to be added, perhaps. */
+
+#include <assert.h>
+
+/* The mutex structure we use, k5_mutex_t, is defined to some
+ OS-specific bits. The use of multiple layers of typedefs are an
+ artifact resulting from debugging code we once used, implemented as
+ wrappers around the OS mutex scheme.
+
+ The OS specific bits, in k5_os_mutex, break down into three primary
+ implementations, POSIX threads, Windows threads, and no thread
+ support. However, the POSIX thread version is further subdivided:
+ In one case, we can determine at run time whether the thread
+ library is linked into the application, and use it only if it is
+ present; in the other case, we cannot, and the thread library must
+ be linked in always, but can be used unconditionally. In the
+ former case, the k5_os_mutex structure needs to hold both the POSIX
+ and the non-threaded versions.
+
+ The various k5_os_mutex_* operations are the OS-specific versions,
+ applied to the OS-specific data, and k5_mutex_* uses k5_os_mutex_*
+ to do the OS-specific parts of the work. */
+
+/* Define the OS mutex bit. */
+
+typedef char k5_os_nothread_mutex;
+# define K5_OS_NOTHREAD_MUTEX_PARTIAL_INITIALIZER 0
+/* Empty inline functions avoid the "statement with no effect"
+ warnings, and do better type-checking than functions that don't use
+ their arguments. */
+static inline int k5_os_nothread_mutex_finish_init(k5_os_nothread_mutex *m) {
+ return 0;
+}
+static inline int k5_os_nothread_mutex_init(k5_os_nothread_mutex *m) {
+ return 0;
+}
+static inline int k5_os_nothread_mutex_destroy(k5_os_nothread_mutex *m) {
+ return 0;
+}
+static inline int k5_os_nothread_mutex_lock(k5_os_nothread_mutex *m) {
+ return 0;
+}
+static inline int k5_os_nothread_mutex_unlock(k5_os_nothread_mutex *m) {
+ return 0;
+}
+
+/* Values:
+ 2 - function has not been run
+ 3 - function has been run
+ 4 - function is being run -- deadlock detected */
+typedef unsigned char k5_os_nothread_once_t;
+# define K5_OS_NOTHREAD_ONCE_INIT 2
+# define k5_os_nothread_once(O,F) \
+ (*(O) == 3 ? 0 \
+ : *(O) == 2 ? (*(O) = 4, (F)(), *(O) = 3, 0) \
+ : (assert(*(O) != 4), assert(*(O) == 2 || *(O) == 3), 0))
+
+
+
+#ifndef ENABLE_THREADS
+
+typedef k5_os_nothread_mutex k5_os_mutex;
+# define K5_OS_MUTEX_PARTIAL_INITIALIZER \
+ K5_OS_NOTHREAD_MUTEX_PARTIAL_INITIALIZER
+# define k5_os_mutex_finish_init k5_os_nothread_mutex_finish_init
+# define k5_os_mutex_init k5_os_nothread_mutex_init
+# define k5_os_mutex_destroy k5_os_nothread_mutex_destroy
+# define k5_os_mutex_lock k5_os_nothread_mutex_lock
+# define k5_os_mutex_unlock k5_os_nothread_mutex_unlock
+
+# define k5_once_t k5_os_nothread_once_t
+# define K5_ONCE_INIT K5_OS_NOTHREAD_ONCE_INIT
+# define k5_once k5_os_nothread_once
+
+#elif HAVE_PTHREAD
+
+# include <pthread.h>
+
+/* Weak reference support, etc.
+
+ Linux: Stub mutex routines exist, but pthread_once does not.
+
+ Solaris <10: In libc there's a pthread_once that doesn't seem to do
+ anything. Bleah. But pthread_mutexattr_setrobust_np is defined
+ only in libpthread. However, some version of GNU libc (Red Hat's
+ Fedora Core 5, reportedly) seems to have that function, but no
+ declaration, so we'd have to declare it in order to test for its
+ address. We now have tests to see if pthread_once actually works,
+ so stick with that for now.
+
+ Solaris 10: The real thread support now lives in libc, and
+ libpthread is just a filter object. So we might as well use the
+ real functions unconditionally. Since we haven't got a test for
+ this property yet, we use NO_WEAK_PTHREADS defined in aclocal.m4
+ depending on the OS type.
+
+ IRIX 6.5 stub pthread support in libc is really annoying. The
+ pthread_mutex_lock function returns ENOSYS for a program not linked
+ against -lpthread. No link-time failure, no weak symbols, etc.
+ The C library doesn't provide pthread_once; we can use weak
+ reference support for that.
+
+ If weak references are not available, then for now, we assume that
+ the pthread support routines will always be available -- either the
+ real thing, or functional stubs that merely prohibit creating
+ threads.
+
+ If we find a platform with non-functional stubs and no weak
+ references, we may have to resort to some hack like dlsym on the
+ symbol tables of the current process. */
+
+#if defined(HAVE_PRAGMA_WEAK_REF) && !defined(NO_WEAK_PTHREADS)
+# define USE_CONDITIONAL_PTHREADS
+#endif
+
+#ifdef USE_CONDITIONAL_PTHREADS
+
+/* Can't rely on useful stubs -- see above regarding Solaris. */
+typedef struct {
+ pthread_once_t o;
+ k5_os_nothread_once_t n;
+} k5_once_t;
+# define K5_ONCE_INIT { PTHREAD_ONCE_INIT, K5_OS_NOTHREAD_ONCE_INIT }
+
+int k5_once(k5_once_t *once, void (*fn)(void));
+#else
+
+/* no pragma weak support */
+
+typedef pthread_once_t k5_once_t;
+# define K5_ONCE_INIT PTHREAD_ONCE_INIT
+# define k5_once pthread_once
+
+#endif
+
+#if defined(__mips) && defined(__sgi) && (defined(_SYSTYPE_SVR4) || defined(__SYSTYPE_SVR4__))
+# ifndef HAVE_PRAGMA_WEAK_REF
+# if defined(__GNUC__) && __GNUC__ < 3
+# error "Please update to a newer gcc with weak symbol support, or switch to native cc, reconfigure and recompile."
+# else
+# error "Weak reference support is required"
+# endif
+# endif
+#endif
+
+typedef pthread_mutex_t k5_os_mutex;
+# define K5_OS_MUTEX_PARTIAL_INITIALIZER \
+ PTHREAD_MUTEX_INITIALIZER
+
+#ifdef USE_CONDITIONAL_PTHREADS
+
+# define k5_os_mutex_finish_init(M) (0)
+int k5_os_mutex_init(k5_os_mutex *m);
+int k5_os_mutex_destroy(k5_os_mutex *m);
+int k5_os_mutex_lock(k5_os_mutex *m);
+int k5_os_mutex_unlock(k5_os_mutex *m);
+
+#else
+
+static inline int k5_os_mutex_finish_init(k5_os_mutex *m) { return 0; }
+# define k5_os_mutex_init(M) pthread_mutex_init((M), 0)
+# define k5_os_mutex_destroy(M) pthread_mutex_destroy((M))
+# define k5_os_mutex_lock(M) pthread_mutex_lock(M)
+# define k5_os_mutex_unlock(M) pthread_mutex_unlock(M)
+
+#endif /* is pthreads always available? */
+
+#elif defined _WIN32
+
+# define k5_once_t k5_os_nothread_once_t
+
+typedef struct {
+ HANDLE h;
+ int is_locked;
+} k5_os_mutex;
+
+# define K5_OS_MUTEX_PARTIAL_INITIALIZER { INVALID_HANDLE_VALUE, 0 }
+
+# define k5_os_mutex_finish_init(M) \
+ (assert((M)->h == INVALID_HANDLE_VALUE), \
+ ((M)->h = CreateMutex(NULL, FALSE, NULL)) ? 0 : GetLastError())
+# define k5_os_mutex_init(M) \
+ ((M)->is_locked = 0, \
+ ((M)->h = CreateMutex(NULL, FALSE, NULL)) ? 0 : GetLastError())
+# define k5_os_mutex_destroy(M) \
+ (CloseHandle((M)->h) ? ((M)->h = 0, 0) : GetLastError())
+# define k5_os_mutex_lock k5_win_mutex_lock
+
+static inline int k5_win_mutex_lock(k5_os_mutex *m)
+{
+ DWORD res;
+ res = WaitForSingleObject(m->h, INFINITE);
+ if (res == WAIT_FAILED)
+ return GetLastError();
+ /* Eventually these should be turned into some reasonable error
+ code. */
+ assert(res != WAIT_TIMEOUT);
+ assert(res != WAIT_ABANDONED);
+ assert(res == WAIT_OBJECT_0);
+ /* Avoid locking twice. */
+ assert(m->is_locked == 0);
+ m->is_locked = 1;
+ return 0;
+}
+
+# define k5_os_mutex_unlock(M) \
+ (assert((M)->is_locked == 1), \
+ (M)->is_locked = 0, \
+ ReleaseMutex((M)->h) ? 0 : GetLastError())
+
+#else
+
+# error "Thread support enabled, but thread system unknown"
+
+#endif
+
+typedef k5_os_mutex k5_mutex_t;
+#define K5_MUTEX_PARTIAL_INITIALIZER K5_OS_MUTEX_PARTIAL_INITIALIZER
+static inline int k5_mutex_init(k5_mutex_t *m)
+{
+ return k5_os_mutex_init(m);
+}
+static inline int k5_mutex_finish_init(k5_mutex_t *m)
+{
+ return k5_os_mutex_finish_init(m);
+}
+#define k5_mutex_destroy(M) \
+ (k5_os_mutex_destroy(M))
+
+static inline void k5_mutex_lock(k5_mutex_t *m)
+{
+ int r = k5_os_mutex_lock(m);
+ assert(r == 0);
+}
+
+static inline void k5_mutex_unlock(k5_mutex_t *m)
+{
+ int r = k5_os_mutex_unlock(m);
+ assert(r == 0);
+}
+
+#define k5_mutex_assert_locked(M) ((void)(M))
+#define k5_mutex_assert_unlocked(M) ((void)(M))
+#define k5_assert_locked k5_mutex_assert_locked
+#define k5_assert_unlocked k5_mutex_assert_unlocked
+
+/* Thread-specific data; implemented in a support file, because we'll
+ need to keep track of some global data for cleanup purposes.
+
+ Note that the callback function type is such that the C library
+ routine free() is a valid callback. */
+typedef enum {
+ K5_KEY_COM_ERR,
+ K5_KEY_GSS_KRB5_SET_CCACHE_OLD_NAME,
+ K5_KEY_GSS_KRB5_CCACHE_NAME,
+ K5_KEY_GSS_KRB5_ERROR_MESSAGE,
+ K5_KEY_GSS_SPNEGO_STATUS,
+#if defined(__MACH__) && defined(__APPLE__)
+ K5_KEY_IPC_CONNECTION_INFO,
+#endif
+ K5_KEY_MAX
+} k5_key_t;
+/* rename shorthand symbols for export */
+#define k5_key_register krb5int_key_register
+#define k5_getspecific krb5int_getspecific
+#define k5_setspecific krb5int_setspecific
+#define k5_key_delete krb5int_key_delete
+extern int k5_key_register(k5_key_t, void (*)(void *));
+extern void *k5_getspecific(k5_key_t);
+extern int k5_setspecific(k5_key_t, void *);
+extern int k5_key_delete(k5_key_t);
+
+extern int KRB5_CALLCONV krb5int_mutex_alloc (k5_mutex_t **);
+extern void KRB5_CALLCONV krb5int_mutex_free (k5_mutex_t *);
+extern void KRB5_CALLCONV krb5int_mutex_lock (k5_mutex_t *);
+extern void KRB5_CALLCONV krb5int_mutex_unlock (k5_mutex_t *);
+
+/* In time, many of the definitions above should move into the support
+ library, and this file should be greatly simplified. For type
+ definitions, that'll take some work, since other data structures
+ incorporate mutexes directly, and our mutex type is dependent on
+ configuration options and system attributes. For most functions,
+ though, it should be relatively easy.
+
+ For now, plugins should use the exported functions, and not the
+ above macros, and use krb5int_mutex_alloc for allocations. */
+#if defined(PLUGIN) || (defined(CONFIG_SMALL) && !defined(THREAD_SUPPORT_IMPL))
+#undef k5_mutex_lock
+#define k5_mutex_lock krb5int_mutex_lock
+#undef k5_mutex_unlock
+#define k5_mutex_unlock krb5int_mutex_unlock
+#endif
+
+#endif /* multiple inclusion? */
diff --git a/src/include/k5-tls.h b/src/include/k5-tls.h
new file mode 100644
index 000000000000..0661c05882b7
--- /dev/null
+++ b/src/include/k5-tls.h
@@ -0,0 +1,104 @@
+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/* include/k5-tls.h - internal pluggable interface for TLS */
+/*
+ * Copyright (C) 2014 by the Massachusetts Institute of Technology.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * This internal pluggable interface allows libkrb5 to load an in-tree module
+ * providing TLS support at runtime. It is currently tailored for the needs of
+ * the OpenSSL module as used for HTTP proxy support. As an internal
+ * interface, it can be changed to fit different implementations and consumers
+ * without regard for backward compatibility.
+ */
+
+#ifndef K5_TLS_H
+#define K5_TLS_H
+
+#include "k5-int.h"
+
+/* An abstract type for localauth module data. */
+typedef struct k5_tls_handle_st *k5_tls_handle;
+
+typedef enum {
+ DATA_READ, DONE, WANT_READ, WANT_WRITE, ERROR_TLS
+} k5_tls_status;
+
+/*
+ * Create a handle for fd, where the server certificate must match servername
+ * and be trusted according to anchors. anchors is a null-terminated list
+ * using the DIR:/FILE:/ENV: syntax borrowed from PKINIT. If anchors is null,
+ * use the system default trust anchors.
+ */
+typedef krb5_error_code
+(*k5_tls_setup_fn)(krb5_context context, SOCKET fd, const char *servername,
+ char **anchors, k5_tls_handle *handle_out);
+
+/*
+ * Write len bytes of data using TLS. Return DONE if writing is complete,
+ * WANT_READ or WANT_WRITE if the underlying socket must be readable or
+ * writable to continue, and ERROR_TLS if the TLS channel or underlying socket
+ * experienced an error. After WANT_READ or WANT_WRITE, the operation will be
+ * retried with the same arguments even if some data has already been written.
+ * (OpenSSL makes this contract easy to fulfill. For other implementations we
+ * might want to change it.)
+ */
+typedef k5_tls_status
+(*k5_tls_write_fn)(krb5_context context, k5_tls_handle handle,
+ const void *data, size_t len);
+
+/*
+ * Read up to data_size bytes of data using TLS. Return DATA_READ and set
+ * *len_out if any data is read. Return DONE if there is no more data to be
+ * read on the connection, WANT_READ or WANT_WRITE if the underlying socket
+ * must be readable or writable to continue, and ERROR_TLS if the TLS channel
+ * or underlying socket experienced an error.
+ *
+ * After DATA_READ, there may still be pending buffered data to read. The
+ * caller must call this method again with additional buffer space before
+ * selecting for reading on the underlying socket.
+ */
+typedef k5_tls_status
+(*k5_tls_read_fn)(krb5_context context, k5_tls_handle handle, void *data,
+ size_t data_size, size_t *len_out);
+
+/* Release a handle. Do not pass a null pointer. */
+typedef void
+(*k5_tls_free_handle_fn)(krb5_context context, k5_tls_handle handle);
+
+/* All functions are mandatory unless they are all null, in which case the
+ * caller should assume that TLS is unsupported. */
+typedef struct k5_tls_vtable_st {
+ k5_tls_setup_fn setup;
+ k5_tls_write_fn write;
+ k5_tls_read_fn read;
+ k5_tls_free_handle_fn free_handle;
+} *k5_tls_vtable;
+
+#endif /* K5_TLS_H */
diff --git a/src/include/k5-trace.h b/src/include/k5-trace.h
new file mode 100644
index 000000000000..c75e264e04f2
--- /dev/null
+++ b/src/include/k5-trace.h
@@ -0,0 +1,457 @@
+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/* include/k5-trace.h */
+/*
+ * Copyright (C) 2010 by the Massachusetts Institute of Technology.
+ * All rights reserved.
+ *
+ * Export of this software from the United States of America may
+ * require a specific license from the United States Government.
+ * It is the responsibility of any person or organization contemplating
+ * export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission. Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose. It is provided "as is" without express
+ * or implied warranty.
+ */
+
+/*
+ * This header contains trace macro definitions, which map trace points within
+ * the code to krb5int_trace() calls with descriptive text strings.
+ *
+ * A new trace macro must be defined in this file for each new location to
+ * be traced; the TRACE() macro should never be used directly. This keeps
+ * the tracing logic centralized in one place, to facilitate integration with
+ * alternate tracing backends such as DTrace.
+ *
+ * Trace logging is intended to aid power users in diagnosing configuration
+ * problems by showing what's going on behind the scenes of complex operations.
+ * Although trace logging is sometimes useful to developers, it is not intended
+ * as a replacement for a debugger, and it is not desirable to drown the user
+ * in output. Observe the following guidelines when adding trace points:
+ *
+ * - Avoid mentioning function or variable names in messages.
+ *
+ * - Try to convey what decisions are being made and what external inputs
+ * they are based on, not the process of making decisions.
+ *
+ * - It is generally not necessary to trace before returning an unrecoverable
+ * error. If an error code is unclear by itself, make it clearer with
+ * krb5_set_error_message().
+ *
+ * - Keep macros simple. Add format specifiers to krb5int_trace's formatter
+ * as necessary (and document them here) instead of transforming macro
+ * arguments.
+ *
+ * - Like printf, the trace formatter interface is not type-safe. Check your
+ * formats carefully. Cast integral arguments to the appropriate type if
+ * they do not already patch.
+ *
+ * The following specifiers are supported by the formatter (see the
+ * implementation in lib/krb5/os/trace.c for details):
+ *
+ * {int} int, in decimal
+ * {long} long, in decimal
+ * {str} const char *, display as C string
+ * {lenstr} size_t and const char *, as a counted string
+ * {hexlenstr} size_t and const char *, as hex bytes
+ * {hashlenstr} size_t and const char *, as four-character hex hash
+ * {raddr} struct remote_address *, show socket type, address, port
+ * {data} krb5_data *, display as counted string
+ * {hexdata} krb5_data *, display as hex bytes
+ * {errno} int, display as number/errorstring
+ * {kerr} krb5_error_code, display as number/errorstring
+ * {keyblock} const krb5_keyblock *, display enctype and hash of key
+ * {key} krb5_key, display enctype and hash of key
+ * {cksum} const krb5_checksum *, display cksumtype and hex checksum
+ * {princ} krb5_principal, unparse and display
+ * {ptype} krb5_int32, krb5_principal type, display name
+ * {patypes} krb5_pa_data **, display list of padata type numbers
+ * {etype} krb5_enctype, display shortest name of enctype
+ * {etypes} krb5_enctype *, display list of enctypes
+ * {ccache} krb5_ccache, display type:name
+ * {keytab} krb5_keytab, display name
+ * {creds} krb5_creds *, display clientprinc -> serverprinc
+ */
+
+#ifndef K5_TRACE_H
+#define K5_TRACE_H
+
+#ifdef DISABLE_TRACING
+#define TRACE(ctx, ...)
+#else
+
+void krb5int_trace(krb5_context context, const char *fmt, ...);
+
+/* Try to optimize away argument evaluation and function call when we're not
+ * tracing, if this source file knows the internals of the context. */
+#ifdef _KRB5_INT_H
+#define TRACE(ctx, ...) \
+ do { if (ctx->trace_callback != NULL) \
+ krb5int_trace(ctx, __VA_ARGS__); } while (0)
+#else
+#define TRACE(ctx, ...) krb5int_trace(ctx, __VA_ARGS__)
+#endif
+
+#endif /* DISABLE_TRACING */
+
+#define TRACE_CC_DESTROY(c, cache) \
+ TRACE(c, "Destroying ccache {ccache}", cache)
+#define TRACE_CC_GEN_NEW(c, cache) \
+ TRACE(c, "Generating new unique ccache based on {ccache}", cache)
+#define TRACE_CC_GET_CONFIG(c, cache, princ, key, data) \
+ TRACE(c, "Read config in {ccache} for {princ}: {str}: {data}", \
+ cache, princ, key, data)
+#define TRACE_CC_INIT(c, cache, princ) \
+ TRACE(c, "Initializing {ccache} with default princ {princ}", \
+ cache, princ)
+#define TRACE_CC_MOVE(c, src, dst) \
+ TRACE(c, "Moving contents of ccache {src} to {dst}", src, dst)
+#define TRACE_CC_NEW_UNIQUE(c, type) \
+ TRACE(c, "Resolving unique ccache of type {str}", type)
+#define TRACE_CC_REMOVE(c, cache, creds) \
+ TRACE(c, "Removing {creds} from {ccache}", creds, cache)
+#define TRACE_CC_RETRIEVE(c, cache, creds, ret) \
+ TRACE(c, "Retrieving {creds} from {ccache} with result: {kerr}", \
+ creds, cache, ret)
+#define TRACE_CC_RETRIEVE_REF(c, cache, creds, ret) \
+ TRACE(c, "Retrying {creds} with result: {kerr}", creds, ret)
+#define TRACE_CC_SET_CONFIG(c, cache, princ, key, data) \
+ TRACE(c, "Storing config in {ccache} for {princ}: {str}: {data}", \
+ cache, princ, key, data)
+#define TRACE_CC_STORE(c, cache, creds) \
+ TRACE(c, "Storing {creds} in {ccache}", creds, cache)
+#define TRACE_CC_STORE_TKT(c, cache, creds) \
+ TRACE(c, "Also storing {creds} based on ticket", creds)
+
+#define TRACE_CCSELECT_VTINIT_FAIL(c, ret) \
+ TRACE(c, "ccselect module failed to init vtable: {kerr}", ret)
+#define TRACE_CCSELECT_INIT_FAIL(c, name, ret) \
+ TRACE(c, "ccselect module {str} failed to init: {kerr}", name, ret)
+#define TRACE_CCSELECT_MODCHOICE(c, name, server, cache, princ) \
+ TRACE(c, "ccselect module {str} chose cache {ccache} with client " \
+ "principal {princ} for server principal {princ}", name, cache, \
+ princ, server)
+#define TRACE_CCSELECT_MODNOTFOUND(c, name, server, princ) \
+ TRACE(c, "ccselect module {str} chose client principal {princ} " \
+ "for server principal {princ} but found no cache", name, princ, \
+ server)
+#define TRACE_CCSELECT_MODFAIL(c, name, ret, server) \
+ TRACE(c, "ccselect module {str} yielded error {kerr} for server " \
+ "principal {princ}", name, ret, server)
+#define TRACE_CCSELECT_NOTFOUND(c, server) \
+ TRACE(c, "ccselect can't find appropriate cache for server " \
+ "principal {princ}", server)
+#define TRACE_CCSELECT_DEFAULT(c, cache, server) \
+ TRACE(c, "ccselect choosing default cache {ccache} for server " \
+ "principal {princ}", cache, server)
+
+#define TRACE_FAST_ARMOR_CCACHE(c, ccache_name) \
+ TRACE(c, "FAST armor ccache: {str}", ccache_name)
+#define TRACE_FAST_ARMOR_CCACHE_KEY(c, keyblock) \
+ TRACE(c, "Armor ccache sesion key: {keyblock}", keyblock)
+#define TRACE_FAST_ARMOR_KEY(c, keyblock) \
+ TRACE(c, "FAST armor key: {keyblock}", keyblock)
+#define TRACE_FAST_CCACHE_CONFIG(c) \
+ TRACE(c, "Using FAST due to armor ccache negotiation result")
+#define TRACE_FAST_DECODE(c) \
+ TRACE(c, "Decoding FAST response")
+#define TRACE_FAST_ENCODE(c) \
+ TRACE(c, "Encoding request body and padata into FAST request")
+#define TRACE_FAST_NEGO(c, avail) \
+ TRACE(c, "FAST negotiation: {str}available", (avail) ? "" : "un")
+#define TRACE_FAST_PADATA_UPGRADE(c) \
+ TRACE(c, "Upgrading to FAST due to presence of PA_FX_FAST in reply")
+#define TRACE_FAST_REPLY_KEY(c, keyblock) \
+ TRACE(c, "FAST reply key: {keyblock}", keyblock)
+#define TRACE_FAST_REQUIRED(c) \
+ TRACE(c, "Using FAST due to KRB5_FAST_REQUIRED flag")
+
+#define TRACE_GIC_PWD_CHANGED(c) \
+ TRACE(c, "Getting initial TGT with changed password")
+#define TRACE_GIC_PWD_CHANGEPW(c, tries) \
+ TRACE(c, "Attempting password change; {int} tries remaining", tries)
+#define TRACE_GIC_PWD_EXPIRED(c) \
+ TRACE(c, "Principal expired; getting changepw ticket")
+#define TRACE_GIC_PWD_MASTER(c) \
+ TRACE(c, "Retrying AS request with master KDC")
+
+#define TRACE_GSS_CLIENT_KEYTAB_FAIL(c, ret) \
+ TRACE(c, "Unable to resolve default client keytab: {kerr}", ret)
+
+#define TRACE_ENCTYPE_LIST_UNKNOWN(c, profvar, name) \
+ TRACE(c, "Unrecognized enctype name in {str}: {str}", profvar, name)
+
+#define TRACE_HOSTREALM_VTINIT_FAIL(c, ret) \
+ TRACE(c, "hostrealm module failed to init vtable: {kerr}", ret)
+#define TRACE_HOSTREALM_INIT_FAIL(c, name, ret) \
+ TRACE(c, "hostrealm module {str} failed to init: {kerr}", name, ret)
+
+#define TRACE_INIT_CREDS(c, princ) \
+ TRACE(c, "Getting initial credentials for {princ}", princ)
+#define TRACE_INIT_CREDS_AS_KEY_GAK(c, keyblock) \
+ TRACE(c, "AS key obtained from gak_fct: {keyblock}", keyblock)
+#define TRACE_INIT_CREDS_AS_KEY_PREAUTH(c, keyblock) \
+ TRACE(c, "AS key determined by preauth: {keyblock}", keyblock)
+#define TRACE_INIT_CREDS_DECRYPTED_REPLY(c, keyblock) \
+ TRACE(c, "Decrypted AS reply; session key is: {keyblock}", keyblock)
+#define TRACE_INIT_CREDS_ERROR_REPLY(c, code) \
+ TRACE(c, "Received error from KDC: {kerr}", code)
+#define TRACE_INIT_CREDS_GAK(c, salt, s2kparams) \
+ TRACE(c, "Getting AS key, salt \"{data}\", params \"{data}\"", \
+ salt, s2kparams)
+#define TRACE_INIT_CREDS_KEYTAB_LOOKUP(c, etypes) \
+ TRACE(c, "Looked up etypes in keytab: {etypes}", etypes)
+#define TRACE_INIT_CREDS_KEYTAB_LOOKUP_FAILED(c, code) \
+ TRACE(c, "Couldn't lookup etypes in keytab: {kerr}", code)
+#define TRACE_INIT_CREDS_PREAUTH_DECRYPT_FAIL(c, code) \
+ TRACE(c, "Decrypt with preauth AS key failed: {kerr}", code)
+#define TRACE_INIT_CREDS_RESTART_FAST(c) \
+ TRACE(c, "Restarting to upgrade to FAST")
+#define TRACE_INIT_CREDS_RESTART_PREAUTH_FAILED(c) \
+ TRACE(c, "Restarting due to PREAUTH_FAILED from FAST negotiation")
+#define TRACE_INIT_CREDS_REFERRAL(c, realm) \
+ TRACE(c, "Following referral to realm {data}", realm)
+#define TRACE_INIT_CREDS_RETRY_TCP(c) \
+ TRACE(c, "Request or response is too big for UDP; retrying with TCP")
+#define TRACE_INIT_CREDS_SALT_PRINC(c, salt) \
+ TRACE(c, "Salt derived from principal: {data}", salt)
+#define TRACE_INIT_CREDS_SERVICE(c, service) \
+ TRACE(c, "Setting initial creds service to {str}", service)
+
+#define TRACE_KT_GET_ENTRY(c, keytab, princ, vno, enctype, err) \
+ TRACE(c, "Retrieving {princ} from {keytab} (vno {int}, enctype {etype}) " \
+ "with result: {kerr}", princ, keytab, (int) vno, enctype, err)
+
+#define TRACE_LOCALAUTH_INIT_CONFLICT(c, type, oldname, newname) \
+ TRACE(c, "Ignoring localauth module {str} because it conflicts " \
+ "with an2ln type {str} from module {str}", newname, type, oldname)
+#define TRACE_LOCALAUTH_VTINIT_FAIL(c, ret) \
+ TRACE(c, "localauth module failed to init vtable: {kerr}", ret)
+#define TRACE_LOCALAUTH_INIT_FAIL(c, name, ret) \
+ TRACE(c, "localauth module {str} failed to init: {kerr}", name, ret)
+
+#define TRACE_MK_REP(c, ctime, cusec, subkey, seqnum) \
+ TRACE(c, "Creating AP-REP, time {long}.{int}, subkey {keyblock}, " \
+ "seqnum {int}", (long) ctime, (int) cusec, subkey, (int) seqnum)
+
+#define TRACE_MK_REQ(c, creds, seqnum, subkey, sesskeyblock) \
+ TRACE(c, "Creating authenticator for {creds}, seqnum {int}, " \
+ "subkey {key}, session key {keyblock}", creds, (int) seqnum, \
+ subkey, sesskeyblock)
+#define TRACE_MK_REQ_ETYPES(c, etypes) \
+ TRACE(c, "Negotiating for enctypes in authenticator: {etypes}", etypes)
+
+#define TRACE_MSPAC_VERIFY_FAIL(c, err) \
+ TRACE(c, "PAC checksum verification failed: {kerr}", err)
+#define TRACE_MSPAC_DISCARD_UNVERF(c) \
+ TRACE(c, "Filtering out unverified MS PAC")
+
+#define TRACE_PREAUTH_CONFLICT(c, name1, name2, patype) \
+ TRACE(c, "Preauth module {str} conflicts with module {str} for pa " \
+ "type {int}", name1, name2, (int) patype)
+#define TRACE_PREAUTH_COOKIE(c, len, data) \
+ TRACE(c, "Received cookie: {lenstr}", (size_t) len, data)
+#define TRACE_PREAUTH_ENC_TS_KEY_GAK(c, keyblock) \
+ TRACE(c, "AS key obtained for encrypted timestamp: {keyblock}", keyblock)
+#define TRACE_PREAUTH_ENC_TS(c, sec, usec, plain, enc) \
+ TRACE(c, "Encrypted timestamp (for {long}.{int}): plain {hexdata}, " \
+ "encrypted {hexdata}", (long) sec, (int) usec, plain, enc)
+#define TRACE_PREAUTH_ETYPE_INFO(c, etype, salt, s2kparams) \
+ TRACE(c, "Selected etype info: etype {etype}, salt \"{data}\", " \
+ "params \"{data}\"", etype, salt, s2kparams)
+#define TRACE_PREAUTH_INFO_FAIL(c, patype, code) \
+ TRACE(c, "Preauth builtin info function failure, type={int}: {kerr}", \
+ (int) patype, code)
+#define TRACE_PREAUTH_INPUT(c, padata) \
+ TRACE(c, "Processing preauth types: {patypes}", padata)
+#define TRACE_PREAUTH_OUTPUT(c, padata) \
+ TRACE(c, "Produced preauth for next request: {patypes}", padata)
+#define TRACE_PREAUTH_PROCESS(c, name, patype, real, code) \
+ TRACE(c, "Preauth module {str} ({int}) ({str}) returned: " \
+ "{kerr}", name, (int) patype, real ? "real" : "info", code)
+#define TRACE_PREAUTH_SAM_KEY_GAK(c, keyblock) \
+ TRACE(c, "AS key obtained for SAM: {keyblock}", keyblock)
+#define TRACE_PREAUTH_SALT(c, salt, patype) \
+ TRACE(c, "Received salt \"{data}\" via padata type {int}", salt, \
+ (int) patype)
+#define TRACE_PREAUTH_SKIP(c, name, patype) \
+ TRACE(c, "Skipping previously used preauth module {str} ({int})", \
+ name, (int) patype)
+#define TRACE_PREAUTH_TRYAGAIN_INPUT(c, padata) \
+ TRACE(c, "Preauth tryagain input types: {patypes}", padata)
+#define TRACE_PREAUTH_TRYAGAIN_OUTPUT(c, padata) \
+ TRACE(c, "Followup preauth for next request: {patypes}", padata)
+
+#define TRACE_PROFILE_ERR(c,subsection, section, retval) \
+ TRACE(c, "Bad value of {str} from [{str}] in conf file: {kerr}", \
+ subsection, section, retval)
+
+#define TRACE_RD_REP(c, ctime, cusec, subkey, seqnum) \
+ TRACE(c, "Read AP-REP, time {long}.{int}, subkey {keyblock}, " \
+ "seqnum {int}", (long) ctime, (int) cusec, subkey, (int) seqnum)
+#define TRACE_RD_REP_DCE(c, ctime, cusec, seqnum) \
+ TRACE(c, "Read DCE-style AP-REP, time {long}.{int}, seqnum {int}", \
+ (long) ctime, (int) cusec, (int) seqnum)
+
+#define TRACE_RD_REQ_DECRYPT_ANY(c, princ, keyblock) \
+ TRACE(c, "Decrypted AP-REQ with server principal {princ}: " \
+ "{keyblock}", princ, keyblock)
+#define TRACE_RD_REQ_DECRYPT_SPECIFIC(c, princ, keyblock) \
+ TRACE(c, "Decrypted AP-REQ with specified server principal {princ}: " \
+ "{keyblock}", princ, keyblock)
+#define TRACE_RD_REQ_DECRYPT_FAIL(c, err) \
+ TRACE(c, "Failed to decrypt AP-REQ ticket: {kerr}", err)
+#define TRACE_RD_REQ_NEGOTIATED_ETYPE(c, etype) \
+ TRACE(c, "Negotiated enctype based on authenticator: {etype}", \
+ etype)
+#define TRACE_RD_REQ_SUBKEY(c, keyblock) \
+ TRACE(c, "Authenticator contains subkey: {keyblock}", keyblock)
+#define TRACE_RD_REQ_TICKET(c, client, server, keyblock) \
+ TRACE(c, "AP-REQ ticket: {princ} -> {princ}, session key {keyblock}", \
+ client, server, keyblock)
+
+#define TRACE_SENDTO_KDC_ERROR_SET_MESSAGE(c, raddr, err) \
+ TRACE(c, "Error preparing message to send to {raddr}: {errno}", \
+ raddr, err)
+#define TRACE_SENDTO_KDC(c, len, rlm, master, tcp) \
+ TRACE(c, "Sending request ({int} bytes) to {data}{str}{str}", len, \
+ rlm, (master) ? " (master)" : "", (tcp) ? " (tcp only)" : "")
+#define TRACE_SENDTO_KDC_MASTER(c, master) \
+ TRACE(c, "Response was{str} from master KDC", (master) ? "" : " not")
+#define TRACE_SENDTO_KDC_RESOLVING(c, hostname) \
+ TRACE(c, "Resolving hostname {str}", hostname)
+#define TRACE_SENDTO_KDC_RESPONSE(c, len, raddr) \
+ TRACE(c, "Received answer ({int} bytes) from {raddr}", len, raddr)
+#define TRACE_SENDTO_KDC_HTTPS_ERROR_CONNECT(c, raddr) \
+ TRACE(c, "HTTPS error connecting to {raddr}", raddr)
+#define TRACE_SENDTO_KDC_HTTPS_ERROR_RECV(c, raddr) \
+ TRACE(c, "HTTPS error receiving from {raddr}", raddr)
+#define TRACE_SENDTO_KDC_HTTPS_ERROR_SEND(c, raddr) \
+ TRACE(c, "HTTPS error sending to {raddr}", raddr)
+#define TRACE_SENDTO_KDC_HTTPS_SEND(c, raddr) \
+ TRACE(c, "Sending HTTPS request to {raddr}", raddr)
+#define TRACE_SENDTO_KDC_HTTPS_ERROR(c, errs) \
+ TRACE(c, "HTTPS error: {str}", errs)
+#define TRACE_SENDTO_KDC_TCP_CONNECT(c, raddr) \
+ TRACE(c, "Initiating TCP connection to {raddr}", raddr)
+#define TRACE_SENDTO_KDC_TCP_DISCONNECT(c, raddr) \
+ TRACE(c, "Terminating TCP connection to {raddr}", raddr)
+#define TRACE_SENDTO_KDC_TCP_ERROR_CONNECT(c, raddr, err) \
+ TRACE(c, "TCP error connecting to {raddr}: {errno}", raddr, err)
+#define TRACE_SENDTO_KDC_TCP_ERROR_RECV(c, raddr, err) \
+ TRACE(c, "TCP error receiving from {raddr}: {errno}", raddr, err)
+#define TRACE_SENDTO_KDC_TCP_ERROR_RECV_LEN(c, raddr, err) \
+ TRACE(c, "TCP error receiving from {raddr}: {errno}", raddr, err)
+#define TRACE_SENDTO_KDC_TCP_ERROR_SEND(c, raddr, err) \
+ TRACE(c, "TCP error sending to {raddr}: {errno}", raddr, err)
+#define TRACE_SENDTO_KDC_TCP_SEND(c, raddr) \
+ TRACE(c, "Sending TCP request to {raddr}", raddr)
+#define TRACE_SENDTO_KDC_UDP_ERROR_RECV(c, raddr, err) \
+ TRACE(c, "UDP error receiving from {raddr}: {errno}", raddr, err)
+#define TRACE_SENDTO_KDC_UDP_ERROR_SEND_INITIAL(c, raddr, err) \
+ TRACE(c, "UDP error sending to {raddr}: {errno}", raddr, err)
+#define TRACE_SENDTO_KDC_UDP_ERROR_SEND_RETRY(c, raddr, err) \
+ TRACE(c, "UDP error sending to {raddr}: {errno}", raddr, err)
+#define TRACE_SENDTO_KDC_UDP_SEND_INITIAL(c, raddr) \
+ TRACE(c, "Sending initial UDP request to {raddr}", raddr)
+#define TRACE_SENDTO_KDC_UDP_SEND_RETRY(c, raddr) \
+ TRACE(c, "Sending retry UDP request to {raddr}", raddr)
+
+#define TRACE_SEND_TGS_ETYPES(c, etypes) \
+ TRACE(c, "etypes requested in TGS request: {etypes}", etypes)
+#define TRACE_SEND_TGS_SUBKEY(c, keyblock) \
+ TRACE(c, "Generated subkey for TGS request: {keyblock}", keyblock)
+
+#define TRACE_TGS_REPLY(c, client, server, keyblock) \
+ TRACE(c, "TGS reply is for {princ} -> {princ} with session key " \
+ "{keyblock}", client, server, keyblock)
+#define TRACE_TGS_REPLY_DECODE_SESSION(c, keyblock) \
+ TRACE(c, "TGS reply didn't decode with subkey; trying session key " \
+ "({keyblock)}", keyblock)
+
+#define TRACE_TLS_ERROR(c, errs) \
+ TRACE(c, "TLS error: {str}", errs)
+#define TRACE_TLS_NO_REMOTE_CERTIFICATE(c) \
+ TRACE(c, "TLS server certificate not received")
+#define TRACE_TLS_CERT_ERROR(c, depth, namelen, name, err, errs) \
+ TRACE(c, "TLS certificate error at {int} ({lenstr}): {int} ({str})", \
+ depth, namelen, name, err, errs)
+#define TRACE_TLS_SERVER_NAME_MISMATCH(c, hostname) \
+ TRACE(c, "TLS certificate name mismatch: server certificate is " \
+ "not for \"{str}\"", hostname)
+#define TRACE_TLS_SERVER_NAME_MATCH(c, hostname) \
+ TRACE(c, "TLS certificate name matched \"{str}\"", hostname)
+
+#define TRACE_TKT_CREDS(c, creds, cache) \
+ TRACE(c, "Getting credentials {creds} using ccache {ccache}", \
+ creds, cache)
+#define TRACE_TKT_CREDS_ADVANCE(c, realm) \
+ TRACE(c, "Received TGT for {data}; advancing current realm", realm)
+#define TRACE_TKT_CREDS_CACHED_INTERMEDIATE_TGT(c, tgt) \
+ TRACE(c, "Found cached TGT for intermediate realm: {creds}", tgt)
+#define TRACE_TKT_CREDS_CACHED_SERVICE_TGT(c, tgt) \
+ TRACE(c, "Found cached TGT for service realm: {creds}", tgt)
+#define TRACE_TKT_CREDS_CLOSER_REALM(c, realm) \
+ TRACE(c, "Trying next closer realm in path: {data}", realm)
+#define TRACE_TKT_CREDS_COMPLETE(c, princ) \
+ TRACE(c, "Received creds for desired service {princ}", princ)
+#define TRACE_TKT_CREDS_FALLBACK(c, realm) \
+ TRACE(c, "Local realm referral failed; trying fallback realm {data}", \
+ realm)
+#define TRACE_TKT_CREDS_LOCAL_TGT(c, tgt) \
+ TRACE(c, "Starting with TGT for client realm: {creds}", tgt)
+#define TRACE_TKT_CREDS_NON_TGT(c, princ) \
+ TRACE(c, "Received non-TGT referral response ({princ}); trying " \
+ "again without referrals", princ)
+#define TRACE_TKT_CREDS_OFFPATH(c, realm) \
+ TRACE(c, "Received TGT for offpath realm {data}", realm)
+#define TRACE_TKT_CREDS_REFERRAL(c, princ) \
+ TRACE(c, "Following referral TGT {princ}", princ)
+#define TRACE_TKT_CREDS_REFERRAL_REALM(c, princ) \
+ TRACE(c, "Server has referral realm; starting with {princ}", princ)
+#define TRACE_TKT_CREDS_RESPONSE_CODE(c, code) \
+ TRACE(c, "TGS request result: {kerr}", code)
+#define TRACE_TKT_CREDS_RETRY_TCP(c) \
+ TRACE(c, "Request or response is too big for UDP; retrying with TCP")
+#define TRACE_TKT_CREDS_SAME_REALM_TGT(c, realm) \
+ TRACE(c, "Received TGT referral back to same realm ({data}); trying " \
+ "again without referrals", realm)
+#define TRACE_TKT_CREDS_SERVICE_REQ(c, princ, referral) \
+ TRACE(c, "Requesting tickets for {princ}, referrals {str}", princ, \
+ (referral) ? "on" : "off")
+#define TRACE_TKT_CREDS_TARGET_TGT(c, princ) \
+ TRACE(c, "Received TGT for service realm: {princ}", princ)
+#define TRACE_TKT_CREDS_TARGET_TGT_OFFPATH(c, princ) \
+ TRACE(c, "Received TGT for service realm: {princ}", princ)
+#define TRACE_TKT_CREDS_TGT_REQ(c, next, cur) \
+ TRACE(c, "Requesting TGT {princ} using TGT {princ}", next, cur)
+#define TRACE_TKT_CREDS_WRONG_ENCTYPE(c) \
+ TRACE(c, "Retrying TGS request with desired service ticket enctypes")
+
+#define TRACE_TXT_LOOKUP_NOTFOUND(c, host) \
+ TRACE(c, "TXT record {str} not found", host)
+#define TRACE_TXT_LOOKUP_SUCCESS(c, host, realm) \
+ TRACE(c, "TXT record {str} found: {str}", host, realm)
+
+#define TRACE_CHECK_REPLY_SERVER_DIFFERS(c, request, reply) \
+ TRACE(c, "Reply server {princ} differs from requested {princ}", \
+ reply, request)
+
+#define TRACE_GET_CRED_VIA_TKT_EXT(c, request, reply, kdcoptions) \
+ TRACE(c, "Get cred via TGT {princ} after requesting {princ} " \
+ "(canonicalize {str})", \
+ reply, request, (kdcoptions & KDC_OPT_CANONICALIZE) ? "on" : "off")
+#define TRACE_GET_CRED_VIA_TKT_EXT_RETURN(c, ret) \
+ TRACE(c, "Got cred; {kerr}", ret)
+
+#endif /* K5_TRACE_H */
diff --git a/src/include/k5-unicode.h b/src/include/k5-unicode.h
new file mode 100644
index 000000000000..77f5facb0bad
--- /dev/null
+++ b/src/include/k5-unicode.h
@@ -0,0 +1,130 @@
+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/*
+ * Copyright (C) 2008 by the Massachusetts Institute of Technology,
+ * Cambridge, MA, USA. All Rights Reserved.
+ *
+ * This software is being provided to you, the LICENSEE, by the
+ * Massachusetts Institute of Technology (M.I.T.) under the following
+ * license. By obtaining, using and/or copying this software, you agree
+ * that you have read, understood, and will comply with these terms and
+ * conditions:
+ *
+ * Export of this software from the United States of America may
+ * require a specific license from the United States Government.
+ * It is the responsibility of any person or organization contemplating
+ * export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify and distribute
+ * this software and its documentation for any purpose and without fee or
+ * royalty is hereby granted, provided that you agree to comply with the
+ * following copyright notice and statements, including the disclaimer, and
+ * that the same appear on ALL copies of the software and documentation,
+ * including modifications that you make for internal use or for
+ * distribution:
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS", AND M.I.T. MAKES NO REPRESENTATIONS
+ * OR WARRANTIES, EXPRESS OR IMPLIED. By way of example, but not
+ * limitation, M.I.T. MAKES NO REPRESENTATIONS OR WARRANTIES OF
+ * MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF
+ * THE LICENSED SOFTWARE OR DOCUMENTATION WILL NOT INFRINGE ANY THIRD PARTY
+ * PATENTS, COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS.
+ *
+ * The name of the Massachusetts Institute of Technology or M.I.T. may NOT
+ * be used in advertising or publicity pertaining to distribution of the
+ * software. Title to copyright in this software and any associated
+ * documentation shall at all times remain with M.I.T., and USER agrees to
+ * preserve same.
+ *
+ * Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ */
+/*
+ * Copyright 1998-2008 The OpenLDAP Foundation.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted only as authorized by the OpenLDAP
+ * Public License.
+ *
+ * A copy of this license is available in file LICENSE in the
+ * top-level directory of the distribution or, alternatively, at
+ * <http://www.OpenLDAP.org/license.html>.
+ */
+/*
+ * Copyright (C) 2000 Novell, Inc. All Rights Reserved.
+ *
+ * THIS WORK IS SUBJECT TO U.S. AND INTERNATIONAL COPYRIGHT LAWS AND TREATIES.
+ * USE, MODIFICATION, AND REDISTRIBUTION OF THIS WORK IS SUBJECT TO VERSION
+ * 2.0.1 OF THE OPENLDAP PUBLIC LICENSE, A COPY OF WHICH IS AVAILABLE AT
+ * HTTP://WWW.OPENLDAP.ORG/LICENSE.HTML OR IN THE FILE "LICENSE" IN THE
+ * TOP-LEVEL DIRECTORY OF THE DISTRIBUTION. ANY USE OR EXPLOITATION OF THIS
+ * WORK OTHER THAN AS AUTHORIZED IN VERSION 2.0.1 OF THE OPENLDAP PUBLIC
+ * LICENSE, OR OTHER PRIOR WRITTEN CONSENT FROM NOVELL, COULD SUBJECT THE
+ * PERPETRATOR TO CRIMINAL AND CIVIL LIABILITY.
+ */
+
+/* This work is part of OpenLDAP Software <http://www.openldap.org/>. */
+
+#ifndef K5_UNICODE_H
+#define K5_UNICODE_H
+
+#include "autoconf.h"
+
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+
+#include "k5-utf8.h"
+
+typedef krb5_ucs4 krb5_unicode;
+
+int krb5int_ucstrncmp(
+ const krb5_unicode *,
+ const krb5_unicode *,
+ size_t);
+
+int krb5int_ucstrncasecmp(
+ const krb5_unicode *,
+ const krb5_unicode *,
+ size_t);
+
+krb5_unicode *krb5int_ucstrnchr(
+ const krb5_unicode *,
+ size_t,
+ krb5_unicode);
+
+krb5_unicode *krb5int_ucstrncasechr(
+ const krb5_unicode *,
+ size_t,
+ krb5_unicode);
+
+void krb5int_ucstr2upper(
+ krb5_unicode *,
+ size_t);
+
+#define KRB5_UTF8_NOCASEFOLD 0x0U
+#define KRB5_UTF8_CASEFOLD 0x1U
+#define KRB5_UTF8_ARG1NFC 0x2U
+#define KRB5_UTF8_ARG2NFC 0x4U
+#define KRB5_UTF8_APPROX 0x8U
+
+krb5_error_code krb5int_utf8_normalize(
+ const krb5_data *,
+ krb5_data **,
+ unsigned);
+
+int krb5int_utf8_normcmp(
+ const krb5_data *,
+ const krb5_data *,
+ unsigned);
+
+#endif /* K5_UNICODE_H */
diff --git a/src/include/k5-utf8.h b/src/include/k5-utf8.h
new file mode 100644
index 000000000000..22f433c8e981
--- /dev/null
+++ b/src/include/k5-utf8.h
@@ -0,0 +1,223 @@
+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/*
+ * Copyright (C) 2008 by the Massachusetts Institute of Technology,
+ * Cambridge, MA, USA. All Rights Reserved.
+ *
+ * This software is being provided to you, the LICENSEE, by the
+ * Massachusetts Institute of Technology (M.I.T.) under the following
+ * license. By obtaining, using and/or copying this software, you agree
+ * that you have read, understood, and will comply with these terms and
+ * conditions:
+ *
+ * Export of this software from the United States of America may
+ * require a specific license from the United States Government.
+ * It is the responsibility of any person or organization contemplating
+ * export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify and distribute
+ * this software and its documentation for any purpose and without fee or
+ * royalty is hereby granted, provided that you agree to comply with the
+ * following copyright notice and statements, including the disclaimer, and
+ * that the same appear on ALL copies of the software and documentation,
+ * including modifications that you make for internal use or for
+ * distribution:
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS", AND M.I.T. MAKES NO REPRESENTATIONS
+ * OR WARRANTIES, EXPRESS OR IMPLIED. By way of example, but not
+ * limitation, M.I.T. MAKES NO REPRESENTATIONS OR WARRANTIES OF
+ * MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF
+ * THE LICENSED SOFTWARE OR DOCUMENTATION WILL NOT INFRINGE ANY THIRD PARTY
+ * PATENTS, COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS.
+ *
+ * The name of the Massachusetts Institute of Technology or M.I.T. may NOT
+ * be used in advertising or publicity pertaining to distribution of the
+ * software. Title to copyright in this software and any associated
+ * documentation shall at all times remain with M.I.T., and USER agrees to
+ * preserve same.
+ *
+ * Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ */
+/*
+ * Copyright 1998-2008 The OpenLDAP Foundation.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted only as authorized by the OpenLDAP
+ * Public License.
+ *
+ * A copy of this license is available in file LICENSE in the
+ * top-level directory of the distribution or, alternatively, at
+ * <http://www.OpenLDAP.org/license.html>.
+ */
+/*
+ * Copyright (C) 2000 Novell, Inc. All Rights Reserved.
+ *
+ * THIS WORK IS SUBJECT TO U.S. AND INTERNATIONAL COPYRIGHT LAWS AND TREATIES.
+ * USE, MODIFICATION, AND REDISTRIBUTION OF THIS WORK IS SUBJECT TO VERSION
+ * 2.0.1 OF THE OPENLDAP PUBLIC LICENSE, A COPY OF WHICH IS AVAILABLE AT
+ * HTTP://WWW.OPENLDAP.ORG/LICENSE.HTML OR IN THE FILE "LICENSE" IN THE
+ * TOP-LEVEL DIRECTORY OF THE DISTRIBUTION. ANY USE OR EXPLOITATION OF THIS
+ * WORK OTHER THAN AS AUTHORIZED IN VERSION 2.0.1 OF THE OPENLDAP PUBLIC
+ * LICENSE, OR OTHER PRIOR WRITTEN CONSENT FROM NOVELL, COULD SUBJECT THE
+ * PERPETRATOR TO CRIMINAL AND CIVIL LIABILITY.
+ */
+/* This work is part of OpenLDAP Software <http://www.openldap.org/>. */
+
+#ifndef K5_UTF8_H
+#define K5_UTF8_H
+
+#include "k5-platform.h"
+
+typedef uint16_t krb5_ucs2;
+typedef uint32_t krb5_ucs4;
+
+#define KRB5_MAX_UTF8_LEN (sizeof(krb5_ucs2) * 3/2)
+
+int krb5int_utf8_to_ucs2(const char *p, krb5_ucs2 *out);
+size_t krb5int_ucs2_to_utf8(krb5_ucs2 c, char *buf);
+
+int krb5int_utf8_to_ucs4(const char *p, krb5_ucs4 *out);
+size_t krb5int_ucs4_to_utf8(krb5_ucs4 c, char *buf);
+
+int
+krb5int_ucs2s_to_utf8s(const krb5_ucs2 *ucs2s,
+ char **utf8s,
+ size_t *utf8slen);
+
+int
+krb5int_ucs2cs_to_utf8s(const krb5_ucs2 *ucs2s,
+ size_t ucs2slen,
+ char **utf8s,
+ size_t *utf8slen);
+
+int
+krb5int_ucs2les_to_utf8s(const unsigned char *ucs2les,
+ char **utf8s,
+ size_t *utf8slen);
+
+int
+krb5int_ucs2lecs_to_utf8s(const unsigned char *ucs2les,
+ size_t ucs2leslen,
+ char **utf8s,
+ size_t *utf8slen);
+
+int
+krb5int_utf8s_to_ucs2s(const char *utf8s,
+ krb5_ucs2 **ucs2s,
+ size_t *ucs2chars);
+
+int
+krb5int_utf8cs_to_ucs2s(const char *utf8s,
+ size_t utf8slen,
+ krb5_ucs2 **ucs2s,
+ size_t *ucs2chars);
+
+int
+krb5int_utf8s_to_ucs2les(const char *utf8s,
+ unsigned char **ucs2les,
+ size_t *ucs2leslen);
+
+int
+krb5int_utf8cs_to_ucs2les(const char *utf8s,
+ size_t utf8slen,
+ unsigned char **ucs2les,
+ size_t *ucs2leslen);
+
+/* returns the number of bytes in the UTF-8 string */
+size_t krb5int_utf8_bytes(const char *);
+/* returns the number of UTF-8 characters in the string */
+size_t krb5int_utf8_chars(const char *);
+/* returns the number of UTF-8 characters in the counted string */
+size_t krb5int_utf8c_chars(const char *, size_t);
+/* returns the length (in bytes) of the UTF-8 character */
+int krb5int_utf8_offset(const char *);
+/* returns the length (in bytes) indicated by the UTF-8 character */
+int krb5int_utf8_charlen(const char *);
+
+/* returns the length (in bytes) indicated by the UTF-8 character
+ * also checks that shortest possible encoding was used
+ */
+int krb5int_utf8_charlen2(const char *);
+
+/* copies a UTF-8 character and returning number of bytes copied */
+int krb5int_utf8_copy(char *, const char *);
+
+/* returns pointer of next UTF-8 character in string */
+char *krb5int_utf8_next( const char *);
+/* returns pointer of previous UTF-8 character in string */
+char *krb5int_utf8_prev( const char *);
+
+/* primitive ctype routines -- not aware of non-ascii characters */
+int krb5int_utf8_isascii( const char *);
+int krb5int_utf8_isalpha( const char *);
+int krb5int_utf8_isalnum( const char *);
+int krb5int_utf8_isdigit( const char *);
+int krb5int_utf8_isxdigit( const char *);
+int krb5int_utf8_isspace( const char *);
+
+/* span characters not in set, return bytes spanned */
+size_t krb5int_utf8_strcspn( const char* str, const char *set);
+/* span characters in set, return bytes spanned */
+size_t krb5int_utf8_strspn( const char* str, const char *set);
+/* return first occurance of character in string */
+char *krb5int_utf8_strchr( const char* str, const char *chr);
+/* return first character of set in string */
+char *krb5int_utf8_strpbrk( const char* str, const char *set);
+/* reentrant tokenizer */
+char *krb5int_utf8_strtok( char* sp, const char* sep, char **last);
+
+/* Optimizations */
+extern const char krb5int_utf8_lentab[128];
+extern const char krb5int_utf8_mintab[32];
+
+#define KRB5_UTF8_BV(p) (*(const unsigned char *)(p))
+#define KRB5_UTF8_ISASCII(p) (!(KRB5_UTF8_BV(p) & 0x80))
+#define KRB5_UTF8_CHARLEN(p) (KRB5_UTF8_ISASCII(p) ? 1 : \
+ krb5int_utf8_lentab[KRB5_UTF8_BV(p) ^ 0x80])
+
+/* This is like CHARLEN but additionally validates to make sure
+ * the char used the shortest possible encoding.
+ * 'l' is used to temporarily hold the result of CHARLEN.
+ */
+#define KRB5_UTF8_CHARLEN2(p, l) ( \
+ ((l = KRB5_UTF8_CHARLEN(p)) < 3 || \
+ (krb5int_utf8_mintab[KRB5_UTF8_BV(p) & 0x1f] & (p)[1])) ? \
+ l : 0)
+
+#define KRB5_UTF8_OFFSET(p) (KRB5_UTF8_ISASCII(p) \
+ ? 1 : krb5int_utf8_offset((p)) )
+
+#define KRB5_UTF8_COPY(d,s) (KRB5_UTF8_ISASCII(s) \
+ ? (*(d) = *(s), 1) : krb5int_utf8_copy((d),(s)))
+
+#define KRB5_UTF8_NEXT(p) (KRB5_UTF8_ISASCII(p) \
+ ? (char *)(p)+1 : krb5int_utf8_next((p)))
+
+#define KRB5_UTF8_INCR(p) ((p) = KRB5_UTF8_NEXT(p))
+
+/* For symmetry */
+#define KRB5_UTF8_PREV(p) (krb5int_utf8_prev((p)))
+#define KRB5_UTF8_DECR(p) ((p)=KRB5_UTF8_PREV((p)))
+
+/*
+ * these macros assume 'x' is an ASCII x
+ * and assume the "C" locale
+ */
+#define KRB5_ASCII(c) (!((c) & 0x80))
+#define KRB5_SPACE(c) ((c) == ' ' || (c) == '\t' || (c) == '\n')
+#define KRB5_DIGIT(c) ((c) >= '0' && (c) <= '9')
+#define KRB5_LOWER(c) ((c) >= 'a' && (c) <= 'z')
+#define KRB5_UPPER(c) ((c) >= 'A' && (c) <= 'Z')
+#define KRB5_ALPHA(c) (KRB5_LOWER(c) || KRB5_UPPER(c))
+#define KRB5_ALNUM(c) (KRB5_ALPHA(c) || KRB5_DIGIT(c))
+
+#define KRB5_LDH(c) (KRB5_ALNUM(c) || (c) == '-')
+
+#define KRB5_HEXLOWER(c) ((c) >= 'a' && (c) <= 'f')
+#define KRB5_HEXUPPER(c) ((c) >= 'A' && (c) <= 'F')
+#define KRB5_HEX(c) (KRB5_DIGIT(c) || \
+ KRB5_HEXLOWER(c) || KRB5_HEXUPPER(c))
+
+#endif /* K5_UTF8_H */
diff --git a/src/include/k5-util.h b/src/include/k5-util.h
new file mode 100644
index 000000000000..b978760cab73
--- /dev/null
+++ b/src/include/k5-util.h
@@ -0,0 +1,88 @@
+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/*
+ * Copyright (C) 1989-1998,2002 by the Massachusetts Institute of Technology,
+ * Cambridge, MA, USA. All Rights Reserved.
+ *
+ * This software is being provided to you, the LICENSEE, by the
+ * Massachusetts Institute of Technology (M.I.T.) under the following
+ * license. By obtaining, using and/or copying this software, you agree
+ * that you have read, understood, and will comply with these terms and
+ * conditions:
+ *
+ * Export of this software from the United States of America may
+ * require a specific license from the United States Government.
+ * It is the responsibility of any person or organization contemplating
+ * export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify and distribute
+ * this software and its documentation for any purpose and without fee or
+ * royalty is hereby granted, provided that you agree to comply with the
+ * following copyright notice and statements, including the disclaimer, and
+ * that the same appear on ALL copies of the software and documentation,
+ * including modifications that you make for internal use or for
+ * distribution:
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS", AND M.I.T. MAKES NO REPRESENTATIONS
+ * OR WARRANTIES, EXPRESS OR IMPLIED. By way of example, but not
+ * limitation, M.I.T. MAKES NO REPRESENTATIONS OR WARRANTIES OF
+ * MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF
+ * THE LICENSED SOFTWARE OR DOCUMENTATION WILL NOT INFRINGE ANY THIRD PARTY
+ * PATENTS, COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS.
+ *
+ * The name of the Massachusetts Institute of Technology or M.I.T. may NOT
+ * be used in advertising or publicity pertaining to distribution of the
+ * software. Title to copyright in this software and any associated
+ * documentation shall at all times remain with M.I.T., and USER agrees to
+ * preserve same.
+ *
+ * Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ */
+
+/*
+ * "internal" utility functions used by various applications.
+ * They live in libkrb5util.
+ */
+
+#include "autoconf.h"
+
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+
+#include <errno.h>
+
+#ifndef krb5_seteuid
+
+#if defined(HAVE_SETEUID)
+# define krb5_seteuid(EUID) (seteuid((uid_t)(EUID)))
+#elif defined(HAVE_SETRESUID)
+# define krb5_seteuid(EUID) setresuid(getuid(), (uid_t)(EUID), geteuid())
+#elif defined(HAVE_SETREUID)
+# define krb5_seteuid(EUID) setreuid(geteuid(), (uid_t)(EUID))
+#else
+/* You need to add a case to deal with this operating system.*/
+# define krb5_seteuid(EUID) (errno = EPERM, -1)
+#endif
+
+#ifdef HAVE_SETEGID
+# define krb5_setegid(EGID) (setegid((gid_t)(EGID)))
+#elif defined(HAVE_SETRESGID)
+# define krb5_setegid(EGID) (setresgid(getgid(), (gid_t)(EGID), getegid()))
+#elif defined(HAVE_SETREGID)
+# define krb5_setegid(EGID) (setregid(getegid(), (gid_t)(EGID)))
+#else
+/* You need to add a case to deal with this operating system.*/
+# define krb5_setegid(EGID) (errno = EPERM, -1)
+#endif
+
+#endif
diff --git a/src/include/kcm.h b/src/include/kcm.h
new file mode 100644
index 000000000000..5ea1447cd644
--- /dev/null
+++ b/src/include/kcm.h
@@ -0,0 +1,95 @@
+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/* include/kcm.h - Kerberos cache manager protocol declarations */
+/*
+ * Copyright (C) 2014 by the Massachusetts Institute of Technology.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef KCM_H
+#define KCM_H
+
+#define KCM_PROTOCOL_VERSION_MAJOR 2
+#define KCM_PROTOCOL_VERSION_MINOR 0
+
+#define KCM_UUID_LEN 16
+
+/* This should ideally be in RUNSTATEDIR, but Heimdal uses a hardcoded
+ * /var/run, and we need to use the same default path. */
+#define DEFAULT_KCM_SOCKET_PATH "/var/run/.heim_org.h5l.kcm-socket"
+#define DEFAULT_KCM_MACH_SERVICE "org.h5l.kcm"
+
+/*
+ * All requests begin with:
+ * major version (1 bytes)
+ * minor version (1 bytes)
+ * opcode (16-bit big-endian)
+ *
+ * All replies begin with a 32-bit big-endian reply code.
+ *
+ * Parameters are appended to the request or reply with no delimiters. Flags
+ * and time offsets are stored as 32-bit big-endian integers. Names are
+ * marshalled as zero-terminated strings. Principals and credentials are
+ * marshalled in the v4 FILE ccache format. UUIDs are 16 bytes. UUID lists
+ * are not delimited, so nothing can come after them.
+ */
+
+/* Opcodes without comments are currently unused in the MIT client
+ * implementation. */
+typedef enum kcm_opcode {
+ KCM_OP_NOOP,
+ KCM_OP_GET_NAME,
+ KCM_OP_RESOLVE,
+ KCM_OP_GEN_NEW, /* () -> (name) */
+ KCM_OP_INITIALIZE, /* (name, princ) -> () */
+ KCM_OP_DESTROY, /* (name) -> () */
+ KCM_OP_STORE, /* (name, cred) -> () */
+ KCM_OP_RETRIEVE,
+ KCM_OP_GET_PRINCIPAL, /* (name) -> (princ) */
+ KCM_OP_GET_CRED_UUID_LIST, /* (name) -> (uuid, ...) */
+ KCM_OP_GET_CRED_BY_UUID, /* (name, uuid) -> (cred) */
+ KCM_OP_REMOVE_CRED, /* (name, flags, credtag) -> () */
+ KCM_OP_SET_FLAGS,
+ KCM_OP_CHOWN,
+ KCM_OP_CHMOD,
+ KCM_OP_GET_INITIAL_TICKET,
+ KCM_OP_GET_TICKET,
+ KCM_OP_MOVE_CACHE,
+ KCM_OP_GET_CACHE_UUID_LIST, /* () -> (uuid, ...) */
+ KCM_OP_GET_CACHE_BY_UUID, /* (uuid) -> (name) */
+ KCM_OP_GET_DEFAULT_CACHE, /* () -> (name) */
+ KCM_OP_SET_DEFAULT_CACHE, /* (name) -> () */
+ KCM_OP_GET_KDC_OFFSET, /* (name) -> (offset) */
+ KCM_OP_SET_KDC_OFFSET, /* (name, offset) -> () */
+ KCM_OP_ADD_NTLM_CRED,
+ KCM_OP_HAVE_NTLM_CRED,
+ KCM_OP_DEL_NTLM_CRED,
+ KCM_OP_DO_NTLM_AUTH,
+ KCM_OP_GET_NTLM_USER_LIST
+} kcm_opcode;
+
+#endif /* KCM_H */
diff --git a/src/include/kdb.h b/src/include/kdb.h
new file mode 100644
index 000000000000..da04724fcedb
--- /dev/null
+++ b/src/include/kdb.h
@@ -0,0 +1,1400 @@
+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/*
+ * Copyright 1990, 1991, 2016 by the Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ * require a specific license from the United States Government.
+ * It is the responsibility of any person or organization contemplating
+ * export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission. Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose. It is provided "as is" without express
+ * or implied warranty.
+ */
+/*
+ * Copyright (C) 1998 by the FundsXpress, INC.
+ *
+ * All rights reserved.
+ *
+ * Export of this software from the United States of America may require
+ * a specific license from the United States Government. It is the
+ * responsibility of any person or organization contemplating export to
+ * obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of FundsXpress. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission. FundsXpress makes no representations about the suitability of
+ * this software for any purpose. It is provided "as is" without express
+ * or implied warranty.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+/*
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/* KDC Database interface definitions */
+
+/* This API is not considered as stable as the main krb5 API.
+ *
+ * - We may make arbitrary incompatible changes between feature
+ * releases (e.g. from 1.7 to 1.8).
+ * - We will make some effort to avoid making incompatible changes for
+ * bugfix releases, but will make them if necessary.
+ */
+
+#ifndef KRB5_KDB5__
+#define KRB5_KDB5__
+
+#include <krb5.h>
+
+/* This version will be incremented when incompatible changes are made to the
+ * KDB API, and will be kept in sync with the libkdb major version. */
+#define KRB5_KDB_API_VERSION 8
+
+/* Salt types */
+#define KRB5_KDB_SALTTYPE_NORMAL 0
+#define KRB5_KDB_SALTTYPE_V4 1
+#define KRB5_KDB_SALTTYPE_NOREALM 2
+#define KRB5_KDB_SALTTYPE_ONLYREALM 3
+#define KRB5_KDB_SALTTYPE_SPECIAL 4
+#define KRB5_KDB_SALTTYPE_AFS3 5
+#define KRB5_KDB_SALTTYPE_CERTHASH 6
+
+/* Attributes */
+#define KRB5_KDB_DISALLOW_POSTDATED 0x00000001
+#define KRB5_KDB_DISALLOW_FORWARDABLE 0x00000002
+#define KRB5_KDB_DISALLOW_TGT_BASED 0x00000004
+#define KRB5_KDB_DISALLOW_RENEWABLE 0x00000008
+#define KRB5_KDB_DISALLOW_PROXIABLE 0x00000010
+#define KRB5_KDB_DISALLOW_DUP_SKEY 0x00000020
+#define KRB5_KDB_DISALLOW_ALL_TIX 0x00000040
+#define KRB5_KDB_REQUIRES_PRE_AUTH 0x00000080
+#define KRB5_KDB_REQUIRES_HW_AUTH 0x00000100
+#define KRB5_KDB_REQUIRES_PWCHANGE 0x00000200
+#define KRB5_KDB_DISALLOW_SVR 0x00001000
+#define KRB5_KDB_PWCHANGE_SERVICE 0x00002000
+#define KRB5_KDB_SUPPORT_DESMD5 0x00004000
+#define KRB5_KDB_NEW_PRINC 0x00008000
+#define KRB5_KDB_OK_AS_DELEGATE 0x00100000
+#define KRB5_KDB_OK_TO_AUTH_AS_DELEGATE 0x00200000 /* S4U2Self OK */
+#define KRB5_KDB_NO_AUTH_DATA_REQUIRED 0x00400000
+#define KRB5_KDB_LOCKDOWN_KEYS 0x00800000
+
+/* Creation flags */
+#define KRB5_KDB_CREATE_BTREE 0x00000001
+#define KRB5_KDB_CREATE_HASH 0x00000002
+
+/* Private flag used to indicate principal is local TGS */
+#define KRB5_KDB_TICKET_GRANTING_SERVICE 0x01000000
+/* Private flag used to indicate xrealm relationship is non-transitive */
+#define KRB5_KDB_XREALM_NON_TRANSITIVE 0x02000000
+
+/* Entry get flags */
+/* Name canonicalization requested */
+#define KRB5_KDB_FLAG_CANONICALIZE 0x00000010
+/* Include authorization data generated by backend */
+#define KRB5_KDB_FLAG_INCLUDE_PAC 0x00000020
+/* Is AS-REQ (client referrals only) */
+#define KRB5_KDB_FLAG_CLIENT_REFERRALS_ONLY 0x00000040
+/* Map cross-realm principals */
+#define KRB5_KDB_FLAG_MAP_PRINCIPALS 0x00000080
+/* Protocol transition */
+#define KRB5_KDB_FLAG_PROTOCOL_TRANSITION 0x00000100
+/* Constrained delegation */
+#define KRB5_KDB_FLAG_CONSTRAINED_DELEGATION 0x00000200
+/* User-to-user */
+#define KRB5_KDB_FLAG_USER_TO_USER 0x00000800
+/* Cross-realm */
+#define KRB5_KDB_FLAG_CROSS_REALM 0x00001000
+/* Allow in-realm aliases */
+#define KRB5_KDB_FLAG_ALIAS_OK 0x00002000
+
+#define KRB5_KDB_FLAGS_S4U ( KRB5_KDB_FLAG_PROTOCOL_TRANSITION | \
+ KRB5_KDB_FLAG_CONSTRAINED_DELEGATION )
+
+/* KDB iteration flags */
+#define KRB5_DB_ITER_WRITE 0x00000001
+#define KRB5_DB_ITER_REV 0x00000002
+#define KRB5_DB_ITER_RECURSE 0x00000004
+
+/* String attribute names recognized by krb5 */
+#define KRB5_KDB_SK_SESSION_ENCTYPES "session_enctypes"
+#define KRB5_KDB_SK_REQUIRE_AUTH "require_auth"
+
+#if !defined(_WIN32)
+
+/*
+ * Note --- these structures cannot be modified without changing the
+ * database version number in libkdb.a, but should be expandable by
+ * adding new tl_data types.
+ */
+typedef struct _krb5_tl_data {
+ struct _krb5_tl_data* tl_data_next; /* NOT saved */
+ krb5_int16 tl_data_type;
+ krb5_ui_2 tl_data_length;
+ krb5_octet * tl_data_contents;
+} krb5_tl_data;
+
+/* String attributes (currently stored inside tl-data) map C string keys to
+ * values. They can be set via kadmin and consumed by KDC plugins. */
+typedef struct krb5_string_attr_st {
+ char *key;
+ char *value;
+} krb5_string_attr;
+
+/*
+ * If this ever changes up the version number and make the arrays be as
+ * big as necessary.
+ *
+ * Currently the first type is the enctype and the second is the salt type.
+ */
+typedef struct _krb5_key_data {
+ krb5_int16 key_data_ver; /* Version */
+ krb5_ui_2 key_data_kvno; /* Key Version */
+ krb5_int16 key_data_type[2]; /* Array of types */
+ krb5_ui_2 key_data_length[2]; /* Array of lengths */
+ krb5_octet * key_data_contents[2]; /* Array of pointers */
+} krb5_key_data;
+
+#define KRB5_KDB_V1_KEY_DATA_ARRAY 2 /* # of array elements */
+
+typedef struct _krb5_keysalt {
+ krb5_int16 type;
+ krb5_data data; /* Length, data */
+} krb5_keysalt;
+
+/*
+ * A principal database entry. Extensions to this structure currently use the
+ * tl_data list. The e_data and e_length fields are not used by any calling
+ * code except kdb5_util dump and load, which marshal and unmarshal the array
+ * in the dump record. KDB modules may use these fields internally as long as
+ * they set e_length appropriately (non-zero if the data should be marshalled
+ * across dump and load, zero if not) and handle null e_data values in
+ * caller-constructed principal entries.
+ */
+typedef struct _krb5_db_entry_new {
+ krb5_magic magic; /* NOT saved */
+ krb5_ui_2 len;
+ krb5_ui_4 mask; /* members currently changed/set */
+ krb5_flags attributes;
+ krb5_deltat max_life;
+ krb5_deltat max_renewable_life;
+ krb5_timestamp expiration; /* When the client expires */
+ krb5_timestamp pw_expiration; /* When its passwd expires */
+ krb5_timestamp last_success; /* Last successful passwd */
+ krb5_timestamp last_failed; /* Last failed passwd attempt */
+ krb5_kvno fail_auth_count; /* # of failed passwd attempt */
+ krb5_int16 n_tl_data;
+ krb5_int16 n_key_data;
+ krb5_ui_2 e_length; /* Length of extra data */
+ krb5_octet * e_data; /* Extra data to be saved */
+
+ krb5_principal princ; /* Length, data */
+ krb5_tl_data * tl_data; /* Linked list */
+
+ /* key_data must be sorted by kvno in descending order. */
+ krb5_key_data * key_data; /* Array */
+} krb5_db_entry;
+
+typedef struct _osa_policy_ent_t {
+ int version;
+ char *name;
+ krb5_ui_4 pw_min_life;
+ krb5_ui_4 pw_max_life;
+ krb5_ui_4 pw_min_length;
+ krb5_ui_4 pw_min_classes;
+ krb5_ui_4 pw_history_num;
+ krb5_ui_4 policy_refcnt; /* no longer used */
+ /* Only valid if version > 1 */
+ krb5_ui_4 pw_max_fail; /* pwdMaxFailure */
+ krb5_ui_4 pw_failcnt_interval; /* pwdFailureCountInterval */
+ krb5_ui_4 pw_lockout_duration; /* pwdLockoutDuration */
+ /* Only valid if version > 2 */
+ krb5_ui_4 attributes;
+ krb5_ui_4 max_life;
+ krb5_ui_4 max_renewable_life;
+ char * allowed_keysalts;
+ krb5_int16 n_tl_data;
+ krb5_tl_data * tl_data;
+} osa_policy_ent_rec, *osa_policy_ent_t;
+
+typedef void (*osa_adb_iter_policy_func) (void *, osa_policy_ent_t);
+
+typedef struct __krb5_key_salt_tuple {
+ krb5_enctype ks_enctype;
+ krb5_int32 ks_salttype;
+} krb5_key_salt_tuple;
+
+#define KRB5_KDB_MAGIC_NUMBER 0xdbdbdbdb
+#define KRB5_KDB_V1_BASE_LENGTH 38
+
+#define KRB5_KDB_MAX_ALLOWED_KS_LEN 512
+
+#define KRB5_TL_LAST_PWD_CHANGE 0x0001
+#define KRB5_TL_MOD_PRINC 0x0002
+#define KRB5_TL_KADM_DATA 0x0003
+#define KRB5_TL_KADM5_E_DATA 0x0004
+#define KRB5_TL_RB1_CHALLENGE 0x0005
+#ifdef SECURID
+#define KRB5_TL_SECURID_STATE 0x0006
+#endif /* SECURID */
+#define KRB5_TL_USER_CERTIFICATE 0x0007
+#define KRB5_TL_MKVNO 0x0008
+#define KRB5_TL_ACTKVNO 0x0009
+#define KRB5_TL_MKEY_AUX 0x000a
+
+/* String attributes may not always be represented in tl-data. kadmin clients
+ * must use the get_strings and set_string RPCs. */
+#define KRB5_TL_STRING_ATTRS 0x000b
+
+#define KRB5_TL_PAC_LOGON_INFO 0x0100 /* NDR encoded validation info */
+#define KRB5_TL_SERVER_REFERRAL 0x0200 /* ASN.1 encoded ServerReferralInfo */
+#define KRB5_TL_SVR_REFERRAL_DATA 0x0300 /* ASN.1 encoded PA-SVR-REFERRAL-DATA */
+#define KRB5_TL_CONSTRAINED_DELEGATION_ACL 0x0400 /* Each entry is a permitted SPN */
+#define KRB5_TL_LM_KEY 0x0500 /* LM OWF */
+#define KRB5_TL_X509_SUBJECT_ISSUER_NAME 0x0600 /* <I>IssuerDN<S>SubjectDN */
+#define KRB5_TL_LAST_ADMIN_UNLOCK 0x0700 /* Timestamp of admin unlock */
+
+#define KRB5_TL_DB_ARGS 0x7fff
+
+/* version number for KRB5_TL_ACTKVNO data */
+#define KRB5_TL_ACTKVNO_VER 1
+
+/* version number for KRB5_TL_MKEY_AUX data */
+#define KRB5_TL_MKEY_AUX_VER 1
+
+typedef struct _krb5_actkvno_node {
+ struct _krb5_actkvno_node *next;
+ krb5_kvno act_kvno;
+ krb5_timestamp act_time;
+} krb5_actkvno_node;
+
+typedef struct _krb5_mkey_aux_node {
+ struct _krb5_mkey_aux_node *next;
+ krb5_kvno mkey_kvno; /* kvno of mkey protecting the latest_mkey */
+ krb5_key_data latest_mkey; /* most recent mkey */
+} krb5_mkey_aux_node;
+
+typedef struct _krb5_keylist_node {
+ krb5_keyblock keyblock;
+ krb5_kvno kvno;
+ struct _krb5_keylist_node *next;
+} krb5_keylist_node;
+
+/*
+ * Determines the number of failed KDC requests before DISALLOW_ALL_TIX is set
+ * on the principal.
+ */
+#define KRB5_MAX_FAIL_COUNT 5
+
+/* XXX depends on knowledge of krb5_parse_name() formats */
+#define KRB5_KDB_M_NAME "K/M" /* Kerberos/Master */
+
+/* prompts used by default when reading the KDC password from the keyboard. */
+#define KRB5_KDC_MKEY_1 "Enter KDC database master key"
+#define KRB5_KDC_MKEY_2 "Re-enter KDC database master key to verify"
+
+
+extern char *krb5_mkey_pwd_prompt1;
+extern char *krb5_mkey_pwd_prompt2;
+
+/*
+ * These macros specify the encoding of data within the database.
+ *
+ * Data encoding is little-endian.
+ */
+#ifdef _KRB5_INT_H
+#include "k5-platform.h"
+#define krb5_kdb_decode_int16(cp, i16) \
+ *((krb5_int16 *) &(i16)) = load_16_le(cp)
+#define krb5_kdb_decode_int32(cp, i32) \
+ *((krb5_int32 *) &(i32)) = load_32_le(cp)
+#define krb5_kdb_encode_int16(i16, cp) store_16_le(i16, cp)
+#define krb5_kdb_encode_int32(i32, cp) store_32_le(i32, cp)
+#endif /* _KRB5_INT_H */
+
+#define KRB5_KDB_OPEN_RW 0
+#define KRB5_KDB_OPEN_RO 1
+
+#ifndef KRB5_KDB_SRV_TYPE_KDC
+#define KRB5_KDB_SRV_TYPE_KDC 0x0100
+#endif
+
+#ifndef KRB5_KDB_SRV_TYPE_ADMIN
+#define KRB5_KDB_SRV_TYPE_ADMIN 0x0200
+#endif
+
+/* 0x0300 was KRB5_KDB_SRV_TYPE_PASSWD but it is no longer used. */
+
+#ifndef KRB5_KDB_SRV_TYPE_OTHER
+#define KRB5_KDB_SRV_TYPE_OTHER 0x0400
+#endif
+
+#define KRB5_KDB_OPT_SET_DB_NAME 0
+#define KRB5_KDB_OPT_SET_LOCK_MODE 1
+
+#define KRB5_DB_LOCKMODE_SHARED 0x0001
+#define KRB5_DB_LOCKMODE_EXCLUSIVE 0x0002
+#define KRB5_DB_LOCKMODE_PERMANENT 0x0008
+
+/* libkdb.spec */
+krb5_error_code krb5_db_setup_lib_handle(krb5_context kcontext);
+krb5_error_code krb5_db_open( krb5_context kcontext, char **db_args, int mode );
+krb5_error_code krb5_db_init ( krb5_context kcontext );
+krb5_error_code krb5_db_create ( krb5_context kcontext, char **db_args );
+krb5_error_code krb5_db_inited ( krb5_context kcontext );
+krb5_error_code kdb5_db_create ( krb5_context kcontext, char **db_args );
+krb5_error_code krb5_db_fini ( krb5_context kcontext );
+const char * krb5_db_errcode2string ( krb5_context kcontext, long err_code );
+krb5_error_code krb5_db_destroy ( krb5_context kcontext, char **db_args );
+krb5_error_code krb5_db_promote ( krb5_context kcontext, char **db_args );
+krb5_error_code krb5_db_get_age ( krb5_context kcontext, char *db_name, time_t *t );
+krb5_error_code krb5_db_lock ( krb5_context kcontext, int lock_mode );
+krb5_error_code krb5_db_unlock ( krb5_context kcontext );
+krb5_error_code krb5_db_get_principal ( krb5_context kcontext,
+ krb5_const_principal search_for,
+ unsigned int flags,
+ krb5_db_entry **entry );
+void krb5_db_free_principal ( krb5_context kcontext, krb5_db_entry *entry );
+krb5_error_code krb5_db_put_principal ( krb5_context kcontext,
+ krb5_db_entry *entry );
+krb5_error_code krb5_db_delete_principal ( krb5_context kcontext,
+ krb5_principal search_for );
+krb5_error_code krb5_db_rename_principal ( krb5_context kcontext,
+ krb5_principal source,
+ krb5_principal target );
+
+/*
+ * Iterate over principals in the KDB. If the callback may write to the DB,
+ * the caller must get an exclusive lock with krb5_db_lock before iterating,
+ * and release it with krb5_db_unlock after iterating.
+ */
+krb5_error_code krb5_db_iterate ( krb5_context kcontext,
+ char *match_entry,
+ int (*func) (krb5_pointer, krb5_db_entry *),
+ krb5_pointer func_arg, krb5_flags iterflags );
+
+
+krb5_error_code krb5_db_store_master_key ( krb5_context kcontext,
+ char *keyfile,
+ krb5_principal mname,
+ krb5_kvno kvno,
+ krb5_keyblock *key,
+ char *master_pwd);
+krb5_error_code krb5_db_store_master_key_list ( krb5_context kcontext,
+ char *keyfile,
+ krb5_principal mname,
+ char *master_pwd);
+krb5_error_code krb5_db_fetch_mkey ( krb5_context context,
+ krb5_principal mname,
+ krb5_enctype etype,
+ krb5_boolean fromkeyboard,
+ krb5_boolean twice,
+ char *db_args,
+ krb5_kvno *kvno,
+ krb5_data *salt,
+ krb5_keyblock *key);
+krb5_error_code
+krb5_db_fetch_mkey_list( krb5_context context,
+ krb5_principal mname,
+ const krb5_keyblock * mkey );
+
+krb5_error_code
+krb5_dbe_find_enctype( krb5_context kcontext,
+ krb5_db_entry *dbentp,
+ krb5_int32 ktype,
+ krb5_int32 stype,
+ krb5_int32 kvno,
+ krb5_key_data **kdatap);
+
+
+krb5_error_code krb5_dbe_search_enctype ( krb5_context kcontext,
+ krb5_db_entry *dbentp,
+ krb5_int32 *start,
+ krb5_int32 ktype,
+ krb5_int32 stype,
+ krb5_int32 kvno,
+ krb5_key_data **kdatap);
+
+krb5_error_code
+krb5_db_setup_mkey_name ( krb5_context context,
+ const char *keyname,
+ const char *realm,
+ char **fullname,
+ krb5_principal *principal);
+
+/**
+ * Decrypts the key given in @@a key_data. If @a mkey is specified, that
+ * master key is used. If @a mkey is NULL, then all master keys are tried.
+ */
+krb5_error_code
+krb5_dbe_decrypt_key_data( krb5_context context,
+ const krb5_keyblock * mkey,
+ const krb5_key_data * key_data,
+ krb5_keyblock * dbkey,
+ krb5_keysalt * keysalt);
+
+krb5_error_code
+krb5_dbe_encrypt_key_data( krb5_context context,
+ const krb5_keyblock * mkey,
+ const krb5_keyblock * dbkey,
+ const krb5_keysalt * keysalt,
+ int keyver,
+ krb5_key_data * key_data);
+
+krb5_error_code
+krb5_dbe_fetch_act_key_list(krb5_context context,
+ krb5_principal princ,
+ krb5_actkvno_node **act_key_list);
+
+krb5_error_code
+krb5_dbe_find_act_mkey( krb5_context context,
+ krb5_actkvno_node * act_mkey_list,
+ krb5_kvno * act_kvno,
+ krb5_keyblock ** act_mkey);
+
+krb5_error_code
+krb5_dbe_find_mkey( krb5_context context,
+ krb5_db_entry * entry,
+ krb5_keyblock ** mkey);
+
+/* Set *mkvno to mkvno in entry tl_data, or 0 if not present. */
+krb5_error_code
+krb5_dbe_lookup_mkvno( krb5_context context,
+ krb5_db_entry * entry,
+ krb5_kvno * mkvno);
+
+krb5_keylist_node *
+krb5_db_mkey_list_alias( krb5_context kcontext );
+
+/* Set *mkvno to mkvno in entry tl_data, or minimum value from mkey_list. */
+krb5_error_code
+krb5_dbe_get_mkvno( krb5_context context,
+ krb5_db_entry * entry,
+ krb5_kvno * mkvno);
+
+krb5_error_code
+krb5_dbe_lookup_mod_princ_data( krb5_context context,
+ krb5_db_entry * entry,
+ krb5_timestamp * mod_time,
+ krb5_principal * mod_princ);
+
+krb5_error_code
+krb5_dbe_lookup_mkey_aux( krb5_context context,
+ krb5_db_entry * entry,
+ krb5_mkey_aux_node ** mkey_aux_data_list);
+krb5_error_code
+krb5_dbe_update_mkvno( krb5_context context,
+ krb5_db_entry * entry,
+ krb5_kvno mkvno);
+
+krb5_error_code
+krb5_dbe_lookup_actkvno( krb5_context context,
+ krb5_db_entry * entry,
+ krb5_actkvno_node ** actkvno_list);
+
+krb5_error_code
+krb5_dbe_update_mkey_aux( krb5_context context,
+ krb5_db_entry * entry,
+ krb5_mkey_aux_node * mkey_aux_data_list);
+
+krb5_error_code
+krb5_dbe_update_actkvno(krb5_context context,
+ krb5_db_entry * entry,
+ const krb5_actkvno_node *actkvno_list);
+
+krb5_error_code
+krb5_dbe_update_last_pwd_change( krb5_context context,
+ krb5_db_entry * entry,
+ krb5_timestamp stamp);
+
+krb5_error_code
+krb5_dbe_update_last_admin_unlock( krb5_context context,
+ krb5_db_entry * entry,
+ krb5_timestamp stamp);
+
+krb5_error_code
+krb5_dbe_lookup_tl_data( krb5_context context,
+ krb5_db_entry * entry,
+ krb5_tl_data * ret_tl_data);
+
+krb5_error_code
+krb5_dbe_create_key_data( krb5_context context,
+ krb5_db_entry * entry);
+
+
+krb5_error_code
+krb5_dbe_update_mod_princ_data( krb5_context context,
+ krb5_db_entry * entry,
+ krb5_timestamp mod_date,
+ krb5_const_principal mod_princ);
+
+/*
+ * These are wrappers around realloc() and free(). Applications and KDB
+ * modules can use them when manipulating principal and policy entries to
+ * ensure that they allocate and free memory in a manner compatible with the
+ * library. Using libkrb5 or libkbd5 functions to construct values (such as
+ * krb5_copy_principal() to construct the princ field of a krb5_db_entry) is
+ * also safe. On Unix platforms, just using malloc() and free() is safe as
+ * long as the application or module does not use a malloc replacement.
+ */
+void *krb5_db_alloc( krb5_context kcontext,
+ void *ptr,
+ size_t size );
+void krb5_db_free( krb5_context kcontext,
+ void *ptr);
+
+
+krb5_error_code
+krb5_dbe_lookup_last_pwd_change( krb5_context context,
+ krb5_db_entry * entry,
+ krb5_timestamp * stamp);
+
+krb5_error_code
+krb5_dbe_lookup_last_admin_unlock( krb5_context context,
+ krb5_db_entry * entry,
+ krb5_timestamp * stamp);
+
+/* Retrieve the set of string attributes in entry, in no particular order.
+ * Free *strings_out with krb5_dbe_free_strings when done. */
+krb5_error_code
+krb5_dbe_get_strings(krb5_context context, krb5_db_entry *entry,
+ krb5_string_attr **strings_out, int *count_out);
+
+/* Retrieve a single string attribute from entry, or NULL if there is no
+ * attribute for key. Free *value_out with krb5_dbe_free_string when done. */
+krb5_error_code
+krb5_dbe_get_string(krb5_context context, krb5_db_entry *entry,
+ const char *key, char **value_out);
+
+/* Change or add a string attribute in entry, or delete it if value is NULL. */
+krb5_error_code
+krb5_dbe_set_string(krb5_context context, krb5_db_entry *entry,
+ const char *key, const char *value);
+
+krb5_error_code
+krb5_dbe_delete_tl_data( krb5_context context,
+ krb5_db_entry * entry,
+ krb5_int16 tl_data_type);
+
+krb5_error_code
+krb5_db_update_tl_data(krb5_context context,
+ krb5_int16 * n_tl_datap,
+ krb5_tl_data **tl_datap,
+ krb5_tl_data * new_tl_data);
+
+krb5_error_code
+krb5_dbe_update_tl_data( krb5_context context,
+ krb5_db_entry * entry,
+ krb5_tl_data * new_tl_data);
+
+/* Compute the salt for a key data entry given the corresponding principal. */
+krb5_error_code
+krb5_dbe_compute_salt(krb5_context context, const krb5_key_data *key,
+ krb5_const_principal princ, krb5_int16 *salttype_out,
+ krb5_data **salt_out);
+
+/*
+ * Modify the key data of entry to explicitly store salt values using the
+ * KRB5_KDB_SALTTYPE_SPECIAL salt type.
+ */
+krb5_error_code
+krb5_dbe_specialize_salt(krb5_context context, krb5_db_entry *entry);
+
+krb5_error_code
+krb5_dbe_cpw( krb5_context kcontext,
+ krb5_keyblock * master_key,
+ krb5_key_salt_tuple * ks_tuple,
+ int ks_tuple_count,
+ char * passwd,
+ int new_kvno,
+ krb5_boolean keepold,
+ krb5_db_entry * db_entry);
+
+
+krb5_error_code
+krb5_dbe_ark( krb5_context context,
+ krb5_keyblock * master_key,
+ krb5_key_salt_tuple * ks_tuple,
+ int ks_tuple_count,
+ krb5_db_entry * db_entry);
+
+krb5_error_code
+krb5_dbe_crk( krb5_context context,
+ krb5_keyblock * master_key,
+ krb5_key_salt_tuple * ks_tuple,
+ int ks_tuple_count,
+ krb5_boolean keepold,
+ krb5_db_entry * db_entry);
+
+krb5_error_code
+krb5_dbe_apw( krb5_context context,
+ krb5_keyblock * master_key,
+ krb5_key_salt_tuple * ks_tuple,
+ int ks_tuple_count,
+ char * passwd,
+ krb5_db_entry * db_entry);
+
+int
+krb5_db_get_key_data_kvno( krb5_context context,
+ int count,
+ krb5_key_data * data);
+
+krb5_error_code krb5_db_sign_authdata(krb5_context kcontext,
+ unsigned int flags,
+ krb5_const_principal client_princ,
+ krb5_db_entry *client,
+ krb5_db_entry *server,
+ krb5_db_entry *krbtgt,
+ krb5_keyblock *client_key,
+ krb5_keyblock *server_key,
+ krb5_keyblock *krbtgt_key,
+ krb5_keyblock *session_key,
+ krb5_timestamp authtime,
+ krb5_authdata **tgt_auth_data,
+ krb5_authdata ***signed_auth_data);
+
+krb5_error_code krb5_db_check_transited_realms(krb5_context kcontext,
+ const krb5_data *tr_contents,
+ const krb5_data *client_realm,
+ const krb5_data *server_realm);
+
+krb5_error_code krb5_db_check_policy_as(krb5_context kcontext,
+ krb5_kdc_req *request,
+ krb5_db_entry *client,
+ krb5_db_entry *server,
+ krb5_timestamp kdc_time,
+ const char **status,
+ krb5_pa_data ***e_data);
+
+krb5_error_code krb5_db_check_policy_tgs(krb5_context kcontext,
+ krb5_kdc_req *request,
+ krb5_db_entry *server,
+ krb5_ticket *ticket,
+ const char **status,
+ krb5_pa_data ***e_data);
+
+void krb5_db_audit_as_req(krb5_context kcontext, krb5_kdc_req *request,
+ krb5_db_entry *client, krb5_db_entry *server,
+ krb5_timestamp authtime, krb5_error_code error_code);
+
+void krb5_db_refresh_config(krb5_context kcontext);
+
+krb5_error_code krb5_db_check_allowed_to_delegate(krb5_context kcontext,
+ krb5_const_principal client,
+ const krb5_db_entry *server,
+ krb5_const_principal proxy);
+
+/**
+ * Sort an array of @a krb5_key_data keys in descending order by their kvno.
+ * Key data order within a kvno is preserved.
+ *
+ * @param key_data
+ * The @a krb5_key_data array to sort. This is sorted in place so the
+ * array will be modified.
+ * @param key_data_length
+ * The length of @a key_data.
+ */
+void
+krb5_dbe_sort_key_data(krb5_key_data *key_data, size_t key_data_length);
+
+/* default functions. Should not be directly called */
+/*
+ * Default functions prototype
+ */
+
+krb5_error_code
+krb5_dbe_def_search_enctype( krb5_context kcontext,
+ krb5_db_entry *dbentp,
+ krb5_int32 *start,
+ krb5_int32 ktype,
+ krb5_int32 stype,
+ krb5_int32 kvno,
+ krb5_key_data **kdatap);
+
+krb5_error_code
+krb5_def_store_mkey_list( krb5_context context,
+ char *keyfile,
+ krb5_principal mname,
+ krb5_keylist_node *keylist,
+ char *master_pwd);
+
+krb5_error_code
+krb5_db_def_fetch_mkey( krb5_context context,
+ krb5_principal mname,
+ krb5_keyblock *key,
+ krb5_kvno *kvno,
+ char *db_args);
+
+krb5_error_code
+krb5_def_fetch_mkey_list( krb5_context context,
+ krb5_principal mprinc,
+ const krb5_keyblock *mkey,
+ krb5_keylist_node **mkeys_list);
+
+krb5_error_code
+krb5_dbe_def_cpw( krb5_context context,
+ krb5_keyblock * master_key,
+ krb5_key_salt_tuple * ks_tuple,
+ int ks_tuple_count,
+ char * passwd,
+ int new_kvno,
+ krb5_boolean keepold,
+ krb5_db_entry * db_entry);
+
+krb5_error_code
+krb5_dbe_def_decrypt_key_data( krb5_context context,
+ const krb5_keyblock * mkey,
+ const krb5_key_data * key_data,
+ krb5_keyblock * dbkey,
+ krb5_keysalt * keysalt);
+
+krb5_error_code
+krb5_dbe_def_encrypt_key_data( krb5_context context,
+ const krb5_keyblock * mkey,
+ const krb5_keyblock * dbkey,
+ const krb5_keysalt * keysalt,
+ int keyver,
+ krb5_key_data * key_data);
+
+krb5_error_code
+krb5_db_def_rename_principal( krb5_context kcontext,
+ krb5_const_principal source,
+ krb5_const_principal target);
+
+krb5_error_code
+krb5_db_create_policy( krb5_context kcontext,
+ osa_policy_ent_t policy);
+
+krb5_error_code
+krb5_db_get_policy ( krb5_context kcontext,
+ char *name,
+ osa_policy_ent_t *policy );
+
+krb5_error_code
+krb5_db_put_policy( krb5_context kcontext,
+ osa_policy_ent_t policy);
+
+krb5_error_code
+krb5_db_iter_policy( krb5_context kcontext,
+ char *match_entry,
+ osa_adb_iter_policy_func func,
+ void *data);
+
+krb5_error_code
+krb5_db_delete_policy( krb5_context kcontext,
+ char *policy);
+
+void
+krb5_db_free_policy( krb5_context kcontext,
+ osa_policy_ent_t policy);
+
+
+krb5_error_code
+krb5_db_set_context(krb5_context, void *db_context);
+
+krb5_error_code
+krb5_db_get_context(krb5_context, void **db_context);
+
+void
+krb5_dbe_free_key_data_contents(krb5_context, krb5_key_data *);
+
+void
+krb5_dbe_free_key_list(krb5_context, krb5_keylist_node *);
+
+void
+krb5_dbe_free_actkvno_list(krb5_context, krb5_actkvno_node *);
+
+void
+krb5_dbe_free_mkey_aux_list(krb5_context, krb5_mkey_aux_node *);
+
+void
+krb5_dbe_free_tl_data(krb5_context, krb5_tl_data *);
+
+void
+krb5_dbe_free_strings(krb5_context, krb5_string_attr *, int count);
+
+void
+krb5_dbe_free_string(krb5_context, char *);
+
+/*
+ * Register the KDB keytab type, allowing "KDB:" to be used as a keytab name.
+ * For this type to work, the context used for keytab operations must have an
+ * associated database handle (via krb5_db_open()).
+ */
+krb5_error_code krb5_db_register_keytab(krb5_context context);
+
+#define KRB5_KDB_DEF_FLAGS 0
+
+#define KDB_MAX_DB_NAME 128
+#define KDB_REALM_SECTION "realms"
+#define KDB_MODULE_POINTER "database_module"
+#define KDB_MODULE_DEF_SECTION "dbdefaults"
+#define KDB_MODULE_SECTION "dbmodules"
+#define KDB_LIB_POINTER "db_library"
+#define KDB_DATABASE_CONF_FILE DEFAULT_SECURE_PROFILE_PATH
+#define KDB_DATABASE_ENV_PROF KDC_PROFILE_ENV
+
+#define KRB5_KDB_OPEN_RW 0
+#define KRB5_KDB_OPEN_RO 1
+
+#define KRB5_KDB_OPT_SET_DB_NAME 0
+#define KRB5_KDB_OPT_SET_LOCK_MODE 1
+
+/*
+ * This number indicates the date of the last incompatible change to the DAL.
+ * The maj_ver field of the module's vtable structure must match this version.
+ */
+#define KRB5_KDB_DAL_MAJOR_VERSION 6
+
+/*
+ * A krb5_context can hold one database object. Modules should use
+ * krb5_db_set_context and krb5_db_get_context to store state associated with
+ * the database object.
+ *
+ * Some module functions are mandatory for KDC operation; others are optional
+ * or apply only to administrative operations. If a function is optional, a
+ * module can leave the function pointer as NULL. Alternatively, modules can
+ * return KRB5_PLUGIN_OP_NOTSUPP when asked to perform an inapplicable action.
+ *
+ * Some module functions have default implementations which will call back into
+ * the vtable interface. Leave these functions as NULL to use the default
+ * implementations.
+ *
+ * The documentation in these comments describes the DAL as it is currently
+ * implemented and used, not as it should be. So if anything seems off, that
+ * probably means the current state of things is off.
+ *
+ * Modules must allocate memory for principal entries, policy entries, and
+ * other structures using an allocator compatible with malloc() as seen by
+ * libkdb5 and libkrb5. Modules may link against libkdb5 and call
+ * krb5_db_alloc() to be certain that the same malloc implementation is used.
+ */
+
+typedef struct _kdb_vftabl {
+ short int maj_ver;
+ short int min_ver;
+
+ /*
+ * Mandatory: Invoked after the module library is loaded, when the first DB
+ * using the module is opened, across all contexts.
+ */
+ krb5_error_code (*init_library)(void);
+
+ /*
+ * Mandatory: Invoked before the module library is unloaded, after the last
+ * DB using the module is closed, across all contexts.
+ */
+ krb5_error_code (*fini_library)(void);
+
+ /*
+ * Mandatory: Initialize a database object. Profile settings should be
+ * read from conf_section inside KDB_MODULE_SECTION. db_args communicates
+ * command-line arguments for module-specific flags. mode will be one of
+ * KRB5_KDB_OPEN_{RW,RO} or'd with one of
+ * KRB5_KDB_SRV_TYPE_{KDC,ADMIN,PASSWD,OTHER}.
+ */
+ krb5_error_code (*init_module)(krb5_context kcontext, char *conf_section,
+ char **db_args, int mode);
+
+ /*
+ * Mandatory: Finalize the database object contained in a context. Free
+ * any state contained in the db_context pointer and null it out.
+ */
+ krb5_error_code (*fini_module)(krb5_context kcontext);
+
+ /*
+ * Optional: Initialize a database object while creating the underlying
+ * database. conf_section and db_args have the same meaning as in
+ * init_module. This function may return an error if the database already
+ * exists. Used by kdb5_util create.
+ *
+ * If db_args contains the value "temporary", the module should create an
+ * exclusively locked side copy of the database suitable for loading in a
+ * propagation from master to slave. This side copy will later be promoted
+ * with promote_db, allowing complete updates of the DB with no loss in
+ * read availability. If the module cannot comply with this architecture,
+ * it should return an error.
+ */
+ krb5_error_code (*create)(krb5_context kcontext, char *conf_section,
+ char **db_args);
+
+ /*
+ * Optional: Destroy a database. conf_section and db_args have the same
+ * meaning as in init_module. Used by kdb5_util destroy. In current
+ * usage, the database is destroyed while open, so the module should handle
+ * that.
+ */
+ krb5_error_code (*destroy)(krb5_context kcontext, char *conf_section,
+ char **db_args);
+
+ /*
+ * Deprecated: No longer used as of krb5 1.10; can be removed in the next
+ * DAL revision. Modules should leave as NULL.
+ */
+ krb5_error_code (*get_age)(krb5_context kcontext, char *db_name,
+ time_t *age);
+
+ /*
+ * Optional: Lock the database, with semantics depending on the mode
+ * argument:
+ *
+ * KRB5_DB_LOCKMODE_SHARED: Lock may coexist with other shared locks.
+ * KRB5_DB_LOCKMODE_EXCLUSIVE: Lock may not coexist with other locks.
+ * KRB5_DB_LOCKMODE_PERMANENT: Exclusive lock surviving process exit.
+ *
+ * Used by the "kadmin lock" command, incremental propagation, and
+ * kdb5_util dump. Incremental propagation support requires shared locks
+ * to operate. kdb5_util dump will continue unlocked if the module returns
+ * KRB5_PLUGIN_OP_NOTSUPP.
+ */
+ krb5_error_code (*lock)(krb5_context kcontext, int mode);
+
+ /* Optional: Release a lock created with db_lock. */
+ krb5_error_code (*unlock)(krb5_context kcontext);
+
+ /*
+ * Mandatory: Set *entry to an allocated entry for the principal
+ * search_for. If the principal is not found, return KRB5_KDB_NOENTRY.
+ *
+ * The meaning of flags are as follows:
+ *
+ * KRB5_KDB_FLAG_CANONICALIZE: Set by the KDC when looking up entries for
+ * an AS or TGS request with canonicalization requested. Determines
+ * whether the module should return out-of-realm referrals.
+ *
+ * KRB5_KDB_FLAG_INCLUDE_PAC: Set by the KDC during an AS request when the
+ * client requested PAC information during padata, and during most TGS
+ * requests. Indicates that the module should include PAC information
+ * when its sign_authdata method is invoked.
+ *
+ * KRB5_KDB_FLAG_CLIENT_REFERRALS_ONLY: Set by the KDC when looking up the
+ * client entry in an AS request. Affects how the module should return
+ * out-of-realm referrals.
+ *
+ * KRB5_KDB_FLAG_MAP_PRINCIPALS: Set by the KDC when looking up the client
+ * entry during TGS requests, except for S4U TGS requests and requests
+ * where the server entry has the KRB5_KDB_NO_AUTH_DATA_REQUIRED
+ * attribute. Indicates that the module should map foreign principals
+ * to local principals if it supports doing so.
+ *
+ * KRB5_KDB_FLAG_PROTOCOL_TRANSITION: Set by the KDC when looking up the
+ * client entry during an S4U2Self TGS request. This affects the PAC
+ * information which should be included when authorization data is
+ * generated; see the Microsoft S4U specification for details.
+ *
+ * KRB5_KDB_FLAG_CONSTRAINED_DELEGATION: Set by the KDC when looking up the
+ * client entry during an S4U2Proxy TGS request. Also affects PAC
+ * generation.
+ *
+ * KRB5_KDB_FLAG_CROSS_REALM: Set by the KDC when looking up a client entry
+ * during a TGS request, if the client principal is not part of the
+ * realm being served.
+ *
+ * KRB5_KDB_FLAG_ALIAS_OK: Set by the KDC for server principal lookups and
+ * for AS request client principal lookups with canonicalization
+ * requested; also set by the admin interface. Determines whether the
+ * module should return in-realm aliases.
+ *
+ * A module can return in-realm aliases if KRB5_KDB_FLAG_ALIAS_OK is set.
+ * To return an in-realm alias, fill in a different value for
+ * entries->princ than the one requested.
+ *
+ * A module can return out-of-realm referrals if KRB5_KDB_FLAG_CANONICALIZE
+ * is set. For AS request clients (KRB5_KDB_FLAG_CLIENT_REFERRALS_ONLY is
+ * also set), the module should do so by simply filling in an out-of-realm
+ * name in entries->princ and setting all other fields to NULL. Otherwise,
+ * the module should return the entry for the cross-realm TGS of the
+ * referred-to realm. For TGS referals, the module can also include
+ * tl-data of type KRB5_TL_SERVER_REFERRAL containing ASN.1-encoded Windows
+ * referral data as documented in draft-ietf-krb-wg-kerberos-referrals-11
+ * appendix A; this will be returned to the client as encrypted padata.
+ */
+ krb5_error_code (*get_principal)(krb5_context kcontext,
+ krb5_const_principal search_for,
+ unsigned int flags,
+ krb5_db_entry **entry);
+
+ /*
+ * Optional: Create or modify a principal entry. db_args communicates
+ * command-line arguments for module-specific flags.
+ *
+ * The mask field of an entry indicates the changed fields. Mask values
+ * are defined in kadmin's admin.h header. If KADM5_PRINCIPAL is set in
+ * the mask, the entry is new; otherwise it already exists. All fields of
+ * an entry are expected to contain correct values, regardless of whether
+ * they are specified in the mask, so it is acceptable for a module to
+ * ignore the mask and update the entire entry.
+ */
+ krb5_error_code (*put_principal)(krb5_context kcontext,
+ krb5_db_entry *entry, char **db_args);
+
+ /*
+ * Optional: Delete the entry for the principal search_for. If the
+ * principal did not exist, return KRB5_KDB_NOENTRY.
+ */
+ krb5_error_code (*delete_principal)(krb5_context kcontext,
+ krb5_const_principal search_for);
+
+ /*
+ * Optional with default: Rename a principal. If the source principal does
+ * not exist, return KRB5_KDB_NOENTRY. If the target exists, return an
+ * error.
+ *
+ * NOTE: If the module chooses to implement a custom function for renaming
+ * a principal instead of using the default, then rename operations will
+ * fail if iprop logging is enabled.
+ */
+ krb5_error_code (*rename_principal)(krb5_context kcontext,
+ krb5_const_principal source,
+ krb5_const_principal target);
+
+ /*
+ * Optional: For each principal entry in the database, invoke func with the
+ * argments func_arg and the entry data. If match_entry is specified, the
+ * module may narrow the iteration to principal names matching that regular
+ * expression; a module may alternatively ignore match_entry.
+ */
+ krb5_error_code (*iterate)(krb5_context kcontext,
+ char *match_entry,
+ int (*func)(krb5_pointer, krb5_db_entry *),
+ krb5_pointer func_arg, krb5_flags iterflags);
+
+ /*
+ * Optional: Create a password policy entry. Return an error if the policy
+ * already exists.
+ */
+ krb5_error_code (*create_policy)(krb5_context kcontext,
+ osa_policy_ent_t policy);
+
+ /*
+ * Optional: Set *policy to the policy entry of the specified name. If the
+ * entry does not exist, return KRB5_KDB_NOENTRY.
+ */
+ krb5_error_code (*get_policy)(krb5_context kcontext, char *name,
+ osa_policy_ent_t *policy);
+
+ /*
+ * Optional: Modify an existing password policy entry to match the values
+ * in policy. Return an error if the policy does not already exist.
+ */
+ krb5_error_code (*put_policy)(krb5_context kcontext,
+ osa_policy_ent_t policy);
+
+ /*
+ * Optional: For each password policy entry in the database, invoke func
+ * with the argments data and the entry data. If match_entry is specified,
+ * the module may narrow the iteration to policy names matching that
+ * regular expression; a module may alternatively ignore match_entry.
+ */
+ krb5_error_code (*iter_policy)(krb5_context kcontext, char *match_entry,
+ osa_adb_iter_policy_func func,
+ void *data);
+
+ /*
+ * Optional: Delete the password policy entry with the name policy. Return
+ * an error if the entry does not exist.
+ */
+ krb5_error_code (*delete_policy)(krb5_context kcontext, char *policy);
+
+ /*
+ * Optional with default: Retrieve a master keyblock from the stash file
+ * db_args, filling in *key and *kvno. mname is the name of the master
+ * principal for the realm.
+ *
+ * The default implementation reads the master keyblock from a keytab or
+ * old-format stash file.
+ */
+ krb5_error_code (*fetch_master_key)(krb5_context kcontext,
+ krb5_principal mname,
+ krb5_keyblock *key, krb5_kvno *kvno,
+ char *db_args);
+
+ /*
+ * Optional with default: Given a keyblock for some version of the
+ * database's master key, fetch the decrypted master key values from the
+ * database and store the list into *mkeys_list. The caller will free
+ * *mkeys_list using a libkdb5 function which uses the standard free()
+ * function, so the module must not use a custom allocator.
+ *
+ * The caller may not know the version number of the master key it has, in
+ * which case it will pass IGNORE_VNO.
+ *
+ * The default implementation ignores kvno and tries the key against the
+ * current master key data and all KRB5_TL_MKEY_AUX values, which contain
+ * copies of the master keys encrypted with old master keys.
+ */
+ krb5_error_code (*fetch_master_key_list)(krb5_context kcontext,
+ krb5_principal mname,
+ const krb5_keyblock *key,
+ krb5_keylist_node **mkeys_list);
+
+ /*
+ * Optional with default: Save a list of master keyblocks, obtained from
+ * fetch_master_key_list, into the stash file db_arg. The caller will set
+ * master_pwd to NULL, so the module should just ignore it. mname is the
+ * name of the master principal for the realm.
+ *
+ * The default implementation saves the list of master keys in a
+ * keytab-format file.
+ */
+ krb5_error_code (*store_master_key_list)(krb5_context kcontext,
+ char *db_arg,
+ krb5_principal mname,
+ krb5_keylist_node *keylist,
+ char *master_pwd);
+
+ /*
+ * Optional with default: Starting at position *start, scan the key data of
+ * a database entry for a key matching the enctype ktype, the salt type
+ * stype, and the version kvno. Store the resulting key into *kdatap and
+ * set *start to the position after the key found. If ktype is negative,
+ * match any enctype. If stype is negative, match any salt type. If kvno
+ * is zero or negative, find the most recent key version satisfying the
+ * other constraints.
+ */
+ krb5_error_code (*dbe_search_enctype)(krb5_context kcontext,
+ krb5_db_entry *dbentp,
+ krb5_int32 *start, krb5_int32 ktype,
+ krb5_int32 stype, krb5_int32 kvno,
+ krb5_key_data **kdatap);
+
+
+ /*
+ * Optional with default: Change the key data for db_entry to include keys
+ * derived from the password passwd in each of the specified key-salt
+ * types, at version new_kvno. Discard the old key data if keepold is not
+ * set.
+ *
+ * The default implementation uses the keyblock master_key to encrypt each
+ * new key, via the function encrypt_key_data.
+ */
+ krb5_error_code (*change_pwd)(krb5_context context,
+ krb5_keyblock *master_key,
+ krb5_key_salt_tuple *ks_tuple,
+ int ks_tuple_count, char *passwd,
+ int new_kvno, krb5_boolean keepold,
+ krb5_db_entry *db_entry);
+
+ /*
+ * Optional: Promote a temporary database to be the live one. context must
+ * be initialized with an exclusively locked database created with the
+ * "temporary" db_arg. On success, the database object contained in
+ * context will be finalized.
+ *
+ * This method is used by kdb5_util load to replace the live database with
+ * minimal loss of read availability.
+ */
+ krb5_error_code (*promote_db)(krb5_context context, char *conf_section,
+ char **db_args);
+
+ /*
+ * Optional with default: Decrypt the key in key_data with master keyblock
+ * mkey, placing the result into dbkey. Copy the salt from key_data, if
+ * any, into keysalt. Either dbkey or keysalt may be left unmodified on
+ * successful return if key_data does not contain key or salt information.
+ *
+ * The default implementation expects the encrypted key (in krb5_c_encrypt
+ * format) to be stored in key_data_contents[0], with length given by
+ * key_data_length[0]. If key_data_ver is 2, it expects the salt to be
+ * stored, unencrypted, in key_data_contents[1], with length given by
+ * key_data_length[1].
+ */
+ krb5_error_code (*decrypt_key_data)(krb5_context kcontext,
+ const krb5_keyblock *mkey,
+ const krb5_key_data *key_data,
+ krb5_keyblock *dbkey,
+ krb5_keysalt *keysalt);
+
+ /*
+ * Optional with default: Encrypt dbkey with master keyblock mkey, placing
+ * the result into key_data along with keysalt.
+ *
+ * The default implementation stores the encrypted key (in krb5_c_encrypt
+ * format) in key_data_contents[0] and the length in key_data_length[0].
+ * If keysalt is specified, it sets key_data_ver to 2, and stores the salt
+ * in key_data_contents[1] and its length in key_data_length[1]. If
+ * keysalt is not specified, key_data_ver is set to 1.
+ */
+ krb5_error_code (*encrypt_key_data)(krb5_context kcontext,
+ const krb5_keyblock *mkey,
+ const krb5_keyblock *dbkey,
+ const krb5_keysalt *keysalt,
+ int keyver, krb5_key_data *key_data);
+
+ /*
+ * Optional: Generate signed authorization data, such as a Windows PAC, for
+ * the ticket to be returned to the client. Place the signed authorization
+ * data, if any, in *signed_auth_data. This function will be invoked for
+ * an AS request if the client included padata requesting a PAC. This
+ * function will be invoked for a TGS request if there is authorization
+ * data in the TGT, if the client is from another realm, or if the TGS
+ * request is an S4U2Self or S4U2Proxy request. This function will not be
+ * invoked during TGS requests if the server principal has the
+ * no_auth_data_required attribute set. Input parameters are:
+ *
+ * flags: The flags used to look up the client principal.
+ *
+ * client_princ: For S4U2Proxy TGS requests, the client principal
+ * requested by the service; for regular TGS requests, the
+ * possibly-canonicalized client principal.
+ *
+ * client: The DB entry of the client. For S4U2Self, this will be the DB
+ * entry for the client principal requested by the service).
+ *
+ * server: The DB entry of the service principal.
+ *
+ * krbtgt: For TGS requests, the DB entry of the server of the ticket in
+ * the PA-TGS-REQ padata; this is usually a local or cross-realm krbtgt
+ * principal, but not always. For AS requests, the DB entry of the
+ * service principal; this is usually a local krbtgt principal, but not
+ * always.
+ *
+ * client_key: The reply key for the KDC request, before any FAST armor
+ * is applied. For AS requests, this may be the client's long-term key
+ * or a key chosen by a preauth mechanism. For TGS requests, this may
+ * be the subkey found in the AP-REQ or the session key of the TGT.
+ *
+ * server_key: The server key used to encrypt the returned ticket.
+ *
+ * krbtgt_key: For TGS requests, the key used to decrypt the ticket in
+ * the PA-TGS-REQ padata. For AS requests, the server key used to
+ * encrypt the returned ticket.
+ *
+ * session_key: The session key of the ticket being granted to the
+ * requestor.
+ *
+ * authtime: The timestamp of the original client authentication time.
+ * For AS requests, this is the current time. For TGS requests, this
+ * is the authtime of the subject ticket (TGT or S4U2Proxy evidence
+ * ticket).
+ *
+ * tgt_auth_data: For TGS requests, the authorization data present in the
+ * subject ticket. For AS requests, NULL.
+ */
+ krb5_error_code (*sign_authdata)(krb5_context kcontext,
+ unsigned int flags,
+ krb5_const_principal client_princ,
+ krb5_db_entry *client,
+ krb5_db_entry *server,
+ krb5_db_entry *krbtgt,
+ krb5_keyblock *client_key,
+ krb5_keyblock *server_key,
+ krb5_keyblock *krbtgt_key,
+ krb5_keyblock *session_key,
+ krb5_timestamp authtime,
+ krb5_authdata **tgt_auth_data,
+ krb5_authdata ***signed_auth_data);
+
+ /*
+ * Optional: Perform a policy check on a cross-realm ticket's transited
+ * field. Return 0 if the check authoritatively succeeds,
+ * KRB5_PLUGIN_NO_HANDLE to use the core transited-checking mechanisms, or
+ * another error (other than KRB5_PLUGIN_OP_NOTSUPP) if the check fails.
+ */
+ krb5_error_code (*check_transited_realms)(krb5_context kcontext,
+ const krb5_data *tr_contents,
+ const krb5_data *client_realm,
+ const krb5_data *server_realm);
+
+ /*
+ * Optional: Perform a policy check on an AS request, in addition to the
+ * standard policy checks. Return 0 if the AS request is allowed. If the
+ * AS request is not allowed:
+ * - Place a short string literal into *status.
+ * - If desired, place data into e_data. Any data placed here will be
+ * freed by the caller using the standard free function.
+ * - Return an appropriate error (such as KRB5KDC_ERR_POLICY).
+ */
+ krb5_error_code (*check_policy_as)(krb5_context kcontext,
+ krb5_kdc_req *request,
+ krb5_db_entry *client,
+ krb5_db_entry *server,
+ krb5_timestamp kdc_time,
+ const char **status,
+ krb5_pa_data ***e_data);
+
+ /*
+ * Optional: Perform a policy check on a TGS request, in addition to the
+ * standard policy checks. Return 0 if the TGS request is allowed. If the
+ * TGS request is not allowed:
+ * - Place a short string literal into *status.
+ * - If desired, place data into e_data. Any data placed here will be
+ * freed by the caller using the standard free function.
+ * - Return an appropriate error (such as KRB5KDC_ERR_POLICY).
+ * The input parameter ticket contains the TGT used in the TGS request.
+ */
+ krb5_error_code (*check_policy_tgs)(krb5_context kcontext,
+ krb5_kdc_req *request,
+ krb5_db_entry *server,
+ krb5_ticket *ticket,
+ const char **status,
+ krb5_pa_data ***e_data);
+
+ /*
+ * Optional: This method informs the module of a successful or unsuccessful
+ * AS request.
+ */
+ void (*audit_as_req)(krb5_context kcontext, krb5_kdc_req *request,
+ krb5_db_entry *client, krb5_db_entry *server,
+ krb5_timestamp authtime, krb5_error_code error_code);
+
+ /* Note: there is currently no method for auditing TGS requests. */
+
+ /*
+ * Optional: This method informs the module of a request to reload
+ * configuration or other state (that is, the KDC received a SIGHUP).
+ */
+ void (*refresh_config)(krb5_context kcontext);
+
+ /*
+ * Optional: Perform a policy check on server being allowed to obtain
+ * tickets from client to proxy. (Note that proxy is the target of the
+ * delegation, not the delegating service; the term "proxy" is from the
+ * viewpoint of the delegating service asking another service to perform
+ * some of its work in the authentication context of the client. This
+ * terminology comes from the Microsoft S4U protocol documentation.)
+ * Return 0 if policy allows it, or an appropriate error (such as
+ * KRB5KDC_ERR_POLICY) if not. If this method is not implemented, all
+ * S4U2Proxy delegation requests will be rejected.
+ */
+ krb5_error_code (*check_allowed_to_delegate)(krb5_context context,
+ krb5_const_principal client,
+ const krb5_db_entry *server,
+ krb5_const_principal proxy);
+
+ /* End of minor version 0. */
+
+ /*
+ * Optional: Free the e_data pointer of a database entry. If this method
+ * is not implemented, the e_data pointer in principal entries will be
+ * freed with free() as seen by libkdb5.
+ */
+ void (*free_principal_e_data)(krb5_context kcontext, krb5_octet *e_data);
+
+ /* End of minor version 1 for major version 6. */
+} kdb_vftabl;
+
+#endif /* !defined(_WIN32) */
+
+#endif /* KRB5_KDB5__ */
diff --git a/src/include/kdb_kt.h b/src/include/kdb_kt.h
new file mode 100644
index 000000000000..6a71c3c10943
--- /dev/null
+++ b/src/include/kdb_kt.h
@@ -0,0 +1,38 @@
+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/* include/kdb_kt.h - KDC keytab declarations */
+/*
+ * Copyright 1997 by the Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ * require a specific license from the United States Government.
+ * It is the responsibility of any person or organization contemplating
+ * export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission. Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose. It is provided "as is" without express
+ * or implied warranty.
+ */
+
+#ifndef KRB5_KDB5_KT_H
+#define KRB5_KDB5_KT_H
+
+#include "kdb.h"
+
+extern struct _krb5_kt_ops krb5_kt_kdb_ops;
+
+krb5_error_code krb5_ktkdb_resolve (krb5_context, const char *, krb5_keytab *);
+
+krb5_error_code krb5_ktkdb_set_context(krb5_context);
+
+#endif /* KRB5_KDB5_DBM__ */
diff --git a/src/include/kdb_log.h b/src/include/kdb_log.h
new file mode 100644
index 000000000000..25b823674a9f
--- /dev/null
+++ b/src/include/kdb_log.h
@@ -0,0 +1,114 @@
+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/*
+ * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#ifndef _KDB_LOG_H
+#define _KDB_LOG_H
+
+/* #pragma ident "@(#)kdb_log.h 1.3 04/02/23 SMI" */
+
+#include <iprop_hdr.h>
+#include <iprop.h>
+#include <limits.h>
+#include "kdb.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * DB macros
+ */
+#define INDEX(ulog, i) (kdb_ent_header_t *)((char *)(ulog) + \
+ sizeof(kdb_hlog_t) + \
+ (i) * ulog->kdb_block)
+
+/*
+ * Current DB version #
+ */
+#define KDB_VERSION 1
+
+/*
+ * DB log states
+ */
+#define KDB_STABLE 1
+#define KDB_UNSTABLE 2
+#define KDB_CORRUPT 3
+
+/*
+ * DB log constants
+ */
+#define KDB_ULOG_MAGIC 0x6661212
+#define KDB_ULOG_HDR_MAGIC 0x6662323
+
+/*
+ * Default ulog file attributes
+ */
+#define DEF_ULOGENTRIES 1000
+#define ULOG_IDLE_TIME 10 /* in seconds */
+/*
+ * Max size of update entry + update header
+ * We make this large since resizing can be costly.
+ */
+#define ULOG_BLOCK 2048 /* Default size of principal record */
+
+#define MAXLOGLEN 0x10000000 /* 256 MB log file */
+
+/*
+ * Prototype declarations
+ */
+krb5_error_code ulog_map(krb5_context context, const char *logname,
+ uint32_t entries);
+krb5_error_code ulog_init_header(krb5_context context);
+krb5_error_code ulog_add_update(krb5_context context, kdb_incr_update_t *upd);
+krb5_error_code ulog_get_entries(krb5_context context, const kdb_last_t *last,
+ kdb_incr_result_t *ulog_handle);
+krb5_error_code ulog_replay(krb5_context context, kdb_incr_result_t *incr_ret,
+ char **db_args);
+krb5_error_code ulog_conv_2logentry(krb5_context context, krb5_db_entry *entry,
+ kdb_incr_update_t *update);
+krb5_error_code ulog_conv_2dbentry(krb5_context context, krb5_db_entry **entry,
+ kdb_incr_update_t *update);
+void ulog_free_entries(kdb_incr_update_t *updates, int no_of_updates);
+krb5_error_code ulog_set_role(krb5_context ctx, iprop_role role);
+update_status_t ulog_get_sno_status(krb5_context context,
+ const kdb_last_t *last);
+krb5_error_code ulog_get_last(krb5_context context, kdb_last_t *last_out);
+krb5_error_code ulog_set_last(krb5_context context, const kdb_last_t *last);
+void ulog_fini(krb5_context context);
+
+typedef struct kdb_hlog {
+ uint32_t kdb_hmagic; /* Log header magic # */
+ uint16_t db_version_num; /* Kerberos database version no. */
+ uint32_t kdb_num; /* # of updates in log */
+ kdbe_time_t kdb_first_time; /* Timestamp of first update */
+ kdbe_time_t kdb_last_time; /* Timestamp of last update */
+ kdb_sno_t kdb_first_sno; /* First serial # in the update log */
+ kdb_sno_t kdb_last_sno; /* Last serial # in the update log */
+ uint16_t kdb_state; /* State of update log */
+ uint16_t kdb_block; /* Block size of each element */
+} kdb_hlog_t;
+
+typedef struct kdb_ent_header {
+ uint32_t kdb_umagic; /* Update entry magic # */
+ kdb_sno_t kdb_entry_sno; /* Serial # of entry */
+ kdbe_time_t kdb_time; /* Timestamp of update */
+ bool_t kdb_commit; /* Is the entry committed or not */
+ uint32_t kdb_entry_size; /* Size of update entry */
+ uint8_t entry_data[4]; /* Address of kdb_incr_update_t */
+} kdb_ent_header_t;
+
+typedef struct _kdb_log_context {
+ iprop_role iproprole;
+ kdb_hlog_t *ulog;
+ uint32_t ulogentries;
+ int ulogfd;
+} kdb_log_context;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* !_KDB_LOG_H */
diff --git a/src/include/krad.h b/src/include/krad.h
new file mode 100644
index 000000000000..e4edb524caf6
--- /dev/null
+++ b/src/include/krad.h
@@ -0,0 +1,265 @@
+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/*
+ * Copyright 2013 Red Hat, Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * This API is not considered as stable as the main krb5 API.
+ *
+ * - We may make arbitrary incompatible changes between feature releases
+ * (e.g. from 1.12 to 1.13).
+ * - We will make some effort to avoid making incompatible changes for
+ * bugfix releases, but will make them if necessary.
+ */
+
+#ifndef KRAD_H_
+#define KRAD_H_
+
+#include <krb5.h>
+#include <verto.h>
+#include <stddef.h>
+#include <stdio.h>
+
+#define KRAD_PACKET_SIZE_MAX 4096
+
+#define KRAD_SERVICE_TYPE_LOGIN 1
+#define KRAD_SERVICE_TYPE_FRAMED 2
+#define KRAD_SERVICE_TYPE_CALLBACK_LOGIN 3
+#define KRAD_SERVICE_TYPE_CALLBACK_FRAMED 4
+#define KRAD_SERVICE_TYPE_OUTBOUND 5
+#define KRAD_SERVICE_TYPE_ADMINISTRATIVE 6
+#define KRAD_SERVICE_TYPE_NAS_PROMPT 7
+#define KRAD_SERVICE_TYPE_AUTHENTICATE_ONLY 8
+#define KRAD_SERVICE_TYPE_CALLBACK_NAS_PROMPT 9
+#define KRAD_SERVICE_TYPE_CALL_CHECK 10
+#define KRAD_SERVICE_TYPE_CALLBACK_ADMINISTRATIVE 11
+
+typedef struct krad_attrset_st krad_attrset;
+typedef struct krad_packet_st krad_packet;
+typedef struct krad_client_st krad_client;
+typedef unsigned char krad_code;
+typedef unsigned char krad_attr;
+
+/* Called when a response is received or the request times out. */
+typedef void
+(*krad_cb)(krb5_error_code retval, const krad_packet *request,
+ const krad_packet *response, void *data);
+
+/*
+ * Called to iterate over a set of requests. Either the callback will be
+ * called until it returns NULL, or it will be called with cancel = TRUE to
+ * terminate in the middle of an iteration.
+ */
+typedef const krad_packet *
+(*krad_packet_iter_cb)(void *data, krb5_boolean cancel);
+
+/*
+ * Code
+ */
+
+/* Convert a code name to its number. Only works for codes defined
+ * by RFC 2875 or 2882. Returns 0 if the name was not found. */
+krad_code
+krad_code_name2num(const char *name);
+
+/* Convert a code number to its name. Only works for attributes defined
+ * by RFC 2865 or 2882. Returns NULL if the name was not found. */
+const char *
+krad_code_num2name(krad_code code);
+
+/*
+ * Attribute
+ */
+
+/* Convert an attribute name to its number. Only works for attributes defined
+ * by RFC 2865. Returns 0 if the name was not found. */
+krad_attr
+krad_attr_name2num(const char *name);
+
+/* Convert an attribute number to its name. Only works for attributes defined
+ * by RFC 2865. Returns NULL if the name was not found. */
+const char *
+krad_attr_num2name(krad_attr type);
+
+/*
+ * Attribute set
+ */
+
+/* Create a new attribute set. */
+krb5_error_code
+krad_attrset_new(krb5_context ctx, krad_attrset **set);
+
+/* Create a deep copy of an attribute set. */
+krb5_error_code
+krad_attrset_copy(const krad_attrset *set, krad_attrset **copy);
+
+/* Free an attribute set. */
+void
+krad_attrset_free(krad_attrset *set);
+
+/* Add an attribute to a set. */
+krb5_error_code
+krad_attrset_add(krad_attrset *set, krad_attr type, const krb5_data *data);
+
+/* Add a four-octet unsigned number attribute to the given set. */
+krb5_error_code
+krad_attrset_add_number(krad_attrset *set, krad_attr type, krb5_ui_4 num);
+
+/* Delete the specified attribute. */
+void
+krad_attrset_del(krad_attrset *set, krad_attr type, size_t indx);
+
+/* Get the specified attribute. */
+const krb5_data *
+krad_attrset_get(const krad_attrset *set, krad_attr type, size_t indx);
+
+/*
+ * Packet
+ */
+
+/* Determine the bytes needed from the socket to get the whole packet. Don't
+ * cache the return value as it can change! Returns -1 on EBADMSG. */
+ssize_t
+krad_packet_bytes_needed(const krb5_data *buffer);
+
+/* Free a packet. */
+void
+krad_packet_free(krad_packet *pkt);
+
+/*
+ * Create a new request packet.
+ *
+ * This function takes the attributes specified in set and converts them into a
+ * radius packet. The packet will have a randomized id. If cb is not NULL, it
+ * will be called passing data as the argument to iterate over a set of
+ * outstanding requests. In this case, the id will be both random and unique
+ * across the set of requests.
+ */
+krb5_error_code
+krad_packet_new_request(krb5_context ctx, const char *secret, krad_code code,
+ const krad_attrset *set, krad_packet_iter_cb cb,
+ void *data, krad_packet **request);
+
+/*
+ * Create a new response packet.
+ *
+ * This function is similar to krad_packet_new_requst() except that it crafts a
+ * packet in response to a request packet. This new packet will borrow values
+ * from the request such as the id and the authenticator.
+ */
+krb5_error_code
+krad_packet_new_response(krb5_context ctx, const char *secret, krad_code code,
+ const krad_attrset *set, const krad_packet *request,
+ krad_packet **response);
+
+/*
+ * Decode a request radius packet from krb5_data.
+ *
+ * The resulting decoded packet will be a request packet stored in *reqpkt.
+ *
+ * If cb is NULL, *duppkt will always be NULL.
+ *
+ * If cb is not NULL, it will be called (with the data argument) to iterate
+ * over a set of requests currently being processed. In this case, if the
+ * packet is a duplicate of an already received request, the original request
+ * will be set in *duppkt.
+ */
+krb5_error_code
+krad_packet_decode_request(krb5_context ctx, const char *secret,
+ const krb5_data *buffer, krad_packet_iter_cb cb,
+ void *data, const krad_packet **duppkt,
+ krad_packet **reqpkt);
+
+/*
+ * Decode a response radius packet from krb5_data.
+ *
+ * The resulting decoded packet will be a response packet stored in *rsppkt.
+ *
+ * If cb is NULL, *reqpkt will always be NULL.
+ *
+ * If cb is not NULL, it will be called (with the data argument) to iterate
+ * over a set of requests awaiting responses. In this case, if the response
+ * packet matches one of these requests, the original request will be set in
+ * *reqpkt.
+ */
+krb5_error_code
+krad_packet_decode_response(krb5_context ctx, const char *secret,
+ const krb5_data *buffer, krad_packet_iter_cb cb,
+ void *data, const krad_packet **reqpkt,
+ krad_packet **rsppkt);
+
+/* Encode packet. */
+const krb5_data *
+krad_packet_encode(const krad_packet *pkt);
+
+/* Get the code for the given packet. */
+krad_code
+krad_packet_get_code(const krad_packet *pkt);
+
+/* Get the specified attribute. */
+const krb5_data *
+krad_packet_get_attr(const krad_packet *pkt, krad_attr type, size_t indx);
+
+/*
+ * Client
+ */
+
+/* Create a new client. */
+krb5_error_code
+krad_client_new(krb5_context kctx, verto_ctx *vctx, krad_client **client);
+
+/* Free the client. */
+void
+krad_client_free(krad_client *client);
+
+/*
+ * Send a request to a radius server.
+ *
+ * The remote host may be specified by one of the following formats:
+ * - /path/to/unix.socket
+ * - IPv4
+ * - IPv4:port
+ * - IPv4:service
+ * - [IPv6]
+ * - [IPv6]:port
+ * - [IPv6]:service
+ * - hostname
+ * - hostname:port
+ * - hostname:service
+ *
+ * The timeout parameter (milliseconds) is the total timeout across all remote
+ * hosts (when DNS returns multiple entries) and all retries. For stream
+ * sockets, the retries parameter is ignored and no retries are performed.
+ *
+ * The cb function will be called with the data argument when either a response
+ * is received or the request times out on all possible remote hosts.
+ */
+krb5_error_code
+krad_client_send(krad_client *rc, krad_code code, const krad_attrset *attrs,
+ const char *remote, const char *secret, int timeout,
+ size_t retries, krad_cb cb, void *data);
+
+#endif /* KRAD_H_ */
diff --git a/src/include/krb5.h b/src/include/krb5.h
new file mode 100644
index 000000000000..62ef9bb957fc
--- /dev/null
+++ b/src/include/krb5.h
@@ -0,0 +1,8 @@
+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/* The MIT Kerberos header file krb5.h used to live here.
+
+ As of the 1.5 release, we're installing multiple Kerberos headers,
+ so they're all moving to a krb5/ subdirectory. This file is
+ present just to keep old software still compiling. Please update
+ your code to use the new path for the header. */
+#include <krb5/krb5.h>
diff --git a/src/include/krb5/audit_plugin.h b/src/include/krb5/audit_plugin.h
new file mode 100644
index 000000000000..b6e90649a095
--- /dev/null
+++ b/src/include/krb5/audit_plugin.h
@@ -0,0 +1,270 @@
+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/* include/krb5/audit_plugin.h - Audit plugin interface */
+/*
+ * Copyright (C) 2013 by the Massachusetts Institute of Technology.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/*
+ * NOTE: This is a private interface and may change incompatibly
+ * between versions.
+ */
+/*
+ * Declarations for KDC audit plugin module implementers. Audit modules allow
+ * the KDC to produce log output or audit records in any desired form.
+ *
+ * The audit interface has a single supported major version, which is 1. Major
+ * version 1 has a current minor version of 1. Audit modules should define a
+ * function named audit_<modulename>_initvt, matching the signature:
+ *
+ * krb5_error_code
+ * audit_modname_initvt(krb5_context context, int maj_ver, int min_ver,
+ * krb5_plugin_vtable vtable);
+ *
+ * The initvt function should:
+ *
+ * - Check that the supplied maj_ver number is supported by the module, or
+ * return KRB5_PLUGIN_VER_NOTSUPP if it is not.
+ *
+ * - Cast the vtable pointer as appropriate for the interface and maj_ver:
+ * maj_ver == 1: Cast to krb5_audit_vtable
+ *
+ * - Initialize the methods of the vtable, stopping as appropriate for the
+ * supplied min_ver. Optional methods may be left uninitialized.
+ *
+ * Memory for the vtable is allocated by the caller, not by the module.
+ */
+
+#ifndef KRB5_AU_PLUGIN_H_INCLUDED
+#define KRB5_AU_PLUGIN_H_INCLUDED
+#include <krb5/krb5.h>
+
+/** KDC processing steps */
+#define AUTHN_REQ_CL 1 /**< Authenticate request and client */
+#define SRVC_PRINC 2 /**< Determine service principal */
+#define VALIDATE_POL 3 /**< Validate local and protocol policies */
+#define ISSUE_TKT 4 /**< Issue ticket */
+#define ENCR_REP 5 /**< Encrypt reply */
+
+/** Types of violations */
+#define PROT_CONSTRAINT 1 /**< Protocol constraint */
+#define LOCAL_POLICY 2 /**< Local policy violation */
+
+#define REQID_LEN 32 /* Size of the alpha-numeric request ID */
+
+/** KDC audit state structure and declarations */
+typedef struct _krb5_audit_state {
+ krb5_kdc_req *request;
+ krb5_kdc_rep *reply;
+ krb5_address *cl_addr; /**< client address */
+ krb5_ui_4 cl_port; /**< client port */
+ int stage; /**< step in KDC processing */
+ const char *status; /**< KDC status message */
+ char *tkt_in_id; /**< primary (TGT) ticket ID */
+ char *tkt_out_id; /**< derived (service or referral TGT) ticket ID */
+ /** for s4u2proxy - evidence ticket ID; for u2u - second ticket ID */
+ char *evid_tkt_id;
+ char req_id[REQID_LEN]; /**< request ID */
+ krb5_data *cl_realm; /**< referrals: remote client's realm */
+ krb5_principal s4u2self_user; /**< impersonated user */
+ int violation; /**< local or protocol policy problem */
+} krb5_audit_state;
+
+/** An abstract type for audit module data. */
+typedef struct krb5_audit_moddata_st *krb5_audit_moddata;
+
+/*
+ * Mandatory:
+ * - krb5_audit_open_fn,
+ * Open connection to the audit system and initialize audit module data. If
+ * the underlying (OS or third party) audit facility fails to open, no
+ * auditable KDC events should be recorded.
+ */
+typedef krb5_error_code
+(*krb5_audit_open_fn)(krb5_audit_moddata *auctx);
+
+/*
+ * Mandatory:
+ * - krb5_audit_close_fn.
+ * Close connection to the underlying audit system.
+ */
+typedef krb5_error_code
+(*krb5_audit_close_fn)(krb5_audit_moddata auctx);
+
+/**
+ * Log KDC-start event.
+ *
+ * @param [in] auctx Audit context
+ * @param [in] ev_success Success/failure of the event being audited
+ *
+ * @note Optional.
+ *
+ * @retval 0 Success; otherwise - Kerberos error codes
+ */
+typedef krb5_error_code
+(*krb5_audit_kdc_start_fn)(krb5_audit_moddata auctx, krb5_boolean ev_success);
+
+/**
+ * Log KDC-stop event.
+ *
+ * @param [in] auctx Audit context
+ * @param [in] ev_success Success/failure of the event being audited
+ *
+ * @note Optional.
+ *
+ * @retval 0 Success; otherwise - Kerberos error codes
+ */
+typedef krb5_error_code
+(*krb5_audit_kdc_stop_fn)(krb5_audit_moddata auctx, krb5_boolean ev_success);
+
+/**
+ * Log AS exchange event.
+ *
+ * @param [in] auctx Audit context
+ * @param [in] ev_success Success/failure of the event being audited
+ * @param [in] state AS-request related auditable information
+ *
+ * The @a state provides the following data:
+ * - Full information about KDC request, assigned request ID, client address
+ * and port, and stage of the AS exchange
+ * - If available, the information about the encryption types of the short- and
+ * long-term keys, non-local client's referral realm, KDC status, the TGT
+ * and its ticket ID
+ *
+ * @note Optional.
+ *
+ * @retval 0 Success; otherwise - Kerberos error codes
+ */
+typedef krb5_error_code
+(*krb5_audit_as_req_fn)(krb5_audit_moddata auctx,
+ krb5_boolean ev_success, krb5_audit_state *state);
+
+/**
+ * Log TGS exchange event.
+ *
+ * @param [in] auctx Audit context
+ * @param [in] ev_success Success/failure of the event being audited
+ * @param [in] state TGS-request related auditable information
+ *
+ * The @a state provides the following data:
+ * - Full information about KDC request, assigned request ID, primary ticket
+ * ID, client address and port, and stage of the TGS exchange
+ * - If available, the information about the encryption types of the short- and
+ * long-term keys, KDC status, KDC reply, and the output ticket ID
+ *
+ * @note Optional.
+ *
+ * @retval 0 Success; otherwise - Kerberos error codes
+ */
+typedef krb5_error_code
+(*krb5_audit_tgs_req_fn)(krb5_audit_moddata auctx,
+ krb5_boolean ev_success, krb5_audit_state *state);
+
+/**
+ * Log S4U2SELF event.
+ *
+ * @param [in] auctx Audit context
+ * @param [in] ev_success Report on success or failure
+ * @param [in] state s4u2self related auditable information
+ *
+ * The @a state provides the following data:
+ * - Full information about KDC request, assigned request ID, client address
+ * and port, and stage of the TGS exchange
+ * - Requesting server's TGT ID, impersonated user principal name, and service
+ * "to self" ticket or referral TGT ID
+ * - If available, KDC status, local policy violation or S4U protocol
+ * constraints
+ *
+ * @note Optional.
+ *
+ * @retval 0 Success; otherwise - Kerberos error codes
+ */
+typedef krb5_error_code
+(*krb5_audit_s4u2self_fn)(krb5_audit_moddata auctx,
+ krb5_boolean ev_success, krb5_audit_state *state);
+
+/**
+ * Log S4U2PROXY event.
+ *
+ * @param [in] auctx Audit context
+ * @param [in] ev_success Report on success or failure
+ * @param [in] state s4u2proxy related auditable information
+ *
+ * The @a state provides the following data:
+ * - Full information about request, assigned request ID, client address and
+ * port, and stage of the TGS exchange
+ * - Requesting server's TGT ID, delegated user principal name, and evidence
+ * ticket ID
+ * - If available, KDC status, local policy violation or S4U protocol
+ * constraints
+ *
+ * @note Optional.
+ *
+ * @retval 0 Success; otherwise - Kerberos error codes
+ */
+typedef krb5_error_code
+(*krb5_audit_s4u2proxy_fn)(krb5_audit_moddata auctx,
+ krb5_boolean ev_success, krb5_audit_state *state);
+
+/**
+ * Log U2U event.
+ *
+ * @param [in] auctx Audit context
+ * @param [in] ev_success Report on success or failure
+ * @param [in] state user-to-user related auditable information
+ *
+ * The @a state provides the following data:
+ * - Full information about request, assigned request ID, client address and
+ * port, and stage of the TGS exchange,
+ * - Requestor's TGT ID, service ticket ID, and client's principal name in the
+ * second ticket
+ * - If available, KDC status
+ *
+ * @note Optional.
+ *
+ * @retval 0 Success; otherwise - Kerberos error codes
+ */
+typedef krb5_error_code
+(*krb5_audit_u2u_fn)(krb5_audit_moddata auctx,
+ krb5_boolean ev_success, krb5_audit_state *state);
+
+/* vtable declaration */
+typedef struct krb5_audit_vtable_st {
+ /* Mandatory: name of module. */
+ char *name;
+ krb5_audit_open_fn open;
+ krb5_audit_close_fn close;
+ krb5_audit_kdc_start_fn kdc_start;
+ krb5_audit_kdc_stop_fn kdc_stop;
+ krb5_audit_as_req_fn as_req;
+ krb5_audit_tgs_req_fn tgs_req;
+ krb5_audit_s4u2self_fn tgs_s4u2self;
+ krb5_audit_s4u2proxy_fn tgs_s4u2proxy;
+ krb5_audit_u2u_fn tgs_u2u;
+} *krb5_audit_vtable;
+
+#endif /* KRB5_AU_PLUGIN_H_INCLUDED */
diff --git a/src/include/krb5/authdata_plugin.h b/src/include/krb5/authdata_plugin.h
new file mode 100644
index 000000000000..5bb95fa59876
--- /dev/null
+++ b/src/include/krb5/authdata_plugin.h
@@ -0,0 +1,216 @@
+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/*
+ * Copyright (C) 2007 Apple Inc. All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ * require a specific license from the United States Government.
+ * It is the responsibility of any person or organization contemplating
+ * export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission. Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose. It is provided "as is" without express
+ * or implied warranty.
+ */
+
+/*
+ * Authorization data plugin definitions for Kerberos 5.
+ * This is considered an INTERNAL interface at this time.
+ *
+ * Some work is needed before exporting it:
+ *
+ * + Documentation.
+ * + Sample code.
+ * + Test cases (preferably automated testing under "make check").
+ *
+ * Other changes that would be nice to have, but not necessarily
+ * before making this interface public:
+ *
+ * + Library support for AD-IF-RELEVANT and similar wrappers. (We can
+ * make the plugin construct them if it wants them.)
+ * + KDC could combine/optimize wrapped AD elements provided by
+ * multiple plugins, e.g., two IF-RELEVANT sequences could be
+ * merged. (The preauth plugin API also has this bug, we're going
+ * to need a general fix.)
+ */
+
+#ifndef KRB5_AUTHDATA_PLUGIN_H_INCLUDED
+#define KRB5_AUTHDATA_PLUGIN_H_INCLUDED
+#include <krb5/krb5.h>
+
+typedef krb5_error_code
+(*authdata_client_plugin_init_proc)(krb5_context context,
+ void **plugin_context);
+
+#define AD_USAGE_AS_REQ 0x01
+#define AD_USAGE_TGS_REQ 0x02
+#define AD_USAGE_AP_REQ 0x04
+#define AD_USAGE_KDC_ISSUED 0x08
+#define AD_INFORMATIONAL 0x10
+#define AD_CAMMAC_PROTECTED 0x20
+#define AD_USAGE_MASK 0x2F
+
+struct _krb5_authdata_context;
+
+typedef void
+(*authdata_client_plugin_flags_proc)(krb5_context kcontext,
+ void *plugin_context,
+ krb5_authdatatype ad_type,
+ krb5_flags *flags);
+
+typedef void
+(*authdata_client_plugin_fini_proc)(krb5_context kcontext,
+ void *plugin_context);
+
+typedef krb5_error_code
+(*authdata_client_request_init_proc)(krb5_context kcontext,
+ struct _krb5_authdata_context *context,
+ void *plugin_context,
+ void **request_context);
+
+typedef void
+(*authdata_client_request_fini_proc)(krb5_context kcontext,
+ struct _krb5_authdata_context *context,
+ void *plugin_context,
+ void *request_context);
+
+typedef krb5_error_code
+(*authdata_client_import_authdata_proc)(krb5_context kcontext,
+ struct _krb5_authdata_context *context,
+ void *plugin_context,
+ void *request_context,
+ krb5_authdata **authdata,
+ krb5_boolean kdc_issued_flag,
+ krb5_const_principal issuer);
+
+typedef krb5_error_code
+(*authdata_client_export_authdata_proc)(krb5_context kcontext,
+ struct _krb5_authdata_context *context,
+ void *plugin_context,
+ void *request_context,
+ krb5_flags usage,
+ krb5_authdata ***authdata);
+
+typedef krb5_error_code
+(*authdata_client_get_attribute_types_proc)(krb5_context kcontext,
+ struct _krb5_authdata_context *context,
+ void *plugin_context,
+ void *request_context,
+ krb5_data **attrs);
+
+typedef krb5_error_code
+(*authdata_client_get_attribute_proc)(krb5_context kcontext,
+ struct _krb5_authdata_context *context,
+ void *plugin_context,
+ void *request_context,
+ const krb5_data *attribute,
+ krb5_boolean *authenticated,
+ krb5_boolean *complete,
+ krb5_data *value,
+ krb5_data *display_value,
+ int *more);
+
+typedef krb5_error_code
+(*authdata_client_set_attribute_proc)(krb5_context kcontext,
+ struct _krb5_authdata_context *context,
+ void *plugin_context,
+ void *request_context,
+ krb5_boolean complete,
+ const krb5_data *attribute,
+ const krb5_data *value);
+
+typedef krb5_error_code
+(*authdata_client_delete_attribute_proc)(krb5_context kcontext,
+ struct _krb5_authdata_context *context,
+ void *plugin_context,
+ void *request_context,
+ const krb5_data *attribute);
+
+typedef krb5_error_code
+(*authdata_client_export_internal_proc)(krb5_context kcontext,
+ struct _krb5_authdata_context *context,
+ void *plugin_context,
+ void *request_context,
+ krb5_boolean restrict_authenticated,
+ void **ptr);
+
+typedef void
+(*authdata_client_free_internal_proc)(krb5_context kcontext,
+ struct _krb5_authdata_context *context,
+ void *plugin_context,
+ void *request_context,
+ void *ptr);
+
+typedef krb5_error_code
+(*authdata_client_verify_proc)(krb5_context kcontext,
+ struct _krb5_authdata_context *context,
+ void *plugin_context,
+ void *request_context,
+ const krb5_auth_context *auth_context,
+ const krb5_keyblock *key,
+ const krb5_ap_req *req);
+
+typedef krb5_error_code
+(*authdata_client_size_proc)(krb5_context kcontext,
+ struct _krb5_authdata_context *context,
+ void *plugin_context,
+ void *request_context,
+ size_t *sizep);
+
+typedef krb5_error_code
+(*authdata_client_externalize_proc)(krb5_context kcontext,
+ struct _krb5_authdata_context *context,
+ void *plugin_context,
+ void *request_context,
+ krb5_octet **buffer,
+ size_t *lenremain);
+
+typedef krb5_error_code
+(*authdata_client_internalize_proc)(krb5_context kcontext,
+ struct _krb5_authdata_context *context,
+ void *plugin_context,
+ void *request_context,
+ krb5_octet **buffer,
+ size_t *lenremain);
+
+typedef krb5_error_code
+(*authdata_client_copy_proc)(krb5_context kcontext,
+ struct _krb5_authdata_context *context,
+ void *plugin_context,
+ void *request_context,
+ void *dst_plugin_context,
+ void *dst_request_context);
+
+typedef struct krb5plugin_authdata_client_ftable_v0 {
+ char *name;
+ krb5_authdatatype *ad_type_list;
+ authdata_client_plugin_init_proc init;
+ authdata_client_plugin_fini_proc fini;
+ authdata_client_plugin_flags_proc flags;
+ authdata_client_request_init_proc request_init;
+ authdata_client_request_fini_proc request_fini;
+ authdata_client_get_attribute_types_proc get_attribute_types;
+ authdata_client_get_attribute_proc get_attribute;
+ authdata_client_set_attribute_proc set_attribute;
+ authdata_client_delete_attribute_proc delete_attribute;
+ authdata_client_export_authdata_proc export_authdata;
+ authdata_client_import_authdata_proc import_authdata;
+ authdata_client_export_internal_proc export_internal;
+ authdata_client_free_internal_proc free_internal;
+ authdata_client_verify_proc verify;
+ authdata_client_size_proc size;
+ authdata_client_externalize_proc externalize;
+ authdata_client_internalize_proc internalize;
+ authdata_client_copy_proc copy; /* optional */
+} krb5plugin_authdata_client_ftable_v0;
+
+#endif /* KRB5_AUTHDATA_PLUGIN_H_INCLUDED */
diff --git a/src/include/krb5/ccselect_plugin.h b/src/include/krb5/ccselect_plugin.h
new file mode 100644
index 000000000000..ff9631311603
--- /dev/null
+++ b/src/include/krb5/ccselect_plugin.h
@@ -0,0 +1,105 @@
+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/*
+ * Copyright (C) 2011 by the Massachusetts Institute of Technology.
+ * All rights reserved.
+ *
+ * Export of this software from the United States of America may
+ * require a specific license from the United States Government.
+ * It is the responsibility of any person or organization contemplating
+ * export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission. Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose. It is provided "as is" without express
+ * or implied warranty.
+ */
+
+/*
+ * Declarations for credential cache selection module implementors.
+ *
+ * The ccselect pluggable interface currently has only one supported major
+ * version, which is 1. Major version 1 has a current minor version number of
+ * 1.
+ *
+ * Credential cache selection modules should define a function named
+ * ccselect_<modulename>_initvt, matching the signature:
+ *
+ * krb5_error_code
+ * ccselect_modname_initvt(krb5_context context, int maj_ver, int min_ver,
+ * krb5_plugin_vtable vtable);
+ *
+ * The initvt function should:
+ *
+ * - Check that the supplied maj_ver number is supported by the module, or
+ * return KRB5_PLUGIN_VER_NOTSUPP if it is not.
+ *
+ * - Cast the vtable pointer as appropriate for maj_ver:
+ * maj_ver == 1: Cast to krb5_ccselect_vtable
+ *
+ * - Initialize the methods of the vtable, stopping as appropriate for the
+ * supplied min_ver. Optional methods may be left uninitialized.
+ *
+ * Memory for the vtable is allocated by the caller, not by the module.
+ */
+
+#ifndef KRB5_CCSELECT_PLUGIN_H
+#define KRB5_CCSELECT_PLUGIN_H
+
+#include <krb5/krb5.h>
+#include <krb5/plugin.h>
+
+/* An abstract type for credential cache selection module data. */
+typedef struct krb5_ccselect_moddata_st *krb5_ccselect_moddata;
+
+#define KRB5_CCSELECT_PRIORITY_AUTHORITATIVE 2
+#define KRB5_CCSELECT_PRIORITY_HEURISTIC 1
+
+/*** Method type declarations ***/
+
+/*
+ * Mandatory: Initialize module data and set *priority_out to one of the
+ * KRB5_CCSELECT_PRIORITY constants above. Authoritative modules will be
+ * consulted before heuristic ones.
+ */
+typedef krb5_error_code
+(*krb5_ccselect_init_fn)(krb5_context context, krb5_ccselect_moddata *data_out,
+ int *priority_out);
+
+/*
+ * Mandatory: Select a cache based on a server principal. Return 0 on success,
+ * with *cache_out set to the selected cache and *princ_out set to its default
+ * principal. Return KRB5_PLUGIN_NO_HANDLE to defer to other modules. Return
+ * KRB5_CC_NOTFOUND with *princ_out set if the client principal can be
+ * authoritatively determined but no cache exists for it. Return other errors
+ * as appropriate.
+ */
+typedef krb5_error_code
+(*krb5_ccselect_choose_fn)(krb5_context context, krb5_ccselect_moddata data,
+ krb5_principal server, krb5_ccache *cache_out,
+ krb5_principal *princ_out);
+
+/* Optional: Release resources used by module data. */
+typedef void
+(*krb5_ccselect_fini_fn)(krb5_context context, krb5_ccselect_moddata data);
+
+/*** vtable declarations **/
+
+/* Credential cache selection plugin vtable for major version 1. */
+typedef struct krb5_ccselect_vtable_st {
+ const char *name; /* Mandatory: name of module. */
+ krb5_ccselect_init_fn init;
+ krb5_ccselect_choose_fn choose;
+ krb5_ccselect_fini_fn fini;
+ /* Minor version 1 ends here. */
+} *krb5_ccselect_vtable;
+
+#endif /* KRB5_CCSELECT_PLUGIN_H */
diff --git a/src/include/krb5/clpreauth_plugin.h b/src/include/krb5/clpreauth_plugin.h
new file mode 100644
index 000000000000..0106734ad734
--- /dev/null
+++ b/src/include/krb5/clpreauth_plugin.h
@@ -0,0 +1,333 @@
+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/*
+ * Copyright (c) 2006 Red Hat, Inc.
+ * Portions copyright (c) 2006, 2011 Massachusetts Institute of Technology
+ * All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Red Hat, Inc., nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Declarations for clpreauth plugin module implementors.
+ *
+ * The clpreauth interface has a single supported major version, which is
+ * 1. Major version 1 has a current minor version of 2. clpreauth modules
+ * should define a function named clpreauth_<modulename>_initvt, matching
+ * the signature:
+ *
+ * krb5_error_code
+ * clpreauth_modname_initvt(krb5_context context, int maj_ver,
+ * int min_ver, krb5_plugin_vtable vtable);
+ * The initvt function should:
+ *
+ * - Check that the supplied maj_ver number is supported by the module, or
+ * return KRB5_PLUGIN_VER_NOTSUPP if it is not.
+ *
+ * - Cast the vtable pointer as appropriate for the interface and maj_ver:
+ * maj_ver == 1: Cast to krb5_clpreauth_vtable
+ *
+ * - Initialize the methods of the vtable, stopping as appropriate for the
+ * supplied min_ver. Optional methods may be left uninitialized.
+ *
+ * Memory for the vtable is allocated by the caller, not by the module.
+ */
+
+#ifndef KRB5_CLPREAUTH_PLUGIN_H
+#define KRB5_CLPREAUTH_PLUGIN_H
+
+#include <krb5/krb5.h>
+#include <krb5/plugin.h>
+
+/* clpreauth mechanism property flags */
+
+/* Provides a real answer which we can send back to the KDC. The client
+ * assumes that one real answer will be enough. */
+#define PA_REAL 0x00000001
+
+/* Doesn't provide a real answer, but must be given a chance to run before any
+ * REAL mechanism callbacks. */
+#define PA_INFO 0x00000002
+
+/* Abstract type for a client request information handle. */
+typedef struct krb5_clpreauth_rock_st *krb5_clpreauth_rock;
+
+/* Abstract types for module data and per-request module data. */
+typedef struct krb5_clpreauth_moddata_st *krb5_clpreauth_moddata;
+typedef struct krb5_clpreauth_modreq_st *krb5_clpreauth_modreq;
+
+/* Before using a callback after version 1, modules must check the vers
+ * field of the callback structure. */
+typedef struct krb5_clpreauth_callbacks_st {
+ int vers;
+
+ /*
+ * Get the enctype expected to be used to encrypt the encrypted portion of
+ * the AS_REP packet. When handling a PREAUTH_REQUIRED error, this
+ * typically comes from etype-info2. When handling an AS reply, it is
+ * initialized from the AS reply itself.
+ */
+ krb5_enctype (*get_etype)(krb5_context context, krb5_clpreauth_rock rock);
+
+ /* Get a pointer to the FAST armor key, or NULL if the client is not using
+ * FAST. The returned pointer is an alias and should not be freed. */
+ krb5_keyblock *(*fast_armor)(krb5_context context,
+ krb5_clpreauth_rock rock);
+
+ /*
+ * Get a pointer to the client-supplied reply key, possibly invoking the
+ * prompter to ask for a password if this has not already been done. The
+ * returned pointer is an alias and should not be freed.
+ */
+ krb5_error_code (*get_as_key)(krb5_context context,
+ krb5_clpreauth_rock rock,
+ krb5_keyblock **keyblock);
+
+ /* Replace the reply key to be used to decrypt the AS response. */
+ krb5_error_code (*set_as_key)(krb5_context context,
+ krb5_clpreauth_rock rock,
+ const krb5_keyblock *keyblock);
+
+ /* End of version 1 clpreauth callbacks. */
+
+ /*
+ * Get the current time for use in a preauth response. If
+ * allow_unauth_time is true and the library has been configured to allow
+ * it, the current time will be offset using unauthenticated timestamp
+ * information received from the KDC in the preauth-required error, if one
+ * has been received. Otherwise, the timestamp in a preauth-required error
+ * will only be used if it is protected by a FAST channel. Only set
+ * allow_unauth_time if using an unauthenticated time offset would not
+ * create a security issue.
+ */
+ krb5_error_code (*get_preauth_time)(krb5_context context,
+ krb5_clpreauth_rock rock,
+ krb5_boolean allow_unauth_time,
+ krb5_timestamp *time_out,
+ krb5_int32 *usec_out);
+
+ /* Set a question to be answered by the responder and optionally provide
+ * a challenge. */
+ krb5_error_code (*ask_responder_question)(krb5_context context,
+ krb5_clpreauth_rock rock,
+ const char *question,
+ const char *challenge);
+
+ /* Get an answer from the responder, or NULL if the question was
+ * unanswered. */
+ const char *(*get_responder_answer)(krb5_context context,
+ krb5_clpreauth_rock rock,
+ const char *question);
+
+ /* Indicate interest in the AS key through the responder interface. */
+ void (*need_as_key)(krb5_context context, krb5_clpreauth_rock rock);
+
+ /*
+ * Get a configuration/state item from an input ccache, which may allow it
+ * to retrace the steps it took last time. The returned data string is an
+ * alias and should not be freed.
+ */
+ const char *(*get_cc_config)(krb5_context context,
+ krb5_clpreauth_rock rock, const char *key);
+
+ /*
+ * Set a configuration/state item which will be recorded to an output
+ * ccache, if the calling application supplied one. Both key and data
+ * should be valid UTF-8 text.
+ */
+ krb5_error_code (*set_cc_config)(krb5_context context,
+ krb5_clpreauth_rock rock,
+ const char *key, const char *data);
+ /* End of version 2 clpreauth callbacks (added in 1.11). */
+} *krb5_clpreauth_callbacks;
+
+/*
+ * Optional: per-plugin initialization/cleanup. The init function is called by
+ * libkrb5 when the plugin is loaded, and the fini function is called before
+ * the plugin is unloaded. These may be called multiple times in case the
+ * plugin is used in multiple contexts. The returned context lives the
+ * lifetime of the krb5_context.
+ */
+typedef krb5_error_code
+(*krb5_clpreauth_init_fn)(krb5_context context,
+ krb5_clpreauth_moddata *moddata_out);
+typedef void
+(*krb5_clpreauth_fini_fn)(krb5_context context,
+ krb5_clpreauth_moddata moddata);
+
+/*
+ * Optional (mandatory before MIT krb5 1.12): pa_type will be a member of the
+ * vtable's pa_type_list. Return PA_REAL if pa_type is a real
+ * preauthentication type or PA_INFO if it is an informational type. If this
+ * function is not defined in 1.12 or later, all pa_type values advertised by
+ * the module will be assumed to be real.
+ */
+typedef int
+(*krb5_clpreauth_get_flags_fn)(krb5_context context, krb5_preauthtype pa_type);
+
+/*
+ * Optional: per-request initialization/cleanup. The request_init function is
+ * called when beginning to process a get_init_creds request and the
+ * request_fini function is called when processing of the request is complete.
+ * This is optional. It may be called multiple times in the lifetime of a
+ * krb5_context.
+ */
+typedef void
+(*krb5_clpreauth_request_init_fn)(krb5_context context,
+ krb5_clpreauth_moddata moddata,
+ krb5_clpreauth_modreq *modreq_out);
+typedef void
+(*krb5_clpreauth_request_fini_fn)(krb5_context context,
+ krb5_clpreauth_moddata moddata,
+ krb5_clpreauth_modreq modreq);
+
+/*
+ * Optional: process server-supplied data in pa_data and set responder
+ * questions.
+ *
+ * encoded_previous_request may be NULL if there has been no previous request
+ * in the AS exchange.
+ */
+typedef krb5_error_code
+(*krb5_clpreauth_prep_questions_fn)(krb5_context context,
+ krb5_clpreauth_moddata moddata,
+ krb5_clpreauth_modreq modreq,
+ krb5_get_init_creds_opt *opt,
+ krb5_clpreauth_callbacks cb,
+ krb5_clpreauth_rock rock,
+ krb5_kdc_req *request,
+ krb5_data *encoded_request_body,
+ krb5_data *encoded_previous_request,
+ krb5_pa_data *pa_data);
+
+/*
+ * Mandatory: process server-supplied data in pa_data and return created data
+ * in pa_data_out. Also called after the AS-REP is received if the AS-REP
+ * includes preauthentication data of the associated type.
+ *
+ * as_key contains the client-supplied key if known, or an empty keyblock if
+ * not. If it is empty, the module may use gak_fct to fill it in.
+ *
+ * encoded_previous_request may be NULL if there has been no previous request
+ * in the AS exchange.
+ */
+typedef krb5_error_code
+(*krb5_clpreauth_process_fn)(krb5_context context,
+ krb5_clpreauth_moddata moddata,
+ krb5_clpreauth_modreq modreq,
+ krb5_get_init_creds_opt *opt,
+ krb5_clpreauth_callbacks cb,
+ krb5_clpreauth_rock rock,
+ krb5_kdc_req *request,
+ krb5_data *encoded_request_body,
+ krb5_data *encoded_previous_request,
+ krb5_pa_data *pa_data,
+ krb5_prompter_fct prompter, void *prompter_data,
+ krb5_pa_data ***pa_data_out);
+
+/*
+ * Optional: Attempt to use error and error_padata to try to recover from the
+ * given error. To work with both FAST and non-FAST errors, an implementation
+ * should generally consult error_padata rather than decoding error->e_data.
+ * For non-FAST errors, it contains the e_data decoded as either pa-data or
+ * typed-data.
+ *
+ * If this function is provided, and it returns 0 and stores data in
+ * pa_data_out, then the client library will retransmit the request.
+ */
+typedef krb5_error_code
+(*krb5_clpreauth_tryagain_fn)(krb5_context context,
+ krb5_clpreauth_moddata moddata,
+ krb5_clpreauth_modreq modreq,
+ krb5_get_init_creds_opt *opt,
+ krb5_clpreauth_callbacks cb,
+ krb5_clpreauth_rock rock,
+ krb5_kdc_req *request,
+ krb5_data *encoded_request_body,
+ krb5_data *encoded_previous_request,
+ krb5_preauthtype pa_type,
+ krb5_error *error,
+ krb5_pa_data **error_padata,
+ krb5_prompter_fct prompter, void *prompter_data,
+ krb5_pa_data ***pa_data_out);
+
+/*
+ * Optional: receive krb5_get_init_creds_opt information. The attr and value
+ * information supplied should be copied into moddata by the module if it
+ * wishes to reference it after returning from this call.
+ */
+typedef krb5_error_code
+(*krb5_clpreauth_supply_gic_opts_fn)(krb5_context context,
+ krb5_clpreauth_moddata moddata,
+ krb5_get_init_creds_opt *opt,
+ const char *attr, const char *value);
+
+typedef struct krb5_clpreauth_vtable_st {
+ /* Mandatory: name of module. */
+ char *name;
+
+ /* Mandatory: pointer to zero-terminated list of pa_types which this module
+ * can provide services for. */
+ krb5_preauthtype *pa_type_list;
+
+ /* Optional: pointer to zero-terminated list of enc_types which this module
+ * claims to add support for. */
+ krb5_enctype *enctype_list;
+
+ krb5_clpreauth_init_fn init;
+ krb5_clpreauth_fini_fn fini;
+ krb5_clpreauth_get_flags_fn flags;
+ krb5_clpreauth_request_init_fn request_init;
+ krb5_clpreauth_request_fini_fn request_fini;
+ krb5_clpreauth_process_fn process;
+ krb5_clpreauth_tryagain_fn tryagain;
+ krb5_clpreauth_supply_gic_opts_fn gic_opts;
+ /* Minor version 1 ends here. */
+
+ krb5_clpreauth_prep_questions_fn prep_questions;
+ /* Minor version 2 ends here. */
+} *krb5_clpreauth_vtable;
+
+/*
+ * This function allows a clpreauth plugin to obtain preauth options. The
+ * preauth_data returned from this function should be freed by calling
+ * krb5_get_init_creds_opt_free_pa().
+ */
+krb5_error_code KRB5_CALLCONV
+krb5_get_init_creds_opt_get_pa(krb5_context context,
+ krb5_get_init_creds_opt *opt,
+ int *num_preauth_data,
+ krb5_gic_opt_pa_data **preauth_data);
+
+/*
+ * This function frees the preauth_data that was returned by
+ * krb5_get_init_creds_opt_get_pa().
+ */
+void KRB5_CALLCONV
+krb5_get_init_creds_opt_free_pa(krb5_context context,
+ int num_preauth_data,
+ krb5_gic_opt_pa_data *preauth_data);
+
+#endif /* KRB5_CLPREAUTH_PLUGIN_H */
diff --git a/src/include/krb5/hostrealm_plugin.h b/src/include/krb5/hostrealm_plugin.h
new file mode 100644
index 000000000000..5012c8cb1ced
--- /dev/null
+++ b/src/include/krb5/hostrealm_plugin.h
@@ -0,0 +1,135 @@
+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/*
+ * Copyright (C) 2013 by the Massachusetts Institute of Technology.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS