diff options
author | Cy Schubert <cy@FreeBSD.org> | 2017-07-07 17:03:42 +0000 |
---|---|---|
committer | Cy Schubert <cy@FreeBSD.org> | 2017-07-07 17:03:42 +0000 |
commit | 33a9b234e7087f573ef08cd7318c6497ba08b439 (patch) | |
tree | d0ea40ad3bf5463a3c55795977c71bcb7d781b4b /src/include | |
download | src-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')
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 |