diff options
Diffstat (limited to 'source4/heimdal/lib/gssapi')
123 files changed, 22785 insertions, 0 deletions
| diff --git a/source4/heimdal/lib/gssapi/gssapi/gssapi.h b/source4/heimdal/lib/gssapi/gssapi/gssapi.h new file mode 100644 index 0000000000..d6417cdf0c --- /dev/null +++ b/source4/heimdal/lib/gssapi/gssapi/gssapi.h @@ -0,0 +1,821 @@ +/* + * Copyright (c) 1997 - 2007 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.  + */ + +/* $Id$ */ + +#ifndef GSSAPI_GSSAPI_H_ +#define GSSAPI_GSSAPI_H_ + +/* + * First, include stddef.h to get size_t defined. + */ +#include <stddef.h> + +#include <krb5-types.h> + +#ifndef BUILD_GSSAPI_LIB +#if defined(_WIN32) +#define GSSAPI_LIB_FUNCTION _stdcall __declspec(dllimport) +#define GSSAPI_LIB_VARIABLE __declspec(dllimport) +#else +#define GSSAPI_LIB_FUNCTION +#define GSSAPI_LIB_VARIABLE +#endif +#endif + +/* + * Now define the three implementation-dependent types. + */ + +typedef uint32_t OM_uint32; +typedef uint64_t OM_uint64; + +typedef uint32_t gss_uint32; + +struct gss_name_t_desc_struct; +typedef struct gss_name_t_desc_struct *gss_name_t; + +struct gss_ctx_id_t_desc_struct; +typedef struct gss_ctx_id_t_desc_struct *gss_ctx_id_t; + +typedef struct gss_OID_desc_struct { +      OM_uint32 length; +      void      *elements; +} gss_OID_desc, *gss_OID; + +typedef struct gss_OID_set_desc_struct  { +      size_t     count; +      gss_OID    elements; +} gss_OID_set_desc, *gss_OID_set; + +typedef int gss_cred_usage_t; + +struct gss_cred_id_t_desc_struct; +typedef struct gss_cred_id_t_desc_struct *gss_cred_id_t; + +typedef struct gss_buffer_desc_struct { +      size_t length; +      void *value; +} gss_buffer_desc, *gss_buffer_t; + +typedef struct gss_channel_bindings_struct { +      OM_uint32 initiator_addrtype; +      gss_buffer_desc initiator_address; +      OM_uint32 acceptor_addrtype; +      gss_buffer_desc acceptor_address; +      gss_buffer_desc application_data; +} *gss_channel_bindings_t; + +/* GGF extension data types */ +typedef struct gss_buffer_set_desc_struct { +      size_t count; +      gss_buffer_desc *elements; +} gss_buffer_set_desc, *gss_buffer_set_t; + +/* + * For now, define a QOP-type as an OM_uint32 + */ +typedef OM_uint32 gss_qop_t; + +/* + * Flag bits for context-level services. + */ +#define GSS_C_DELEG_FLAG 1 +#define GSS_C_MUTUAL_FLAG 2 +#define GSS_C_REPLAY_FLAG 4 +#define GSS_C_SEQUENCE_FLAG 8 +#define GSS_C_CONF_FLAG 16 +#define GSS_C_INTEG_FLAG 32 +#define GSS_C_ANON_FLAG 64 +#define GSS_C_PROT_READY_FLAG 128 +#define GSS_C_TRANS_FLAG 256 + +#define GSS_C_DCE_STYLE 4096 +#define GSS_C_IDENTIFY_FLAG 8192 +#define GSS_C_EXTENDED_ERROR_FLAG 16384 +#define GSS_C_DELEG_POLICY_FLAG 32768 + +/* + * Credential usage options + */ +#define GSS_C_BOTH 0 +#define GSS_C_INITIATE 1 +#define GSS_C_ACCEPT 2 + +/* + * Status code types for gss_display_status + */ +#define GSS_C_GSS_CODE 1 +#define GSS_C_MECH_CODE 2 + +/* + * The constant definitions for channel-bindings address families + */ +#define GSS_C_AF_UNSPEC     0 +#define GSS_C_AF_LOCAL      1 +#define GSS_C_AF_INET       2 +#define GSS_C_AF_IMPLINK    3 +#define GSS_C_AF_PUP        4 +#define GSS_C_AF_CHAOS      5 +#define GSS_C_AF_NS         6 +#define GSS_C_AF_NBS        7 +#define GSS_C_AF_ECMA       8 +#define GSS_C_AF_DATAKIT    9 +#define GSS_C_AF_CCITT      10 +#define GSS_C_AF_SNA        11 +#define GSS_C_AF_DECnet     12 +#define GSS_C_AF_DLI        13 +#define GSS_C_AF_LAT        14 +#define GSS_C_AF_HYLINK     15 +#define GSS_C_AF_APPLETALK  16 +#define GSS_C_AF_BSC        17 +#define GSS_C_AF_DSS        18 +#define GSS_C_AF_OSI        19 +#define GSS_C_AF_X25        21 +#define GSS_C_AF_INET6	    24 + +#define GSS_C_AF_NULLADDR   255 + +/* + * Various Null values + */ +#define GSS_C_NO_NAME ((gss_name_t) 0) +#define GSS_C_NO_BUFFER ((gss_buffer_t) 0) +#define GSS_C_NO_BUFFER_SET ((gss_buffer_set_t) 0) +#define GSS_C_NO_OID ((gss_OID) 0) +#define GSS_C_NO_OID_SET ((gss_OID_set) 0) +#define GSS_C_NO_CONTEXT ((gss_ctx_id_t) 0) +#define GSS_C_NO_CREDENTIAL ((gss_cred_id_t) 0) +#define GSS_C_NO_CHANNEL_BINDINGS ((gss_channel_bindings_t) 0) +#define GSS_C_EMPTY_BUFFER {0, NULL} + +/* + * Some alternate names for a couple of the above + * values.  These are defined for V1 compatibility. + */ +#define GSS_C_NULL_OID GSS_C_NO_OID +#define GSS_C_NULL_OID_SET GSS_C_NO_OID_SET + +/* + * Define the default Quality of Protection for per-message + * services.  Note that an implementation that offers multiple + * levels of QOP may define GSS_C_QOP_DEFAULT to be either zero + * (as done here) to mean "default protection", or to a specific + * explicit QOP value.  However, a value of 0 should always be + * interpreted by a GSSAPI implementation as a request for the + * default protection level. + */ +#define GSS_C_QOP_DEFAULT 0 + +#define GSS_KRB5_CONF_C_QOP_DES		0x0100 +#define GSS_KRB5_CONF_C_QOP_DES3_KD	0x0200 + +/* + * Expiration time of 2^32-1 seconds means infinite lifetime for a + * credential or security context + */ +#define GSS_C_INDEFINITE 0xfffffffful + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * The implementation must reserve static storage for a + * gss_OID_desc object containing the value + * {10, (void *)"\x2a\x86\x48\x86\xf7\x12" + *              "\x01\x02\x01\x01"}, + * corresponding to an object-identifier value of + * {iso(1) member-body(2) United States(840) mit(113554) + *  infosys(1) gssapi(2) generic(1) user_name(1)}.  The constant + * GSS_C_NT_USER_NAME should be initialized to point + * to that gss_OID_desc. + */ +extern GSSAPI_LIB_VARIABLE gss_OID GSS_C_NT_USER_NAME; + +/* + * The implementation must reserve static storage for a + * gss_OID_desc object containing the value + * {10, (void *)"\x2a\x86\x48\x86\xf7\x12" + *              "\x01\x02\x01\x02"}, + * corresponding to an object-identifier value of + * {iso(1) member-body(2) United States(840) mit(113554) + *  infosys(1) gssapi(2) generic(1) machine_uid_name(2)}. + * The constant GSS_C_NT_MACHINE_UID_NAME should be + * initialized to point to that gss_OID_desc. + */ +extern GSSAPI_LIB_VARIABLE gss_OID GSS_C_NT_MACHINE_UID_NAME; + +/* + * The implementation must reserve static storage for a + * gss_OID_desc object containing the value + * {10, (void *)"\x2a\x86\x48\x86\xf7\x12" + *              "\x01\x02\x01\x03"}, + * corresponding to an object-identifier value of + * {iso(1) member-body(2) United States(840) mit(113554) + *  infosys(1) gssapi(2) generic(1) string_uid_name(3)}. + * The constant GSS_C_NT_STRING_UID_NAME should be + * initialized to point to that gss_OID_desc. + */ +extern GSSAPI_LIB_VARIABLE gss_OID GSS_C_NT_STRING_UID_NAME; + +/* + * The implementation must reserve static storage for a + * gss_OID_desc object containing the value + * {6, (void *)"\x2b\x06\x01\x05\x06\x02"}, + * corresponding to an object-identifier value of + * {iso(1) org(3) dod(6) internet(1) security(5) + * nametypes(6) gss-host-based-services(2)).  The constant + * GSS_C_NT_HOSTBASED_SERVICE_X should be initialized to point + * to that gss_OID_desc.  This is a deprecated OID value, and + * implementations wishing to support hostbased-service names + * should instead use the GSS_C_NT_HOSTBASED_SERVICE OID, + * defined below, to identify such names; + * GSS_C_NT_HOSTBASED_SERVICE_X should be accepted a synonym + * for GSS_C_NT_HOSTBASED_SERVICE when presented as an input + * parameter, but should not be emitted by GSS-API + * implementations + */ +extern GSSAPI_LIB_VARIABLE gss_OID GSS_C_NT_HOSTBASED_SERVICE_X; + +/* + * The implementation must reserve static storage for a + * gss_OID_desc object containing the value + * {10, (void *)"\x2a\x86\x48\x86\xf7\x12" + *              "\x01\x02\x01\x04"}, corresponding to an + * object-identifier value of {iso(1) member-body(2) + * Unites States(840) mit(113554) infosys(1) gssapi(2) + * generic(1) service_name(4)}.  The constant + * GSS_C_NT_HOSTBASED_SERVICE should be initialized + * to point to that gss_OID_desc. + */ +extern GSSAPI_LIB_VARIABLE gss_OID GSS_C_NT_HOSTBASED_SERVICE; + +/* + * The implementation must reserve static storage for a + * gss_OID_desc object containing the value + * {6, (void *)"\x2b\x06\01\x05\x06\x03"}, + * corresponding to an object identifier value of + * {1(iso), 3(org), 6(dod), 1(internet), 5(security), + * 6(nametypes), 3(gss-anonymous-name)}.  The constant + * and GSS_C_NT_ANONYMOUS should be initialized to point + * to that gss_OID_desc. + */ +extern GSSAPI_LIB_VARIABLE gss_OID GSS_C_NT_ANONYMOUS; + +/* + * The implementation must reserve static storage for a + * gss_OID_desc object containing the value + * {6, (void *)"\x2b\x06\x01\x05\x06\x04"}, + * corresponding to an object-identifier value of + * {1(iso), 3(org), 6(dod), 1(internet), 5(security), + * 6(nametypes), 4(gss-api-exported-name)}.  The constant + * GSS_C_NT_EXPORT_NAME should be initialized to point + * to that gss_OID_desc. + */ +extern GSSAPI_LIB_VARIABLE gss_OID GSS_C_NT_EXPORT_NAME; + +/* + * Digest mechanism + */ + +extern GSSAPI_LIB_VARIABLE gss_OID GSS_SASL_DIGEST_MD5_MECHANISM; + +/* + * NTLM mechanism + */ + +extern GSSAPI_LIB_VARIABLE gss_OID GSS_NTLM_MECHANISM; + +/* Major status codes */ + +#define GSS_S_COMPLETE 0 + +/* + * Some "helper" definitions to make the status code macros obvious. + */ +#define GSS_C_CALLING_ERROR_OFFSET 24 +#define GSS_C_ROUTINE_ERROR_OFFSET 16 +#define GSS_C_SUPPLEMENTARY_OFFSET 0 +#define GSS_C_CALLING_ERROR_MASK 0377ul +#define GSS_C_ROUTINE_ERROR_MASK 0377ul +#define GSS_C_SUPPLEMENTARY_MASK 0177777ul + +/* + * The macros that test status codes for error conditions. + * Note that the GSS_ERROR() macro has changed slightly from + * the V1 GSSAPI so that it now evaluates its argument + * only once. + */ +#define GSS_CALLING_ERROR(x) \ +  (x & (GSS_C_CALLING_ERROR_MASK << GSS_C_CALLING_ERROR_OFFSET)) +#define GSS_ROUTINE_ERROR(x) \ +  (x & (GSS_C_ROUTINE_ERROR_MASK << GSS_C_ROUTINE_ERROR_OFFSET)) +#define GSS_SUPPLEMENTARY_INFO(x) \ +  (x & (GSS_C_SUPPLEMENTARY_MASK << GSS_C_SUPPLEMENTARY_OFFSET)) +#define GSS_ERROR(x) \ +  (x & ((GSS_C_CALLING_ERROR_MASK << GSS_C_CALLING_ERROR_OFFSET) | \ +        (GSS_C_ROUTINE_ERROR_MASK << GSS_C_ROUTINE_ERROR_OFFSET))) + +/* + * Now the actual status code definitions + */ + +/* + * Calling errors: + */ +#define GSS_S_CALL_INACCESSIBLE_READ \ +                             (1ul << GSS_C_CALLING_ERROR_OFFSET) +#define GSS_S_CALL_INACCESSIBLE_WRITE \ +                             (2ul << GSS_C_CALLING_ERROR_OFFSET) +#define GSS_S_CALL_BAD_STRUCTURE \ +                             (3ul << GSS_C_CALLING_ERROR_OFFSET) + +/* + * Routine errors: + */ +#define GSS_S_BAD_MECH (1ul << GSS_C_ROUTINE_ERROR_OFFSET) +#define GSS_S_BAD_NAME (2ul << GSS_C_ROUTINE_ERROR_OFFSET) +#define GSS_S_BAD_NAMETYPE (3ul << GSS_C_ROUTINE_ERROR_OFFSET) + +#define GSS_S_BAD_BINDINGS (4ul << GSS_C_ROUTINE_ERROR_OFFSET) +#define GSS_S_BAD_STATUS (5ul << GSS_C_ROUTINE_ERROR_OFFSET) +#define GSS_S_BAD_SIG (6ul << GSS_C_ROUTINE_ERROR_OFFSET) +#define GSS_S_BAD_MIC GSS_S_BAD_SIG +#define GSS_S_NO_CRED (7ul << GSS_C_ROUTINE_ERROR_OFFSET) +#define GSS_S_NO_CONTEXT (8ul << GSS_C_ROUTINE_ERROR_OFFSET) +#define GSS_S_DEFECTIVE_TOKEN (9ul << GSS_C_ROUTINE_ERROR_OFFSET) +#define GSS_S_DEFECTIVE_CREDENTIAL (10ul << GSS_C_ROUTINE_ERROR_OFFSET) +#define GSS_S_CREDENTIALS_EXPIRED (11ul << GSS_C_ROUTINE_ERROR_OFFSET) +#define GSS_S_CONTEXT_EXPIRED (12ul << GSS_C_ROUTINE_ERROR_OFFSET) +#define GSS_S_FAILURE (13ul << GSS_C_ROUTINE_ERROR_OFFSET) +#define GSS_S_BAD_QOP (14ul << GSS_C_ROUTINE_ERROR_OFFSET) +#define GSS_S_UNAUTHORIZED (15ul << GSS_C_ROUTINE_ERROR_OFFSET) +#define GSS_S_UNAVAILABLE (16ul << GSS_C_ROUTINE_ERROR_OFFSET) +#define GSS_S_DUPLICATE_ELEMENT (17ul << GSS_C_ROUTINE_ERROR_OFFSET) +#define GSS_S_NAME_NOT_MN (18ul << GSS_C_ROUTINE_ERROR_OFFSET) + +/* + * Supplementary info bits: + */ +#define GSS_S_CONTINUE_NEEDED (1ul << (GSS_C_SUPPLEMENTARY_OFFSET + 0)) +#define GSS_S_DUPLICATE_TOKEN (1ul << (GSS_C_SUPPLEMENTARY_OFFSET + 1)) +#define GSS_S_OLD_TOKEN (1ul << (GSS_C_SUPPLEMENTARY_OFFSET + 2)) +#define GSS_S_UNSEQ_TOKEN (1ul << (GSS_C_SUPPLEMENTARY_OFFSET + 3)) +#define GSS_S_GAP_TOKEN (1ul << (GSS_C_SUPPLEMENTARY_OFFSET + 4)) + +/* + * Finally, function prototypes for the GSS-API routines. + */ + +OM_uint32 GSSAPI_LIB_FUNCTION gss_acquire_cred +           (OM_uint32 * /*minor_status*/, +            const gss_name_t /*desired_name*/, +            OM_uint32 /*time_req*/, +            const gss_OID_set /*desired_mechs*/, +            gss_cred_usage_t /*cred_usage*/, +            gss_cred_id_t * /*output_cred_handle*/, +            gss_OID_set * /*actual_mechs*/, +            OM_uint32 * /*time_rec*/ +           ); + +OM_uint32 GSSAPI_LIB_FUNCTION gss_release_cred +           (OM_uint32 * /*minor_status*/, +            gss_cred_id_t * /*cred_handle*/ +           ); + +OM_uint32 GSSAPI_LIB_FUNCTION gss_init_sec_context +           (OM_uint32 * /*minor_status*/, +            const gss_cred_id_t /*initiator_cred_handle*/, +            gss_ctx_id_t * /*context_handle*/, +            const gss_name_t /*target_name*/, +            const gss_OID /*mech_type*/, +            OM_uint32 /*req_flags*/, +            OM_uint32 /*time_req*/, +            const gss_channel_bindings_t /*input_chan_bindings*/, +            const gss_buffer_t /*input_token*/, +            gss_OID * /*actual_mech_type*/, +            gss_buffer_t /*output_token*/, +            OM_uint32 * /*ret_flags*/, +            OM_uint32 * /*time_rec*/ +           ); + +OM_uint32 GSSAPI_LIB_FUNCTION gss_accept_sec_context +           (OM_uint32 * /*minor_status*/, +            gss_ctx_id_t * /*context_handle*/, +            const gss_cred_id_t /*acceptor_cred_handle*/, +            const gss_buffer_t /*input_token_buffer*/, +            const gss_channel_bindings_t /*input_chan_bindings*/, +            gss_name_t * /*src_name*/, +            gss_OID * /*mech_type*/, +            gss_buffer_t /*output_token*/, +            OM_uint32 * /*ret_flags*/, +            OM_uint32 * /*time_rec*/, +            gss_cred_id_t * /*delegated_cred_handle*/ +           ); + +OM_uint32 GSSAPI_LIB_FUNCTION gss_process_context_token +           (OM_uint32 * /*minor_status*/, +            const gss_ctx_id_t /*context_handle*/, +            const gss_buffer_t /*token_buffer*/ +           ); + +OM_uint32 GSSAPI_LIB_FUNCTION gss_delete_sec_context +           (OM_uint32 * /*minor_status*/, +            gss_ctx_id_t * /*context_handle*/, +            gss_buffer_t /*output_token*/ +           ); + +OM_uint32 GSSAPI_LIB_FUNCTION gss_context_time +           (OM_uint32 * /*minor_status*/, +            const gss_ctx_id_t /*context_handle*/, +            OM_uint32 * /*time_rec*/ +           ); + +OM_uint32 GSSAPI_LIB_FUNCTION gss_get_mic +           (OM_uint32 * /*minor_status*/, +            const gss_ctx_id_t /*context_handle*/, +            gss_qop_t /*qop_req*/, +            const gss_buffer_t /*message_buffer*/, +            gss_buffer_t /*message_token*/ +           ); + +OM_uint32 GSSAPI_LIB_FUNCTION gss_verify_mic +           (OM_uint32 * /*minor_status*/, +            const gss_ctx_id_t /*context_handle*/, +            const gss_buffer_t /*message_buffer*/, +            const gss_buffer_t /*token_buffer*/, +            gss_qop_t * /*qop_state*/ +           ); + +OM_uint32 GSSAPI_LIB_FUNCTION gss_wrap +           (OM_uint32 * /*minor_status*/, +            const gss_ctx_id_t /*context_handle*/, +            int /*conf_req_flag*/, +            gss_qop_t /*qop_req*/, +            const gss_buffer_t /*input_message_buffer*/, +            int * /*conf_state*/, +            gss_buffer_t /*output_message_buffer*/ +           ); + +OM_uint32 GSSAPI_LIB_FUNCTION gss_unwrap +           (OM_uint32 * /*minor_status*/, +            const gss_ctx_id_t /*context_handle*/, +            const gss_buffer_t /*input_message_buffer*/, +            gss_buffer_t /*output_message_buffer*/, +            int * /*conf_state*/, +            gss_qop_t * /*qop_state*/ +           ); + +OM_uint32 GSSAPI_LIB_FUNCTION gss_display_status +           (OM_uint32 * /*minor_status*/, +            OM_uint32 /*status_value*/, +            int /*status_type*/, +            const gss_OID /*mech_type*/, +            OM_uint32 * /*message_context*/, +            gss_buffer_t /*status_string*/ +           ); + +OM_uint32 GSSAPI_LIB_FUNCTION gss_indicate_mechs +           (OM_uint32 * /*minor_status*/, +            gss_OID_set * /*mech_set*/ +           ); + +OM_uint32 GSSAPI_LIB_FUNCTION gss_compare_name +           (OM_uint32 * /*minor_status*/, +            const gss_name_t /*name1*/, +            const gss_name_t /*name2*/, +            int * /*name_equal*/ +           ); + +OM_uint32 GSSAPI_LIB_FUNCTION gss_display_name +           (OM_uint32 * /*minor_status*/, +            const gss_name_t /*input_name*/, +            gss_buffer_t /*output_name_buffer*/, +            gss_OID * /*output_name_type*/ +           ); + +OM_uint32 GSSAPI_LIB_FUNCTION gss_import_name +           (OM_uint32 * /*minor_status*/, +            const gss_buffer_t /*input_name_buffer*/, +            const gss_OID /*input_name_type*/, +            gss_name_t * /*output_name*/ +           ); + +OM_uint32 GSSAPI_LIB_FUNCTION gss_export_name +           (OM_uint32  * /*minor_status*/, +            const gss_name_t /*input_name*/, +            gss_buffer_t /*exported_name*/ +           ); + +OM_uint32 GSSAPI_LIB_FUNCTION gss_release_name +           (OM_uint32 * /*minor_status*/, +            gss_name_t * /*input_name*/ +           ); + +OM_uint32 GSSAPI_LIB_FUNCTION gss_release_buffer +           (OM_uint32 * /*minor_status*/, +            gss_buffer_t /*buffer*/ +           ); + +OM_uint32 GSSAPI_LIB_FUNCTION gss_release_oid_set +           (OM_uint32 * /*minor_status*/, +            gss_OID_set * /*set*/ +           ); + +OM_uint32 GSSAPI_LIB_FUNCTION gss_inquire_cred +           (OM_uint32 * /*minor_status*/, +            const gss_cred_id_t /*cred_handle*/, +            gss_name_t * /*name*/, +            OM_uint32 * /*lifetime*/, +            gss_cred_usage_t * /*cred_usage*/, +            gss_OID_set * /*mechanisms*/ +           ); + +OM_uint32 GSSAPI_LIB_FUNCTION gss_inquire_context ( +            OM_uint32 * /*minor_status*/, +            const gss_ctx_id_t /*context_handle*/, +            gss_name_t * /*src_name*/, +            gss_name_t * /*targ_name*/, +            OM_uint32 * /*lifetime_rec*/, +            gss_OID * /*mech_type*/, +            OM_uint32 * /*ctx_flags*/, +            int * /*locally_initiated*/, +            int * /*open_context*/ +           ); + +OM_uint32 GSSAPI_LIB_FUNCTION gss_wrap_size_limit ( +            OM_uint32 * /*minor_status*/, +            const gss_ctx_id_t /*context_handle*/, +            int /*conf_req_flag*/, +            gss_qop_t /*qop_req*/, +            OM_uint32 /*req_output_size*/, +            OM_uint32 * /*max_input_size*/ +           ); + +OM_uint32 GSSAPI_LIB_FUNCTION gss_add_cred ( +            OM_uint32 * /*minor_status*/, +            const gss_cred_id_t /*input_cred_handle*/, +            const gss_name_t /*desired_name*/, +            const gss_OID /*desired_mech*/, +            gss_cred_usage_t /*cred_usage*/, +            OM_uint32 /*initiator_time_req*/, +            OM_uint32 /*acceptor_time_req*/, +            gss_cred_id_t * /*output_cred_handle*/, +            gss_OID_set * /*actual_mechs*/, +            OM_uint32 * /*initiator_time_rec*/, +            OM_uint32 * /*acceptor_time_rec*/ +           ); + +OM_uint32 GSSAPI_LIB_FUNCTION gss_inquire_cred_by_mech ( +            OM_uint32 * /*minor_status*/, +            const gss_cred_id_t /*cred_handle*/, +            const gss_OID /*mech_type*/, +            gss_name_t * /*name*/, +            OM_uint32 * /*initiator_lifetime*/, +            OM_uint32 * /*acceptor_lifetime*/, +            gss_cred_usage_t * /*cred_usage*/ +           ); + +OM_uint32 GSSAPI_LIB_FUNCTION gss_export_sec_context ( +            OM_uint32 * /*minor_status*/, +            gss_ctx_id_t * /*context_handle*/, +            gss_buffer_t /*interprocess_token*/ +           ); + +OM_uint32 GSSAPI_LIB_FUNCTION gss_import_sec_context ( +            OM_uint32 * /*minor_status*/, +            const gss_buffer_t /*interprocess_token*/, +            gss_ctx_id_t * /*context_handle*/ +           ); + +OM_uint32 GSSAPI_LIB_FUNCTION gss_create_empty_oid_set ( +            OM_uint32 * /*minor_status*/, +            gss_OID_set * /*oid_set*/ +           ); + +OM_uint32 GSSAPI_LIB_FUNCTION gss_add_oid_set_member ( +            OM_uint32 * /*minor_status*/, +            const gss_OID /*member_oid*/, +            gss_OID_set * /*oid_set*/ +           ); + +OM_uint32 GSSAPI_LIB_FUNCTION gss_test_oid_set_member ( +            OM_uint32 * /*minor_status*/, +            const gss_OID /*member*/, +            const gss_OID_set /*set*/, +            int * /*present*/ +           ); + +OM_uint32 GSSAPI_LIB_FUNCTION gss_inquire_names_for_mech ( +            OM_uint32 * /*minor_status*/, +            const gss_OID /*mechanism*/, +            gss_OID_set * /*name_types*/ +           ); + +OM_uint32 GSSAPI_LIB_FUNCTION gss_inquire_mechs_for_name ( +            OM_uint32 * /*minor_status*/, +            const gss_name_t /*input_name*/, +            gss_OID_set * /*mech_types*/ +           ); + +OM_uint32 GSSAPI_LIB_FUNCTION gss_canonicalize_name ( +            OM_uint32 * /*minor_status*/, +            const gss_name_t /*input_name*/, +            const gss_OID /*mech_type*/, +            gss_name_t * /*output_name*/ +           ); + +OM_uint32 GSSAPI_LIB_FUNCTION gss_duplicate_name ( +            OM_uint32 * /*minor_status*/, +            const gss_name_t /*src_name*/, +            gss_name_t * /*dest_name*/ +           ); + +OM_uint32 GSSAPI_LIB_FUNCTION gss_duplicate_oid ( +	    OM_uint32 * /* minor_status */, +	    gss_OID /* src_oid */, +	    gss_OID * /* dest_oid */ +           ); + +OM_uint32 GSSAPI_LIB_FUNCTION +gss_release_oid +	(OM_uint32 * /*minor_status*/, +	 gss_OID * /* oid */ +	); + +OM_uint32 GSSAPI_LIB_FUNCTION +gss_oid_to_str( +	    OM_uint32 * /*minor_status*/, +	    gss_OID /* oid */, +	    gss_buffer_t /* str */ +           ); + +OM_uint32 GSSAPI_LIB_FUNCTION +gss_inquire_sec_context_by_oid( +	    OM_uint32 * minor_status, +            const gss_ctx_id_t context_handle, +            const gss_OID desired_object, +            gss_buffer_set_t *data_set +           ); + +OM_uint32 GSSAPI_LIB_FUNCTION +gss_set_sec_context_option (OM_uint32 *minor_status, +			    gss_ctx_id_t *context_handle, +			    const gss_OID desired_object, +			    const gss_buffer_t value); + +OM_uint32 GSSAPI_LIB_FUNCTION +gss_set_cred_option (OM_uint32 *minor_status, +		     gss_cred_id_t *cred_handle, +		     const gss_OID object, +		     const gss_buffer_t value); + +int GSSAPI_LIB_FUNCTION +gss_oid_equal(const gss_OID a, const gss_OID b); + +OM_uint32 GSSAPI_LIB_FUNCTION +gss_create_empty_buffer_set +	   (OM_uint32 * minor_status, +	    gss_buffer_set_t *buffer_set); + +OM_uint32 GSSAPI_LIB_FUNCTION +gss_add_buffer_set_member +	   (OM_uint32 * minor_status, +	    const gss_buffer_t member_buffer, +	    gss_buffer_set_t *buffer_set); + +OM_uint32 GSSAPI_LIB_FUNCTION +gss_release_buffer_set +	   (OM_uint32 * minor_status, +	    gss_buffer_set_t *buffer_set); + +OM_uint32 GSSAPI_LIB_FUNCTION +gss_inquire_cred_by_oid(OM_uint32 *minor_status, +	                const gss_cred_id_t cred_handle, +	                const gss_OID desired_object, +	                gss_buffer_set_t *data_set); + +/* + * RFC 4401 + */ + +#define GSS_C_PRF_KEY_FULL 0 +#define GSS_C_PRF_KEY_PARTIAL 1 + +OM_uint32 GSSAPI_LIB_FUNCTION +gss_pseudo_random +	(OM_uint32 *minor_status, +	 gss_ctx_id_t context, +	 int prf_key, +	 const gss_buffer_t prf_in, +	 ssize_t desired_output_len, +	 gss_buffer_t prf_out +	); + +/* + * The following routines are obsolete variants of gss_get_mic, + * gss_verify_mic, gss_wrap and gss_unwrap.  They should be + * provided by GSSAPI V2 implementations for backwards + * compatibility with V1 applications.  Distinct entrypoints + * (as opposed to #defines) should be provided, both to allow + * GSSAPI V1 applications to link against GSSAPI V2 implementations, + * and to retain the slight parameter type differences between the + * obsolete versions of these routines and their current forms. + */ + +OM_uint32 GSSAPI_LIB_FUNCTION gss_sign +           (OM_uint32 * /*minor_status*/, +            gss_ctx_id_t /*context_handle*/, +            int /*qop_req*/, +            gss_buffer_t /*message_buffer*/, +            gss_buffer_t /*message_token*/ +           ); + +OM_uint32 GSSAPI_LIB_FUNCTION gss_verify +           (OM_uint32 * /*minor_status*/, +            gss_ctx_id_t /*context_handle*/, +            gss_buffer_t /*message_buffer*/, +            gss_buffer_t /*token_buffer*/, +            int * /*qop_state*/ +           ); + +OM_uint32 GSSAPI_LIB_FUNCTION gss_seal +           (OM_uint32 * /*minor_status*/, +            gss_ctx_id_t /*context_handle*/, +            int /*conf_req_flag*/, +            int /*qop_req*/, +            gss_buffer_t /*input_message_buffer*/, +            int * /*conf_state*/, +            gss_buffer_t /*output_message_buffer*/ +           ); + +OM_uint32 GSSAPI_LIB_FUNCTION gss_unseal +           (OM_uint32 * /*minor_status*/, +            gss_ctx_id_t /*context_handle*/, +            gss_buffer_t /*input_message_buffer*/, +            gss_buffer_t /*output_message_buffer*/, +            int * /*conf_state*/, +            int * /*qop_state*/ +           ); + +/* + * + */ + +OM_uint32 GSSAPI_LIB_FUNCTION +gss_inquire_sec_context_by_oid (OM_uint32 *minor_status, +	                        const gss_ctx_id_t context_handle, +	                        const gss_OID desired_object, +	                        gss_buffer_set_t *data_set); + +OM_uint32 GSSAPI_LIB_FUNCTION +gss_encapsulate_token(gss_buffer_t /* input_token */, +		      gss_OID /* oid */, +		      gss_buffer_t /* output_token */); + +OM_uint32 GSSAPI_LIB_FUNCTION +gss_decapsulate_token(gss_buffer_t /* input_token */, +		      gss_OID /* oid */, +		      gss_buffer_t /* output_token */); + + + +#ifdef __cplusplus +} +#endif + +#include <gssapi/gssapi_krb5.h> +#include <gssapi/gssapi_spnego.h> + +#endif /* GSSAPI_GSSAPI_H_ */ diff --git a/source4/heimdal/lib/gssapi/gssapi/gssapi_krb5.h b/source4/heimdal/lib/gssapi/gssapi/gssapi_krb5.h new file mode 100644 index 0000000000..bab719019d --- /dev/null +++ b/source4/heimdal/lib/gssapi/gssapi/gssapi_krb5.h @@ -0,0 +1,232 @@ +/* + * Copyright (c) 1997 - 2006 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.  + */ + +/* $Id$ */ + +#ifndef GSSAPI_KRB5_H_ +#define GSSAPI_KRB5_H_ + +#include <gssapi/gssapi.h> + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * This is for kerberos5 names. + */ + +extern GSSAPI_LIB_VARIABLE gss_OID GSS_KRB5_NT_PRINCIPAL_NAME; +extern GSSAPI_LIB_VARIABLE gss_OID GSS_KRB5_NT_USER_NAME; +extern GSSAPI_LIB_VARIABLE gss_OID GSS_KRB5_NT_MACHINE_UID_NAME; +extern GSSAPI_LIB_VARIABLE gss_OID GSS_KRB5_NT_STRING_UID_NAME; + +extern GSSAPI_LIB_VARIABLE gss_OID GSS_KRB5_MECHANISM; + +/* for compatibility with MIT api */ + +#define gss_mech_krb5 GSS_KRB5_MECHANISM +#define gss_krb5_nt_general_name GSS_KRB5_NT_PRINCIPAL_NAME + +/* Extensions set contexts options */ +extern GSSAPI_LIB_VARIABLE gss_OID GSS_KRB5_COPY_CCACHE_X; +extern GSSAPI_LIB_VARIABLE gss_OID GSS_KRB5_COMPAT_DES3_MIC_X; +extern GSSAPI_LIB_VARIABLE gss_OID GSS_KRB5_REGISTER_ACCEPTOR_IDENTITY_X; +extern GSSAPI_LIB_VARIABLE gss_OID GSS_KRB5_SET_DNS_CANONICALIZE_X; +extern GSSAPI_LIB_VARIABLE gss_OID GSS_KRB5_SEND_TO_KDC_X; +extern GSSAPI_LIB_VARIABLE gss_OID GSS_KRB5_SET_DEFAULT_REALM_X; +extern GSSAPI_LIB_VARIABLE gss_OID GSS_KRB5_CCACHE_NAME_X; +extern GSSAPI_LIB_VARIABLE gss_OID GSS_KRB5_SET_TIME_OFFSET_X; +extern GSSAPI_LIB_VARIABLE gss_OID GSS_KRB5_GET_TIME_OFFSET_X; +/* Extensions inquire context */ +extern GSSAPI_LIB_VARIABLE gss_OID GSS_KRB5_GET_TKT_FLAGS_X; +extern GSSAPI_LIB_VARIABLE gss_OID GSS_KRB5_EXTRACT_AUTHZ_DATA_FROM_SEC_CONTEXT_X; +extern GSSAPI_LIB_VARIABLE gss_OID GSS_C_PEER_HAS_UPDATED_SPNEGO; +extern GSSAPI_LIB_VARIABLE gss_OID GSS_KRB5_EXPORT_LUCID_CONTEXT_X; +extern GSSAPI_LIB_VARIABLE gss_OID GSS_KRB5_EXPORT_LUCID_CONTEXT_V1_X; +extern GSSAPI_LIB_VARIABLE gss_OID GSS_KRB5_GET_SUBKEY_X; +extern GSSAPI_LIB_VARIABLE gss_OID GSS_KRB5_GET_INITIATOR_SUBKEY_X; +extern GSSAPI_LIB_VARIABLE gss_OID GSS_KRB5_GET_ACCEPTOR_SUBKEY_X; +extern GSSAPI_LIB_VARIABLE gss_OID GSS_KRB5_GET_AUTHTIME_X; +extern GSSAPI_LIB_VARIABLE gss_OID GSS_KRB5_GET_SERVICE_KEYBLOCK_X; +/* Extensions creds */ +extern GSSAPI_LIB_VARIABLE gss_OID GSS_KRB5_IMPORT_CRED_X; +extern GSSAPI_LIB_VARIABLE gss_OID GSS_KRB5_SET_ALLOWABLE_ENCTYPES_X; +extern GSSAPI_LIB_VARIABLE gss_OID GSS_KRB5_CRED_NO_CI_FLAGS_X; + +/* + * kerberos mechanism specific functions + */ + +struct krb5_keytab_data; +struct krb5_ccache_data; +struct Principal; + +OM_uint32 GSSAPI_LIB_FUNCTION +gss_krb5_ccache_name(OM_uint32 * /*minor_status*/,  +		     const char * /*name */, +		     const char ** /*out_name */); + +OM_uint32 GSSAPI_LIB_FUNCTION gsskrb5_register_acceptor_identity +        (const char */*identity*/); + +OM_uint32 GSSAPI_LIB_FUNCTION krb5_gss_register_acceptor_identity +	(const char */*identity*/); + +OM_uint32 GSSAPI_LIB_FUNCTION gss_krb5_copy_ccache +	(OM_uint32 */*minor*/, +	 gss_cred_id_t /*cred*/, +	 struct krb5_ccache_data */*out*/); + +OM_uint32 GSSAPI_LIB_FUNCTION +gss_krb5_import_cred(OM_uint32 */*minor*/, +		     struct krb5_ccache_data * /*in*/, +		     struct Principal * /*keytab_principal*/, +		     struct krb5_keytab_data * /*keytab*/, +		     gss_cred_id_t */*out*/); + +OM_uint32 GSSAPI_LIB_FUNCTION gss_krb5_get_tkt_flags +	(OM_uint32 */*minor*/, +	 gss_ctx_id_t /*context_handle*/, +	 OM_uint32 */*tkt_flags*/); + +OM_uint32 GSSAPI_LIB_FUNCTION +gsskrb5_extract_authz_data_from_sec_context +	(OM_uint32 * /*minor_status*/, +	 gss_ctx_id_t /*context_handle*/, +	 int /*ad_type*/, +	 gss_buffer_t /*ad_data*/); + +OM_uint32 GSSAPI_LIB_FUNCTION +gsskrb5_set_dns_canonicalize(int); + +struct gsskrb5_send_to_kdc { +    void *func; +    void *ptr; +}; + +OM_uint32 GSSAPI_LIB_FUNCTION +gsskrb5_set_send_to_kdc(struct gsskrb5_send_to_kdc *); + +OM_uint32 GSSAPI_LIB_FUNCTION +gsskrb5_set_default_realm(const char *); + +OM_uint32 GSSAPI_LIB_FUNCTION +gsskrb5_extract_authtime_from_sec_context(OM_uint32 *, gss_ctx_id_t, time_t *); + +struct EncryptionKey; + +OM_uint32 GSSAPI_LIB_FUNCTION +gsskrb5_extract_service_keyblock(OM_uint32 *minor_status, +				 gss_ctx_id_t context_handle, +				 struct EncryptionKey **out); +OM_uint32 GSSAPI_LIB_FUNCTION +gsskrb5_get_initiator_subkey(OM_uint32 *minor_status, +				 gss_ctx_id_t context_handle, +				 struct EncryptionKey **out); +OM_uint32 GSSAPI_LIB_FUNCTION +gsskrb5_get_subkey(OM_uint32 *minor_status, +		   gss_ctx_id_t context_handle, +		   struct EncryptionKey **out); + +OM_uint32 GSSAPI_LIB_FUNCTION +gsskrb5_set_time_offset(int); + +OM_uint32 GSSAPI_LIB_FUNCTION +gsskrb5_get_time_offset(int *); + +/* + * Lucid - NFSv4 interface to GSS-API KRB5 to expose key material to + * do GSS content token handling in-kernel. + */ + +typedef struct gss_krb5_lucid_key { +	OM_uint32	type; +	OM_uint32	length; +	void *		data; +} gss_krb5_lucid_key_t; + +typedef struct gss_krb5_rfc1964_keydata { +	OM_uint32		sign_alg; +	OM_uint32		seal_alg; +	gss_krb5_lucid_key_t	ctx_key; +} gss_krb5_rfc1964_keydata_t; + +typedef struct gss_krb5_cfx_keydata { +	OM_uint32		have_acceptor_subkey; +	gss_krb5_lucid_key_t	ctx_key; +	gss_krb5_lucid_key_t	acceptor_subkey; +} gss_krb5_cfx_keydata_t; + +typedef struct gss_krb5_lucid_context_v1 { +	OM_uint32	version; +	OM_uint32	initiate; +	OM_uint32	endtime; +	OM_uint64	send_seq; +	OM_uint64	recv_seq; +	OM_uint32	protocol; +	gss_krb5_rfc1964_keydata_t rfc1964_kd; +	gss_krb5_cfx_keydata_t	   cfx_kd; +} gss_krb5_lucid_context_v1_t; + +typedef struct gss_krb5_lucid_context_version { +	OM_uint32	version;	/* Structure version number */ +} gss_krb5_lucid_context_version_t; + +/* + * Function declarations + */ + +OM_uint32 GSSAPI_LIB_FUNCTION +gss_krb5_export_lucid_sec_context(OM_uint32 *minor_status, +				  gss_ctx_id_t *context_handle, +				  OM_uint32 version, +				  void **kctx); + + +OM_uint32 GSSAPI_LIB_FUNCTION +gss_krb5_free_lucid_sec_context(OM_uint32 *minor_status, +				void *kctx); + + +OM_uint32 GSSAPI_LIB_FUNCTION +gss_krb5_set_allowable_enctypes(OM_uint32 *minor_status,  +				gss_cred_id_t cred, +				OM_uint32 num_enctypes, +				int32_t *enctypes); + +#ifdef __cplusplus +} +#endif + +#endif /* GSSAPI_SPNEGO_H_ */ diff --git a/source4/heimdal/lib/gssapi/gssapi/gssapi_spnego.h b/source4/heimdal/lib/gssapi/gssapi/gssapi_spnego.h new file mode 100644 index 0000000000..6587acd7d0 --- /dev/null +++ b/source4/heimdal/lib/gssapi/gssapi/gssapi_spnego.h @@ -0,0 +1,58 @@ +/* + * Copyright (c) 1997 - 2006 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.  + */ + +/* $Id$ */ + +#ifndef GSSAPI_SPNEGO_H_ +#define GSSAPI_SPNEGO_H_ + +#include <gssapi.h> + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * RFC2478, SPNEGO: + *  The security mechanism of the initial + *  negotiation token is identified by the Object Identifier + *  iso.org.dod.internet.security.mechanism.snego (1.3.6.1.5.5.2). + */ +extern GSSAPI_LIB_VARIABLE gss_OID GSS_SPNEGO_MECHANISM; +#define gss_mech_spnego GSS_SPNEGO_MECHANISM + +#ifdef __cplusplus +} +#endif + +#endif /* GSSAPI_SPNEGO_H_ */ diff --git a/source4/heimdal/lib/gssapi/gssapi_mech.h b/source4/heimdal/lib/gssapi/gssapi_mech.h new file mode 100644 index 0000000000..b360de13fc --- /dev/null +++ b/source4/heimdal/lib/gssapi/gssapi_mech.h @@ -0,0 +1,361 @@ +/*- + * Copyright (c) 2005 Doug Rabson + * 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 AUTHOR 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 AUTHOR 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. + * + *	$FreeBSD: src/lib/libgssapi/mech_switch.h,v 1.1 2005/12/29 14:40:20 dfr Exp $ + */ + +#ifndef GSSAPI_MECH_H +#define GSSAPI_MECH_H 1 + +#include <gssapi.h> + +typedef OM_uint32 _gss_acquire_cred_t +	      (OM_uint32 *,            /* minor_status */ +	       const gss_name_t,       /* desired_name */ +	       OM_uint32,              /* time_req */ +	       const gss_OID_set,      /* desired_mechs */ +	       gss_cred_usage_t,       /* cred_usage */ +	       gss_cred_id_t *,        /* output_cred_handle */ +	       gss_OID_set *,          /* actual_mechs */ +	       OM_uint32 *             /* time_rec */ +	      ); + +typedef OM_uint32 _gss_release_cred_t +	      (OM_uint32 *,            /* minor_status */ +	       gss_cred_id_t *         /* cred_handle */ +	      ); + +typedef OM_uint32 _gss_init_sec_context_t +	      (OM_uint32 *,            /* minor_status */ +	       const gss_cred_id_t,    /* initiator_cred_handle */ +	       gss_ctx_id_t *,         /* context_handle */ +	       const gss_name_t,       /* target_name */ +	       const gss_OID,          /* mech_type */ +	       OM_uint32,              /* req_flags */ +	       OM_uint32,              /* time_req */ +	       const gss_channel_bindings_t, +				       /* input_chan_bindings */ +	       const gss_buffer_t,     /* input_token */ +	       gss_OID *,              /* actual_mech_type */ +	       gss_buffer_t,           /* output_token */ +	       OM_uint32 *,            /* ret_flags */ +	       OM_uint32 *             /* time_rec */ +	      ); + +typedef OM_uint32 _gss_accept_sec_context_t +	      (OM_uint32 *,            /* minor_status */ +	       gss_ctx_id_t *,         /* context_handle */ +	       const gss_cred_id_t,    /* acceptor_cred_handle */ +	       const gss_buffer_t,     /* input_token_buffer */ +	       const gss_channel_bindings_t, +				       /* input_chan_bindings */ +	       gss_name_t *,           /* src_name */ +	       gss_OID *,              /* mech_type */ +	       gss_buffer_t,           /* output_token */ +	       OM_uint32 *,            /* ret_flags */ +	       OM_uint32 *,            /* time_rec */ +	       gss_cred_id_t *         /* delegated_cred_handle */ +	      ); + +typedef OM_uint32 _gss_process_context_token_t +	      (OM_uint32 *,            /* minor_status */ +	       const gss_ctx_id_t,     /* context_handle */ +	       const gss_buffer_t      /* token_buffer */ +	      ); + +typedef OM_uint32 _gss_delete_sec_context_t +	      (OM_uint32 *,            /* minor_status */ +	       gss_ctx_id_t *,         /* context_handle */ +	       gss_buffer_t            /* output_token */ +	      ); + +typedef OM_uint32 _gss_context_time_t +	      (OM_uint32 *,            /* minor_status */ +	       const gss_ctx_id_t,     /* context_handle */ +	       OM_uint32 *             /* time_rec */ +	      ); + +typedef OM_uint32 _gss_get_mic_t +	      (OM_uint32 *,            /* minor_status */ +	       const gss_ctx_id_t,     /* context_handle */ +	       gss_qop_t,              /* qop_req */ +	       const gss_buffer_t,     /* message_buffer */ +	       gss_buffer_t            /* message_token */ +	      ); + +typedef OM_uint32 _gss_verify_mic_t +	      (OM_uint32 *,            /* minor_status */ +	       const gss_ctx_id_t,     /* context_handle */ +	       const gss_buffer_t,     /* message_buffer */ +	       const gss_buffer_t,     /* token_buffer */ +	       gss_qop_t *             /* qop_state */ +	      ); + +typedef OM_uint32 _gss_wrap_t +	      (OM_uint32 *,            /* minor_status */ +	       const gss_ctx_id_t,     /* context_handle */ +	       int,                    /* conf_req_flag */ +	       gss_qop_t,              /* qop_req */ +	       const gss_buffer_t,     /* input_message_buffer */ +	       int *,                  /* conf_state */ +	       gss_buffer_t            /* output_message_buffer */ +	      ); + +typedef OM_uint32 _gss_unwrap_t +	      (OM_uint32 *,            /* minor_status */ +	       const gss_ctx_id_t,     /* context_handle */ +	       const gss_buffer_t,     /* input_message_buffer */ +	       gss_buffer_t,           /* output_message_buffer */ +	       int *,                  /* conf_state */ +	       gss_qop_t *             /* qop_state */ +	      ); + +typedef OM_uint32 _gss_display_status_t +	      (OM_uint32 *,            /* minor_status */ +	       OM_uint32,              /* status_value */ +	       int,                    /* status_type */ +	       const gss_OID,          /* mech_type */ +	       OM_uint32 *,            /* message_context */ +	       gss_buffer_t            /* status_string */ +	      ); + +typedef OM_uint32 _gss_indicate_mechs_t +	      (OM_uint32 *,            /* minor_status */ +	       gss_OID_set *           /* mech_set */ +	      ); + +typedef OM_uint32 _gss_compare_name_t +	      (OM_uint32 *,            /* minor_status */ +	       const gss_name_t,       /* name1 */ +	       const gss_name_t,       /* name2 */ +	       int *                   /* name_equal */ +	      ); + +typedef OM_uint32 _gss_display_name_t +	      (OM_uint32 *,            /* minor_status */ +	       const gss_name_t,       /* input_name */ +	       gss_buffer_t,           /* output_name_buffer */ +	       gss_OID *               /* output_name_type */ +	      ); + +typedef OM_uint32 _gss_import_name_t +	      (OM_uint32 *,            /* minor_status */ +	       const gss_buffer_t,     /* input_name_buffer */ +	       const gss_OID,          /* input_name_type */ +	       gss_name_t *            /* output_name */ +	      ); + +typedef OM_uint32 _gss_export_name_t +	      (OM_uint32 *,            /* minor_status */ +	       const gss_name_t,       /* input_name */ +	       gss_buffer_t            /* exported_name */ +	      ); + +typedef OM_uint32 _gss_release_name_t +	      (OM_uint32 *,            /* minor_status */ +	       gss_name_t *            /* input_name */ +	      ); + +typedef OM_uint32 _gss_inquire_cred_t +	      (OM_uint32 *,            /* minor_status */ +	       const gss_cred_id_t,    /* cred_handle */ +	       gss_name_t *,           /* name */ +	       OM_uint32 *,            /* lifetime */ +	       gss_cred_usage_t *,     /* cred_usage */ +	       gss_OID_set *           /* mechanisms */ +	      ); + +typedef OM_uint32 _gss_inquire_context_t +	      (OM_uint32 *,            /* minor_status */ +	       const gss_ctx_id_t,     /* context_handle */ +	       gss_name_t *,           /* src_name */ +	       gss_name_t *,           /* targ_name */ +	       OM_uint32 *,            /* lifetime_rec */ +	       gss_OID *,              /* mech_type */ +	       OM_uint32 *,            /* ctx_flags */ +	       int *,                  /* locally_initiated */ +	       int *                   /* open */ +	      ); + +typedef OM_uint32 _gss_wrap_size_limit_t +	      (OM_uint32 *,            /* minor_status */ +	       const gss_ctx_id_t,     /* context_handle */ +	       int,                    /* conf_req_flag */ +	       gss_qop_t,              /* qop_req */ +	       OM_uint32,              /* req_output_size */ +	       OM_uint32 *             /* max_input_size */ +	      ); + +typedef OM_uint32 _gss_add_cred_t ( +	       OM_uint32 *,            /* minor_status */ +	       const gss_cred_id_t,    /* input_cred_handle */ +	       const gss_name_t,       /* desired_name */ +	       const gss_OID,          /* desired_mech */ +	       gss_cred_usage_t,       /* cred_usage */ +	       OM_uint32,              /* initiator_time_req */ +	       OM_uint32,              /* acceptor_time_req */ +	       gss_cred_id_t *,        /* output_cred_handle */ +	       gss_OID_set *,          /* actual_mechs */ +	       OM_uint32 *,            /* initiator_time_rec */ +	       OM_uint32 *             /* acceptor_time_rec */ +	      ); + +typedef OM_uint32 _gss_inquire_cred_by_mech_t ( +	       OM_uint32 *,            /* minor_status */ +	       const gss_cred_id_t,    /* cred_handle */ +	       const gss_OID,          /* mech_type */ +	       gss_name_t *,           /* name */ +	       OM_uint32 *,            /* initiator_lifetime */ +	       OM_uint32 *,            /* acceptor_lifetime */ +	       gss_cred_usage_t *      /* cred_usage */ +	      ); + +typedef OM_uint32 _gss_export_sec_context_t ( +	       OM_uint32 *,            /* minor_status */ +	       gss_ctx_id_t *,         /* context_handle */ +	       gss_buffer_t            /* interprocess_token */ +	      ); + +typedef OM_uint32 _gss_import_sec_context_t ( +	       OM_uint32 *,            /* minor_status */ +	       const gss_buffer_t,     /* interprocess_token */ +	       gss_ctx_id_t *          /* context_handle */ +	      ); + +typedef OM_uint32 _gss_inquire_names_for_mech_t ( +	       OM_uint32 *,            /* minor_status */ +	       const gss_OID,          /* mechanism */ +	       gss_OID_set *           /* name_types */ +	      ); + +typedef OM_uint32 _gss_inquire_mechs_for_name_t ( +	       OM_uint32 *,            /* minor_status */ +	       const gss_name_t,       /* input_name */ +	       gss_OID_set *           /* mech_types */ +	      ); + +typedef OM_uint32 _gss_canonicalize_name_t ( +	       OM_uint32 *,            /* minor_status */ +	       const gss_name_t,       /* input_name */ +	       const gss_OID,          /* mech_type */ +	       gss_name_t *            /* output_name */ +	      ); + +typedef OM_uint32 _gss_duplicate_name_t ( +	       OM_uint32 *,            /* minor_status */ +	       const gss_name_t,       /* src_name */ +	       gss_name_t *            /* dest_name */ +	      ); + +typedef OM_uint32 _gss_inquire_sec_context_by_oid ( +	       OM_uint32 *minor_status, +	       const gss_ctx_id_t context_handle, +	       const gss_OID desired_object, +	       gss_buffer_set_t *data_set +	      ); + +typedef OM_uint32 _gss_inquire_cred_by_oid ( +	       OM_uint32 *minor_status, +	       const gss_cred_id_t cred, +	       const gss_OID desired_object, +	       gss_buffer_set_t *data_set +	      ); + +typedef OM_uint32 _gss_set_sec_context_option ( +	       OM_uint32 *minor_status, +	       gss_ctx_id_t *cred_handle, +	       const gss_OID desired_object, +	       const gss_buffer_t value + 	      ); + +typedef OM_uint32 _gss_set_cred_option ( +	       OM_uint32 *minor_status, +	       gss_cred_id_t *cred_handle, +	       const gss_OID desired_object, +	       const gss_buffer_t value + 	      ); + + +typedef OM_uint32 _gss_pseudo_random( +    	       OM_uint32 *minor_status, +	       gss_ctx_id_t context, +	       int prf_key, +	       const gss_buffer_t prf_in, +	       ssize_t desired_output_len, +	       gss_buffer_t prf_out +              ); + +#define GMI_VERSION 1 + +typedef struct gssapi_mech_interface_desc { +	unsigned			gm_version; +	const char			*gm_name; +	gss_OID_desc			gm_mech_oid; +	_gss_acquire_cred_t		*gm_acquire_cred; +	_gss_release_cred_t		*gm_release_cred; +	_gss_init_sec_context_t		*gm_init_sec_context; +	_gss_accept_sec_context_t	*gm_accept_sec_context; +	_gss_process_context_token_t	*gm_process_context_token; +	_gss_delete_sec_context_t	*gm_delete_sec_context; +	_gss_context_time_t		*gm_context_time; +	_gss_get_mic_t			*gm_get_mic; +	_gss_verify_mic_t		*gm_verify_mic; +	_gss_wrap_t			*gm_wrap; +	_gss_unwrap_t			*gm_unwrap; +	_gss_display_status_t		*gm_display_status; +	_gss_indicate_mechs_t		*gm_indicate_mechs; +	_gss_compare_name_t		*gm_compare_name; +	_gss_display_name_t		*gm_display_name; +	_gss_import_name_t		*gm_import_name; +	_gss_export_name_t		*gm_export_name; +	_gss_release_name_t		*gm_release_name; +	_gss_inquire_cred_t		*gm_inquire_cred; +	_gss_inquire_context_t		*gm_inquire_context; +	_gss_wrap_size_limit_t		*gm_wrap_size_limit; +	_gss_add_cred_t			*gm_add_cred; +	_gss_inquire_cred_by_mech_t	*gm_inquire_cred_by_mech; +	_gss_export_sec_context_t	*gm_export_sec_context; +	_gss_import_sec_context_t	*gm_import_sec_context; +	_gss_inquire_names_for_mech_t	*gm_inquire_names_for_mech; +	_gss_inquire_mechs_for_name_t	*gm_inquire_mechs_for_name; +	_gss_canonicalize_name_t	*gm_canonicalize_name; +	_gss_duplicate_name_t		*gm_duplicate_name; +	_gss_inquire_sec_context_by_oid	*gm_inquire_sec_context_by_oid; +	_gss_inquire_cred_by_oid	*gm_inquire_cred_by_oid; +	_gss_set_sec_context_option	*gm_set_sec_context_option; +	_gss_set_cred_option		*gm_set_cred_option; +	_gss_pseudo_random		*gm_pseudo_random; +} gssapi_mech_interface_desc, *gssapi_mech_interface; + +gssapi_mech_interface +__gss_get_mechanism(gss_OID /* oid */); + +gssapi_mech_interface __gss_spnego_initialize(void); +gssapi_mech_interface __gss_krb5_initialize(void); +gssapi_mech_interface __gss_ntlm_initialize(void); + +void		gss_mg_collect_error(gss_OID, OM_uint32, OM_uint32); + +#endif /* GSSAPI_MECH_H */ diff --git a/source4/heimdal/lib/gssapi/krb5/8003.c b/source4/heimdal/lib/gssapi/krb5/8003.c new file mode 100644 index 0000000000..a9b93d32a6 --- /dev/null +++ b/source4/heimdal/lib/gssapi/krb5/8003.c @@ -0,0 +1,248 @@ +/* + * Copyright (c) 1997 - 2003 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.  + */ + +#include "krb5/gsskrb5_locl.h" + +RCSID("$Id$"); + +krb5_error_code +_gsskrb5_encode_om_uint32(OM_uint32 n, u_char *p) +{ +  p[0] = (n >> 0)  & 0xFF; +  p[1] = (n >> 8)  & 0xFF; +  p[2] = (n >> 16) & 0xFF; +  p[3] = (n >> 24) & 0xFF; +  return 0; +} + +krb5_error_code +_gsskrb5_encode_be_om_uint32(OM_uint32 n, u_char *p) +{ +  p[0] = (n >> 24) & 0xFF; +  p[1] = (n >> 16) & 0xFF; +  p[2] = (n >> 8)  & 0xFF; +  p[3] = (n >> 0)  & 0xFF; +  return 0; +} + +krb5_error_code +_gsskrb5_decode_om_uint32(const void *ptr, OM_uint32 *n) +{ +    const u_char *p = ptr; +    *n = (p[0] << 0) | (p[1] << 8) | (p[2] << 16) | (p[3] << 24); +    return 0; +} + +krb5_error_code +_gsskrb5_decode_be_om_uint32(const void *ptr, OM_uint32 *n) +{ +    const u_char *p = ptr; +    *n = (p[0] <<24) | (p[1] << 16) | (p[2] << 8) | (p[3] << 0); +    return 0; +} + +static krb5_error_code +hash_input_chan_bindings (const gss_channel_bindings_t b, +			  u_char *p) +{ +  u_char num[4]; +  MD5_CTX md5; + +  MD5_Init(&md5); +  _gsskrb5_encode_om_uint32 (b->initiator_addrtype, num); +  MD5_Update (&md5, num, sizeof(num)); +  _gsskrb5_encode_om_uint32 (b->initiator_address.length, num); +  MD5_Update (&md5, num, sizeof(num)); +  if (b->initiator_address.length) +    MD5_Update (&md5, +		b->initiator_address.value, +		b->initiator_address.length); +  _gsskrb5_encode_om_uint32 (b->acceptor_addrtype, num); +  MD5_Update (&md5, num, sizeof(num)); +  _gsskrb5_encode_om_uint32 (b->acceptor_address.length, num); +  MD5_Update (&md5, num, sizeof(num)); +  if (b->acceptor_address.length) +    MD5_Update (&md5, +		b->acceptor_address.value, +		b->acceptor_address.length); +  _gsskrb5_encode_om_uint32 (b->application_data.length, num); +  MD5_Update (&md5, num, sizeof(num)); +  if (b->application_data.length) +    MD5_Update (&md5, +		b->application_data.value, +		b->application_data.length); +  MD5_Final (p, &md5); +  return 0; +} + +/* + * create a checksum over the chanel bindings in + * `input_chan_bindings', `flags' and `fwd_data' and return it in + * `result' + */ + +OM_uint32 +_gsskrb5_create_8003_checksum ( +		      OM_uint32 *minor_status,     +		      const gss_channel_bindings_t input_chan_bindings, +		      OM_uint32 flags, +		      const krb5_data *fwd_data, +		      Checksum *result) +{ +    u_char *p; + +    /*  +     * see rfc1964 (section 1.1.1 (Initial Token), and the checksum value  +     * field's format) */ +    result->cksumtype = CKSUMTYPE_GSSAPI; +    if (fwd_data->length > 0 && (flags & GSS_C_DELEG_FLAG)) +	result->checksum.length = 24 + 4 + fwd_data->length; +    else  +	result->checksum.length = 24; +    result->checksum.data   = malloc (result->checksum.length); +    if (result->checksum.data == NULL) { +	*minor_status = ENOMEM; +	return GSS_S_FAILURE; +    } +   +    p = result->checksum.data; +    _gsskrb5_encode_om_uint32 (16, p); +    p += 4; +    if (input_chan_bindings == GSS_C_NO_CHANNEL_BINDINGS) { +	memset (p, 0, 16); +    } else { +	hash_input_chan_bindings (input_chan_bindings, p); +    } +    p += 16; +    _gsskrb5_encode_om_uint32 (flags, p); +    p += 4; + +    if (fwd_data->length > 0 && (flags & GSS_C_DELEG_FLAG)) { + +	*p++ = (1 >> 0) & 0xFF;                   /* DlgOpt */ /* == 1 */ +	*p++ = (1 >> 8) & 0xFF;                   /* DlgOpt */ /* == 0 */ +	*p++ = (fwd_data->length >> 0) & 0xFF;    /* Dlgth  */ +	*p++ = (fwd_data->length >> 8) & 0xFF;    /* Dlgth  */ +	memcpy(p, (unsigned char *) fwd_data->data, fwd_data->length); + +	p += fwd_data->length; +    } +      +    return GSS_S_COMPLETE; +} + +/* + * verify the checksum in `cksum' over `input_chan_bindings' + * returning  `flags' and `fwd_data' + */ + +OM_uint32 +_gsskrb5_verify_8003_checksum( +		      OM_uint32 *minor_status,     +		      const gss_channel_bindings_t input_chan_bindings, +		      const Checksum *cksum, +		      OM_uint32 *flags, +		      krb5_data *fwd_data) +{ +    unsigned char hash[16]; +    unsigned char *p; +    OM_uint32 length; +    int DlgOpt; +    static unsigned char zeros[16]; + +    if (cksum == NULL) { +	*minor_status = 0; +	return GSS_S_BAD_BINDINGS; +    } + +    /* XXX should handle checksums > 24 bytes */ +    if(cksum->cksumtype != CKSUMTYPE_GSSAPI || cksum->checksum.length < 24) { +	*minor_status = 0; +	return GSS_S_BAD_BINDINGS; +    } +     +    p = cksum->checksum.data; +    _gsskrb5_decode_om_uint32(p, &length); +    if(length != sizeof(hash)) { +	*minor_status = 0; +	return GSS_S_BAD_BINDINGS; +    } +     +    p += 4; +     +    if (input_chan_bindings != GSS_C_NO_CHANNEL_BINDINGS +	&& memcmp(p, zeros, sizeof(zeros)) != 0) { +	if(hash_input_chan_bindings(input_chan_bindings, hash) != 0) { +	    *minor_status = 0; +	    return GSS_S_BAD_BINDINGS; +	} +	if(memcmp(hash, p, sizeof(hash)) != 0) { +	    *minor_status = 0; +	    return GSS_S_BAD_BINDINGS; +	} +    } +     +    p += sizeof(hash); +     +    _gsskrb5_decode_om_uint32(p, flags); +    p += 4; + +    if (cksum->checksum.length > 24 && (*flags & GSS_C_DELEG_FLAG)) { +	if(cksum->checksum.length < 28) { +	    *minor_status = 0; +	    return GSS_S_BAD_BINDINGS; +	} +     +	DlgOpt = (p[0] << 0) | (p[1] << 8); +	p += 2; +	if (DlgOpt != 1) { +	    *minor_status = 0; +	    return GSS_S_BAD_BINDINGS; +	} + +	fwd_data->length = (p[0] << 0) | (p[1] << 8); +	p += 2; +	if(cksum->checksum.length < 28 + fwd_data->length) { +	    *minor_status = 0; +	    return GSS_S_BAD_BINDINGS; +	} +	fwd_data->data = malloc(fwd_data->length); +	if (fwd_data->data == NULL) { +	    *minor_status = ENOMEM; +	    return GSS_S_FAILURE; +	} +	memcpy(fwd_data->data, p, fwd_data->length); +    } +     +    return GSS_S_COMPLETE; +} diff --git a/source4/heimdal/lib/gssapi/krb5/accept_sec_context.c b/source4/heimdal/lib/gssapi/krb5/accept_sec_context.c new file mode 100644 index 0000000000..84110b7a82 --- /dev/null +++ b/source4/heimdal/lib/gssapi/krb5/accept_sec_context.c @@ -0,0 +1,888 @@ +/* + * Copyright (c) 1997 - 2006 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.  + */ + +#include "krb5/gsskrb5_locl.h" + +RCSID("$Id$"); + +HEIMDAL_MUTEX gssapi_keytab_mutex = HEIMDAL_MUTEX_INITIALIZER; +krb5_keytab _gsskrb5_keytab; + +OM_uint32 +_gsskrb5_register_acceptor_identity (const char *identity) +{ +    krb5_context context; +    krb5_error_code ret; + +    ret = _gsskrb5_init(&context); +    if(ret) +	return GSS_S_FAILURE; +     +    HEIMDAL_MUTEX_lock(&gssapi_keytab_mutex); + +    if(_gsskrb5_keytab != NULL) { +	krb5_kt_close(context, _gsskrb5_keytab); +	_gsskrb5_keytab = NULL; +    } +    if (identity == NULL) { +	ret = krb5_kt_default(context, &_gsskrb5_keytab); +    } else { +	char *p; + +	asprintf(&p, "FILE:%s", identity); +	if(p == NULL) { +	    HEIMDAL_MUTEX_unlock(&gssapi_keytab_mutex); +	    return GSS_S_FAILURE; +	} +	ret = krb5_kt_resolve(context, p, &_gsskrb5_keytab); +	free(p); +    } +    HEIMDAL_MUTEX_unlock(&gssapi_keytab_mutex); +    if(ret) +	return GSS_S_FAILURE; +    return GSS_S_COMPLETE; +} + +void +_gsskrb5i_is_cfx(gsskrb5_ctx ctx, int *is_cfx) +{ +    krb5_keyblock *key; +    int acceptor = (ctx->more_flags & LOCAL) == 0; + +    *is_cfx = 0; + +    if (acceptor) { +	if (ctx->auth_context->local_subkey) +	    key = ctx->auth_context->local_subkey; +	else +	    key = ctx->auth_context->remote_subkey; +    } else { +	if (ctx->auth_context->remote_subkey) +	    key = ctx->auth_context->remote_subkey; +	else +	    key = ctx->auth_context->local_subkey; +    } +    if (key == NULL) +	key = ctx->auth_context->keyblock; + +    if (key == NULL) +	return; +	     +    switch (key->keytype) { +    case ETYPE_DES_CBC_CRC: +    case ETYPE_DES_CBC_MD4: +    case ETYPE_DES_CBC_MD5: +    case ETYPE_DES3_CBC_MD5: +    case ETYPE_DES3_CBC_SHA1: +    case ETYPE_ARCFOUR_HMAC_MD5: +    case ETYPE_ARCFOUR_HMAC_MD5_56: +	break; +    default : +	*is_cfx = 1; +	if ((acceptor && ctx->auth_context->local_subkey) || +	    (!acceptor && ctx->auth_context->remote_subkey)) +	    ctx->more_flags |= ACCEPTOR_SUBKEY; +	break; +    } +} + + +static OM_uint32 +gsskrb5_accept_delegated_token +(OM_uint32 * minor_status, + gsskrb5_ctx ctx, + krb5_context context, + gss_cred_id_t * delegated_cred_handle +    ) +{ +    krb5_ccache ccache = NULL; +    krb5_error_code kret; +    int32_t ac_flags, ret = GSS_S_COMPLETE; +       +    *minor_status = 0; + +    /* XXX Create a new delegated_cred_handle? */ +    if (delegated_cred_handle == NULL) { +	kret = krb5_cc_default (context, &ccache); +    } else { +	*delegated_cred_handle = NULL; +	kret = krb5_cc_gen_new (context, &krb5_mcc_ops, &ccache); +    } +    if (kret) { +	ctx->flags &= ~GSS_C_DELEG_FLAG; +	goto out; +    } + +    kret = krb5_cc_initialize(context, ccache, ctx->source); +    if (kret) { +	ctx->flags &= ~GSS_C_DELEG_FLAG; +	goto out; +    } +       +    krb5_auth_con_removeflags(context, +			      ctx->auth_context, +			      KRB5_AUTH_CONTEXT_DO_TIME, +			      &ac_flags); +    kret = krb5_rd_cred2(context, +			 ctx->auth_context, +			 ccache, +			 &ctx->fwd_data); +    krb5_auth_con_setflags(context, +			   ctx->auth_context, +			   ac_flags); +    if (kret) { +	ctx->flags &= ~GSS_C_DELEG_FLAG; +	ret = GSS_S_FAILURE; +	*minor_status = kret; +	goto out; +    } + +    if (delegated_cred_handle) { +	gsskrb5_cred handle; + +	ret = _gsskrb5_import_cred(minor_status, +				   ccache, +				   NULL, +				   NULL, +				   delegated_cred_handle); +	if (ret != GSS_S_COMPLETE) +	    goto out; + +	handle = (gsskrb5_cred) *delegated_cred_handle; +     +	handle->cred_flags |= GSS_CF_DESTROY_CRED_ON_RELEASE; +	krb5_cc_close(context, ccache); +	ccache = NULL; +    } + +out: +    if (ccache) { +	/* Don't destroy the default cred cache */ +	if (delegated_cred_handle == NULL) +	    krb5_cc_close(context, ccache); +	else +	    krb5_cc_destroy(context, ccache); +    } +    return ret; +} + +static OM_uint32 +gsskrb5_acceptor_ready(OM_uint32 * minor_status, +		       gsskrb5_ctx ctx, +		       krb5_context context, +		       gss_cred_id_t *delegated_cred_handle) +{ +    OM_uint32 ret; +    int32_t seq_number; +    int is_cfx = 0; + +    krb5_auth_getremoteseqnumber (context, +				  ctx->auth_context, +				  &seq_number); + +    _gsskrb5i_is_cfx(ctx, &is_cfx); + +    ret = _gssapi_msg_order_create(minor_status, +				   &ctx->order, +				   _gssapi_msg_order_f(ctx->flags), +				   seq_number, 0, is_cfx); +    if (ret) +	return ret; + +    /*  +     * If requested, set local sequence num to remote sequence if this +     * isn't a mutual authentication context +     */ +    if (!(ctx->flags & GSS_C_MUTUAL_FLAG) && _gssapi_msg_order_f(ctx->flags)) { +	krb5_auth_con_setlocalseqnumber(context, +					ctx->auth_context, +					seq_number); +    } + +    /* +     * We should handle the delegation ticket, in case it's there +     */ +    if (ctx->fwd_data.length > 0 && (ctx->flags & GSS_C_DELEG_FLAG)) { +	ret = gsskrb5_accept_delegated_token(minor_status, +					     ctx, +					     context, +					     delegated_cred_handle); +	if (ret) +	    return ret; +    } else { +	/* Well, looks like it wasn't there after all */ +	ctx->flags &= ~GSS_C_DELEG_FLAG; +    } + +    ctx->state = ACCEPTOR_READY; +    ctx->more_flags |= OPEN; + +    return GSS_S_COMPLETE; +} + +static OM_uint32 +send_error_token(OM_uint32 *minor_status, +		 krb5_context context, +		 krb5_error_code kret, +		 krb5_principal server, +		 krb5_data *indata, +		 gss_buffer_t output_token) +{ +    krb5_principal ap_req_server = NULL; +    krb5_error_code ret; +    krb5_data outbuf; + +    /* build server from request if the acceptor had not selected one */ +    if (server == NULL) { +	AP_REQ ap_req; + +	ret = krb5_decode_ap_req(context, indata, &ap_req); +	if (ret) { +	    *minor_status = ret; +	    return GSS_S_FAILURE; +	} +	ret = _krb5_principalname2krb5_principal(context, +						  &ap_req_server, +						  ap_req.ticket.sname, +						  ap_req.ticket.realm); +	free_AP_REQ(&ap_req); +	if (ret) { +	    *minor_status = ret; +	    return GSS_S_FAILURE; +	} +	server = ap_req_server; +    } +     +    ret = krb5_mk_error(context, kret, NULL, NULL, NULL, +			server, NULL, NULL, &outbuf); +    if (ap_req_server) +	krb5_free_principal(context, ap_req_server); +    if (ret) { +	*minor_status = ret; +	return GSS_S_FAILURE; +    } +     +    ret = _gsskrb5_encapsulate(minor_status, +			       &outbuf, +			       output_token, +			       "\x03\x00", +			       GSS_KRB5_MECHANISM); +    krb5_data_free (&outbuf); +    if (ret) +	return ret; + +    *minor_status = 0; +    return GSS_S_CONTINUE_NEEDED; +} + + +static OM_uint32 +gsskrb5_acceptor_start(OM_uint32 * minor_status, +		       gsskrb5_ctx ctx, +		       krb5_context context, +		       const gss_cred_id_t acceptor_cred_handle, +		       const gss_buffer_t input_token_buffer, +		       const gss_channel_bindings_t input_chan_bindings, +		       gss_name_t * src_name, +		       gss_OID * mech_type, +		       gss_buffer_t output_token, +		       OM_uint32 * ret_flags, +		       OM_uint32 * time_rec, +		       gss_cred_id_t * delegated_cred_handle) +{ +    krb5_error_code kret; +    OM_uint32 ret = GSS_S_COMPLETE; +    krb5_data indata; +    krb5_flags ap_options; +    krb5_keytab keytab = NULL; +    int is_cfx = 0; +    const gsskrb5_cred acceptor_cred = (gsskrb5_cred)acceptor_cred_handle; + +    /* +     * We may, or may not, have an escapsulation. +     */ +    ret = _gsskrb5_decapsulate (minor_status, +				input_token_buffer, +				&indata, +				"\x01\x00", +				GSS_KRB5_MECHANISM); + +    if (ret) { +	/* Assume that there is no OID wrapping. */ +	indata.length	= input_token_buffer->length; +	indata.data	= input_token_buffer->value; +    } + +    /* +     * We need to get our keytab +     */ +    if (acceptor_cred == NULL) { +	if (_gsskrb5_keytab != NULL) +	    keytab = _gsskrb5_keytab; +    } else if (acceptor_cred->keytab != NULL) { +	keytab = acceptor_cred->keytab; +    } +     +    /* +     * We need to check the ticket and create the AP-REP packet +     */ + +    { +	krb5_rd_req_in_ctx in = NULL; +	krb5_rd_req_out_ctx out = NULL; +	krb5_principal server = NULL; + +	if (acceptor_cred) +	    server = acceptor_cred->principal; + +	kret = krb5_rd_req_in_ctx_alloc(context, &in); +	if (kret == 0) +	    kret = krb5_rd_req_in_set_keytab(context, in, keytab); +	if (kret) { +	    if (in) +		krb5_rd_req_in_ctx_free(context, in); +	    *minor_status = kret; +	    return GSS_S_FAILURE; +	} + +	kret = krb5_rd_req_ctx(context, +			       &ctx->auth_context, +			       &indata, +			       server, +			       in, &out); +	krb5_rd_req_in_ctx_free(context, in); +	if (kret == KRB5KRB_AP_ERR_SKEW) { +	    /*  +	     * No reply in non-MUTUAL mode, but we don't know that its +	     * non-MUTUAL mode yet, thats inside the 8003 checksum, so +	     * lets only send the error token on clock skew, that +	     * limit when send error token for non-MUTUAL. +	     */ +	    return send_error_token(minor_status, context, kret, +				    server, &indata, output_token); +	} else if (kret) { +	    *minor_status = kret; +	    return GSS_S_FAILURE; +	} + +	/* +	 * we need to remember some data on the context_handle. +	 */ +	kret = krb5_rd_req_out_get_ap_req_options(context, out, +						  &ap_options); +	if (kret == 0) +	    kret = krb5_rd_req_out_get_ticket(context, out,  +					      &ctx->ticket); +	if (kret == 0) +	    kret = krb5_rd_req_out_get_keyblock(context, out, +						&ctx->service_keyblock); +	ctx->lifetime = ctx->ticket->ticket.endtime; + +	krb5_rd_req_out_ctx_free(context, out); +	if (kret) { +	    ret = GSS_S_FAILURE; +	    *minor_status = kret; +	    return ret; +	} +    } +     +     +    /* +     * We need to copy the principal names to the context and the +     * calling layer. +     */ +    kret = krb5_copy_principal(context, +			       ctx->ticket->client, +			       &ctx->source); +    if (kret) { +	ret = GSS_S_FAILURE; +	*minor_status = kret; +    } + +    kret = krb5_copy_principal(context,  +			       ctx->ticket->server, +			       &ctx->target); +    if (kret) { +	ret = GSS_S_FAILURE; +	*minor_status = kret; +	return ret; +    } +     +    /* +     * We need to setup some compat stuff, this assumes that +     * context_handle->target is already set. +     */ +    ret = _gss_DES3_get_mic_compat(minor_status, ctx, context); +    if (ret) +	return ret; + +    if (src_name != NULL) { +	kret = krb5_copy_principal (context, +				    ctx->ticket->client, +				    (gsskrb5_name*)src_name); +	if (kret) { +	    ret = GSS_S_FAILURE; +	    *minor_status = kret; +	    return ret; +	} +    } + +    /* +     * We need to get the flags out of the 8003 checksum. +     */ +    { +	krb5_authenticator authenticator; +       +	kret = krb5_auth_con_getauthenticator(context, +					      ctx->auth_context, +					      &authenticator); +	if(kret) { +	    ret = GSS_S_FAILURE; +	    *minor_status = kret; +	    return ret; +	} + +        if (authenticator->cksum->cksumtype == CKSUMTYPE_GSSAPI) { +            ret = _gsskrb5_verify_8003_checksum(minor_status, +						input_chan_bindings, +						authenticator->cksum, +						&ctx->flags, +						&ctx->fwd_data); + +	    krb5_free_authenticator(context, &authenticator); +	    if (ret) { +		return ret; +	    } +        } else { +	    krb5_crypto crypto; + +	    kret = krb5_crypto_init(context,  +				    ctx->auth_context->keyblock,  +				    0, &crypto); +	    if(kret) { +		krb5_free_authenticator(context, &authenticator); + +		ret = GSS_S_FAILURE; +		*minor_status = kret; +		return ret; +	    } + +	    /*  +	     * Windows accepts Samba3's use of a kerberos, rather than +	     * GSSAPI checksum here  +	     */ + +	    kret = krb5_verify_checksum(context, +					crypto, KRB5_KU_AP_REQ_AUTH_CKSUM, NULL, 0, +					authenticator->cksum); +	    krb5_free_authenticator(context, &authenticator); +	    krb5_crypto_destroy(context, crypto); + +	    if(kret) { +		ret = GSS_S_BAD_SIG; +		*minor_status = kret; +		return ret; +	    } + +	    /*  +	     * Samba style get some flags (but not DCE-STYLE) +	     */ +	    ctx->flags =  +		GSS_C_MUTUAL_FLAG | GSS_C_REPLAY_FLAG | GSS_C_SEQUENCE_FLAG; +        } +    } +     +    if(ctx->flags & GSS_C_MUTUAL_FLAG) { +	krb5_data outbuf; +	int use_subkey = 0; +	     +	_gsskrb5i_is_cfx(ctx, &is_cfx); +	     +	if (is_cfx || (ap_options & AP_OPTS_USE_SUBKEY)) { +	    use_subkey = 1; +	} else { +	    krb5_keyblock *rkey; + +	    /*  +	     * If there is a initiator subkey, copy that to acceptor +	     * subkey to match Windows behavior +	     */ +	    kret = krb5_auth_con_getremotesubkey(context, +						 ctx->auth_context, +						 &rkey); +	    if (kret == 0) { +		kret = krb5_auth_con_setlocalsubkey(context,  +						    ctx->auth_context, +						    rkey); +		if (kret == 0) +		    use_subkey = 1; +		krb5_free_keyblock(context, rkey); +	    } +	} +	if (use_subkey) { +	    ctx->more_flags |= ACCEPTOR_SUBKEY; +	    krb5_auth_con_addflags(context, ctx->auth_context, +				   KRB5_AUTH_CONTEXT_USE_SUBKEY, +				   NULL); +	} +	     +	kret = krb5_mk_rep(context, +			   ctx->auth_context, +			   &outbuf); +	if (kret) { +	    *minor_status = kret; +	    return GSS_S_FAILURE; +	} +	     +	if (IS_DCE_STYLE(ctx)) { +	    output_token->length = outbuf.length; +	    output_token->value = outbuf.data; +	} else { +	    ret = _gsskrb5_encapsulate(minor_status, +				       &outbuf, +				       output_token, +				       "\x02\x00", +				       GSS_KRB5_MECHANISM); +	    krb5_data_free (&outbuf); +	    if (ret) +		return ret; +	} +    } +     +    ctx->flags |= GSS_C_TRANS_FLAG; + +    /* Remember the flags */ +     +    ctx->lifetime = ctx->ticket->ticket.endtime; +    ctx->more_flags |= OPEN; +     +    if (mech_type) +	*mech_type = GSS_KRB5_MECHANISM; +     +    if (time_rec) { +	ret = _gsskrb5_lifetime_left(minor_status, +				     context, +				     ctx->lifetime, +				     time_rec); +	if (ret) { +	    return ret; +	} +    } + +    /* +     * When GSS_C_DCE_STYLE is in use, we need ask for a AP-REP from +     * the client. +     */ +    if (IS_DCE_STYLE(ctx)) { +	/* +	 * Return flags to caller, but we haven't processed +	 * delgations yet +	 */ +	if (ret_flags) +	    *ret_flags = (ctx->flags & ~GSS_C_DELEG_FLAG); + +	ctx->state = ACCEPTOR_WAIT_FOR_DCESTYLE; +	return GSS_S_CONTINUE_NEEDED; +    } + +    ret = gsskrb5_acceptor_ready(minor_status, ctx, context,  +				 delegated_cred_handle); + +    if (ret_flags) +	*ret_flags = ctx->flags; + +    return ret; +} + +static OM_uint32 +acceptor_wait_for_dcestyle(OM_uint32 * minor_status, +			   gsskrb5_ctx ctx, +			   krb5_context context, +			   const gss_cred_id_t acceptor_cred_handle, +			   const gss_buffer_t input_token_buffer, +			   const gss_channel_bindings_t input_chan_bindings, +			   gss_name_t * src_name, +			   gss_OID * mech_type, +			   gss_buffer_t output_token, +			   OM_uint32 * ret_flags, +			   OM_uint32 * time_rec, +			   gss_cred_id_t * delegated_cred_handle) +{ +    OM_uint32 ret; +    krb5_error_code kret; +    krb5_data inbuf; +    int32_t r_seq_number, l_seq_number; +	 +    /*  +     * We know it's GSS_C_DCE_STYLE so we don't need to decapsulate the AP_REP +     */ + +    inbuf.length = input_token_buffer->length; +    inbuf.data = input_token_buffer->value; + +    /*  +     * We need to remeber the old remote seq_number, then check if the +     * client has replied with our local seq_number, and then reset +     * the remote seq_number to the old value +     */ +    { +	kret = krb5_auth_con_getlocalseqnumber(context, +					       ctx->auth_context, +					       &l_seq_number); +	if (kret) { +	    *minor_status = kret; +	    return GSS_S_FAILURE; +	} + +	kret = krb5_auth_getremoteseqnumber(context, +					    ctx->auth_context, +					    &r_seq_number); +	if (kret) { +	    *minor_status = kret; +	    return GSS_S_FAILURE; +	} + +	kret = krb5_auth_con_setremoteseqnumber(context, +						ctx->auth_context, +						l_seq_number); +	if (kret) { +	    *minor_status = kret; +	    return GSS_S_FAILURE; +	} +    } + +    /*  +     * We need to verify the AP_REP, but we need to flag that this is +     * DCE_STYLE, so don't check the timestamps this time, but put the +     * flag DO_TIME back afterward. +    */  +    { +	krb5_ap_rep_enc_part *repl; +	int32_t auth_flags; +		 +	krb5_auth_con_removeflags(context, +				  ctx->auth_context, +				  KRB5_AUTH_CONTEXT_DO_TIME, +				  &auth_flags); + +	kret = krb5_rd_rep(context, ctx->auth_context, &inbuf, &repl); +	if (kret) { +	    *minor_status = kret; +	    return GSS_S_FAILURE; +	} +	krb5_free_ap_rep_enc_part(context, repl); +	krb5_auth_con_setflags(context, ctx->auth_context, auth_flags); +    } + +    /* We need to check the liftime */ +    { +	OM_uint32 lifetime_rec; + +	ret = _gsskrb5_lifetime_left(minor_status, +				     context, +				     ctx->lifetime, +				     &lifetime_rec); +	if (ret) { +	    return ret; +	} +	if (lifetime_rec == 0) { +	    return GSS_S_CONTEXT_EXPIRED; +	} +	 +	if (time_rec) *time_rec = lifetime_rec; +    } + +    /* We need to give the caller the flags which are in use */ +    if (ret_flags) *ret_flags = ctx->flags; + +    if (src_name) { +	kret = krb5_copy_principal(context, +				   ctx->source, +				   (gsskrb5_name*)src_name); +	if (kret) { +	    *minor_status = kret; +	    return GSS_S_FAILURE; +	} +    } + +    /* +     * After the krb5_rd_rep() the remote and local seq_number should +     * be the same, because the client just replies the seq_number +     * from our AP-REP in its AP-REP, but then the client uses the +     * seq_number from its AP-REQ for GSS_wrap() +     */ +    { +	int32_t tmp_r_seq_number, tmp_l_seq_number; + +	kret = krb5_auth_getremoteseqnumber(context, +					    ctx->auth_context, +					    &tmp_r_seq_number); +	if (kret) { +	    *minor_status = kret; +	    return GSS_S_FAILURE; +	} + +	kret = krb5_auth_con_getlocalseqnumber(context, +					       ctx->auth_context, +					       &tmp_l_seq_number); +	if (kret) { + +	    *minor_status = kret; +	    return GSS_S_FAILURE; +	} + +	/* +	 * Here we check if the client has responsed with our local seq_number, +	 */ +	if (tmp_r_seq_number != tmp_l_seq_number) { +	    return GSS_S_UNSEQ_TOKEN; +	} +    } + +    /* +     * We need to reset the remote seq_number, because the client will use, +     * the old one for the GSS_wrap() calls +     */ +    { +	kret = krb5_auth_con_setremoteseqnumber(context, +						ctx->auth_context, +						r_seq_number);	 +	if (kret) { +	    *minor_status = kret; +	    return GSS_S_FAILURE; +	} +    } + +    return gsskrb5_acceptor_ready(minor_status, ctx, context,  +				  delegated_cred_handle); +} + + +OM_uint32 +_gsskrb5_accept_sec_context(OM_uint32 * minor_status, +			    gss_ctx_id_t * context_handle, +			    const gss_cred_id_t acceptor_cred_handle, +			    const gss_buffer_t input_token_buffer, +			    const gss_channel_bindings_t input_chan_bindings, +			    gss_name_t * src_name, +			    gss_OID * mech_type, +			    gss_buffer_t output_token, +			    OM_uint32 * ret_flags, +			    OM_uint32 * time_rec, +			    gss_cred_id_t * delegated_cred_handle) +{ +    krb5_context context; +    OM_uint32 ret; +    gsskrb5_ctx ctx; + +    GSSAPI_KRB5_INIT(&context); + +    output_token->length = 0; +    output_token->value = NULL; + +    if (src_name != NULL) +	*src_name = NULL; +    if (mech_type) +	*mech_type = GSS_KRB5_MECHANISM; + +    if (*context_handle == GSS_C_NO_CONTEXT) { +	ret = _gsskrb5_create_ctx(minor_status, +				  context_handle, +				  context, +				  input_chan_bindings, +				  ACCEPTOR_START); +	if (ret) +	    return ret; +    } +     +    ctx = (gsskrb5_ctx)*context_handle; + +     +    /* +     * TODO: check the channel_bindings  +     * (above just sets them to krb5 layer) +     */ + +    HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex); +     +    switch (ctx->state) { +    case ACCEPTOR_START: +	ret = gsskrb5_acceptor_start(minor_status, +				     ctx, +				     context, +				     acceptor_cred_handle, +				     input_token_buffer, +				     input_chan_bindings, +				     src_name, +				     mech_type, +				     output_token, +				     ret_flags, +				     time_rec, +				     delegated_cred_handle); +	break; +    case ACCEPTOR_WAIT_FOR_DCESTYLE: +	ret = acceptor_wait_for_dcestyle(minor_status, +					 ctx, +					 context, +					 acceptor_cred_handle, +					 input_token_buffer, +					 input_chan_bindings, +					 src_name, +					 mech_type, +					 output_token, +					 ret_flags, +					 time_rec, +					 delegated_cred_handle); +	break; +    case ACCEPTOR_READY: +	/*  +	 * If we get there, the caller have called +	 * gss_accept_sec_context() one time too many. +	 */ +	ret =  GSS_S_BAD_STATUS; +	break; +    default: +	/* TODO: is this correct here? --metze */ +	ret =  GSS_S_BAD_STATUS; +	break; +    } +     +    HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); +     +    if (GSS_ERROR(ret)) { +	OM_uint32 min2; +	_gsskrb5_delete_sec_context(&min2, context_handle, GSS_C_NO_BUFFER); +    } + +    return ret; +} diff --git a/source4/heimdal/lib/gssapi/krb5/acquire_cred.c b/source4/heimdal/lib/gssapi/krb5/acquire_cred.c new file mode 100644 index 0000000000..a7caf1a32e --- /dev/null +++ b/source4/heimdal/lib/gssapi/krb5/acquire_cred.c @@ -0,0 +1,403 @@ +/* + * Copyright (c) 1997 - 2005 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.  + */ + +#include "krb5/gsskrb5_locl.h" + +RCSID("$Id$"); + +OM_uint32 +__gsskrb5_ccache_lifetime(OM_uint32 *minor_status, +			  krb5_context context, +			  krb5_ccache id, +			  krb5_principal principal, +			  OM_uint32 *lifetime) +{ +    krb5_creds in_cred, *out_cred; +    krb5_const_realm realm; +    krb5_error_code kret; + +    memset(&in_cred, 0, sizeof(in_cred)); +    in_cred.client = principal; +	 +    realm = krb5_principal_get_realm(context,  principal); +    if (realm == NULL) { +	_gsskrb5_clear_status (); +	*minor_status = KRB5_PRINC_NOMATCH; /* XXX */ +	return GSS_S_FAILURE; +    } + +    kret = krb5_make_principal(context, &in_cred.server,  +			       realm, KRB5_TGS_NAME, realm, NULL); +    if (kret) { +	*minor_status = kret; +	return GSS_S_FAILURE; +    } + +    kret = krb5_get_credentials(context, 0,  +				id, &in_cred, &out_cred); +    krb5_free_principal(context, in_cred.server); +    if (kret) { +	*minor_status = kret; +	return GSS_S_FAILURE; +    } + +    *lifetime = out_cred->times.endtime; +    krb5_free_creds(context, out_cred); + +    return GSS_S_COMPLETE; +} + + + + +static krb5_error_code +get_keytab(krb5_context context, krb5_keytab *keytab) +{ +    char kt_name[256]; +    krb5_error_code kret; + +    HEIMDAL_MUTEX_lock(&gssapi_keytab_mutex); + +    if (_gsskrb5_keytab != NULL) { +	kret = krb5_kt_get_name(context, +				_gsskrb5_keytab, +				kt_name, sizeof(kt_name)); +	if (kret == 0) +	    kret = krb5_kt_resolve(context, kt_name, keytab); +    } else +	kret = krb5_kt_default(context, keytab); + +    HEIMDAL_MUTEX_unlock(&gssapi_keytab_mutex); + +    return (kret); +} + +static OM_uint32 acquire_initiator_cred +		  (OM_uint32 * minor_status, +		   krb5_context context, +		   const gss_name_t desired_name, +		   OM_uint32 time_req, +		   const gss_OID_set desired_mechs, +		   gss_cred_usage_t cred_usage, +		   gsskrb5_cred handle, +		   gss_OID_set * actual_mechs, +		   OM_uint32 * time_rec +		  ) +{ +    OM_uint32 ret; +    krb5_creds cred; +    krb5_principal def_princ; +    krb5_get_init_creds_opt *opt; +    krb5_ccache ccache; +    krb5_keytab keytab; +    krb5_error_code kret; + +    keytab = NULL; +    ccache = NULL; +    def_princ = NULL; +    ret = GSS_S_FAILURE; +    memset(&cred, 0, sizeof(cred)); + +    /*  +     * If we have a preferred principal, lets try to find it in all +     * caches, otherwise, fall back to default cache, ignore all +     * errors while searching. +     */ + +    if (handle->principal) { +	kret = krb5_cc_cache_match (context, +				    handle->principal, +				    NULL, +				    &ccache); +	if (kret == 0) { +	    ret = GSS_S_COMPLETE; +	    goto found; +	} +    } +     +    if (ccache == NULL) { +	kret = krb5_cc_default(context, &ccache); +	if (kret) +	    goto end; +    } +    kret = krb5_cc_get_principal(context, ccache, &def_princ); +    if (kret != 0) { +	/* we'll try to use a keytab below */ +	krb5_cc_close(context, ccache); +	def_princ = NULL; +	kret = 0; +    } else if (handle->principal == NULL)  { +	kret = krb5_copy_principal(context, def_princ, &handle->principal); +	if (kret) +	    goto end; +    } else if (handle->principal != NULL && +	       krb5_principal_compare(context, handle->principal, +				      def_princ) == FALSE) { +	krb5_free_principal(context, def_princ); +	def_princ = NULL; +	krb5_cc_close(context, ccache); +	ccache = NULL; +    } +    if (def_princ == NULL) { +	/* We have no existing credentials cache, +	 * so attempt to get a TGT using a keytab. +	 */ +	if (handle->principal == NULL) { +	    kret = krb5_get_default_principal(context, &handle->principal); +	    if (kret) +		goto end; +	} +	kret = get_keytab(context, &keytab); +	if (kret) +	    goto end; +	kret = krb5_get_init_creds_opt_alloc(context, &opt); +	if (kret) +	    goto end; +	kret = krb5_get_init_creds_keytab(context, &cred, +	    handle->principal, keytab, 0, NULL, opt); +	krb5_get_init_creds_opt_free(context, opt); +	if (kret) +	    goto end; +	kret = krb5_cc_gen_new(context, &krb5_mcc_ops, &ccache); +	if (kret) +	    goto end; +	kret = krb5_cc_initialize(context, ccache, cred.client); +	if (kret) { +	    krb5_cc_destroy(context, ccache); +	    goto end; +	} +	kret = krb5_cc_store_cred(context, ccache, &cred); +	if (kret) { +	    krb5_cc_destroy(context, ccache); +	    goto end; +	} +	handle->lifetime = cred.times.endtime; +	handle->cred_flags |= GSS_CF_DESTROY_CRED_ON_RELEASE; +    } else { + +	ret = __gsskrb5_ccache_lifetime(minor_status, +					context, +					ccache, +					handle->principal, +					&handle->lifetime); +	if (ret != GSS_S_COMPLETE) { +	    krb5_cc_close(context, ccache); +	    goto end; +	} +	kret = 0; +    } + found: +    handle->ccache = ccache; +    ret = GSS_S_COMPLETE; + +end: +    if (cred.client != NULL) +	krb5_free_cred_contents(context, &cred); +    if (def_princ != NULL) +	krb5_free_principal(context, def_princ); +    if (keytab != NULL) +	krb5_kt_close(context, keytab); +    if (ret != GSS_S_COMPLETE && kret != 0) +	*minor_status = kret; +    return (ret); +} + +static OM_uint32 acquire_acceptor_cred +		  (OM_uint32 * minor_status, +		   krb5_context context, +		   const gss_name_t desired_name, +		   OM_uint32 time_req, +		   const gss_OID_set desired_mechs, +		   gss_cred_usage_t cred_usage, +		   gsskrb5_cred handle, +		   gss_OID_set * actual_mechs, +		   OM_uint32 * time_rec +		  ) +{ +    OM_uint32 ret; +    krb5_error_code kret; + +    ret = GSS_S_FAILURE; +    kret = get_keytab(context, &handle->keytab); +    if (kret) +	goto end; +     +    /* check that the requested principal exists in the keytab */ +    if (handle->principal) { +	krb5_keytab_entry entry; + +	kret = krb5_kt_get_entry(context, handle->keytab,  +				 handle->principal, 0, 0, &entry); +	if (kret) +	    goto end; +	krb5_kt_free_entry(context, &entry); +	ret = GSS_S_COMPLETE; +    } else { +	/*  +	 * Check if there is at least one entry in the keytab before +	 * declaring it as an useful keytab. +	 */ +	krb5_keytab_entry tmp; +	krb5_kt_cursor c; + +	kret = krb5_kt_start_seq_get (context, handle->keytab, &c); +	if (kret) +	    goto end; +	if (krb5_kt_next_entry(context, handle->keytab, &tmp, &c) == 0) { +	    krb5_kt_free_entry(context, &tmp); +	    ret = GSS_S_COMPLETE; /* ok found one entry */ +	} +	krb5_kt_end_seq_get (context, handle->keytab, &c); +    }  +end: +    if (ret != GSS_S_COMPLETE) { +	if (handle->keytab != NULL) +	    krb5_kt_close(context, handle->keytab); +	if (kret != 0) { +	    *minor_status = kret; +	} +    } +    return (ret); +} + +OM_uint32 _gsskrb5_acquire_cred +(OM_uint32 * minor_status, + const gss_name_t desired_name, + OM_uint32 time_req, + const gss_OID_set desired_mechs, + gss_cred_usage_t cred_usage, + gss_cred_id_t * output_cred_handle, + gss_OID_set * actual_mechs, + OM_uint32 * time_rec +    ) +{ +    krb5_context context; +    gsskrb5_cred handle; +    OM_uint32 ret; + +    if (cred_usage != GSS_C_ACCEPT && cred_usage != GSS_C_INITIATE && cred_usage != GSS_C_BOTH) { +	*minor_status = GSS_KRB5_S_G_BAD_USAGE; +	return GSS_S_FAILURE; +    } + +    GSSAPI_KRB5_INIT(&context); + +    *output_cred_handle = NULL; +    if (time_rec) +	*time_rec = 0; +    if (actual_mechs) +	*actual_mechs = GSS_C_NO_OID_SET; + +    if (desired_mechs) { +	int present = 0; + +	ret = gss_test_oid_set_member(minor_status, GSS_KRB5_MECHANISM, +				      desired_mechs, &present);  +	if (ret) +	    return ret; +	if (!present) { +	    *minor_status = 0; +	    return GSS_S_BAD_MECH; +	} +    } + +    handle = calloc(1, sizeof(*handle)); +    if (handle == NULL) { +	*minor_status = ENOMEM; +        return (GSS_S_FAILURE); +    } + +    HEIMDAL_MUTEX_init(&handle->cred_id_mutex); + +    if (desired_name != GSS_C_NO_NAME) { + +	ret = _gsskrb5_canon_name(minor_status, context, 0, desired_name,  +				  &handle->principal); +	if (ret) { +	    HEIMDAL_MUTEX_destroy(&handle->cred_id_mutex); +	    free(handle); +	    return ret; +	} +    } +    if (cred_usage == GSS_C_INITIATE || cred_usage == GSS_C_BOTH) { +	ret = acquire_initiator_cred(minor_status, context, +				     desired_name, time_req, +				     desired_mechs, cred_usage, handle, +				     actual_mechs, time_rec); +    	if (ret != GSS_S_COMPLETE) { +	    HEIMDAL_MUTEX_destroy(&handle->cred_id_mutex); +	    krb5_free_principal(context, handle->principal); +	    free(handle); +	    return (ret); +	} +    } +    if (cred_usage == GSS_C_ACCEPT || cred_usage == GSS_C_BOTH) { +	ret = acquire_acceptor_cred(minor_status, context, +				    desired_name, time_req, +				    desired_mechs, cred_usage, handle, actual_mechs, time_rec); +	if (ret != GSS_S_COMPLETE) { +	    HEIMDAL_MUTEX_destroy(&handle->cred_id_mutex); +	    krb5_free_principal(context, handle->principal); +	    free(handle); +	    return (ret); +	} +    } +    ret = gss_create_empty_oid_set(minor_status, &handle->mechanisms); +    if (ret == GSS_S_COMPLETE) +    	ret = gss_add_oid_set_member(minor_status, GSS_KRB5_MECHANISM, +				     &handle->mechanisms); +    if (ret == GSS_S_COMPLETE) +    	ret = _gsskrb5_inquire_cred(minor_status, (gss_cred_id_t)handle,  +				    NULL, time_rec, NULL, actual_mechs); +    if (ret != GSS_S_COMPLETE) { +	if (handle->mechanisms != NULL) +	    gss_release_oid_set(NULL, &handle->mechanisms); +	HEIMDAL_MUTEX_destroy(&handle->cred_id_mutex); +	krb5_free_principal(context, handle->principal); +	free(handle); +	return (ret); +    }  +    *minor_status = 0; +    if (time_rec) { +	ret = _gsskrb5_lifetime_left(minor_status, +				     context, +				     handle->lifetime, +				     time_rec); + +	if (ret) +	    return ret; +    } +    handle->usage = cred_usage; +    *output_cred_handle = (gss_cred_id_t)handle; +    return (GSS_S_COMPLETE); +} diff --git a/source4/heimdal/lib/gssapi/krb5/add_cred.c b/source4/heimdal/lib/gssapi/krb5/add_cred.c new file mode 100644 index 0000000000..5cd17eb35d --- /dev/null +++ b/source4/heimdal/lib/gssapi/krb5/add_cred.c @@ -0,0 +1,252 @@ +/* + * Copyright (c) 2003 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.  + */ + +#include "krb5/gsskrb5_locl.h" + +RCSID("$Id$"); + +OM_uint32 _gsskrb5_add_cred ( +     OM_uint32           *minor_status, +     const gss_cred_id_t input_cred_handle, +     const gss_name_t    desired_name, +     const gss_OID       desired_mech, +     gss_cred_usage_t    cred_usage, +     OM_uint32           initiator_time_req, +     OM_uint32           acceptor_time_req, +     gss_cred_id_t       *output_cred_handle, +     gss_OID_set         *actual_mechs, +     OM_uint32           *initiator_time_rec, +     OM_uint32           *acceptor_time_rec) +{ +    krb5_context context; +    OM_uint32 ret, lifetime; +    gsskrb5_cred cred, handle; +    krb5_const_principal dname; + +    handle = NULL; +    cred = (gsskrb5_cred)input_cred_handle; +    dname = (krb5_const_principal)desired_name; + +    GSSAPI_KRB5_INIT (&context); + +    if (gss_oid_equal(desired_mech, GSS_KRB5_MECHANISM) == 0) { +	*minor_status = 0; +	return GSS_S_BAD_MECH; +    } + +    if (cred == NULL && output_cred_handle == NULL) { +	*minor_status = 0; +	return GSS_S_NO_CRED; +    } + +    if (cred == NULL) { /* XXX standard conformance failure */ +	*minor_status = 0; +	return GSS_S_NO_CRED; +    } + +    /* check if requested output usage is compatible with output usage */  +    if (output_cred_handle != NULL) { +	HEIMDAL_MUTEX_lock(&cred->cred_id_mutex); +	if (cred->usage != cred_usage && cred->usage != GSS_C_BOTH) { +	    HEIMDAL_MUTEX_unlock(&cred->cred_id_mutex); +	    *minor_status = GSS_KRB5_S_G_BAD_USAGE; +	    return(GSS_S_FAILURE); +	} +    } +	 +    /* check that we have the same name */ +    if (dname != NULL && +	krb5_principal_compare(context, dname,  +			       cred->principal) != FALSE) { +	if (output_cred_handle) +	    HEIMDAL_MUTEX_unlock(&cred->cred_id_mutex); +	*minor_status = 0; +	return GSS_S_BAD_NAME; +    } + +    /* make a copy */ +    if (output_cred_handle) { +	krb5_error_code kret; + +	handle = calloc(1, sizeof(*handle)); +	if (handle == NULL) { +	    HEIMDAL_MUTEX_unlock(&cred->cred_id_mutex); +	    *minor_status = ENOMEM; +	    return (GSS_S_FAILURE); +	} + +	handle->usage = cred_usage; +	handle->lifetime = cred->lifetime; +	handle->principal = NULL; +	handle->keytab = NULL; +	handle->ccache = NULL; +	handle->mechanisms = NULL; +	HEIMDAL_MUTEX_init(&handle->cred_id_mutex); +	 +	ret = GSS_S_FAILURE; + +	kret = krb5_copy_principal(context, cred->principal, +				  &handle->principal); +	if (kret) { +	    HEIMDAL_MUTEX_unlock(&cred->cred_id_mutex); +	    free(handle); +	    *minor_status = kret; +	    return GSS_S_FAILURE; +	} + +	if (cred->keytab) { +	    char name[KRB5_KT_PREFIX_MAX_LEN + MAXPATHLEN]; +	    int len; +	     +	    ret = GSS_S_FAILURE; + +	    kret = krb5_kt_get_type(context, cred->keytab, +				    name, KRB5_KT_PREFIX_MAX_LEN); +	    if (kret) { +		*minor_status = kret; +		goto failure; +	    } +	    len = strlen(name); +	    name[len++] = ':'; + +	    kret = krb5_kt_get_name(context, cred->keytab, +				    name + len,  +				    sizeof(name) - len); +	    if (kret) { +		*minor_status = kret; +		goto failure; +	    } + +	    kret = krb5_kt_resolve(context, name, +				   &handle->keytab); +	    if (kret){ +		*minor_status = kret; +		goto failure; +	    } +	} + +	if (cred->ccache) { +	    const char *type, *name; +	    char *type_name; + +	    ret = GSS_S_FAILURE; + +	    type = krb5_cc_get_type(context, cred->ccache); +	    if (type == NULL){ +		*minor_status = ENOMEM; +		goto failure; +	    } + +	    if (strcmp(type, "MEMORY") == 0) { +		ret = krb5_cc_gen_new(context, &krb5_mcc_ops, +				      &handle->ccache); +		if (ret) { +		    *minor_status = ret; +		    goto failure; +		} + +		ret = krb5_cc_copy_cache(context, cred->ccache, +					 handle->ccache); +		if (ret) { +		    *minor_status = ret; +		    goto failure; +		} + +	    } else { +		name = krb5_cc_get_name(context, cred->ccache); +		if (name == NULL) { +		    *minor_status = ENOMEM; +		    goto failure; +		} +		 +		asprintf(&type_name, "%s:%s", type, name); +		if (type_name == NULL) { +		    *minor_status = ENOMEM; +		    goto failure; +		} +		 +		kret = krb5_cc_resolve(context, type_name, +				       &handle->ccache); +		free(type_name); +		if (kret) { +		    *minor_status = kret; +		    goto failure; +		}	     +	    } +	} +	ret = gss_create_empty_oid_set(minor_status, &handle->mechanisms); +	if (ret) +	    goto failure; + +	ret = gss_add_oid_set_member(minor_status, GSS_KRB5_MECHANISM, +				     &handle->mechanisms); +	if (ret) +	    goto failure; +    } + +    HEIMDAL_MUTEX_unlock(&cred->cred_id_mutex); + +    ret = _gsskrb5_inquire_cred(minor_status, (gss_cred_id_t)cred,  +				NULL, &lifetime, NULL, actual_mechs); +    if (ret) +	goto failure; + +    if (initiator_time_rec) +	*initiator_time_rec = lifetime; +    if (acceptor_time_rec) +	*acceptor_time_rec = lifetime; + +    if (output_cred_handle) { +	*output_cred_handle = (gss_cred_id_t)handle; +    } + +    *minor_status = 0; +    return ret; + + failure: + +    if (handle) { +	if (handle->principal) +	    krb5_free_principal(context, handle->principal); +	if (handle->keytab) +	    krb5_kt_close(context, handle->keytab); +	if (handle->ccache) +	    krb5_cc_destroy(context, handle->ccache); +	if (handle->mechanisms) +	    gss_release_oid_set(NULL, &handle->mechanisms); +	free(handle); +    } +    if (output_cred_handle) +	HEIMDAL_MUTEX_unlock(&cred->cred_id_mutex); +    return ret; +} diff --git a/source4/heimdal/lib/gssapi/krb5/address_to_krb5addr.c b/source4/heimdal/lib/gssapi/krb5/address_to_krb5addr.c new file mode 100644 index 0000000000..18a90fe9a7 --- /dev/null +++ b/source4/heimdal/lib/gssapi/krb5/address_to_krb5addr.c @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2000 - 2001 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.  + */ + +#include "krb5/gsskrb5_locl.h" + +#include <roken.h> + +krb5_error_code +_gsskrb5i_address_to_krb5addr(krb5_context context, +			      OM_uint32 gss_addr_type, +			      gss_buffer_desc *gss_addr, +			      int16_t port, +			      krb5_address *address) +{ +   int addr_type; +   struct sockaddr sa; +   krb5_socklen_t sa_size = sizeof(sa); +   krb5_error_code problem; +    +   if (gss_addr == NULL) +      return GSS_S_FAILURE;  +    +   switch (gss_addr_type) { +#ifdef HAVE_IPV6 +      case GSS_C_AF_INET6: addr_type = AF_INET6; +                           break; +#endif /* HAVE_IPV6 */ +                            +      case GSS_C_AF_INET:  addr_type = AF_INET; +                           break; +      default: +                           return GSS_S_FAILURE; +   } +                       +   problem = krb5_h_addr2sockaddr (context, +				   addr_type, +                                   gss_addr->value,  +                                   &sa,  +                                   &sa_size,  +                                   port); +   if (problem) +      return GSS_S_FAILURE; + +   problem = krb5_sockaddr2address (context, &sa, address); + +   return problem;   +} diff --git a/source4/heimdal/lib/gssapi/krb5/arcfour.c b/source4/heimdal/lib/gssapi/krb5/arcfour.c new file mode 100644 index 0000000000..2f39a4e400 --- /dev/null +++ b/source4/heimdal/lib/gssapi/krb5/arcfour.c @@ -0,0 +1,760 @@ +/* + * Copyright (c) 2003 - 2006 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.  + */ + +#include "krb5/gsskrb5_locl.h" + +RCSID("$Id$"); + +/* + * Implements draft-brezak-win2k-krb-rc4-hmac-04.txt + * + * The arcfour message have the following formats: + * + * MIC token + * 	TOK_ID[2] = 01 01 + *	SGN_ALG[2] = 11 00 + *	Filler[4] + *	SND_SEQ[8] + *	SGN_CKSUM[8] + * + * WRAP token + *	TOK_ID[2] = 02 01 + *	SGN_ALG[2]; + *	SEAL_ALG[2] + *	Filler[2] + *	SND_SEQ[2] + *	SGN_CKSUM[8] + *	Confounder[8] + */ + +/* + * WRAP in DCE-style have a fixed size header, the oid and length over + * the WRAP header is a total of + * GSS_ARCFOUR_WRAP_TOKEN_DCE_DER_HEADER_SIZE + + * GSS_ARCFOUR_WRAP_TOKEN_SIZE byte (ie total of 45 bytes overhead, + * remember the 2 bytes from APPL [0] SEQ). + */ + +#define GSS_ARCFOUR_WRAP_TOKEN_SIZE 32 +#define GSS_ARCFOUR_WRAP_TOKEN_DCE_DER_HEADER_SIZE 13 + + +static krb5_error_code +arcfour_mic_key(krb5_context context, krb5_keyblock *key, +		void *cksum_data, size_t cksum_size, +		void *key6_data, size_t key6_size) +{ +    krb5_error_code ret; +     +    Checksum cksum_k5; +    krb5_keyblock key5; +    char k5_data[16]; +     +    Checksum cksum_k6; +     +    char T[4]; + +    memset(T, 0, 4); +    cksum_k5.checksum.data = k5_data; +    cksum_k5.checksum.length = sizeof(k5_data); + +    if (key->keytype == KEYTYPE_ARCFOUR_56) { +	char L40[14] = "fortybits"; + +	memcpy(L40 + 10, T, sizeof(T)); +	ret = krb5_hmac(context, CKSUMTYPE_RSA_MD5, +			L40, 14, 0, key, &cksum_k5); +	memset(&k5_data[7], 0xAB, 9); +    } else { +	ret = krb5_hmac(context, CKSUMTYPE_RSA_MD5, +			T, 4, 0, key, &cksum_k5); +    } +    if (ret) +	return ret; + +    key5.keytype = KEYTYPE_ARCFOUR; +    key5.keyvalue = cksum_k5.checksum; + +    cksum_k6.checksum.data = key6_data; +    cksum_k6.checksum.length = key6_size; + +    return krb5_hmac(context, CKSUMTYPE_RSA_MD5, +		     cksum_data, cksum_size, 0, &key5, &cksum_k6); +} + + +static krb5_error_code +arcfour_mic_cksum(krb5_context context, +		  krb5_keyblock *key, unsigned usage, +		  u_char *sgn_cksum, size_t sgn_cksum_sz, +		  const u_char *v1, size_t l1, +		  const void *v2, size_t l2, +		  const void *v3, size_t l3) +{ +    Checksum CKSUM; +    u_char *ptr; +    size_t len; +    krb5_crypto crypto; +    krb5_error_code ret; +     +    assert(sgn_cksum_sz == 8); + +    len = l1 + l2 + l3; + +    ptr = malloc(len); +    if (ptr == NULL) +	return ENOMEM; + +    memcpy(ptr, v1, l1); +    memcpy(ptr + l1, v2, l2); +    memcpy(ptr + l1 + l2, v3, l3); +     +    ret = krb5_crypto_init(context, key, 0, &crypto); +    if (ret) { +	free(ptr); +	return ret; +    } +     +    ret = krb5_create_checksum(context, +			       crypto, +			       usage, +			       0, +			       ptr, len, +			       &CKSUM); +    free(ptr); +    if (ret == 0) { +	memcpy(sgn_cksum, CKSUM.checksum.data, sgn_cksum_sz); +	free_Checksum(&CKSUM); +    } +    krb5_crypto_destroy(context, crypto); + +    return ret; +} + + +OM_uint32 +_gssapi_get_mic_arcfour(OM_uint32 * minor_status, +			const gsskrb5_ctx context_handle, +			krb5_context context, +			gss_qop_t qop_req, +			const gss_buffer_t message_buffer, +			gss_buffer_t message_token, +			krb5_keyblock *key) +{ +    krb5_error_code ret; +    int32_t seq_number; +    size_t len, total_len; +    u_char k6_data[16], *p0, *p; +    RC4_KEY rc4_key; +     +    _gsskrb5_encap_length (22, &len, &total_len, GSS_KRB5_MECHANISM); +     +    message_token->length = total_len; +    message_token->value  = malloc (total_len); +    if (message_token->value == NULL) { +	*minor_status = ENOMEM; +	return GSS_S_FAILURE; +    } +     +    p0 = _gssapi_make_mech_header(message_token->value, +				  len, +				  GSS_KRB5_MECHANISM); +    p = p0; +     +    *p++ = 0x01; /* TOK_ID */ +    *p++ = 0x01; +    *p++ = 0x11; /* SGN_ALG */ +    *p++ = 0x00; +    *p++ = 0xff; /* Filler */ +    *p++ = 0xff; +    *p++ = 0xff; +    *p++ = 0xff; + +    p = NULL; + +    ret = arcfour_mic_cksum(context, +			    key, KRB5_KU_USAGE_SIGN, +			    p0 + 16, 8,  /* SGN_CKSUM */ +			    p0, 8, /* TOK_ID, SGN_ALG, Filer */ +			    message_buffer->value, message_buffer->length, +			    NULL, 0); +    if (ret) { +	_gsskrb5_release_buffer(minor_status, message_token); +	*minor_status = ret; +	return GSS_S_FAILURE; +    } + +    ret = arcfour_mic_key(context, key, +			  p0 + 16, 8, /* SGN_CKSUM */ +			  k6_data, sizeof(k6_data)); +    if (ret) { +	_gsskrb5_release_buffer(minor_status, message_token); +	*minor_status = ret; +	return GSS_S_FAILURE; +    } + +    HEIMDAL_MUTEX_lock(&context_handle->ctx_id_mutex); +    krb5_auth_con_getlocalseqnumber (context, +				     context_handle->auth_context, +				     &seq_number); +    p = p0 + 8; /* SND_SEQ */ +    _gsskrb5_encode_be_om_uint32(seq_number, p); +     +    krb5_auth_con_setlocalseqnumber (context, +				     context_handle->auth_context, +				     ++seq_number); +    HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); +     +    memset (p + 4, (context_handle->more_flags & LOCAL) ? 0 : 0xff, 4); + +    RC4_set_key (&rc4_key, sizeof(k6_data), k6_data); +    RC4 (&rc4_key, 8, p, p); +	 +    memset(&rc4_key, 0, sizeof(rc4_key)); +    memset(k6_data, 0, sizeof(k6_data)); +     +    *minor_status = 0; +    return GSS_S_COMPLETE; +} + + +OM_uint32 +_gssapi_verify_mic_arcfour(OM_uint32 * minor_status, +			   const gsskrb5_ctx context_handle, +			   krb5_context context, +			   const gss_buffer_t message_buffer, +			   const gss_buffer_t token_buffer, +			   gss_qop_t * qop_state, +			   krb5_keyblock *key, +			   char *type) +{ +    krb5_error_code ret; +    uint32_t seq_number; +    OM_uint32 omret; +    u_char SND_SEQ[8], cksum_data[8], *p; +    char k6_data[16]; +    int cmp; +     +    if (qop_state) +	*qop_state = 0; + +    p = token_buffer->value; +    omret = _gsskrb5_verify_header (&p, +				       token_buffer->length, +				       (u_char *)type, +				       GSS_KRB5_MECHANISM); +    if (omret) +	return omret; +     +    if (memcmp(p, "\x11\x00", 2) != 0) /* SGN_ALG = HMAC MD5 ARCFOUR */ +	return GSS_S_BAD_SIG; +    p += 2; +    if (memcmp (p, "\xff\xff\xff\xff", 4) != 0) +	return GSS_S_BAD_MIC; +    p += 4; + +    ret = arcfour_mic_cksum(context, +			    key, KRB5_KU_USAGE_SIGN, +			    cksum_data, sizeof(cksum_data), +			    p - 8, 8, +			    message_buffer->value, message_buffer->length, +			    NULL, 0); +    if (ret) { +	*minor_status = ret; +	return GSS_S_FAILURE; +    } + +    ret = arcfour_mic_key(context, key, +			  cksum_data, sizeof(cksum_data), +			  k6_data, sizeof(k6_data)); +    if (ret) { +	*minor_status = ret; +	return GSS_S_FAILURE; +    } + +    cmp = memcmp(cksum_data, p + 8, 8); +    if (cmp) { +	*minor_status = 0; +	return GSS_S_BAD_MIC; +    } + +    { +	RC4_KEY rc4_key; +	 +	RC4_set_key (&rc4_key, sizeof(k6_data), (void*)k6_data); +	RC4 (&rc4_key, 8, p, SND_SEQ); +	 +	memset(&rc4_key, 0, sizeof(rc4_key)); +	memset(k6_data, 0, sizeof(k6_data)); +    } + +    _gsskrb5_decode_be_om_uint32(SND_SEQ, &seq_number); + +    if (context_handle->more_flags & LOCAL) +	cmp = memcmp(&SND_SEQ[4], "\xff\xff\xff\xff", 4); +    else +	cmp = memcmp(&SND_SEQ[4], "\x00\x00\x00\x00", 4); + +    memset(SND_SEQ, 0, sizeof(SND_SEQ)); +    if (cmp != 0) { +	*minor_status = 0; +	return GSS_S_BAD_MIC; +    } +     +    HEIMDAL_MUTEX_lock(&context_handle->ctx_id_mutex); +    omret = _gssapi_msg_order_check(context_handle->order, seq_number); +    HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); +    if (omret) +	return omret; + +    *minor_status = 0; +    return GSS_S_COMPLETE; +} + +OM_uint32 +_gssapi_wrap_arcfour(OM_uint32 * minor_status, +		     const gsskrb5_ctx context_handle, +		     krb5_context context, +		     int conf_req_flag, +		     gss_qop_t qop_req, +		     const gss_buffer_t input_message_buffer, +		     int * conf_state, +		     gss_buffer_t output_message_buffer, +		     krb5_keyblock *key) +{ +    u_char Klocaldata[16], k6_data[16], *p, *p0; +    size_t len, total_len, datalen; +    krb5_keyblock Klocal; +    krb5_error_code ret; +    int32_t seq_number; + +    if (conf_state) +	*conf_state = 0; + +    datalen = input_message_buffer->length; + +    if (IS_DCE_STYLE(context_handle)) { +	len = GSS_ARCFOUR_WRAP_TOKEN_SIZE; +	_gssapi_encap_length(len, &len, &total_len, GSS_KRB5_MECHANISM); +	total_len += datalen; +    } else { +	datalen += 1; /* padding */ +	len = datalen + GSS_ARCFOUR_WRAP_TOKEN_SIZE; +	_gssapi_encap_length(len, &len, &total_len, GSS_KRB5_MECHANISM); +    } + +    output_message_buffer->length = total_len; +    output_message_buffer->value  = malloc (total_len); +    if (output_message_buffer->value == NULL) { +	*minor_status = ENOMEM; +	return GSS_S_FAILURE; +    } +     +    p0 = _gssapi_make_mech_header(output_message_buffer->value, +				  len, +				  GSS_KRB5_MECHANISM); +    p = p0; + +    *p++ = 0x02; /* TOK_ID */ +    *p++ = 0x01; +    *p++ = 0x11; /* SGN_ALG */ +    *p++ = 0x00; +    if (conf_req_flag) { +	*p++ = 0x10; /* SEAL_ALG */ +	*p++ = 0x00; +    } else { +	*p++ = 0xff; /* SEAL_ALG */ +	*p++ = 0xff; +    } +    *p++ = 0xff; /* Filler */ +    *p++ = 0xff; + +    p = NULL; + +    HEIMDAL_MUTEX_lock(&context_handle->ctx_id_mutex); +    krb5_auth_con_getlocalseqnumber (context, +				     context_handle->auth_context, +				     &seq_number); + +    _gsskrb5_encode_be_om_uint32(seq_number, p0 + 8); + +    krb5_auth_con_setlocalseqnumber (context, +				     context_handle->auth_context, +				     ++seq_number); +    HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); + +    memset (p0 + 8 + 4, +	    (context_handle->more_flags & LOCAL) ? 0 : 0xff, +	    4); + +    krb5_generate_random_block(p0 + 24, 8); /* fill in Confounder */ +     +    /* p points to data */ +    p = p0 + GSS_ARCFOUR_WRAP_TOKEN_SIZE; +    memcpy(p, input_message_buffer->value, input_message_buffer->length); + +    if (!IS_DCE_STYLE(context_handle)) +	p[input_message_buffer->length] = 1; /* padding */ + +    ret = arcfour_mic_cksum(context, +			    key, KRB5_KU_USAGE_SEAL, +			    p0 + 16, 8, /* SGN_CKSUM */  +			    p0, 8, /* TOK_ID, SGN_ALG, SEAL_ALG, Filler */ +			    p0 + 24, 8, /* Confounder */ +			    p0 + GSS_ARCFOUR_WRAP_TOKEN_SIZE,  +			    datalen); +    if (ret) { +	*minor_status = ret; +	_gsskrb5_release_buffer(minor_status, output_message_buffer); +	return GSS_S_FAILURE; +    } + +    { +	int i; + +	Klocal.keytype = key->keytype; +	Klocal.keyvalue.data = Klocaldata; +	Klocal.keyvalue.length = sizeof(Klocaldata); + +	for (i = 0; i < 16; i++) +	    Klocaldata[i] = ((u_char *)key->keyvalue.data)[i] ^ 0xF0; +    } +    ret = arcfour_mic_key(context, &Klocal, +			  p0 + 8, 4, /* SND_SEQ */ +			  k6_data, sizeof(k6_data)); +    memset(Klocaldata, 0, sizeof(Klocaldata)); +    if (ret) { +	_gsskrb5_release_buffer(minor_status, output_message_buffer); +	*minor_status = ret; +	return GSS_S_FAILURE; +    } + + +    if(conf_req_flag) { +	RC4_KEY rc4_key; + +	RC4_set_key (&rc4_key, sizeof(k6_data), (void *)k6_data); +	/* XXX ? */ +	RC4 (&rc4_key, 8 + datalen, p0 + 24, p0 + 24); /* Confounder + data */ +	memset(&rc4_key, 0, sizeof(rc4_key)); +    } +    memset(k6_data, 0, sizeof(k6_data)); + +    ret = arcfour_mic_key(context, key, +			  p0 + 16, 8, /* SGN_CKSUM */ +			  k6_data, sizeof(k6_data)); +    if (ret) { +	_gsskrb5_release_buffer(minor_status, output_message_buffer); +	*minor_status = ret; +	return GSS_S_FAILURE; +    } + +    { +	RC4_KEY rc4_key; +	 +	RC4_set_key (&rc4_key, sizeof(k6_data), k6_data); +	RC4 (&rc4_key, 8, p0 + 8, p0 + 8); /* SND_SEQ */ +	memset(&rc4_key, 0, sizeof(rc4_key)); +	memset(k6_data, 0, sizeof(k6_data)); +    } + +    if (conf_state) +	*conf_state = conf_req_flag; + +    *minor_status = 0; +    return GSS_S_COMPLETE; +} + +OM_uint32 _gssapi_unwrap_arcfour(OM_uint32 *minor_status, +				 const gsskrb5_ctx context_handle, +				 krb5_context context, +				 const gss_buffer_t input_message_buffer, +				 gss_buffer_t output_message_buffer, +				 int *conf_state, +				 gss_qop_t *qop_state, +				 krb5_keyblock *key) +{ +    u_char Klocaldata[16]; +    krb5_keyblock Klocal; +    krb5_error_code ret; +    uint32_t seq_number; +    size_t datalen; +    OM_uint32 omret; +    u_char k6_data[16], SND_SEQ[8], Confounder[8]; +    u_char cksum_data[8]; +    u_char *p, *p0; +    int cmp; +    int conf_flag; +    size_t padlen = 0, len; +     +    if (conf_state) +	*conf_state = 0; +    if (qop_state) +	*qop_state = 0; + +    p0 = input_message_buffer->value; + +    if (IS_DCE_STYLE(context_handle)) { +	len = GSS_ARCFOUR_WRAP_TOKEN_SIZE +  +	    GSS_ARCFOUR_WRAP_TOKEN_DCE_DER_HEADER_SIZE; +	if (input_message_buffer->length < len) +	    return GSS_S_BAD_MECH; +    } else { +	len = input_message_buffer->length; +    } + +    omret = _gssapi_verify_mech_header(&p0, +				       len, +				       GSS_KRB5_MECHANISM); +    if (omret) +	return omret; + +    /* length of mech header */ +    len = (p0 - (u_char *)input_message_buffer->value) +  +	GSS_ARCFOUR_WRAP_TOKEN_SIZE; + +    if (len > input_message_buffer->length) +	return GSS_S_BAD_MECH; + +    /* length of data */ +    datalen = input_message_buffer->length - len; + +    p = p0; + +    if (memcmp(p, "\x02\x01", 2) != 0) +	return GSS_S_BAD_SIG; +    p += 2; +    if (memcmp(p, "\x11\x00", 2) != 0) /* SGN_ALG = HMAC MD5 ARCFOUR */ +	return GSS_S_BAD_SIG; +    p += 2; + +    if (memcmp (p, "\x10\x00", 2) == 0) +	conf_flag = 1; +    else if (memcmp (p, "\xff\xff", 2) == 0) +	conf_flag = 0; +    else +	return GSS_S_BAD_SIG; + +    p += 2; +    if (memcmp (p, "\xff\xff", 2) != 0) +	return GSS_S_BAD_MIC; +    p = NULL; + +    ret = arcfour_mic_key(context, key, +			  p0 + 16, 8, /* SGN_CKSUM */ +			  k6_data, sizeof(k6_data)); +    if (ret) { +	*minor_status = ret; +	return GSS_S_FAILURE; +    } + +    { +	RC4_KEY rc4_key; +	 +	RC4_set_key (&rc4_key, sizeof(k6_data), k6_data); +	RC4 (&rc4_key, 8, p0 + 8, SND_SEQ); /* SND_SEQ */ +	memset(&rc4_key, 0, sizeof(rc4_key)); +	memset(k6_data, 0, sizeof(k6_data)); +    } + +    _gsskrb5_decode_be_om_uint32(SND_SEQ, &seq_number); + +    if (context_handle->more_flags & LOCAL) +	cmp = memcmp(&SND_SEQ[4], "\xff\xff\xff\xff", 4); +    else +	cmp = memcmp(&SND_SEQ[4], "\x00\x00\x00\x00", 4); + +    if (cmp != 0) { +	*minor_status = 0; +	return GSS_S_BAD_MIC; +    } + +    { +	int i; + +	Klocal.keytype = key->keytype; +	Klocal.keyvalue.data = Klocaldata; +	Klocal.keyvalue.length = sizeof(Klocaldata); + +	for (i = 0; i < 16; i++) +	    Klocaldata[i] = ((u_char *)key->keyvalue.data)[i] ^ 0xF0; +    } +    ret = arcfour_mic_key(context, &Klocal, +			  SND_SEQ, 4, +			  k6_data, sizeof(k6_data)); +    memset(Klocaldata, 0, sizeof(Klocaldata)); +    if (ret) { +	*minor_status = ret; +	return GSS_S_FAILURE; +    } + +    output_message_buffer->value = malloc(datalen); +    if (output_message_buffer->value == NULL) { +	*minor_status = ENOMEM; +	return GSS_S_FAILURE; +    } +    output_message_buffer->length = datalen; + +    if(conf_flag) { +	RC4_KEY rc4_key; + +	RC4_set_key (&rc4_key, sizeof(k6_data), k6_data); +	RC4 (&rc4_key, 8, p0 + 24, Confounder); /* Confounder */ +	RC4 (&rc4_key, datalen, p0 + GSS_ARCFOUR_WRAP_TOKEN_SIZE, +	     output_message_buffer->value); +	memset(&rc4_key, 0, sizeof(rc4_key)); +    } else { +	memcpy(Confounder, p0 + 24, 8); /* Confounder */ +	memcpy(output_message_buffer->value,  +	       p0 + GSS_ARCFOUR_WRAP_TOKEN_SIZE, +	       datalen); +    } +    memset(k6_data, 0, sizeof(k6_data)); + +    if (!IS_DCE_STYLE(context_handle)) { +	ret = _gssapi_verify_pad(output_message_buffer, datalen, &padlen); +	if (ret) { +	    _gsskrb5_release_buffer(minor_status, output_message_buffer); +	    *minor_status = 0; +	    return ret; +	} +	output_message_buffer->length -= padlen; +    } + +    ret = arcfour_mic_cksum(context, +			    key, KRB5_KU_USAGE_SEAL, +			    cksum_data, sizeof(cksum_data), +			    p0, 8,  +			    Confounder, sizeof(Confounder), +			    output_message_buffer->value,  +			    output_message_buffer->length + padlen); +    if (ret) { +	_gsskrb5_release_buffer(minor_status, output_message_buffer); +	*minor_status = ret; +	return GSS_S_FAILURE; +    } + +    cmp = memcmp(cksum_data, p0 + 16, 8); /* SGN_CKSUM */ +    if (cmp) { +	_gsskrb5_release_buffer(minor_status, output_message_buffer); +	*minor_status = 0; +	return GSS_S_BAD_MIC; +    } + +    HEIMDAL_MUTEX_lock(&context_handle->ctx_id_mutex); +    omret = _gssapi_msg_order_check(context_handle->order, seq_number); +    HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); +    if (omret) +	return omret; + +    if (conf_state) +	*conf_state = conf_flag; + +    *minor_status = 0; +    return GSS_S_COMPLETE; +} + +static OM_uint32 +max_wrap_length_arcfour(const gsskrb5_ctx ctx, +			krb5_crypto crypto, +			size_t input_length, +			OM_uint32 *max_input_size) +{ +    /*  +     * if GSS_C_DCE_STYLE is in use: +     *  - we only need to encapsulate the WRAP token +     * However, since this is a fixed since, we just  +     */ +    if (IS_DCE_STYLE(ctx)) { +	size_t len, total_len; + +	len = GSS_ARCFOUR_WRAP_TOKEN_SIZE; +	_gssapi_encap_length(len, &len, &total_len, GSS_KRB5_MECHANISM); + +	if (input_length < len) +	    *max_input_size = 0; +	else +	    *max_input_size = input_length - len; + +    } else { +	size_t extrasize = GSS_ARCFOUR_WRAP_TOKEN_SIZE; +	size_t blocksize = 8; +	size_t len, total_len; + +	len = 8 + input_length + blocksize + extrasize; + +	_gsskrb5_encap_length(len, &len, &total_len, GSS_KRB5_MECHANISM); + +	total_len -= input_length; /* token length */ +	if (total_len < input_length) { +	    *max_input_size = (input_length - total_len); +	    (*max_input_size) &= (~(OM_uint32)(blocksize - 1)); +	} else { +	    *max_input_size = 0; +	} +    } + +    return GSS_S_COMPLETE; +} + +OM_uint32 +_gssapi_wrap_size_arcfour(OM_uint32 *minor_status, +			  const gsskrb5_ctx ctx, +			  krb5_context context, +			  int conf_req_flag, +			  gss_qop_t qop_req, +			  OM_uint32 req_output_size, +			  OM_uint32 *max_input_size, +			  krb5_keyblock *key) +{ +    krb5_error_code ret; +    krb5_crypto crypto; + +    ret = krb5_crypto_init(context, key, 0, &crypto); +    if (ret != 0) { +	*minor_status = ret; +	return GSS_S_FAILURE; +    } + +    ret = max_wrap_length_arcfour(ctx, crypto, +				  req_output_size, max_input_size); +    if (ret != 0) { +	*minor_status = ret; +	krb5_crypto_destroy(context, crypto); +	return GSS_S_FAILURE; +    } + +    krb5_crypto_destroy(context, crypto); + +    return GSS_S_COMPLETE; +} diff --git a/source4/heimdal/lib/gssapi/krb5/canonicalize_name.c b/source4/heimdal/lib/gssapi/krb5/canonicalize_name.c new file mode 100644 index 0000000000..f2143560d0 --- /dev/null +++ b/source4/heimdal/lib/gssapi/krb5/canonicalize_name.c @@ -0,0 +1,60 @@ +/* + * Copyright (c) 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.  + */ + +#include "krb5/gsskrb5_locl.h" + +RCSID("$Id$"); + +OM_uint32 _gsskrb5_canonicalize_name ( +            OM_uint32 * minor_status, +            const gss_name_t input_name, +            const gss_OID mech_type, +            gss_name_t * output_name +           ) +{ +    krb5_context context; +    krb5_principal name; +    OM_uint32 ret; + +    *output_name = NULL; + +    GSSAPI_KRB5_INIT (&context); + +    ret = _gsskrb5_canon_name(minor_status, context, 1, input_name, &name); +    if (ret) +	return ret; + +    *output_name = (gss_name_t)name; + +    return GSS_S_COMPLETE; +} diff --git a/source4/heimdal/lib/gssapi/krb5/cfx.c b/source4/heimdal/lib/gssapi/krb5/cfx.c new file mode 100755 index 0000000000..188344fb26 --- /dev/null +++ b/source4/heimdal/lib/gssapi/krb5/cfx.c @@ -0,0 +1,905 @@ +/* + * Copyright (c) 2003, PADL Software Pty Ltd. + * 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 PADL Software 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 PADL SOFTWARE 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 PADL SOFTWARE 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. + */ + +#include "krb5/gsskrb5_locl.h" + +RCSID("$Id$"); + +/* + * Implementation of draft-ietf-krb-wg-gssapi-cfx-06.txt + */ + +#define CFXSentByAcceptor	(1 << 0) +#define CFXSealed		(1 << 1) +#define CFXAcceptorSubkey	(1 << 2) + +krb5_error_code +_gsskrb5cfx_wrap_length_cfx(const gsskrb5_ctx context_handle, +			    krb5_context context, +			    krb5_crypto crypto, +			    int conf_req_flag, +			    size_t input_length, +			    size_t *output_length, +			    size_t *cksumsize, +			    uint16_t *padlength) +{ +    krb5_error_code ret; +    krb5_cksumtype type; + +    /* 16-byte header is always first */ +    *output_length = sizeof(gss_cfx_wrap_token_desc); +    *padlength = 0; + +    ret = krb5_crypto_get_checksum_type(context, crypto, &type); +    if (ret) +	return ret; + +    ret = krb5_checksumsize(context, type, cksumsize); +    if (ret) +	return ret; + +    if (conf_req_flag) { +	size_t padsize; + +	/* Header is concatenated with data before encryption */ +	input_length += sizeof(gss_cfx_wrap_token_desc); + +	if (IS_DCE_STYLE(context_handle)) { +		ret = krb5_crypto_getblocksize(context, crypto, &padsize); +	} else { +		ret = krb5_crypto_getpadsize(context, crypto, &padsize); +	} +	if (ret) { +	    return ret; +	} +	if (padsize > 1) { +	    /* XXX check this */ +	    *padlength = padsize - (input_length % padsize); + +	    /* We add the pad ourselves (noted here for completeness only) */ +	    input_length += *padlength; +	} + +	*output_length += krb5_get_wrapped_length(context, +						  crypto, input_length); +    } else { +	/* Checksum is concatenated with data */ +	*output_length += input_length + *cksumsize; +    } + +    assert(*output_length > input_length); + +    return 0; +} + +krb5_error_code +_gsskrb5cfx_max_wrap_length_cfx(krb5_context context, +				krb5_crypto crypto, +				int conf_req_flag, +				size_t input_length, +				OM_uint32 *output_length) +{ +    krb5_error_code ret; + +    *output_length = 0; + +    /* 16-byte header is always first */ +    if (input_length < 16) +	return 0; +    input_length -= 16; + +    if (conf_req_flag) { +	size_t wrapped_size, sz; + +	wrapped_size = input_length + 1; +	do { +	    wrapped_size--; +	    sz = krb5_get_wrapped_length(context,  +					 crypto, wrapped_size); +	} while (wrapped_size && sz > input_length); +	if (wrapped_size == 0) { +	    *output_length = 0; +	    return 0; +	} + +	/* inner header */ +	if (wrapped_size < 16) { +	    *output_length = 0; +	    return 0; +	} +	wrapped_size -= 16; + +	*output_length = wrapped_size; +    } else { +	krb5_cksumtype type; +	size_t cksumsize; + +	ret = krb5_crypto_get_checksum_type(context, crypto, &type); +	if (ret) +	    return ret; + +	ret = krb5_checksumsize(context, type, &cksumsize); +	if (ret) +	    return ret; + +	if (input_length < cksumsize) +	    return 0; + +	/* Checksum is concatenated with data */ +	*output_length = input_length - cksumsize; +    } + +    return 0; +} + + +OM_uint32 _gssapi_wrap_size_cfx(OM_uint32 *minor_status, +				const gsskrb5_ctx context_handle, +				krb5_context context, +				int conf_req_flag, +				gss_qop_t qop_req, +				OM_uint32 req_output_size, +				OM_uint32 *max_input_size, +				krb5_keyblock *key) +{ +    krb5_error_code ret; +    krb5_crypto crypto; + +    ret = krb5_crypto_init(context, key, 0, &crypto); +    if (ret != 0) { +	*minor_status = ret; +	return GSS_S_FAILURE; +    } + +    ret = _gsskrb5cfx_max_wrap_length_cfx(context, crypto, conf_req_flag,  +					  req_output_size, max_input_size); +    if (ret != 0) { +	*minor_status = ret; +	krb5_crypto_destroy(context, crypto); +	return GSS_S_FAILURE; +    } + +    krb5_crypto_destroy(context, crypto); + +    return GSS_S_COMPLETE; +} + +/* + * Rotate "rrc" bytes to the front or back + */ + +static krb5_error_code +rrc_rotate(void *data, size_t len, uint16_t rrc, krb5_boolean unrotate) +{ +    u_char *tmp, buf[256]; +    size_t left; + +    if (len == 0) +	return 0; + +    rrc %= len; + +    if (rrc == 0) +	return 0; + +    left = len - rrc; + +    if (rrc <= sizeof(buf)) { +	tmp = buf; +    } else { +	tmp = malloc(rrc); +	if (tmp == NULL)  +	    return ENOMEM; +    } +  +    if (unrotate) { +	memcpy(tmp, data, rrc); +	memmove(data, (u_char *)data + rrc, left); +	memcpy((u_char *)data + left, tmp, rrc); +    } else { +	memcpy(tmp, (u_char *)data + left, rrc); +	memmove((u_char *)data + rrc, data, left); +	memcpy(data, tmp, rrc); +    } + +    if (rrc > sizeof(buf))  +	free(tmp); + +    return 0; +} + +OM_uint32 _gssapi_wrap_cfx(OM_uint32 *minor_status, +			   const gsskrb5_ctx context_handle, +			   krb5_context context, +			   int conf_req_flag, +			   gss_qop_t qop_req, +			   const gss_buffer_t input_message_buffer, +			   int *conf_state, +			   gss_buffer_t output_message_buffer, +			   krb5_keyblock *key) +{ +    krb5_crypto crypto; +    gss_cfx_wrap_token token; +    krb5_error_code ret; +    unsigned usage; +    krb5_data cipher; +    size_t wrapped_len, cksumsize; +    uint16_t padlength, rrc = 0; +    int32_t seq_number; +    u_char *p; + +    ret = krb5_crypto_init(context, key, 0, &crypto); +    if (ret != 0) { +	*minor_status = ret; +	return GSS_S_FAILURE; +    } + +    ret = _gsskrb5cfx_wrap_length_cfx(context_handle, context, +				      crypto, conf_req_flag,  +				      input_message_buffer->length, +				      &wrapped_len, &cksumsize, &padlength); +    if (ret != 0) { +	*minor_status = ret; +	krb5_crypto_destroy(context, crypto); +	return GSS_S_FAILURE; +    } + +    /* Always rotate encrypted token (if any) and checksum to header */ +    rrc = (conf_req_flag ? sizeof(*token) : 0) + (uint16_t)cksumsize; + +    output_message_buffer->length = wrapped_len; +    output_message_buffer->value = malloc(output_message_buffer->length); +    if (output_message_buffer->value == NULL) { +	*minor_status = ENOMEM; +	krb5_crypto_destroy(context, crypto); +	return GSS_S_FAILURE; +    } + +    p = output_message_buffer->value; +    token = (gss_cfx_wrap_token)p; +    token->TOK_ID[0] = 0x05; +    token->TOK_ID[1] = 0x04; +    token->Flags     = 0; +    token->Filler    = 0xFF; +    if ((context_handle->more_flags & LOCAL) == 0) +	token->Flags |= CFXSentByAcceptor; +    if (context_handle->more_flags & ACCEPTOR_SUBKEY) +	token->Flags |= CFXAcceptorSubkey; +    if (conf_req_flag) { +	/* +	 * In Wrap tokens with confidentiality, the EC field is +	 * used to encode the size (in bytes) of the random filler. +	 */ +	token->Flags |= CFXSealed; +	token->EC[0] = (padlength >> 8) & 0xFF; +	token->EC[1] = (padlength >> 0) & 0xFF; +    } else { +	/* +	 * In Wrap tokens without confidentiality, the EC field is +	 * used to encode the size (in bytes) of the trailing +	 * checksum. +	 * +	 * This is not used in the checksum calcuation itself, +	 * because the checksum length could potentially vary +	 * depending on the data length. +	 */ +	token->EC[0] = 0; +	token->EC[1] = 0; +    } + +    /* +     * In Wrap tokens that provide for confidentiality, the RRC +     * field in the header contains the hex value 00 00 before +     * encryption. +     * +     * In Wrap tokens that do not provide for confidentiality, +     * both the EC and RRC fields in the appended checksum +     * contain the hex value 00 00 for the purpose of calculating +     * the checksum. +     */ +    token->RRC[0] = 0; +    token->RRC[1] = 0; + +    HEIMDAL_MUTEX_lock(&context_handle->ctx_id_mutex); +    krb5_auth_con_getlocalseqnumber(context, +				    context_handle->auth_context, +				    &seq_number); +    _gsskrb5_encode_be_om_uint32(0,          &token->SND_SEQ[0]); +    _gsskrb5_encode_be_om_uint32(seq_number, &token->SND_SEQ[4]); +    krb5_auth_con_setlocalseqnumber(context, +				    context_handle->auth_context, +				    ++seq_number); +    HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); + +    /* +     * If confidentiality is requested, the token header is +     * appended to the plaintext before encryption; the resulting +     * token is {"header" | encrypt(plaintext | pad | "header")}. +     * +     * If no confidentiality is requested, the checksum is +     * calculated over the plaintext concatenated with the +     * token header. +     */ +    if (context_handle->more_flags & LOCAL) { +	usage = KRB5_KU_USAGE_INITIATOR_SEAL; +    } else { +	usage = KRB5_KU_USAGE_ACCEPTOR_SEAL; +    } + +    if (conf_req_flag) { +	/* +	 * Any necessary padding is added here to ensure that the +	 * encrypted token header is always at the end of the +	 * ciphertext. +	 * +	 * The specification does not require that the padding +	 * bytes are initialized. +	 */ +	p += sizeof(*token); +	memcpy(p, input_message_buffer->value, input_message_buffer->length); +	memset(p + input_message_buffer->length, 0xFF, padlength); +	memcpy(p + input_message_buffer->length + padlength, +	       token, sizeof(*token)); + +	ret = krb5_encrypt(context, crypto, +			   usage, p, +			   input_message_buffer->length + padlength + +				sizeof(*token), +			   &cipher); +	if (ret != 0) { +	    *minor_status = ret; +	    krb5_crypto_destroy(context, crypto); +	    _gsskrb5_release_buffer(minor_status, output_message_buffer); +	    return GSS_S_FAILURE; +	} +	assert(sizeof(*token) + cipher.length == wrapped_len); +	token->RRC[0] = (rrc >> 8) & 0xFF;   +	token->RRC[1] = (rrc >> 0) & 0xFF; + +	/* +	 * this is really ugly, but needed against windows +	 * for DCERPC, as windows rotates by EC+RRC. +	 */ +	if (IS_DCE_STYLE(context_handle)) { +		ret = rrc_rotate(cipher.data, cipher.length, rrc+padlength, FALSE); +	} else { +		ret = rrc_rotate(cipher.data, cipher.length, rrc, FALSE); +	} +	if (ret != 0) { +	    *minor_status = ret; +	    krb5_crypto_destroy(context, crypto); +	    _gsskrb5_release_buffer(minor_status, output_message_buffer); +	    return GSS_S_FAILURE; +	} +	memcpy(p, cipher.data, cipher.length); +	krb5_data_free(&cipher); +    } else { +	char *buf; +	Checksum cksum; + +	buf = malloc(input_message_buffer->length + sizeof(*token)); +	if (buf == NULL) { +	    *minor_status = ENOMEM; +	    krb5_crypto_destroy(context, crypto); +	    _gsskrb5_release_buffer(minor_status, output_message_buffer); +	    return GSS_S_FAILURE; +	} +	memcpy(buf, input_message_buffer->value, input_message_buffer->length); +	memcpy(buf + input_message_buffer->length, token, sizeof(*token)); + +	ret = krb5_create_checksum(context, crypto, +				   usage, 0, buf,  +				   input_message_buffer->length + +					sizeof(*token),  +				   &cksum); +	if (ret != 0) { +	    *minor_status = ret; +	    krb5_crypto_destroy(context, crypto); +	    _gsskrb5_release_buffer(minor_status, output_message_buffer); +	    free(buf); +	    return GSS_S_FAILURE; +	} + +	free(buf); + +	assert(cksum.checksum.length == cksumsize); +	token->EC[0] =  (cksum.checksum.length >> 8) & 0xFF; +	token->EC[1] =  (cksum.checksum.length >> 0) & 0xFF; +	token->RRC[0] = (rrc >> 8) & 0xFF;   +	token->RRC[1] = (rrc >> 0) & 0xFF; + +	p += sizeof(*token); +	memcpy(p, input_message_buffer->value, input_message_buffer->length); +	memcpy(p + input_message_buffer->length, +	       cksum.checksum.data, cksum.checksum.length); + +	ret = rrc_rotate(p, +	    input_message_buffer->length + cksum.checksum.length, rrc, FALSE); +	if (ret != 0) { +	    *minor_status = ret; +	    krb5_crypto_destroy(context, crypto); +	    _gsskrb5_release_buffer(minor_status, output_message_buffer); +	    free_Checksum(&cksum); +	    return GSS_S_FAILURE; +	} +	free_Checksum(&cksum); +    } + +    krb5_crypto_destroy(context, crypto); + +    if (conf_state != NULL) { +	*conf_state = conf_req_flag; +    } + +    *minor_status = 0; +    return GSS_S_COMPLETE; +} + +OM_uint32 _gssapi_unwrap_cfx(OM_uint32 *minor_status, +			     const gsskrb5_ctx context_handle, +			     krb5_context context, +			     const gss_buffer_t input_message_buffer, +			     gss_buffer_t output_message_buffer, +			     int *conf_state, +			     gss_qop_t *qop_state, +			     krb5_keyblock *key) +{ +    krb5_crypto crypto; +    gss_cfx_wrap_token token; +    u_char token_flags; +    krb5_error_code ret; +    unsigned usage; +    krb5_data data; +    uint16_t ec, rrc; +    OM_uint32 seq_number_lo, seq_number_hi; +    size_t len; +    u_char *p; + +    *minor_status = 0; + +    if (input_message_buffer->length < sizeof(*token)) { +	return GSS_S_DEFECTIVE_TOKEN; +    } + +    p = input_message_buffer->value; + +    token = (gss_cfx_wrap_token)p; + +    if (token->TOK_ID[0] != 0x05 || token->TOK_ID[1] != 0x04) { +	return GSS_S_DEFECTIVE_TOKEN; +    } + +    /* Ignore unknown flags */ +    token_flags = token->Flags & +	(CFXSentByAcceptor | CFXSealed | CFXAcceptorSubkey); + +    if (token_flags & CFXSentByAcceptor) { +	if ((context_handle->more_flags & LOCAL) == 0) +	    return GSS_S_DEFECTIVE_TOKEN; +    } + +    if (context_handle->more_flags & ACCEPTOR_SUBKEY) { +	if ((token_flags & CFXAcceptorSubkey) == 0) +	    return GSS_S_DEFECTIVE_TOKEN; +    } else { +	if (token_flags & CFXAcceptorSubkey) +	    return GSS_S_DEFECTIVE_TOKEN; +    } + +    if (token->Filler != 0xFF) { +	return GSS_S_DEFECTIVE_TOKEN; +    } + +    if (conf_state != NULL) { +	*conf_state = (token_flags & CFXSealed) ? 1 : 0; +    } + +    ec  = (token->EC[0]  << 8) | token->EC[1]; +    rrc = (token->RRC[0] << 8) | token->RRC[1]; + +    /* +     * Check sequence number +     */ +    _gsskrb5_decode_be_om_uint32(&token->SND_SEQ[0], &seq_number_hi); +    _gsskrb5_decode_be_om_uint32(&token->SND_SEQ[4], &seq_number_lo); +    if (seq_number_hi) { +	/* no support for 64-bit sequence numbers */ +	*minor_status = ERANGE; +	return GSS_S_UNSEQ_TOKEN; +    } + +    HEIMDAL_MUTEX_lock(&context_handle->ctx_id_mutex); +    ret = _gssapi_msg_order_check(context_handle->order, seq_number_lo); +    if (ret != 0) { +	*minor_status = 0; +	HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); +	_gsskrb5_release_buffer(minor_status, output_message_buffer); +	return ret; +    } +    HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); + +    /* +     * Decrypt and/or verify checksum +     */ +    ret = krb5_crypto_init(context, key, 0, &crypto); +    if (ret != 0) { +	*minor_status = ret; +	return GSS_S_FAILURE; +    } + +    if (context_handle->more_flags & LOCAL) { +	usage = KRB5_KU_USAGE_ACCEPTOR_SEAL; +    } else { +	usage = KRB5_KU_USAGE_INITIATOR_SEAL; +    } + +    p += sizeof(*token); +    len = input_message_buffer->length; +    len -= (p - (u_char *)input_message_buffer->value); + +    if (token_flags & CFXSealed) { +	/* +	 * this is really ugly, but needed against windows +	 * for DCERPC, as windows rotates by EC+RRC. +	 */ +	if (IS_DCE_STYLE(context_handle)) { +		*minor_status = rrc_rotate(p, len, rrc+ec, TRUE); +	} else { +		*minor_status = rrc_rotate(p, len, rrc, TRUE); +	} +	if (*minor_status != 0) { +	    krb5_crypto_destroy(context, crypto); +	    return GSS_S_FAILURE; +	} + +	ret = krb5_decrypt(context, crypto, usage, +	    p, len, &data); +	if (ret != 0) { +	    *minor_status = ret; +	    krb5_crypto_destroy(context, crypto); +	    return GSS_S_BAD_MIC; +	} + +	/* Check that there is room for the pad and token header */ +	if (data.length < ec + sizeof(*token)) { +	    krb5_crypto_destroy(context, crypto); +	    krb5_data_free(&data); +	    return GSS_S_DEFECTIVE_TOKEN; +	} +	p = data.data; +	p += data.length - sizeof(*token); + +	/* RRC is unprotected; don't modify input buffer */ +	((gss_cfx_wrap_token)p)->RRC[0] = token->RRC[0]; +	((gss_cfx_wrap_token)p)->RRC[1] = token->RRC[1]; + +	/* Check the integrity of the header */ +	if (memcmp(p, token, sizeof(*token)) != 0) { +	    krb5_crypto_destroy(context, crypto); +	    krb5_data_free(&data); +	    return GSS_S_BAD_MIC; +	} + +	output_message_buffer->value = data.data; +	output_message_buffer->length = data.length - ec - sizeof(*token); +    } else { +	Checksum cksum; + +	/* Rotate by RRC; bogus to do this in-place XXX */ +	*minor_status = rrc_rotate(p, len, rrc, TRUE); +	if (*minor_status != 0) { +	    krb5_crypto_destroy(context, crypto); +	    return GSS_S_FAILURE; +	} + +	/* Determine checksum type */ +	ret = krb5_crypto_get_checksum_type(context, +					    crypto, &cksum.cksumtype); +	if (ret != 0) { +	    *minor_status = ret; +	    krb5_crypto_destroy(context, crypto); +	    return GSS_S_FAILURE; +	} + +	cksum.checksum.length = ec; + +	/* Check we have at least as much data as the checksum */ +	if (len < cksum.checksum.length) { +	    *minor_status = ERANGE; +	    krb5_crypto_destroy(context, crypto); +	    return GSS_S_BAD_MIC; +	} + +	/* Length now is of the plaintext only, no checksum */ +	len -= cksum.checksum.length; +	cksum.checksum.data = p + len; + +	output_message_buffer->length = len; /* for later */ +	output_message_buffer->value = malloc(len + sizeof(*token)); +	if (output_message_buffer->value == NULL) { +	    *minor_status = ENOMEM; +	    krb5_crypto_destroy(context, crypto); +	    return GSS_S_FAILURE; +	} + +	/* Checksum is over (plaintext-data | "header") */ +	memcpy(output_message_buffer->value, p, len); +	memcpy((u_char *)output_message_buffer->value + len,  +	       token, sizeof(*token)); + +	/* EC is not included in checksum calculation */ +	token = (gss_cfx_wrap_token)((u_char *)output_message_buffer->value + +				     len); +	token->EC[0]  = 0; +	token->EC[1]  = 0; +	token->RRC[0] = 0; +	token->RRC[1] = 0; + +	ret = krb5_verify_checksum(context, crypto, +				   usage, +				   output_message_buffer->value, +				   len + sizeof(*token), +				   &cksum); +	if (ret != 0) { +	    *minor_status = ret; +	    krb5_crypto_destroy(context, crypto); +	    _gsskrb5_release_buffer(minor_status, output_message_buffer); +	    return GSS_S_BAD_MIC; +	} +    } + +    krb5_crypto_destroy(context, crypto); + +    if (qop_state != NULL) { +	*qop_state = GSS_C_QOP_DEFAULT; +    } + +    *minor_status = 0; +    return GSS_S_COMPLETE; +} + +OM_uint32 _gssapi_mic_cfx(OM_uint32 *minor_status, +			  const gsskrb5_ctx context_handle, +			  krb5_context context, +			  gss_qop_t qop_req, +			  const gss_buffer_t message_buffer, +			  gss_buffer_t message_token, +			  krb5_keyblock *key) +{ +    krb5_crypto crypto; +    gss_cfx_mic_token token; +    krb5_error_code ret; +    unsigned usage; +    Checksum cksum; +    u_char *buf; +    size_t len; +    int32_t seq_number; + +    ret = krb5_crypto_init(context, key, 0, &crypto); +    if (ret != 0) { +	*minor_status = ret; +	return GSS_S_FAILURE; +    } + +    len = message_buffer->length + sizeof(*token); +    buf = malloc(len); +    if (buf == NULL) { +	*minor_status = ENOMEM; +	krb5_crypto_destroy(context, crypto); +	return GSS_S_FAILURE; +    } + +    memcpy(buf, message_buffer->value, message_buffer->length); + +    token = (gss_cfx_mic_token)(buf + message_buffer->length); +    token->TOK_ID[0] = 0x04; +    token->TOK_ID[1] = 0x04; +    token->Flags = 0; +    if ((context_handle->more_flags & LOCAL) == 0) +	token->Flags |= CFXSentByAcceptor; +    if (context_handle->more_flags & ACCEPTOR_SUBKEY) +	token->Flags |= CFXAcceptorSubkey; +    memset(token->Filler, 0xFF, 5); + +    HEIMDAL_MUTEX_lock(&context_handle->ctx_id_mutex); +    krb5_auth_con_getlocalseqnumber(context, +				    context_handle->auth_context, +				    &seq_number); +    _gsskrb5_encode_be_om_uint32(0,          &token->SND_SEQ[0]); +    _gsskrb5_encode_be_om_uint32(seq_number, &token->SND_SEQ[4]); +    krb5_auth_con_setlocalseqnumber(context, +				    context_handle->auth_context, +				    ++seq_number); +    HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); + +    if (context_handle->more_flags & LOCAL) { +	usage = KRB5_KU_USAGE_INITIATOR_SIGN; +    } else { +	usage = KRB5_KU_USAGE_ACCEPTOR_SIGN; +    } + +    ret = krb5_create_checksum(context, crypto, +	usage, 0, buf, len, &cksum); +    if (ret != 0) { +	*minor_status = ret; +	krb5_crypto_destroy(context, crypto); +	free(buf); +	return GSS_S_FAILURE; +    } +    krb5_crypto_destroy(context, crypto); + +    /* Determine MIC length */ +    message_token->length = sizeof(*token) + cksum.checksum.length; +    message_token->value = malloc(message_token->length); +    if (message_token->value == NULL) { +	*minor_status = ENOMEM; +	free_Checksum(&cksum); +	free(buf); +	return GSS_S_FAILURE; +    } + +    /* Token is { "header" | get_mic("header" | plaintext-data) } */ +    memcpy(message_token->value, token, sizeof(*token)); +    memcpy((u_char *)message_token->value + sizeof(*token), +	   cksum.checksum.data, cksum.checksum.length); + +    free_Checksum(&cksum); +    free(buf); + +    *minor_status = 0; +    return GSS_S_COMPLETE; +} + +OM_uint32 _gssapi_verify_mic_cfx(OM_uint32 *minor_status, +				 const gsskrb5_ctx context_handle, +				 krb5_context context, +				 const gss_buffer_t message_buffer, +				 const gss_buffer_t token_buffer, +				 gss_qop_t *qop_state, +				 krb5_keyblock *key) +{ +    krb5_crypto crypto; +    gss_cfx_mic_token token; +    u_char token_flags; +    krb5_error_code ret; +    unsigned usage; +    OM_uint32 seq_number_lo, seq_number_hi; +    u_char *buf, *p; +    Checksum cksum; + +    *minor_status = 0; + +    if (token_buffer->length < sizeof(*token)) { +	return GSS_S_DEFECTIVE_TOKEN; +    } + +    p = token_buffer->value; + +    token = (gss_cfx_mic_token)p; + +    if (token->TOK_ID[0] != 0x04 || token->TOK_ID[1] != 0x04) { +	return GSS_S_DEFECTIVE_TOKEN; +    } + +    /* Ignore unknown flags */ +    token_flags = token->Flags & (CFXSentByAcceptor | CFXAcceptorSubkey); + +    if (token_flags & CFXSentByAcceptor) { +	if ((context_handle->more_flags & LOCAL) == 0) +	    return GSS_S_DEFECTIVE_TOKEN; +    } +    if (context_handle->more_flags & ACCEPTOR_SUBKEY) { +	if ((token_flags & CFXAcceptorSubkey) == 0) +	    return GSS_S_DEFECTIVE_TOKEN; +    } else { +	if (token_flags & CFXAcceptorSubkey) +	    return GSS_S_DEFECTIVE_TOKEN; +    } + +    if (memcmp(token->Filler, "\xff\xff\xff\xff\xff", 5) != 0) { +	return GSS_S_DEFECTIVE_TOKEN; +    } + +    /* +     * Check sequence number +     */ +    _gsskrb5_decode_be_om_uint32(&token->SND_SEQ[0], &seq_number_hi); +    _gsskrb5_decode_be_om_uint32(&token->SND_SEQ[4], &seq_number_lo); +    if (seq_number_hi) { +	*minor_status = ERANGE; +	return GSS_S_UNSEQ_TOKEN; +    } + +    HEIMDAL_MUTEX_lock(&context_handle->ctx_id_mutex); +    ret = _gssapi_msg_order_check(context_handle->order, seq_number_lo); +    if (ret != 0) { +	*minor_status = 0; +	HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); +	return ret; +    } +    HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); + +    /* +     * Verify checksum +     */ +    ret = krb5_crypto_init(context, key, 0, &crypto); +    if (ret != 0) { +	*minor_status = ret; +	return GSS_S_FAILURE; +    } + +    ret = krb5_crypto_get_checksum_type(context, crypto, +					&cksum.cksumtype); +    if (ret != 0) { +	*minor_status = ret; +	krb5_crypto_destroy(context, crypto); +	return GSS_S_FAILURE; +    } + +    cksum.checksum.data = p + sizeof(*token); +    cksum.checksum.length = token_buffer->length - sizeof(*token); + +    if (context_handle->more_flags & LOCAL) { +	usage = KRB5_KU_USAGE_ACCEPTOR_SIGN; +    } else { +	usage = KRB5_KU_USAGE_INITIATOR_SIGN; +    } + +    buf = malloc(message_buffer->length + sizeof(*token)); +    if (buf == NULL) { +	*minor_status = ENOMEM; +	krb5_crypto_destroy(context, crypto); +	return GSS_S_FAILURE; +    } +    memcpy(buf, message_buffer->value, message_buffer->length); +    memcpy(buf + message_buffer->length, token, sizeof(*token)); + +    ret = krb5_verify_checksum(context, crypto, +			       usage, +			       buf, +			       sizeof(*token) + message_buffer->length, +			       &cksum); +    krb5_crypto_destroy(context, crypto); +    if (ret != 0) { +	*minor_status = ret; +	free(buf); +	return GSS_S_BAD_MIC; +    } + +    free(buf); + +    if (qop_state != NULL) { +	*qop_state = GSS_C_QOP_DEFAULT; +    } + +    return GSS_S_COMPLETE; +} diff --git a/source4/heimdal/lib/gssapi/krb5/cfx.h b/source4/heimdal/lib/gssapi/krb5/cfx.h new file mode 100644 index 0000000000..c30ed07840 --- /dev/null +++ b/source4/heimdal/lib/gssapi/krb5/cfx.h @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2003, PADL Software Pty Ltd. + * 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 PADL Software 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 PADL SOFTWARE 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 PADL SOFTWARE 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$ */ + +#ifndef GSSAPI_CFX_H_ +#define GSSAPI_CFX_H_ 1 + +/* + * Implementation of draft-ietf-krb-wg-gssapi-cfx-01.txt + */ + +typedef struct gss_cfx_mic_token_desc_struct { +	u_char TOK_ID[2]; /* 04 04 */ +	u_char Flags; +	u_char Filler[5]; +	u_char SND_SEQ[8]; +} gss_cfx_mic_token_desc, *gss_cfx_mic_token; + +typedef struct gss_cfx_wrap_token_desc_struct { +	u_char TOK_ID[2]; /* 04 05 */ +	u_char Flags; +	u_char Filler; +	u_char EC[2]; +	u_char RRC[2]; +	u_char SND_SEQ[8]; +} gss_cfx_wrap_token_desc, *gss_cfx_wrap_token; + +typedef struct gss_cfx_delete_token_desc_struct { +	u_char TOK_ID[2]; /* 05 04 */ +	u_char Flags; +	u_char Filler[5]; +	u_char SND_SEQ[8]; +} gss_cfx_delete_token_desc, *gss_cfx_delete_token; + +#endif /* GSSAPI_CFX_H_ */ diff --git a/source4/heimdal/lib/gssapi/krb5/compare_name.c b/source4/heimdal/lib/gssapi/krb5/compare_name.c new file mode 100644 index 0000000000..a5406a7f2a --- /dev/null +++ b/source4/heimdal/lib/gssapi/krb5/compare_name.c @@ -0,0 +1,55 @@ +/* + * Copyright (c) 1997-2003 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.  + */ + +#include "krb5/gsskrb5_locl.h" + +RCSID("$Id$"); + +OM_uint32 _gsskrb5_compare_name +           (OM_uint32 * minor_status, +            const gss_name_t name1, +            const gss_name_t name2, +            int * name_equal +           ) +{ +    krb5_const_principal princ1 = (krb5_const_principal)name1; +    krb5_const_principal princ2 = (krb5_const_principal)name2; +    krb5_context context; + +    GSSAPI_KRB5_INIT(&context); + +    *name_equal = krb5_principal_compare (context, +					  princ1, princ2); +    *minor_status = 0; +    return GSS_S_COMPLETE; +} diff --git a/source4/heimdal/lib/gssapi/krb5/compat.c b/source4/heimdal/lib/gssapi/krb5/compat.c new file mode 100644 index 0000000000..0caada04f6 --- /dev/null +++ b/source4/heimdal/lib/gssapi/krb5/compat.c @@ -0,0 +1,128 @@ +/* + * Copyright (c) 2003 - 2005 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.  + */ + +#include "krb5/gsskrb5_locl.h" + +RCSID("$Id$"); + + +static krb5_error_code +check_compat(OM_uint32 *minor_status,  +	     krb5_context context, krb5_const_principal name,  +	     const char *option, krb5_boolean *compat,  +	     krb5_boolean match_val) +{ +    krb5_error_code ret = 0; +    char **p, **q; +    krb5_principal match; + + +    p = krb5_config_get_strings(context, NULL, "gssapi", +				option, NULL); +    if(p == NULL) +	return 0; + +    match = NULL; +    for(q = p; *q; q++) { +	ret = krb5_parse_name(context, *q, &match); +	if (ret) +	    break; + +	if (krb5_principal_match(context, name, match)) { +	    *compat = match_val; +	    break; +	} +	 +	krb5_free_principal(context, match); +	match = NULL; +    } +    if (match) +	krb5_free_principal(context, match); +    krb5_config_free_strings(p); + +    if (ret) { +	if (minor_status) +	    *minor_status = ret; +	return GSS_S_FAILURE; +    } + +    return 0; +} + +/* + * ctx->ctx_id_mutex is assumed to be locked + */ + +OM_uint32 +_gss_DES3_get_mic_compat(OM_uint32 *minor_status, +			 gsskrb5_ctx ctx, +			 krb5_context context) +{ +    krb5_boolean use_compat = FALSE; +    OM_uint32 ret; + +    if ((ctx->more_flags & COMPAT_OLD_DES3_SELECTED) == 0) { +	ret = check_compat(minor_status, context, ctx->target,  +			   "broken_des3_mic", &use_compat, TRUE); +	if (ret) +	    return ret; +	ret = check_compat(minor_status, context, ctx->target,  +			   "correct_des3_mic", &use_compat, FALSE); +	if (ret) +	    return ret; + +	if (use_compat) +	    ctx->more_flags |= COMPAT_OLD_DES3; +	ctx->more_flags |= COMPAT_OLD_DES3_SELECTED; +    } +    return 0; +} + +#if 0 +OM_uint32 +gss_krb5_compat_des3_mic(OM_uint32 *minor_status, gss_ctx_id_t ctx, int on) +{ +    *minor_status = 0; + +    HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex); +    if (on) { +	ctx->more_flags |= COMPAT_OLD_DES3; +    } else { +	ctx->more_flags &= ~COMPAT_OLD_DES3; +    } +    ctx->more_flags |= COMPAT_OLD_DES3_SELECTED; +    HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); + +    return 0; +} +#endif diff --git a/source4/heimdal/lib/gssapi/krb5/context_time.c b/source4/heimdal/lib/gssapi/krb5/context_time.c new file mode 100644 index 0000000000..7f70be733e --- /dev/null +++ b/source4/heimdal/lib/gssapi/krb5/context_time.c @@ -0,0 +1,95 @@ +/* + * Copyright (c) 1997 - 2003 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.  + */ + +#include "krb5/gsskrb5_locl.h" + +RCSID("$Id$"); + +OM_uint32 +_gsskrb5_lifetime_left(OM_uint32 *minor_status,  +		       krb5_context context, +		       OM_uint32 lifetime, +		       OM_uint32 *lifetime_rec) +{ +    krb5_timestamp timeret; +    krb5_error_code kret; + +    if (lifetime == 0) { +	*lifetime_rec = GSS_C_INDEFINITE; +	return GSS_S_COMPLETE; +    } + +    kret = krb5_timeofday(context, &timeret); +    if (kret) { +	*minor_status = kret; +	return GSS_S_FAILURE; +    } + +    if (lifetime < timeret)  +	*lifetime_rec = 0; +    else +	*lifetime_rec = lifetime - timeret; + +    return GSS_S_COMPLETE; +} + + +OM_uint32 _gsskrb5_context_time +           (OM_uint32 * minor_status, +            const gss_ctx_id_t context_handle, +            OM_uint32 * time_rec +           ) +{ +    krb5_context context; +    OM_uint32 lifetime; +    OM_uint32 major_status; +    const gsskrb5_ctx ctx = (const gsskrb5_ctx) context_handle; + +    GSSAPI_KRB5_INIT (&context); + +    HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex); +    lifetime = ctx->lifetime; +    HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); + +    major_status = _gsskrb5_lifetime_left(minor_status, context, +					  lifetime, time_rec); +    if (major_status != GSS_S_COMPLETE) +	return major_status; + +    *minor_status = 0; + +    if (*time_rec == 0) +	return GSS_S_CONTEXT_EXPIRED; +	 +    return GSS_S_COMPLETE; +} diff --git a/source4/heimdal/lib/gssapi/krb5/copy_ccache.c b/source4/heimdal/lib/gssapi/krb5/copy_ccache.c new file mode 100644 index 0000000000..fd348e841b --- /dev/null +++ b/source4/heimdal/lib/gssapi/krb5/copy_ccache.c @@ -0,0 +1,195 @@ +/* + * Copyright (c) 2000 - 2001, 2003 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.  + */ + +#include "krb5/gsskrb5_locl.h" + +RCSID("$Id$"); + +#if 0 +OM_uint32 +gss_krb5_copy_ccache(OM_uint32 *minor_status, +		     krb5_context context, +		     gss_cred_id_t cred, +		     krb5_ccache out) +{ +    krb5_error_code kret; + +    HEIMDAL_MUTEX_lock(&cred->cred_id_mutex); + +    if (cred->ccache == NULL) { +	HEIMDAL_MUTEX_unlock(&cred->cred_id_mutex); +	*minor_status = EINVAL; +	return GSS_S_FAILURE; +    } + +    kret = krb5_cc_copy_cache(context, cred->ccache, out); +    HEIMDAL_MUTEX_unlock(&cred->cred_id_mutex); +    if (kret) { +	*minor_status = kret; +	return GSS_S_FAILURE; +    } +    *minor_status = 0; +    return GSS_S_COMPLETE; +} +#endif + + +OM_uint32 +_gsskrb5_import_cred(OM_uint32 *minor_status, +		     krb5_ccache id, +		     krb5_principal keytab_principal, +		     krb5_keytab keytab, +		     gss_cred_id_t *cred) +{ +    krb5_context context; +    krb5_error_code kret; +    gsskrb5_cred handle; +    OM_uint32 ret; + +    *cred = NULL; + +    GSSAPI_KRB5_INIT (&context); + +    handle = calloc(1, sizeof(*handle)); +    if (handle == NULL) { +	_gsskrb5_clear_status (); +	*minor_status = ENOMEM; +        return (GSS_S_FAILURE); +    } +    HEIMDAL_MUTEX_init(&handle->cred_id_mutex); + +    handle->usage = 0; + +    if (id) { +	char *str; + +	handle->usage |= GSS_C_INITIATE; + +	kret = krb5_cc_get_principal(context, id, +				     &handle->principal); +	if (kret) { +	    free(handle); +	    *minor_status = kret; +	    return GSS_S_FAILURE; +	} +	 +	if (keytab_principal) { +	    krb5_boolean match; + +	    match = krb5_principal_compare(context, +					   handle->principal, +					   keytab_principal); +	    if (match == FALSE) { +		krb5_free_principal(context, handle->principal); +		free(handle); +		_gsskrb5_clear_status (); +		*minor_status = EINVAL; +		return GSS_S_FAILURE; +	    } +	} + +	ret = __gsskrb5_ccache_lifetime(minor_status, +					context, +					id, +					handle->principal, +					&handle->lifetime); +	if (ret != GSS_S_COMPLETE) { +	    krb5_free_principal(context, handle->principal); +	    free(handle); +	    return ret; +	} + + +	kret = krb5_cc_get_full_name(context, id, &str); +	if (kret) +	    goto out; + +	kret = krb5_cc_resolve(context, str, &handle->ccache); +	free(str); +	if (kret) +	    goto out; +    } + + +    if (keytab) { +	char *str; + +	handle->usage |= GSS_C_ACCEPT; + +	if (keytab_principal && handle->principal == NULL) { +	    kret = krb5_copy_principal(context,  +				       keytab_principal,  +				       &handle->principal); +	    if (kret) +		goto out; +	} + +	kret = krb5_kt_get_full_name(context, keytab, &str); +	if (kret) +	    goto out; + +	kret = krb5_kt_resolve(context, str, &handle->keytab); +	free(str); +	if (kret) +	    goto out; +    } + + +    if (id || keytab) { +	ret = gss_create_empty_oid_set(minor_status, &handle->mechanisms); +	if (ret == GSS_S_COMPLETE) +	    ret = gss_add_oid_set_member(minor_status, GSS_KRB5_MECHANISM, +					 &handle->mechanisms); +	if (ret != GSS_S_COMPLETE) { +	    kret = *minor_status; +	    goto out; +	} +    } + +    *minor_status = 0; +    *cred = (gss_cred_id_t)handle; +    return GSS_S_COMPLETE; + +out: +    gss_release_oid_set(minor_status, &handle->mechanisms); +    if (handle->ccache) +	krb5_cc_close(context, handle->ccache); +    if (handle->keytab) +	krb5_kt_close(context, handle->keytab); +    if (handle->principal) +	krb5_free_principal(context, handle->principal); +    HEIMDAL_MUTEX_destroy(&handle->cred_id_mutex); +    free(handle); +    *minor_status = kret; +    return GSS_S_FAILURE; +} diff --git a/source4/heimdal/lib/gssapi/krb5/decapsulate.c b/source4/heimdal/lib/gssapi/krb5/decapsulate.c new file mode 100644 index 0000000000..419e61a436 --- /dev/null +++ b/source4/heimdal/lib/gssapi/krb5/decapsulate.c @@ -0,0 +1,209 @@ +/* + * Copyright (c) 1997 - 2001 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.  + */ + +#include "krb5/gsskrb5_locl.h" + +RCSID("$Id$"); + +/* + * return the length of the mechanism in token or -1 + * (which implies that the token was bad - GSS_S_DEFECTIVE_TOKEN + */ + +ssize_t +_gsskrb5_get_mech (const u_char *ptr, +		      size_t total_len, +		      const u_char **mech_ret) +{ +    size_t len, len_len, mech_len, foo; +    const u_char *p = ptr; +    int e; + +    if (total_len < 1) +	return -1; +    if (*p++ != 0x60) +	return -1; +    e = der_get_length (p, total_len - 1, &len, &len_len); +    if (e || 1 + len_len + len != total_len) +	return -1; +    p += len_len; +    if (*p++ != 0x06) +	return -1; +    e = der_get_length (p, total_len - 1 - len_len - 1, +			&mech_len, &foo); +    if (e) +	return -1; +    p += foo; +    *mech_ret = p; +    return mech_len; +} + +OM_uint32 +_gssapi_verify_mech_header(u_char **str, +			   size_t total_len, +			   gss_OID mech) +{ +    const u_char *p; +    ssize_t mech_len; + +    mech_len = _gsskrb5_get_mech (*str, total_len, &p); +    if (mech_len < 0) +	return GSS_S_DEFECTIVE_TOKEN; + +    if (mech_len != mech->length) +	return GSS_S_BAD_MECH; +    if (memcmp(p, +	       mech->elements, +	       mech->length) != 0) +	return GSS_S_BAD_MECH; +    p += mech_len; +    *str = rk_UNCONST(p); +    return GSS_S_COMPLETE; +} + +OM_uint32 +_gsskrb5_verify_header(u_char **str, +			  size_t total_len, +			  const void *type, +			  gss_OID oid) +{ +    OM_uint32 ret; +    size_t len; +    u_char *p = *str; + +    ret = _gssapi_verify_mech_header(str, total_len, oid); +    if (ret) +	return ret; + +    len = total_len - (*str - p); + +    if (len < 2) +	return GSS_S_DEFECTIVE_TOKEN; + +    if (memcmp (*str, type, 2) != 0) +	return GSS_S_DEFECTIVE_TOKEN; +    *str += 2; + +    return 0; +} + +/* + * Remove the GSS-API wrapping from `in_token' giving `out_data. + * Does not copy data, so just free `in_token'. + */ + +OM_uint32 +_gssapi_decapsulate( +    OM_uint32 *minor_status, +    gss_buffer_t input_token_buffer, +    krb5_data *out_data, +    const gss_OID mech +) +{ +    u_char *p; +    OM_uint32 ret; + +    p = input_token_buffer->value; +    ret = _gssapi_verify_mech_header(&p, +				    input_token_buffer->length, +				    mech); +    if (ret) { +	*minor_status = 0; +	return ret; +    } + +    out_data->length = input_token_buffer->length - +	(p - (u_char *)input_token_buffer->value); +    out_data->data   = p; +    return GSS_S_COMPLETE; +} + +/* + * Remove the GSS-API wrapping from `in_token' giving `out_data. + * Does not copy data, so just free `in_token'. + */ + +OM_uint32 +_gsskrb5_decapsulate(OM_uint32 *minor_status,     +			gss_buffer_t input_token_buffer, +			krb5_data *out_data, +			const void *type, +			gss_OID oid) +{ +    u_char *p; +    OM_uint32 ret; + +    p = input_token_buffer->value; +    ret = _gsskrb5_verify_header(&p, +				    input_token_buffer->length, +				    type, +				    oid); +    if (ret) { +	*minor_status = 0; +	return ret; +    } + +    out_data->length = input_token_buffer->length - +	(p - (u_char *)input_token_buffer->value); +    out_data->data   = p; +    return GSS_S_COMPLETE; +} + +/* + * Verify padding of a gss wrapped message and return its length. + */ + +OM_uint32 +_gssapi_verify_pad(gss_buffer_t wrapped_token,  +		   size_t datalen, +		   size_t *padlen) +{ +    u_char *pad; +    size_t padlength; +    int i; + +    pad = (u_char *)wrapped_token->value + wrapped_token->length - 1; +    padlength = *pad; + +    if (padlength > datalen) +	return GSS_S_BAD_MECH; + +    for (i = padlength; i > 0 && *pad == padlength; i--, pad--) +	; +    if (i != 0) +	return GSS_S_BAD_MIC; + +    *padlen = padlength; + +    return 0; +} diff --git a/source4/heimdal/lib/gssapi/krb5/delete_sec_context.c b/source4/heimdal/lib/gssapi/krb5/delete_sec_context.c new file mode 100644 index 0000000000..ec680d7378 --- /dev/null +++ b/source4/heimdal/lib/gssapi/krb5/delete_sec_context.c @@ -0,0 +1,83 @@ +/* + * Copyright (c) 1997 - 2003 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.  + */ + +#include "krb5/gsskrb5_locl.h" + +RCSID("$Id$"); + +OM_uint32 +_gsskrb5_delete_sec_context(OM_uint32 * minor_status, +			    gss_ctx_id_t * context_handle, +			    gss_buffer_t output_token) +{ +    krb5_context context; +    gsskrb5_ctx ctx; + +    GSSAPI_KRB5_INIT (&context); + +    *minor_status = 0; + +    if (output_token) { +	output_token->length = 0; +	output_token->value  = NULL; +    } + +    if (*context_handle == GSS_C_NO_CONTEXT) +	return GSS_S_COMPLETE; + +    ctx = (gsskrb5_ctx) *context_handle; +    *context_handle = GSS_C_NO_CONTEXT; + +    HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex); + +    krb5_auth_con_free (context, ctx->auth_context); +    if (ctx->kcred) +	krb5_free_creds(context, ctx->kcred); +    if(ctx->source) +	krb5_free_principal (context, ctx->source); +    if(ctx->target) +	krb5_free_principal (context, ctx->target); +    if (ctx->ticket) +	krb5_free_ticket (context, ctx->ticket); +    if(ctx->order) +	_gssapi_msg_order_destroy(&ctx->order); +    if (ctx->service_keyblock) +	krb5_free_keyblock (context, ctx->service_keyblock); +    krb5_data_free(&ctx->fwd_data); + +    HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); +    HEIMDAL_MUTEX_destroy(&ctx->ctx_id_mutex); +    memset(ctx, 0, sizeof(*ctx)); +    free (ctx); +    return GSS_S_COMPLETE; +} diff --git a/source4/heimdal/lib/gssapi/krb5/display_name.c b/source4/heimdal/lib/gssapi/krb5/display_name.c new file mode 100644 index 0000000000..a902ff7ea5 --- /dev/null +++ b/source4/heimdal/lib/gssapi/krb5/display_name.c @@ -0,0 +1,74 @@ +/* + * Copyright (c) 1997 - 2003 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.  + */ + +#include "krb5/gsskrb5_locl.h" + +RCSID("$Id$"); + +OM_uint32 _gsskrb5_display_name +           (OM_uint32 * minor_status, +            const gss_name_t input_name, +            gss_buffer_t output_name_buffer, +            gss_OID * output_name_type +           ) +{ +    krb5_context context; +    krb5_const_principal name = (krb5_const_principal)input_name; +    krb5_error_code kret; +    char *buf; +    size_t len; + +    GSSAPI_KRB5_INIT (&context); + +    kret = krb5_unparse_name_flags (context, name, +				    KRB5_PRINCIPAL_UNPARSE_DISPLAY, &buf); +    if (kret) { +	*minor_status = kret; +	return GSS_S_FAILURE; +    } +    len = strlen (buf); +    output_name_buffer->length = len; +    output_name_buffer->value  = malloc(len + 1); +    if (output_name_buffer->value == NULL) { +	free (buf); +	*minor_status = ENOMEM; +	return GSS_S_FAILURE; +    } +    memcpy (output_name_buffer->value, buf, len); +    ((char *)output_name_buffer->value)[len] = '\0'; +    free (buf); +    if (output_name_type) +	*output_name_type = GSS_KRB5_NT_PRINCIPAL_NAME; +    *minor_status = 0; +    return GSS_S_COMPLETE; +} diff --git a/source4/heimdal/lib/gssapi/krb5/display_status.c b/source4/heimdal/lib/gssapi/krb5/display_status.c new file mode 100644 index 0000000000..52a651c506 --- /dev/null +++ b/source4/heimdal/lib/gssapi/krb5/display_status.c @@ -0,0 +1,199 @@ +/* + * Copyright (c) 1998 - 2006 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.  + */ + +#include "krb5/gsskrb5_locl.h" + +RCSID("$Id$"); + +static const char * +calling_error(OM_uint32 v) +{ +    static const char *msgs[] = { +	NULL,			/* 0 */ +	"A required input parameter could not be read.", /*  */ +	"A required output parameter could not be written.", /*  */ +	"A parameter was malformed" +    }; + +    v >>= GSS_C_CALLING_ERROR_OFFSET; + +    if (v == 0) +	return ""; +    else if (v >= sizeof(msgs)/sizeof(*msgs)) +	return "unknown calling error"; +    else +	return msgs[v]; +} + +static const char * +routine_error(OM_uint32 v) +{ +    static const char *msgs[] = { +	NULL,			/* 0 */ +	"An unsupported mechanism was requested", +	"An invalid name was supplied", +	"A supplied name was of an unsupported type", +	"Incorrect channel bindings were supplied", +	"An invalid status code was supplied", +	"A token had an invalid MIC", +	"No credentials were supplied, " +	"or the credentials were unavailable or inaccessible.", +	"No context has been established", +	"A token was invalid", +	"A credential was invalid", +	"The referenced credentials have expired", +	"The context has expired", +	"Miscellaneous failure (see text)", +	"The quality-of-protection requested could not be provide", +	"The operation is forbidden by local security policy", +	"The operation or option is not available", +	"The requested credential element already exists", +	"The provided name was not a mechanism name.", +    }; + +    v >>= GSS_C_ROUTINE_ERROR_OFFSET; + +    if (v == 0) +	return ""; +    else if (v >= sizeof(msgs)/sizeof(*msgs)) +	return "unknown routine error"; +    else +	return msgs[v]; +} + +static const char * +supplementary_error(OM_uint32 v) +{ +    static const char *msgs[] = { +	"normal completion", +	"continuation call to routine required", +	"duplicate per-message token detected", +	"timed-out per-message token detected", +	"reordered (early) per-message token detected", +	"skipped predecessor token(s) detected" +    }; + +    v >>= GSS_C_SUPPLEMENTARY_OFFSET; + +    if (v >= sizeof(msgs)/sizeof(*msgs)) +	return "unknown routine error"; +    else +	return msgs[v]; +} + +void +_gsskrb5_clear_status (void) +{ +    krb5_context context; + +    if (_gsskrb5_init (&context) != 0) +	return; +    krb5_clear_error_string(context); +} + +void +_gsskrb5_set_status (int ret, const char *fmt, ...) +{ +    krb5_context context; +    va_list args; +    char *str; + +    if (_gsskrb5_init (&context) != 0) +	return; + +    va_start(args, fmt); +    vasprintf(&str, fmt, args); +    va_end(args); +    if (str) { +	krb5_set_error_message(context, ret, str); +	free(str); +    } +} + +OM_uint32 _gsskrb5_display_status +(OM_uint32		*minor_status, + OM_uint32		 status_value, + int			 status_type, + const gss_OID	 mech_type, + OM_uint32		*message_context, + gss_buffer_t	 status_string) +{ +    krb5_context context; +    char *buf; + +    GSSAPI_KRB5_INIT (&context); + +    status_string->length = 0; +    status_string->value = NULL; + +    if (gss_oid_equal(mech_type, GSS_C_NO_OID) == 0 && +	gss_oid_equal(mech_type, GSS_KRB5_MECHANISM) == 0) { +	*minor_status = 0; +	return GSS_C_GSS_CODE; +    } + +    if (status_type == GSS_C_GSS_CODE) { +	if (GSS_SUPPLEMENTARY_INFO(status_value)) +	    asprintf(&buf, "%s",  +		     supplementary_error(GSS_SUPPLEMENTARY_INFO(status_value))); +	else +	    asprintf (&buf, "%s %s", +		      calling_error(GSS_CALLING_ERROR(status_value)), +		      routine_error(GSS_ROUTINE_ERROR(status_value))); +    } else if (status_type == GSS_C_MECH_CODE) { +	const char *buf2 = krb5_get_error_message(context, status_value); +	if (buf2) { +	    buf = strdup(buf2); +	    krb5_free_error_message(context, buf2); +	} else { +	    asprintf(&buf, "unknown mech error-code %u", +		     (unsigned)status_value); +	} +    } else { +	*minor_status = EINVAL; +	return GSS_S_BAD_STATUS; +    } + +    if (buf == NULL) { +	*minor_status = ENOMEM; +	return GSS_S_FAILURE; +    } + +    *message_context = 0; +    *minor_status = 0; + +    status_string->length = strlen(buf); +    status_string->value  = buf; +   +    return GSS_S_COMPLETE; +} diff --git a/source4/heimdal/lib/gssapi/krb5/duplicate_name.c b/source4/heimdal/lib/gssapi/krb5/duplicate_name.c new file mode 100644 index 0000000000..eeb777ed5f --- /dev/null +++ b/source4/heimdal/lib/gssapi/krb5/duplicate_name.c @@ -0,0 +1,60 @@ +/* + * Copyright (c) 1997 - 2003 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.  + */ + +#include "krb5/gsskrb5_locl.h" + +RCSID("$Id$"); + +OM_uint32 _gsskrb5_duplicate_name ( +            OM_uint32 * minor_status, +            const gss_name_t src_name, +            gss_name_t * dest_name +           ) +{ +    krb5_const_principal src = (krb5_const_principal)src_name; +    krb5_context context; +    krb5_principal dest; +    krb5_error_code kret; + +    GSSAPI_KRB5_INIT (&context); + +    kret = krb5_copy_principal (context, src, &dest); +    if (kret) { +	*minor_status = kret; +	return GSS_S_FAILURE; +    } else { +	*dest_name = (gss_name_t)dest; +	*minor_status = 0; +	return GSS_S_COMPLETE; +    } +} diff --git a/source4/heimdal/lib/gssapi/krb5/encapsulate.c b/source4/heimdal/lib/gssapi/krb5/encapsulate.c new file mode 100644 index 0000000000..3f42899a40 --- /dev/null +++ b/source4/heimdal/lib/gssapi/krb5/encapsulate.c @@ -0,0 +1,155 @@ +/* + * Copyright (c) 1997 - 2003 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.  + */ + +#include "krb5/gsskrb5_locl.h" + +RCSID("$Id$"); + +void +_gssapi_encap_length (size_t data_len, +		      size_t *len, +		      size_t *total_len, +		      const gss_OID mech) +{ +    size_t len_len; + +    *len = 1 + 1 + mech->length + data_len; + +    len_len = der_length_len(*len); + +    *total_len = 1 + len_len + *len; +} + +void +_gsskrb5_encap_length (size_t data_len, +			  size_t *len, +			  size_t *total_len, +			  const gss_OID mech) +{ +    _gssapi_encap_length(data_len + 2, len, total_len, mech); +} + +void * +_gsskrb5_make_header (void *ptr, +			 size_t len, +			 const void *type, +			 const gss_OID mech) +{ +    u_char *p = ptr; +    p = _gssapi_make_mech_header(p, len, mech); +    memcpy (p, type, 2); +    p += 2; +    return p; +} + +void * +_gssapi_make_mech_header(void *ptr, +			 size_t len, +			 const gss_OID mech) +{ +    u_char *p = ptr; +    int e; +    size_t len_len, foo; + +    *p++ = 0x60; +    len_len = der_length_len(len); +    e = der_put_length (p + len_len - 1, len_len, len, &foo); +    if(e || foo != len_len) +	abort (); +    p += len_len; +    *p++ = 0x06; +    *p++ = mech->length; +    memcpy (p, mech->elements, mech->length); +    p += mech->length; +    return p; +} + +/* + * Give it a krb5_data and it will encapsulate with extra GSS-API wrappings. + */ + +OM_uint32 +_gssapi_encapsulate( +    OM_uint32 *minor_status, +    const krb5_data *in_data, +    gss_buffer_t output_token, +    const gss_OID mech +) +{ +    size_t len, outer_len; +    void *p; + +    _gssapi_encap_length (in_data->length, &len, &outer_len, mech); +     +    output_token->length = outer_len; +    output_token->value  = malloc (outer_len); +    if (output_token->value == NULL) { +	*minor_status = ENOMEM; +	return GSS_S_FAILURE; +    }	 + +    p = _gssapi_make_mech_header (output_token->value, len, mech); +    memcpy (p, in_data->data, in_data->length); +    return GSS_S_COMPLETE; +} + +/* + * Give it a krb5_data and it will encapsulate with extra GSS-API krb5 + * wrappings. + */ + +OM_uint32 +_gsskrb5_encapsulate( +			OM_uint32 *minor_status,     +			const krb5_data *in_data, +			gss_buffer_t output_token, +			const void *type, +			const gss_OID mech +) +{ +    size_t len, outer_len; +    u_char *p; + +    _gsskrb5_encap_length (in_data->length, &len, &outer_len, mech); +     +    output_token->length = outer_len; +    output_token->value  = malloc (outer_len); +    if (output_token->value == NULL) { +	*minor_status = ENOMEM; +	return GSS_S_FAILURE; +    }	 + +    p = _gsskrb5_make_header (output_token->value, len, type, mech); +    memcpy (p, in_data->data, in_data->length); +    return GSS_S_COMPLETE; +} diff --git a/source4/heimdal/lib/gssapi/krb5/export_name.c b/source4/heimdal/lib/gssapi/krb5/export_name.c new file mode 100644 index 0000000000..92ee101b0d --- /dev/null +++ b/source4/heimdal/lib/gssapi/krb5/export_name.c @@ -0,0 +1,94 @@ +/* + * Copyright (c) 1997, 1999, 2003 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.  + */ + +#include "krb5/gsskrb5_locl.h" + +RCSID("$Id$"); + +OM_uint32 _gsskrb5_export_name +           (OM_uint32  * minor_status, +            const gss_name_t input_name, +            gss_buffer_t exported_name +           ) +{ +    krb5_context context; +    krb5_const_principal princ = (krb5_const_principal)input_name; +    krb5_error_code kret; +    char *buf, *name; +    size_t len; + +    GSSAPI_KRB5_INIT (&context); + +    kret = krb5_unparse_name (context, princ, &name); +    if (kret) { +	*minor_status = kret; +	return GSS_S_FAILURE; +    } +    len = strlen (name); + +    exported_name->length = 10 + len + GSS_KRB5_MECHANISM->length; +    exported_name->value  = malloc(exported_name->length); +    if (exported_name->value == NULL) { +	free (name); +	*minor_status = ENOMEM; +	return GSS_S_FAILURE; +    } + +    /* TOK, MECH_OID_LEN, DER(MECH_OID), NAME_LEN, NAME */ + +    buf = exported_name->value; +    memcpy(buf, "\x04\x01", 2); +    buf += 2; +    buf[0] = ((GSS_KRB5_MECHANISM->length + 2) >> 8) & 0xff; +    buf[1] = (GSS_KRB5_MECHANISM->length + 2) & 0xff; +    buf+= 2; +    buf[0] = 0x06; +    buf[1] = (GSS_KRB5_MECHANISM->length) & 0xFF; +    buf+= 2; + +    memcpy(buf, GSS_KRB5_MECHANISM->elements, GSS_KRB5_MECHANISM->length); +    buf += GSS_KRB5_MECHANISM->length; + +    buf[0] = (len >> 24) & 0xff; +    buf[1] = (len >> 16) & 0xff; +    buf[2] = (len >> 8) & 0xff; +    buf[3] = (len) & 0xff; +    buf += 4; + +    memcpy (buf, name, len); + +    free (name); + +    *minor_status = 0; +    return GSS_S_COMPLETE; +} diff --git a/source4/heimdal/lib/gssapi/krb5/export_sec_context.c b/source4/heimdal/lib/gssapi/krb5/export_sec_context.c new file mode 100644 index 0000000000..2bc50a04ee --- /dev/null +++ b/source4/heimdal/lib/gssapi/krb5/export_sec_context.c @@ -0,0 +1,240 @@ +/* + * Copyright (c) 1999 - 2003 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.  + */ + +#include "krb5/gsskrb5_locl.h" + +RCSID("$Id$"); + +OM_uint32 +_gsskrb5_export_sec_context ( +    OM_uint32 * minor_status, +    gss_ctx_id_t * context_handle, +    gss_buffer_t interprocess_token +    ) +{ +    krb5_context context; +    const gsskrb5_ctx ctx = (const gsskrb5_ctx) *context_handle; +    krb5_storage *sp; +    krb5_auth_context ac; +    OM_uint32 ret = GSS_S_COMPLETE; +    krb5_data data; +    gss_buffer_desc buffer; +    int flags; +    OM_uint32 minor; +    krb5_error_code kret; + +    GSSAPI_KRB5_INIT (&context); + +    HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex); + +    if (!(ctx->flags & GSS_C_TRANS_FLAG)) { +	HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); +	*minor_status = 0; +	return GSS_S_UNAVAILABLE; +    } + +    sp = krb5_storage_emem (); +    if (sp == NULL) { +	HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); +	*minor_status = ENOMEM; +	return GSS_S_FAILURE; +    } +    ac = ctx->auth_context; + +    /* flagging included fields */ + +    flags = 0; +    if (ac->local_address) +	flags |= SC_LOCAL_ADDRESS; +    if (ac->remote_address) +	flags |= SC_REMOTE_ADDRESS; +    if (ac->keyblock) +	flags |= SC_KEYBLOCK; +    if (ac->local_subkey) +	flags |= SC_LOCAL_SUBKEY; +    if (ac->remote_subkey) +	flags |= SC_REMOTE_SUBKEY; + +    kret = krb5_store_int32 (sp, flags); +    if (kret) { +	*minor_status = kret; +	goto failure; +    } + +    /* marshall auth context */ + +    kret = krb5_store_int32 (sp, ac->flags); +    if (kret) { +	*minor_status = kret; +	goto failure; +    } +    if (ac->local_address) { +	kret = krb5_store_address (sp, *ac->local_address); +	if (kret) { +	    *minor_status = kret; +	    goto failure; +	} +    } +    if (ac->remote_address) { +	kret = krb5_store_address (sp, *ac->remote_address); +	if (kret) { +	    *minor_status = kret; +	    goto failure; +	} +    } +    kret = krb5_store_int16 (sp, ac->local_port); +    if (kret) { +	*minor_status = kret; +	goto failure; +    } +    kret = krb5_store_int16 (sp, ac->remote_port); +    if (kret) { +	*minor_status = kret; +	goto failure; +    } +    if (ac->keyblock) { +	kret = krb5_store_keyblock (sp, *ac->keyblock); +	if (kret) { +	    *minor_status = kret; +	    goto failure; +	} +    } +    if (ac->local_subkey) { +	kret = krb5_store_keyblock (sp, *ac->local_subkey); +	if (kret) { +	    *minor_status = kret; +	    goto failure; +	} +    } +    if (ac->remote_subkey) { +	kret = krb5_store_keyblock (sp, *ac->remote_subkey); +	if (kret) { +	    *minor_status = kret; +	    goto failure; +	} +    } +    kret = krb5_store_int32 (sp, ac->local_seqnumber); +	if (kret) { +	    *minor_status = kret; +	    goto failure; +	} +    kret = krb5_store_int32 (sp, ac->remote_seqnumber); +	if (kret) { +	    *minor_status = kret; +	    goto failure; +	} + +    kret = krb5_store_int32 (sp, ac->keytype); +    if (kret) { +	*minor_status = kret; +	goto failure; +    } +    kret = krb5_store_int32 (sp, ac->cksumtype); +    if (kret) { +	*minor_status = kret; +	goto failure; +    } + +    /* names */ + +    ret = _gsskrb5_export_name (minor_status, +				(gss_name_t)ctx->source, &buffer); +    if (ret) +	goto failure; +    data.data   = buffer.value; +    data.length = buffer.length; +    kret = krb5_store_data (sp, data); +    _gsskrb5_release_buffer (&minor, &buffer); +    if (kret) { +	*minor_status = kret; +	goto failure; +    } + +    ret = _gsskrb5_export_name (minor_status, +				(gss_name_t)ctx->target, &buffer); +    if (ret) +	goto failure; +    data.data   = buffer.value; +    data.length = buffer.length; + +    ret = GSS_S_FAILURE; + +    kret = krb5_store_data (sp, data); +    _gsskrb5_release_buffer (&minor, &buffer); +    if (kret) { +	*minor_status = kret; +	goto failure; +    } + +    kret = krb5_store_int32 (sp, ctx->flags); +    if (kret) { +	*minor_status = kret; +	goto failure; +    } +    kret = krb5_store_int32 (sp, ctx->more_flags); +    if (kret) { +	*minor_status = kret; +	goto failure; +    } +    kret = krb5_store_int32 (sp, ctx->lifetime); +    if (kret) { +	*minor_status = kret; +	goto failure; +    } +    kret = _gssapi_msg_order_export(sp, ctx->order); +    if (kret ) { +        *minor_status = kret; +        goto failure; +    } + +    kret = krb5_storage_to_data (sp, &data); +    krb5_storage_free (sp); +    if (kret) { +	HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); +	*minor_status = kret; +	return GSS_S_FAILURE; +    } +    interprocess_token->length = data.length; +    interprocess_token->value  = data.data; +    HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); +    ret = _gsskrb5_delete_sec_context (minor_status, context_handle, +				       GSS_C_NO_BUFFER); +    if (ret != GSS_S_COMPLETE) +	_gsskrb5_release_buffer (NULL, interprocess_token); +    *minor_status = 0; +    return ret; + failure: +    HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); +    krb5_storage_free (sp); +    return ret; +} diff --git a/source4/heimdal/lib/gssapi/krb5/external.c b/source4/heimdal/lib/gssapi/krb5/external.c new file mode 100644 index 0000000000..87e4aa01df --- /dev/null +++ b/source4/heimdal/lib/gssapi/krb5/external.c @@ -0,0 +1,472 @@ +/* + * Copyright (c) 1997 - 2000 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.  + */ + +#include "krb5/gsskrb5_locl.h" +#include <gssapi_mech.h> + +RCSID("$Id$"); + +/* + * The implementation must reserve static storage for a + * gss_OID_desc object containing the value + * {10, (void *)"\x2a\x86\x48\x86\xf7\x12" + *              "\x01\x02\x01\x01"}, + * corresponding to an object-identifier value of + * {iso(1) member-body(2) United States(840) mit(113554) + *  infosys(1) gssapi(2) generic(1) user_name(1)}.  The constant + * GSS_C_NT_USER_NAME should be initialized to point + * to that gss_OID_desc. + */ + +static gss_OID_desc gss_c_nt_user_name_oid_desc = +    {10, rk_UNCONST("\x2a\x86\x48\x86\xf7\x12" "\x01\x02\x01\x01")}; + +gss_OID GSSAPI_LIB_VARIABLE GSS_C_NT_USER_NAME = +    &gss_c_nt_user_name_oid_desc; + +/* + * The implementation must reserve static storage for a + * gss_OID_desc object containing the value + * {10, (void *)"\x2a\x86\x48\x86\xf7\x12" + *              "\x01\x02\x01\x02"}, + * corresponding to an object-identifier value of + * {iso(1) member-body(2) United States(840) mit(113554) + *  infosys(1) gssapi(2) generic(1) machine_uid_name(2)}. + * The constant GSS_C_NT_MACHINE_UID_NAME should be + * initialized to point to that gss_OID_desc. + */ + +static gss_OID_desc gss_c_nt_machine_uid_name_oid_desc = +    {10, rk_UNCONST("\x2a\x86\x48\x86\xf7\x12" "\x01\x02\x01\x02")}; + +gss_OID GSSAPI_LIB_VARIABLE GSS_C_NT_MACHINE_UID_NAME = +    &gss_c_nt_machine_uid_name_oid_desc; + +/* + * The implementation must reserve static storage for a + * gss_OID_desc object containing the value + * {10, (void *)"\x2a\x86\x48\x86\xf7\x12" + *              "\x01\x02\x01\x03"}, + * corresponding to an object-identifier value of + * {iso(1) member-body(2) United States(840) mit(113554) + *  infosys(1) gssapi(2) generic(1) string_uid_name(3)}. + * The constant GSS_C_NT_STRING_UID_NAME should be + * initialized to point to that gss_OID_desc. + */ + +static gss_OID_desc gss_c_nt_string_uid_name_oid_desc = +    {10, rk_UNCONST("\x2a\x86\x48\x86\xf7\x12" "\x01\x02\x01\x03")}; + +gss_OID GSSAPI_LIB_VARIABLE GSS_C_NT_STRING_UID_NAME = +    &gss_c_nt_string_uid_name_oid_desc; + +/* + * The implementation must reserve static storage for a + * gss_OID_desc object containing the value + * {6, (void *)"\x2b\x06\x01\x05\x06\x02"}, + * corresponding to an object-identifier value of + * {iso(1) org(3) dod(6) internet(1) security(5) + * nametypes(6) gss-host-based-services(2)).  The constant + * GSS_C_NT_HOSTBASED_SERVICE_X should be initialized to point + * to that gss_OID_desc.  This is a deprecated OID value, and + * implementations wishing to support hostbased-service names + * should instead use the GSS_C_NT_HOSTBASED_SERVICE OID, + * defined below, to identify such names; + * GSS_C_NT_HOSTBASED_SERVICE_X should be accepted a synonym + * for GSS_C_NT_HOSTBASED_SERVICE when presented as an input + * parameter, but should not be emitted by GSS-API + * implementations + */ + +static gss_OID_desc gss_c_nt_hostbased_service_x_oid_desc = +    {6, rk_UNCONST("\x2b\x06\x01\x05\x06\x02")}; + +gss_OID GSSAPI_LIB_VARIABLE GSS_C_NT_HOSTBASED_SERVICE_X = +    &gss_c_nt_hostbased_service_x_oid_desc; + +/* + * The implementation must reserve static storage for a + * gss_OID_desc object containing the value + * {10, (void *)"\x2a\x86\x48\x86\xf7\x12" + *              "\x01\x02\x01\x04"}, corresponding to an + * object-identifier value of {iso(1) member-body(2) + * Unites States(840) mit(113554) infosys(1) gssapi(2) + * generic(1) service_name(4)}.  The constant + * GSS_C_NT_HOSTBASED_SERVICE should be initialized + * to point to that gss_OID_desc. + */ +static gss_OID_desc gss_c_nt_hostbased_service_oid_desc = +    {10, rk_UNCONST("\x2a\x86\x48\x86\xf7\x12" "\x01\x02\x01\x04")}; + +gss_OID GSSAPI_LIB_VARIABLE GSS_C_NT_HOSTBASED_SERVICE = +    &gss_c_nt_hostbased_service_oid_desc; + +/* + * The implementation must reserve static storage for a + * gss_OID_desc object containing the value + * {6, (void *)"\x2b\x06\01\x05\x06\x03"}, + * corresponding to an object identifier value of + * {1(iso), 3(org), 6(dod), 1(internet), 5(security), + * 6(nametypes), 3(gss-anonymous-name)}.  The constant + * and GSS_C_NT_ANONYMOUS should be initialized to point + * to that gss_OID_desc. + */ + +static gss_OID_desc gss_c_nt_anonymous_oid_desc = +    {6, rk_UNCONST("\x2b\x06\01\x05\x06\x03")}; + +gss_OID GSSAPI_LIB_VARIABLE GSS_C_NT_ANONYMOUS = +    &gss_c_nt_anonymous_oid_desc; + +/* + * The implementation must reserve static storage for a + * gss_OID_desc object containing the value + * {6, (void *)"\x2b\x06\x01\x05\x06\x04"}, + * corresponding to an object-identifier value of + * {1(iso), 3(org), 6(dod), 1(internet), 5(security), + * 6(nametypes), 4(gss-api-exported-name)}.  The constant + * GSS_C_NT_EXPORT_NAME should be initialized to point + * to that gss_OID_desc. + */ + +static gss_OID_desc gss_c_nt_export_name_oid_desc = +    {6, rk_UNCONST("\x2b\x06\x01\x05\x06\x04") }; + +gss_OID GSSAPI_LIB_VARIABLE GSS_C_NT_EXPORT_NAME = +    &gss_c_nt_export_name_oid_desc; + +/* + *   This name form shall be represented by the Object Identifier {iso(1) + *   member-body(2) United States(840) mit(113554) infosys(1) gssapi(2) + *   krb5(2) krb5_name(1)}.  The recommended symbolic name for this type + *   is "GSS_KRB5_NT_PRINCIPAL_NAME". + */ + +static gss_OID_desc gss_krb5_nt_principal_name_oid_desc = +    {10, rk_UNCONST("\x2a\x86\x48\x86\xf7\x12\x01\x02\x02\x01") }; + +gss_OID GSSAPI_LIB_VARIABLE GSS_KRB5_NT_PRINCIPAL_NAME = +    &gss_krb5_nt_principal_name_oid_desc; + +/* + *   This name form shall be represented by the Object Identifier {iso(1) + *   member-body(2) United States(840) mit(113554) infosys(1) gssapi(2) + *   generic(1) user_name(1)}.  The recommended symbolic name for this + *   type is "GSS_KRB5_NT_USER_NAME". + */ + +gss_OID GSSAPI_LIB_VARIABLE GSS_KRB5_NT_USER_NAME = +    &gss_c_nt_user_name_oid_desc; + +/* + *   This name form shall be represented by the Object Identifier {iso(1) + *   member-body(2) United States(840) mit(113554) infosys(1) gssapi(2) + *   generic(1) machine_uid_name(2)}.  The recommended symbolic name for + *   this type is "GSS_KRB5_NT_MACHINE_UID_NAME". + */ + +gss_OID GSSAPI_LIB_VARIABLE GSS_KRB5_NT_MACHINE_UID_NAME = +    &gss_c_nt_machine_uid_name_oid_desc; + +/* + *   This name form shall be represented by the Object Identifier {iso(1) + *   member-body(2) United States(840) mit(113554) infosys(1) gssapi(2) + *   generic(1) string_uid_name(3)}.  The recommended symbolic name for + *   this type is "GSS_KRB5_NT_STRING_UID_NAME". + */ + +gss_OID GSSAPI_LIB_VARIABLE GSS_KRB5_NT_STRING_UID_NAME = +    &gss_c_nt_string_uid_name_oid_desc; + +/* + *   To support ongoing experimentation, testing, and evolution of the + *   specification, the Kerberos V5 GSS-API mechanism as defined in this + *   and any successor memos will be identified with the following Object + *   Identifier, as defined in RFC-1510, until the specification is + *   advanced to the level of Proposed Standard RFC: + * + *   {iso(1), org(3), dod(5), internet(1), security(5), kerberosv5(2)} + * + *   Upon advancement to the level of Proposed Standard RFC, the Kerberos + *   V5 GSS-API mechanism will be identified by an Object Identifier + *   having the value: + * + *   {iso(1) member-body(2) United States(840) mit(113554) infosys(1) + *   gssapi(2) krb5(2)} + */ + +#if 0 /* This is the old OID */ + +static gss_OID_desc gss_krb5_mechanism_oid_desc = +    {5, rk_UNCONST("\x2b\x05\x01\x05\x02")}; + +#endif + +static gss_OID_desc gss_krb5_mechanism_oid_desc = +    {9, rk_UNCONST("\x2a\x86\x48\x86\xf7\x12\x01\x02\x02") }; + +gss_OID GSSAPI_LIB_VARIABLE GSS_KRB5_MECHANISM = +    &gss_krb5_mechanism_oid_desc; + +/* + * draft-ietf-cat-iakerb-09, IAKERB: + *   The mechanism ID for IAKERB proxy GSS-API Kerberos, in accordance + *   with the mechanism proposed by SPNEGO [7] for negotiating protocol + *   variations, is:  {iso(1) org(3) dod(6) internet(1) security(5) + *   mechanisms(5) iakerb(10) iakerbProxyProtocol(1)}.  The proposed + *   mechanism ID for IAKERB minimum messages GSS-API Kerberos, in + *   accordance with the mechanism proposed by SPNEGO for negotiating + *   protocol variations, is: {iso(1) org(3) dod(6) internet(1) + *   security(5) mechanisms(5) iakerb(10) + *   iakerbMinimumMessagesProtocol(2)}. + */ + +static gss_OID_desc gss_iakerb_proxy_mechanism_oid_desc = +    {7, rk_UNCONST("\x2b\x06\x01\x05\x05\x0a\x01")}; + +gss_OID GSSAPI_LIB_VARIABLE GSS_IAKERB_PROXY_MECHANISM = +    &gss_iakerb_proxy_mechanism_oid_desc; + +static gss_OID_desc gss_iakerb_min_msg_mechanism_oid_desc = +    {7, rk_UNCONST("\x2b\x06\x01\x05\x05\x0a\x02") }; + +gss_OID GSSAPI_LIB_VARIABLE GSS_IAKERB_MIN_MSG_MECHANISM = +    &gss_iakerb_min_msg_mechanism_oid_desc; + +/* + * + */ + +static gss_OID_desc gss_c_peer_has_updated_spnego_oid_desc = +    {9, (void *)"\x2b\x06\x01\x04\x01\xa9\x4a\x13\x05"}; + +gss_OID GSSAPI_LIB_VARIABLE GSS_C_PEER_HAS_UPDATED_SPNEGO = +    &gss_c_peer_has_updated_spnego_oid_desc; + +/* + * 1.2.752.43.13 Heimdal GSS-API Extentions + */ + +/* 1.2.752.43.13.1 */ +static gss_OID_desc gss_krb5_copy_ccache_x_oid_desc = +    {6, rk_UNCONST("\x2a\x85\x70\x2b\x0d\x01")}; + +gss_OID GSSAPI_LIB_VARIABLE GSS_KRB5_COPY_CCACHE_X = +    &gss_krb5_copy_ccache_x_oid_desc; + +/* 1.2.752.43.13.2 */ +static gss_OID_desc gss_krb5_get_tkt_flags_x_oid_desc = +    {6, rk_UNCONST("\x2a\x85\x70\x2b\x0d\x02")}; + +gss_OID GSSAPI_LIB_VARIABLE GSS_KRB5_GET_TKT_FLAGS_X = +    &gss_krb5_get_tkt_flags_x_oid_desc; + +/* 1.2.752.43.13.3 */ +static gss_OID_desc gss_krb5_extract_authz_data_from_sec_context_x_oid_desc = +    {6, rk_UNCONST("\x2a\x85\x70\x2b\x0d\x03")}; + +gss_OID GSSAPI_LIB_VARIABLE GSS_KRB5_EXTRACT_AUTHZ_DATA_FROM_SEC_CONTEXT_X = +    &gss_krb5_extract_authz_data_from_sec_context_x_oid_desc; + +/* 1.2.752.43.13.4 */ +static gss_OID_desc gss_krb5_compat_des3_mic_x_oid_desc = +    {6, rk_UNCONST("\x2a\x85\x70\x2b\x0d\x04")}; + +gss_OID GSSAPI_LIB_VARIABLE GSS_KRB5_COMPAT_DES3_MIC_X = +    &gss_krb5_compat_des3_mic_x_oid_desc; + +/* 1.2.752.43.13.5 */ +static gss_OID_desc gss_krb5_register_acceptor_identity_x_desc = +    {6, rk_UNCONST("\x2a\x85\x70\x2b\x0d\x05")}; + +gss_OID GSSAPI_LIB_VARIABLE GSS_KRB5_REGISTER_ACCEPTOR_IDENTITY_X = +    &gss_krb5_register_acceptor_identity_x_desc; + +/* 1.2.752.43.13.6 */ +static gss_OID_desc gss_krb5_export_lucid_context_x_desc = +    {6, rk_UNCONST("\x2a\x85\x70\x2b\x0d\x06")}; + +gss_OID GSSAPI_LIB_VARIABLE GSS_KRB5_EXPORT_LUCID_CONTEXT_X = +    &gss_krb5_export_lucid_context_x_desc; + +/* 1.2.752.43.13.6.1 */ +static gss_OID_desc gss_krb5_export_lucid_context_v1_x_desc = +    {7, rk_UNCONST("\x2a\x85\x70\x2b\x0d\x06\x01")}; + +gss_OID GSSAPI_LIB_VARIABLE GSS_KRB5_EXPORT_LUCID_CONTEXT_V1_X = +    &gss_krb5_export_lucid_context_v1_x_desc; + +/* 1.2.752.43.13.7 */ +static gss_OID_desc gss_krb5_set_dns_canonicalize_x_desc = +    {6, rk_UNCONST("\x2a\x85\x70\x2b\x0d\x07")}; + +gss_OID GSSAPI_LIB_VARIABLE GSS_KRB5_SET_DNS_CANONICALIZE_X = +    &gss_krb5_set_dns_canonicalize_x_desc; + +/* 1.2.752.43.13.8 */ +static gss_OID_desc gss_krb5_get_subkey_x_desc = +    {6, rk_UNCONST("\x2a\x85\x70\x2b\x0d\x08")}; + +gss_OID GSSAPI_LIB_VARIABLE GSS_KRB5_GET_SUBKEY_X = +    &gss_krb5_get_subkey_x_desc; + +/* 1.2.752.43.13.9 */ +static gss_OID_desc gss_krb5_get_initiator_subkey_x_desc = +    {6, rk_UNCONST("\x2a\x85\x70\x2b\x0d\x09")}; + +gss_OID GSSAPI_LIB_VARIABLE GSS_KRB5_GET_INITIATOR_SUBKEY_X = +    &gss_krb5_get_initiator_subkey_x_desc; + +/* 1.2.752.43.13.10 */ +static gss_OID_desc gss_krb5_get_acceptor_subkey_x_desc = +    {6, rk_UNCONST("\x2a\x85\x70\x2b\x0d\x0a")}; + +gss_OID GSSAPI_LIB_VARIABLE GSS_KRB5_GET_ACCEPTOR_SUBKEY_X = +    &gss_krb5_get_acceptor_subkey_x_desc; + +/* 1.2.752.43.13.11 */ +static gss_OID_desc gss_krb5_send_to_kdc_x_desc = +    {6, rk_UNCONST("\x2a\x85\x70\x2b\x0d\x0b")}; + +gss_OID GSSAPI_LIB_VARIABLE GSS_KRB5_SEND_TO_KDC_X = +    &gss_krb5_send_to_kdc_x_desc; + +/* 1.2.752.43.13.12 */ +static gss_OID_desc gss_krb5_get_authtime_x_desc = +    {6, rk_UNCONST("\x2a\x85\x70\x2b\x0d\x0c")}; + +gss_OID GSSAPI_LIB_VARIABLE GSS_KRB5_GET_AUTHTIME_X = +    &gss_krb5_get_authtime_x_desc; + +/* 1.2.752.43.13.13 */ +static gss_OID_desc gss_krb5_get_service_keyblock_x_desc = +    {6, rk_UNCONST("\x2a\x85\x70\x2b\x0d\x0d")}; + +gss_OID GSSAPI_LIB_VARIABLE GSS_KRB5_GET_SERVICE_KEYBLOCK_X = +    &gss_krb5_get_service_keyblock_x_desc; + +/* 1.2.752.43.13.14 */ +static gss_OID_desc gss_krb5_set_allowable_enctypes_x_desc = +    {6, rk_UNCONST("\x2a\x85\x70\x2b\x0d\x0e")}; + +gss_OID GSSAPI_LIB_VARIABLE GSS_KRB5_SET_ALLOWABLE_ENCTYPES_X = +    &gss_krb5_set_allowable_enctypes_x_desc; + +/* 1.2.752.43.13.15 */ +static gss_OID_desc gss_krb5_set_default_realm_x_desc = +    {6, rk_UNCONST("\x2a\x85\x70\x2b\x0d\x0f")}; + +gss_OID GSSAPI_LIB_VARIABLE GSS_KRB5_SET_DEFAULT_REALM_X = +    &gss_krb5_set_default_realm_x_desc; + +/* 1.2.752.43.13.16 */ +static gss_OID_desc gss_krb5_ccache_name_x_desc = +    {6, rk_UNCONST("\x2a\x85\x70\x2b\x0d\x10")}; + +gss_OID GSSAPI_LIB_VARIABLE GSS_KRB5_CCACHE_NAME_X = +    &gss_krb5_ccache_name_x_desc; + +/* 1.2.752.43.13.17 */ +static gss_OID_desc gss_krb5_set_time_offset_x_desc = +    {6, rk_UNCONST("\x2a\x85\x70\x2b\x0d\x11")}; + +gss_OID GSSAPI_LIB_VARIABLE GSS_KRB5_SET_TIME_OFFSET_X = +    &gss_krb5_set_time_offset_x_desc; + +/* 1.2.752.43.13.18 */ +static gss_OID_desc gss_krb5_get_time_offset_x_desc = +    {6, rk_UNCONST("\x2a\x85\x70\x2b\x0d\x12")}; + +gss_OID GSSAPI_LIB_VARIABLE GSS_KRB5_GET_TIME_OFFSET_X = +    &gss_krb5_get_time_offset_x_desc; + +/* 1.2.752.43.14.1 */ +static gss_OID_desc gss_sasl_digest_md5_mechanism_desc = +    {6, rk_UNCONST("\x2a\x85\x70\x2b\x0e\x01") }; + +gss_OID GSSAPI_LIB_VARIABLE GSS_SASL_DIGEST_MD5_MECHANISM =  +    &gss_sasl_digest_md5_mechanism_desc; + +/* + * Context for krb5 calls. + */ + +/* + * + */ + +static gssapi_mech_interface_desc krb5_mech = { +    GMI_VERSION, +    "kerberos 5", +    {9, "\x2a\x86\x48\x86\xf7\x12\x01\x02\x02" }, +    _gsskrb5_acquire_cred, +    _gsskrb5_release_cred, +    _gsskrb5_init_sec_context, +    _gsskrb5_accept_sec_context, +    _gsskrb5_process_context_token, +    _gsskrb5_delete_sec_context, +    _gsskrb5_context_time, +    _gsskrb5_get_mic, +    _gsskrb5_verify_mic, +    _gsskrb5_wrap, +    _gsskrb5_unwrap, +    _gsskrb5_display_status, +    _gsskrb5_indicate_mechs, +    _gsskrb5_compare_name, +    _gsskrb5_display_name, +    _gsskrb5_import_name, +    _gsskrb5_export_name, +    _gsskrb5_release_name, +    _gsskrb5_inquire_cred, +    _gsskrb5_inquire_context, +    _gsskrb5_wrap_size_limit, +    _gsskrb5_add_cred, +    _gsskrb5_inquire_cred_by_mech, +    _gsskrb5_export_sec_context, +    _gsskrb5_import_sec_context, +    _gsskrb5_inquire_names_for_mech, +    _gsskrb5_inquire_mechs_for_name, +    _gsskrb5_canonicalize_name, +    _gsskrb5_duplicate_name, +    _gsskrb5_inquire_sec_context_by_oid, +    _gsskrb5_inquire_cred_by_oid, +    _gsskrb5_set_sec_context_option, +    _gsskrb5_set_cred_option, +    _gsskrb5_pseudo_random +}; + +gssapi_mech_interface +__gss_krb5_initialize(void) +{ +    return &krb5_mech; +} diff --git a/source4/heimdal/lib/gssapi/krb5/get_mic.c b/source4/heimdal/lib/gssapi/krb5/get_mic.c new file mode 100644 index 0000000000..98a3f7e225 --- /dev/null +++ b/source4/heimdal/lib/gssapi/krb5/get_mic.c @@ -0,0 +1,317 @@ +/* + * Copyright (c) 1997 - 2003 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.  + */ + +#include "krb5/gsskrb5_locl.h" + +RCSID("$Id$"); + +static OM_uint32 +mic_des +           (OM_uint32 * minor_status, +            const gsskrb5_ctx ctx, +	    krb5_context context, +            gss_qop_t qop_req, +            const gss_buffer_t message_buffer, +            gss_buffer_t message_token, +	    krb5_keyblock *key +           ) +{ +  u_char *p; +  MD5_CTX md5; +  u_char hash[16]; +  DES_key_schedule schedule; +  DES_cblock deskey; +  DES_cblock zero; +  int32_t seq_number; +  size_t len, total_len; + +  _gsskrb5_encap_length (22, &len, &total_len, GSS_KRB5_MECHANISM); + +  message_token->length = total_len; +  message_token->value  = malloc (total_len); +  if (message_token->value == NULL) { +    message_token->length = 0; +    *minor_status = ENOMEM; +    return GSS_S_FAILURE; +  } + +  p = _gsskrb5_make_header(message_token->value, +			      len, +			      "\x01\x01", /* TOK_ID */ +			      GSS_KRB5_MECHANISM);  + +  memcpy (p, "\x00\x00", 2);	/* SGN_ALG = DES MAC MD5 */ +  p += 2; + +  memcpy (p, "\xff\xff\xff\xff", 4); /* Filler */ +  p += 4; + +  /* Fill in later (SND-SEQ) */ +  memset (p, 0, 16); +  p += 16; + +  /* checksum */ +  MD5_Init (&md5); +  MD5_Update (&md5, p - 24, 8); +  MD5_Update (&md5, message_buffer->value, message_buffer->length); +  MD5_Final (hash, &md5); + +  memset (&zero, 0, sizeof(zero)); +  memcpy (&deskey, key->keyvalue.data, sizeof(deskey)); +  DES_set_key_unchecked (&deskey, &schedule); +  DES_cbc_cksum ((void *)hash, (void *)hash, sizeof(hash), +		 &schedule, &zero); +  memcpy (p - 8, hash, 8);	/* SGN_CKSUM */ + +  HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex); +  /* sequence number */ +  krb5_auth_con_getlocalseqnumber (context, +				   ctx->auth_context, +				   &seq_number); + +  p -= 16;			/* SND_SEQ */ +  p[0] = (seq_number >> 0)  & 0xFF; +  p[1] = (seq_number >> 8)  & 0xFF; +  p[2] = (seq_number >> 16) & 0xFF; +  p[3] = (seq_number >> 24) & 0xFF; +  memset (p + 4, +	  (ctx->more_flags & LOCAL) ? 0 : 0xFF, +	  4); + +  DES_set_key_unchecked (&deskey, &schedule); +  DES_cbc_encrypt ((void *)p, (void *)p, 8, +		   &schedule, (DES_cblock *)(p + 8), DES_ENCRYPT); + +  krb5_auth_con_setlocalseqnumber (context, +			       ctx->auth_context, +			       ++seq_number); +  HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); +   +  memset (deskey, 0, sizeof(deskey)); +  memset (&schedule, 0, sizeof(schedule)); +   +  *minor_status = 0; +  return GSS_S_COMPLETE; +} + +static OM_uint32 +mic_des3 +           (OM_uint32 * minor_status, +            const gsskrb5_ctx ctx, +	    krb5_context context, +            gss_qop_t qop_req, +            const gss_buffer_t message_buffer, +            gss_buffer_t message_token, +	    krb5_keyblock *key +           ) +{ +  u_char *p; +  Checksum cksum; +  u_char seq[8]; + +  int32_t seq_number; +  size_t len, total_len; + +  krb5_crypto crypto; +  krb5_error_code kret; +  krb5_data encdata; +  char *tmp; +  char ivec[8]; + +  _gsskrb5_encap_length (36, &len, &total_len, GSS_KRB5_MECHANISM); + +  message_token->length = total_len; +  message_token->value  = malloc (total_len); +  if (message_token->value == NULL) { +      message_token->length = 0; +      *minor_status = ENOMEM; +      return GSS_S_FAILURE; +  } + +  p = _gsskrb5_make_header(message_token->value, +			      len, +			      "\x01\x01", /* TOK-ID */ +			      GSS_KRB5_MECHANISM); + +  memcpy (p, "\x04\x00", 2);	/* SGN_ALG = HMAC SHA1 DES3-KD */ +  p += 2; + +  memcpy (p, "\xff\xff\xff\xff", 4); /* filler */ +  p += 4; + +  /* this should be done in parts */ + +  tmp = malloc (message_buffer->length + 8); +  if (tmp == NULL) { +      free (message_token->value); +      message_token->value = NULL; +      message_token->length = 0; +      *minor_status = ENOMEM; +      return GSS_S_FAILURE; +  } +  memcpy (tmp, p - 8, 8); +  memcpy (tmp + 8, message_buffer->value, message_buffer->length); + +  kret = krb5_crypto_init(context, key, 0, &crypto); +  if (kret) { +      free (message_token->value); +      message_token->value = NULL; +      message_token->length = 0; +      free (tmp); +      *minor_status = kret; +      return GSS_S_FAILURE; +  } + +  kret = krb5_create_checksum (context, +			       crypto, +			       KRB5_KU_USAGE_SIGN, +			       0, +			       tmp, +			       message_buffer->length + 8, +			       &cksum); +  free (tmp); +  krb5_crypto_destroy (context, crypto); +  if (kret) { +      free (message_token->value); +      message_token->value = NULL; +      message_token->length = 0; +      *minor_status = kret; +      return GSS_S_FAILURE; +  } + +  memcpy (p + 8, cksum.checksum.data, cksum.checksum.length); + +  HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex); +  /* sequence number */ +  krb5_auth_con_getlocalseqnumber (context, +			       ctx->auth_context, +			       &seq_number); + +  seq[0] = (seq_number >> 0)  & 0xFF; +  seq[1] = (seq_number >> 8)  & 0xFF; +  seq[2] = (seq_number >> 16) & 0xFF; +  seq[3] = (seq_number >> 24) & 0xFF; +  memset (seq + 4, +	  (ctx->more_flags & LOCAL) ? 0 : 0xFF, +	  4); + +  kret = krb5_crypto_init(context, key, +			  ETYPE_DES3_CBC_NONE, &crypto); +  if (kret) { +      free (message_token->value); +      message_token->value = NULL; +      message_token->length = 0; +      *minor_status = kret; +      return GSS_S_FAILURE; +  } + +  if (ctx->more_flags & COMPAT_OLD_DES3) +      memset(ivec, 0, 8); +  else +      memcpy(ivec, p + 8, 8); + +  kret = krb5_encrypt_ivec (context, +			    crypto, +			    KRB5_KU_USAGE_SEQ, +			    seq, 8, &encdata, ivec); +  krb5_crypto_destroy (context, crypto); +  if (kret) { +      free (message_token->value); +      message_token->value = NULL; +      message_token->length = 0; +      *minor_status = kret; +      return GSS_S_FAILURE; +  } +   +  assert (encdata.length == 8); + +  memcpy (p, encdata.data, encdata.length); +  krb5_data_free (&encdata); + +  krb5_auth_con_setlocalseqnumber (context, +			       ctx->auth_context, +			       ++seq_number); +  HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); +   +  free_Checksum (&cksum); +  *minor_status = 0; +  return GSS_S_COMPLETE; +} + +OM_uint32 _gsskrb5_get_mic +           (OM_uint32 * minor_status, +            const gss_ctx_id_t context_handle, +            gss_qop_t qop_req, +            const gss_buffer_t message_buffer, +            gss_buffer_t message_token +           ) +{ +  krb5_context context; +  const gsskrb5_ctx ctx = (const gsskrb5_ctx) context_handle; +  krb5_keyblock *key; +  OM_uint32 ret; +  krb5_keytype keytype; + +  GSSAPI_KRB5_INIT (&context); + +  HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex); +  ret = _gsskrb5i_get_token_key(ctx, context, &key); +  HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); +  if (ret) { +      *minor_status = ret; +      return GSS_S_FAILURE; +  } +  krb5_enctype_to_keytype (context, key->keytype, &keytype); + +  switch (keytype) { +  case KEYTYPE_DES : +      ret = mic_des (minor_status, ctx, context, qop_req, +		     message_buffer, message_token, key); +      break; +  case KEYTYPE_DES3 : +      ret = mic_des3 (minor_status, ctx, context, qop_req, +		      message_buffer, message_token, key); +      break; +  case KEYTYPE_ARCFOUR: +  case KEYTYPE_ARCFOUR_56: +      ret = _gssapi_get_mic_arcfour (minor_status, ctx, context, qop_req, +				     message_buffer, message_token, key); +      break; +  default : +      ret = _gssapi_mic_cfx (minor_status, ctx, context, qop_req, +			     message_buffer, message_token, key); +      break; +  } +  krb5_free_keyblock (context, key); +  return ret; +} diff --git a/source4/heimdal/lib/gssapi/krb5/gkrb5_err.et b/source4/heimdal/lib/gssapi/krb5/gkrb5_err.et new file mode 100644 index 0000000000..3c23412a6a --- /dev/null +++ b/source4/heimdal/lib/gssapi/krb5/gkrb5_err.et @@ -0,0 +1,31 @@ +# +# extended gss krb5 error messages +# + +id "$Id$" + +error_table gk5 + +prefix GSS_KRB5_S + +error_code G_BAD_SERVICE_NAME, "No @ in SERVICE-NAME name string" +error_code G_BAD_STRING_UID, "STRING-UID-NAME contains nondigits" +error_code G_NOUSER, "UID does not resolve to username" +error_code G_VALIDATE_FAILED, "Validation error" +error_code G_BUFFER_ALLOC, "Couldn't allocate gss_buffer_t data" +error_code G_BAD_MSG_CTX, "Message context invalid" +error_code G_WRONG_SIZE, "Buffer is the wrong size" +error_code G_BAD_USAGE, "Credential usage type is unknown" +error_code G_UNKNOWN_QOP, "Unknown quality of protection specified" + +index 128 + +error_code KG_CCACHE_NOMATCH, "Principal in credential cache does not match desired name" +error_code KG_KEYTAB_NOMATCH, "No principal in keytab matches desired name" +error_code KG_TGT_MISSING, "Credential cache has no TGT" +error_code KG_NO_SUBKEY, "Authenticator has no subkey" +error_code KG_CONTEXT_ESTABLISHED, "Context is already fully established" +error_code KG_BAD_SIGN_TYPE, "Unknown signature type in token" +error_code KG_BAD_LENGTH, "Invalid field length in token" +error_code KG_CTX_INCOMPLETE, "Attempt to use incomplete security context" +error_code KG_INPUT_TOO_LONG, "Input too long" diff --git a/source4/heimdal/lib/gssapi/krb5/gsskrb5_locl.h b/source4/heimdal/lib/gssapi/krb5/gsskrb5_locl.h new file mode 100644 index 0000000000..dc7adec68f --- /dev/null +++ b/source4/heimdal/lib/gssapi/krb5/gsskrb5_locl.h @@ -0,0 +1,143 @@ +/* + * Copyright (c) 1997 - 2008 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.  + */ + +/* $Id$ */ + +#ifndef GSSKRB5_LOCL_H +#define GSSKRB5_LOCL_H + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <krb5_locl.h> +#include <gkrb5_err.h> +#include <gssapi.h> +#include <gssapi_mech.h> +#include <assert.h> + +#include "cfx.h" + +/* + * + */ + +struct gss_msg_order; + +typedef struct { +  struct krb5_auth_context_data *auth_context; +  krb5_principal source, target; +#define IS_DCE_STYLE(ctx) (((ctx)->flags & GSS_C_DCE_STYLE) != 0) +  OM_uint32 flags; +  enum { LOCAL = 1, OPEN = 2,  +	 COMPAT_OLD_DES3 = 4, +         COMPAT_OLD_DES3_SELECTED = 8, +	 ACCEPTOR_SUBKEY = 16, +	 RETRIED = 32, +	 CLOSE_CCACHE = 64 +  } more_flags; +  enum gss_ctx_id_t_state { +      /* initiator states */ +      INITIATOR_START, +      INITIATOR_RESTART, +      INITIATOR_WAIT_FOR_MUTAL, +      INITIATOR_READY, +      /* acceptor states */ +      ACCEPTOR_START, +      ACCEPTOR_WAIT_FOR_DCESTYLE, +      ACCEPTOR_READY +  } state; +  krb5_creds *kcred; +  krb5_ccache ccache; +  struct krb5_ticket *ticket; +  OM_uint32 lifetime; +  HEIMDAL_MUTEX ctx_id_mutex; +  struct gss_msg_order *order; +  krb5_keyblock *service_keyblock; +  krb5_data fwd_data; +} *gsskrb5_ctx; + +typedef struct { +  krb5_principal principal; +  int cred_flags; +#define GSS_CF_DESTROY_CRED_ON_RELEASE	1 +#define GSS_CF_NO_CI_FLAGS		2 +  struct krb5_keytab_data *keytab; +  OM_uint32 lifetime; +  gss_cred_usage_t usage; +  gss_OID_set mechanisms; +  struct krb5_ccache_data *ccache; +  HEIMDAL_MUTEX cred_id_mutex; +  krb5_enctype *enctypes; +} *gsskrb5_cred; + +typedef struct Principal *gsskrb5_name; + +/* + * + */ + +extern krb5_keytab _gsskrb5_keytab; +extern HEIMDAL_MUTEX gssapi_keytab_mutex; + +struct gssapi_thr_context { +    HEIMDAL_MUTEX mutex; +    char *error_string; +}; + +/* + * Prototypes + */ + +#include <krb5/gsskrb5-private.h> + +#define GSSAPI_KRB5_INIT(ctx) do {				\ +    krb5_error_code kret_gss_init;				\ +    if((kret_gss_init = _gsskrb5_init (ctx)) != 0) {		\ +	*minor_status = kret_gss_init;				\ +	return GSS_S_FAILURE;					\ +    }								\ +} while (0) + +/* sec_context flags */ + +#define SC_LOCAL_ADDRESS  0x01 +#define SC_REMOTE_ADDRESS 0x02 +#define SC_KEYBLOCK	  0x04 +#define SC_LOCAL_SUBKEY	  0x08 +#define SC_REMOTE_SUBKEY  0x10 + +/* type to signal that that dns canon maybe should be done */ +#define MAGIC_HOSTBASED_NAME_TYPE 4711 + +#endif diff --git a/source4/heimdal/lib/gssapi/krb5/import_name.c b/source4/heimdal/lib/gssapi/krb5/import_name.c new file mode 100644 index 0000000000..9589979ee8 --- /dev/null +++ b/source4/heimdal/lib/gssapi/krb5/import_name.c @@ -0,0 +1,252 @@ +/* + * Copyright (c) 1997 - 2003 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.  + */ + +#include "krb5/gsskrb5_locl.h" + +RCSID("$Id$"); + +static OM_uint32 +parse_krb5_name (OM_uint32 *minor_status, +		 krb5_context context, +		 const char *name, +		 gss_name_t *output_name) +{ +    krb5_principal princ; +    krb5_error_code kerr; + +    kerr = krb5_parse_name (context, name, &princ); + +    if (kerr == 0) { +	*output_name = (gss_name_t)princ; +	return GSS_S_COMPLETE; +    } +    *minor_status = kerr; + +    if (kerr == KRB5_PARSE_ILLCHAR || kerr == KRB5_PARSE_MALFORMED) +	return GSS_S_BAD_NAME; + +    return GSS_S_FAILURE; +} + +static OM_uint32 +import_krb5_name (OM_uint32 *minor_status, +		  krb5_context context, +		  const gss_buffer_t input_name_buffer, +		  gss_name_t *output_name) +{ +    OM_uint32 ret; +    char *tmp; + +    tmp = malloc (input_name_buffer->length + 1); +    if (tmp == NULL) { +	*minor_status = ENOMEM; +	return GSS_S_FAILURE; +    } +    memcpy (tmp, +	    input_name_buffer->value, +	    input_name_buffer->length); +    tmp[input_name_buffer->length] = '\0'; + +    ret = parse_krb5_name(minor_status, context, tmp, output_name); +    free(tmp); + +    return ret; +} + +OM_uint32 +_gsskrb5_canon_name(OM_uint32 *minor_status, krb5_context context, +		    int use_dns, gss_name_t name, krb5_principal *out) +{ +    krb5_principal p = (krb5_principal)name; +    krb5_error_code ret; +    char *hostname = NULL, *service; + +    *minor_status = 0; + +    /* If its not a hostname */ +    if (krb5_principal_get_type(context, p) != MAGIC_HOSTBASED_NAME_TYPE) { +	ret = krb5_copy_principal(context, p, out); +    } else if (!use_dns) { +	ret = krb5_copy_principal(context, p, out); +	if (ret == 0) +	    krb5_principal_set_type(context, *out, KRB5_NT_SRV_HST); +    } else { +	if (p->name.name_string.len == 0) +	    return GSS_S_BAD_NAME; +	else if (p->name.name_string.len > 1) +	    hostname = p->name.name_string.val[1]; +	 +	service = p->name.name_string.val[0]; +	 +	ret = krb5_sname_to_principal(context, +				      hostname, +				      service, +				      KRB5_NT_SRV_HST, +				      out); +    } + +    if (ret) { +	*minor_status = ret; +	return GSS_S_FAILURE; +    } + +    return 0; +} + + +static OM_uint32 +import_hostbased_name (OM_uint32 *minor_status, +		       krb5_context context, +		       const gss_buffer_t input_name_buffer, +		       gss_name_t *output_name) +{ +    krb5_principal princ = NULL; +    krb5_error_code kerr; +    char *tmp, *p, *host = NULL; + +    tmp = malloc (input_name_buffer->length + 1); +    if (tmp == NULL) { +	*minor_status = ENOMEM; +	return GSS_S_FAILURE; +    } +    memcpy (tmp, +	    input_name_buffer->value, +	    input_name_buffer->length); +    tmp[input_name_buffer->length] = '\0'; + +    p = strchr (tmp, '@'); +    if (p != NULL) { +	*p = '\0'; +	host = p + 1; +    } + +    kerr = krb5_make_principal(context, &princ, NULL, tmp, host, NULL); +    free (tmp); +    *minor_status = kerr; +    if (kerr == KRB5_PARSE_ILLCHAR || kerr == KRB5_PARSE_MALFORMED) +	return GSS_S_BAD_NAME; +    else if (kerr) +	return GSS_S_FAILURE; + +    krb5_principal_set_type(context, princ, MAGIC_HOSTBASED_NAME_TYPE); +    *output_name = (gss_name_t)princ; + +    return 0; +} + +static OM_uint32 +import_export_name (OM_uint32 *minor_status, +		    krb5_context context, +		    const gss_buffer_t input_name_buffer, +		    gss_name_t *output_name) +{ +    unsigned char *p; +    uint32_t length; +    OM_uint32 ret; +    char *name; + +    if (input_name_buffer->length < 10 + GSS_KRB5_MECHANISM->length) +	return GSS_S_BAD_NAME; + +    /* TOK, MECH_OID_LEN, DER(MECH_OID), NAME_LEN, NAME */ + +    p = input_name_buffer->value; + +    if (memcmp(&p[0], "\x04\x01\x00", 3) != 0 || +	p[3] != GSS_KRB5_MECHANISM->length + 2 || +	p[4] != 0x06 || +	p[5] != GSS_KRB5_MECHANISM->length || +	memcmp(&p[6], GSS_KRB5_MECHANISM->elements,  +	       GSS_KRB5_MECHANISM->length) != 0) +	return GSS_S_BAD_NAME; + +    p += 6 + GSS_KRB5_MECHANISM->length; + +    length = p[0] << 24 | p[1] << 16 | p[2] << 8 | p[3]; +    p += 4; + +    if (length > input_name_buffer->length - 10 - GSS_KRB5_MECHANISM->length) +	return GSS_S_BAD_NAME; + +    name = malloc(length + 1); +    if (name == NULL) { +	*minor_status = ENOMEM; +	return GSS_S_FAILURE; +    } +    memcpy(name, p, length); +    name[length] = '\0'; + +    ret = parse_krb5_name(minor_status, context, name, output_name); +    free(name); + +    return ret; +} + +OM_uint32 _gsskrb5_import_name +           (OM_uint32 * minor_status, +            const gss_buffer_t input_name_buffer, +            const gss_OID input_name_type, +            gss_name_t * output_name +           ) +{ +    krb5_context context; + +    *minor_status = 0; +    *output_name = GSS_C_NO_NAME; +     +    GSSAPI_KRB5_INIT (&context); + +    if (gss_oid_equal(input_name_type, GSS_C_NT_HOSTBASED_SERVICE) || +	gss_oid_equal(input_name_type, GSS_C_NT_HOSTBASED_SERVICE_X)) +	return import_hostbased_name (minor_status, +				      context, +				      input_name_buffer, +				      output_name); +    else if (gss_oid_equal(input_name_type, GSS_C_NO_OID) +	     || gss_oid_equal(input_name_type, GSS_C_NT_USER_NAME) +	     || gss_oid_equal(input_name_type, GSS_KRB5_NT_PRINCIPAL_NAME)) + 	/* default printable syntax */ +	return import_krb5_name (minor_status, +				 context, +				 input_name_buffer, +				 output_name); +    else if (gss_oid_equal(input_name_type, GSS_C_NT_EXPORT_NAME)) { +	return import_export_name(minor_status, +				  context, +				  input_name_buffer,  +				  output_name); +    } else { +	*minor_status = 0; +	return GSS_S_BAD_NAMETYPE; +    } +} diff --git a/source4/heimdal/lib/gssapi/krb5/import_sec_context.c b/source4/heimdal/lib/gssapi/krb5/import_sec_context.c new file mode 100644 index 0000000000..1b709657f4 --- /dev/null +++ b/source4/heimdal/lib/gssapi/krb5/import_sec_context.c @@ -0,0 +1,229 @@ +/* + * Copyright (c) 1999 - 2003 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.  + */ + +#include "krb5/gsskrb5_locl.h" + +RCSID("$Id$"); + +OM_uint32 +_gsskrb5_import_sec_context ( +    OM_uint32 * minor_status, +    const gss_buffer_t interprocess_token, +    gss_ctx_id_t * context_handle +    ) +{ +    OM_uint32 ret = GSS_S_FAILURE; +    krb5_context context; +    krb5_error_code kret; +    krb5_storage *sp; +    krb5_auth_context ac; +    krb5_address local, remote; +    krb5_address *localp, *remotep; +    krb5_data data; +    gss_buffer_desc buffer; +    krb5_keyblock keyblock; +    int32_t flags, tmp; +    gsskrb5_ctx ctx; +    gss_name_t name; + +    GSSAPI_KRB5_INIT (&context); + +    *context_handle = GSS_C_NO_CONTEXT; + +    localp = remotep = NULL; + +    sp = krb5_storage_from_mem (interprocess_token->value, +				interprocess_token->length); +    if (sp == NULL) { +	*minor_status = ENOMEM; +	return GSS_S_FAILURE; +    } + +    ctx = calloc(1, sizeof(*ctx)); +    if (ctx == NULL) { +	*minor_status = ENOMEM; +	krb5_storage_free (sp); +	return GSS_S_FAILURE; +    } +    HEIMDAL_MUTEX_init(&ctx->ctx_id_mutex); + +    kret = krb5_auth_con_init (context, +			       &ctx->auth_context); +    if (kret) { +	*minor_status = kret; +	ret = GSS_S_FAILURE; +	goto failure; +    } + +    /* flags */ + +    *minor_status = 0; + +    if (krb5_ret_int32 (sp, &flags) != 0) +	goto failure; + +    /* retrieve the auth context */ + +    ac = ctx->auth_context; +    if (krb5_ret_int32 (sp, &tmp) != 0) +	goto failure; +    ac->flags = tmp; +    if (flags & SC_LOCAL_ADDRESS) { +	if (krb5_ret_address (sp, localp = &local) != 0) +	    goto failure; +    } + +    if (flags & SC_REMOTE_ADDRESS) { +	if (krb5_ret_address (sp, remotep = &remote) != 0) +	    goto failure; +    } + +    krb5_auth_con_setaddrs (context, ac, localp, remotep); +    if (localp) +	krb5_free_address (context, localp); +    if (remotep) +	krb5_free_address (context, remotep); +    localp = remotep = NULL; + +    if (krb5_ret_int16 (sp, &ac->local_port) != 0) +	goto failure; + +    if (krb5_ret_int16 (sp, &ac->remote_port) != 0) +	goto failure; +    if (flags & SC_KEYBLOCK) { +	if (krb5_ret_keyblock (sp, &keyblock) != 0) +	    goto failure; +	krb5_auth_con_setkey (context, ac, &keyblock); +	krb5_free_keyblock_contents (context, &keyblock); +    } +    if (flags & SC_LOCAL_SUBKEY) { +	if (krb5_ret_keyblock (sp, &keyblock) != 0) +	    goto failure; +	krb5_auth_con_setlocalsubkey (context, ac, &keyblock); +	krb5_free_keyblock_contents (context, &keyblock); +    } +    if (flags & SC_REMOTE_SUBKEY) { +	if (krb5_ret_keyblock (sp, &keyblock) != 0) +	    goto failure; +	krb5_auth_con_setremotesubkey (context, ac, &keyblock); +	krb5_free_keyblock_contents (context, &keyblock); +    } +    if (krb5_ret_uint32 (sp, &ac->local_seqnumber)) +	goto failure; +    if (krb5_ret_uint32 (sp, &ac->remote_seqnumber)) +	goto failure; + +    if (krb5_ret_int32 (sp, &tmp) != 0) +	goto failure; +    ac->keytype = tmp; +    if (krb5_ret_int32 (sp, &tmp) != 0) +	goto failure; +    ac->cksumtype = tmp; + +    /* names */ + +    if (krb5_ret_data (sp, &data)) +	goto failure; +    buffer.value  = data.data; +    buffer.length = data.length; + +    ret = _gsskrb5_import_name (minor_status, &buffer, GSS_C_NT_EXPORT_NAME, +				&name); +    if (ret) { +	ret = _gsskrb5_import_name (minor_status, &buffer, GSS_C_NO_OID, +				    &name); +	if (ret) { +	    krb5_data_free (&data); +	    goto failure; +	} +    } +    ctx->source = (krb5_principal)name; +    krb5_data_free (&data); + +    if (krb5_ret_data (sp, &data) != 0) +	goto failure; +    buffer.value  = data.data; +    buffer.length = data.length; + +    ret = _gsskrb5_import_name (minor_status, &buffer, GSS_C_NT_EXPORT_NAME, +				&name); +    if (ret) { +	ret = _gsskrb5_import_name (minor_status, &buffer, GSS_C_NO_OID, +				    &name); +	if (ret) { +	    krb5_data_free (&data); +	    goto failure; +	} +    }     +    ctx->target = (krb5_principal)name; +    krb5_data_free (&data); + +    if (krb5_ret_int32 (sp, &tmp)) +	goto failure; +    ctx->flags = tmp; +    if (krb5_ret_int32 (sp, &tmp)) +	goto failure; +    ctx->more_flags = tmp; +    if (krb5_ret_int32 (sp, &tmp)) +	goto failure; +    ctx->lifetime = tmp; + +    ret = _gssapi_msg_order_import(minor_status, sp, &ctx->order); +    if (ret) +        goto failure;     +     +    krb5_storage_free (sp); + +    *context_handle = (gss_ctx_id_t)ctx; + +    return GSS_S_COMPLETE; + +failure: +    krb5_auth_con_free (context, +			ctx->auth_context); +    if (ctx->source != NULL) +	krb5_free_principal(context, ctx->source); +    if (ctx->target != NULL) +	krb5_free_principal(context, ctx->target); +    if (localp) +	krb5_free_address (context, localp); +    if (remotep) +	krb5_free_address (context, remotep); +    if(ctx->order) +	_gssapi_msg_order_destroy(&ctx->order); +    HEIMDAL_MUTEX_destroy(&ctx->ctx_id_mutex); +    krb5_storage_free (sp); +    free (ctx); +    *context_handle = GSS_C_NO_CONTEXT; +    return ret; +} diff --git a/source4/heimdal/lib/gssapi/krb5/indicate_mechs.c b/source4/heimdal/lib/gssapi/krb5/indicate_mechs.c new file mode 100644 index 0000000000..b0219fc7ce --- /dev/null +++ b/source4/heimdal/lib/gssapi/krb5/indicate_mechs.c @@ -0,0 +1,57 @@ +/* + * Copyright (c) 1997 - 2001, 2003 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.  + */ + +#include "krb5/gsskrb5_locl.h" + +RCSID("$Id$"); + +OM_uint32 _gsskrb5_indicate_mechs +           (OM_uint32 * minor_status, +            gss_OID_set * mech_set +           ) +{ +  OM_uint32 ret, junk; + +  ret = gss_create_empty_oid_set(minor_status, mech_set); +  if (ret) +      return ret; + +  ret = gss_add_oid_set_member(minor_status, GSS_KRB5_MECHANISM, mech_set); +  if (ret) { +      gss_release_oid_set(&junk, mech_set); +      return ret; +  } + +  *minor_status = 0; +  return GSS_S_COMPLETE; +} diff --git a/source4/heimdal/lib/gssapi/krb5/init.c b/source4/heimdal/lib/gssapi/krb5/init.c new file mode 100644 index 0000000000..ea32fce061 --- /dev/null +++ b/source4/heimdal/lib/gssapi/krb5/init.c @@ -0,0 +1,83 @@ +/* + * Copyright (c) 1997 - 2001, 2003, 2006 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.  + */ + +#include "krb5/gsskrb5_locl.h" + +RCSID("$Id$"); + +static HEIMDAL_MUTEX context_mutex = HEIMDAL_MUTEX_INITIALIZER; +static int created_key; +static HEIMDAL_thread_key context_key; + +static void +destroy_context(void *ptr) +{ +    krb5_context context = ptr; + +    if (context == NULL) +	return; +    krb5_free_context(context); +} + +krb5_error_code +_gsskrb5_init (krb5_context *context) +{ +    krb5_error_code ret = 0; + +    HEIMDAL_MUTEX_lock(&context_mutex); + +    if (!created_key) { +	HEIMDAL_key_create(&context_key, destroy_context, ret); +	if (ret) { +	    HEIMDAL_MUTEX_unlock(&context_mutex); +	    return ret; +	} +	created_key = 1; +    } +    HEIMDAL_MUTEX_unlock(&context_mutex); + +    *context = HEIMDAL_getspecific(context_key); +    if (*context == NULL) { + +	ret = krb5_init_context(context); +	if (ret == 0) { +	    HEIMDAL_setspecific(context_key, *context, ret); +	    if (ret) { +		krb5_free_context(*context); +		*context = NULL; +	    } +	} +    } + +    return ret; +} diff --git a/source4/heimdal/lib/gssapi/krb5/init_sec_context.c b/source4/heimdal/lib/gssapi/krb5/init_sec_context.c new file mode 100644 index 0000000000..3d5e3b71c5 --- /dev/null +++ b/source4/heimdal/lib/gssapi/krb5/init_sec_context.c @@ -0,0 +1,962 @@ +/* + * Copyright (c) 1997 - 2008 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.  + */ + +#include "krb5/gsskrb5_locl.h" + +RCSID("$Id$"); + +/* + * copy the addresses from `input_chan_bindings' (if any) to + * the auth context `ac' + */ + +static OM_uint32 +set_addresses (krb5_context context, +	       krb5_auth_context ac, +	       const gss_channel_bindings_t input_chan_bindings)	        +{ +    /* Port numbers are expected to be in application_data.value,  +     * initator's port first */  + +    krb5_address initiator_addr, acceptor_addr; +    krb5_error_code kret; +        +    if (input_chan_bindings == GSS_C_NO_CHANNEL_BINDINGS +	|| input_chan_bindings->application_data.length != +	2 * sizeof(ac->local_port)) +	return 0; + +    memset(&initiator_addr, 0, sizeof(initiator_addr)); +    memset(&acceptor_addr, 0, sizeof(acceptor_addr)); +        +    ac->local_port = +	*(int16_t *) input_chan_bindings->application_data.value; +        +    ac->remote_port = +	*((int16_t *) input_chan_bindings->application_data.value + 1); +        +    kret = _gsskrb5i_address_to_krb5addr(context, +					 input_chan_bindings->acceptor_addrtype, +					 &input_chan_bindings->acceptor_address, +					 ac->remote_port, +					 &acceptor_addr); +    if (kret) +	return kret; +            +    kret = _gsskrb5i_address_to_krb5addr(context, +					 input_chan_bindings->initiator_addrtype, +					 &input_chan_bindings->initiator_address, +					 ac->local_port, +					 &initiator_addr); +    if (kret) { +	krb5_free_address (context, &acceptor_addr); +	return kret; +    } +        +    kret = krb5_auth_con_setaddrs(context, +				  ac, +				  &initiator_addr,  /* local address */ +				  &acceptor_addr);  /* remote address */ +        +    krb5_free_address (context, &initiator_addr); +    krb5_free_address (context, &acceptor_addr); +        +#if 0 +    free(input_chan_bindings->application_data.value); +    input_chan_bindings->application_data.value = NULL; +    input_chan_bindings->application_data.length = 0; +#endif + +    return kret; +} + +OM_uint32 +_gsskrb5_create_ctx( +        OM_uint32 * minor_status, +	gss_ctx_id_t * context_handle, +	krb5_context context, + 	const gss_channel_bindings_t input_chan_bindings, + 	enum gss_ctx_id_t_state state) +{ +    krb5_error_code kret; +    gsskrb5_ctx ctx; + +    *context_handle = NULL; + +    ctx = malloc(sizeof(*ctx)); +    if (ctx == NULL) { +	*minor_status = ENOMEM; +	return GSS_S_FAILURE; +    } +    ctx->auth_context		= NULL; +    ctx->source			= NULL; +    ctx->target			= NULL; +    ctx->kcred			= NULL; +    ctx->ccache			= NULL; +    ctx->state			= state; +    ctx->flags			= 0; +    ctx->more_flags		= 0; +    ctx->service_keyblock	= NULL; +    ctx->ticket			= NULL; +    krb5_data_zero(&ctx->fwd_data); +    ctx->lifetime		= GSS_C_INDEFINITE; +    ctx->order			= NULL; +    HEIMDAL_MUTEX_init(&ctx->ctx_id_mutex); + +    kret = krb5_auth_con_init (context, &ctx->auth_context); +    if (kret) { +	*minor_status = kret; +	HEIMDAL_MUTEX_destroy(&ctx->ctx_id_mutex); +	return GSS_S_FAILURE; +    } + +    kret = set_addresses(context, ctx->auth_context, input_chan_bindings); +    if (kret) { +	*minor_status = kret; + +	HEIMDAL_MUTEX_destroy(&ctx->ctx_id_mutex); + +	krb5_auth_con_free(context, ctx->auth_context); + +	return GSS_S_BAD_BINDINGS; +    } + +    /* +     * We need a sequence number +     */ + +    krb5_auth_con_addflags(context, +			   ctx->auth_context, +			   KRB5_AUTH_CONTEXT_DO_SEQUENCE | +			   KRB5_AUTH_CONTEXT_CLEAR_FORWARDED_CRED, +			   NULL); + +    *context_handle = (gss_ctx_id_t)ctx; + +    return GSS_S_COMPLETE; +} + + +static OM_uint32 +gsskrb5_get_creds( +        OM_uint32 * minor_status, +	krb5_context context, +	krb5_ccache ccache, +	gsskrb5_ctx ctx, +	krb5_const_principal target_name, +	OM_uint32 time_req, +	OM_uint32 * time_rec, +	krb5_creds ** cred) +{ +    OM_uint32 ret; +    krb5_error_code kret; +    krb5_creds this_cred; +    OM_uint32 lifetime_rec; + +    *cred = NULL; + +    memset(&this_cred, 0, sizeof(this_cred)); +    this_cred.client = ctx->source; +    this_cred.server = ctx->target; + +    if (time_req && time_req != GSS_C_INDEFINITE) { +	krb5_timestamp ts; + +	krb5_timeofday (context, &ts); +	this_cred.times.endtime = ts + time_req; +    } else { +	this_cred.times.endtime   = 0; +    } + +    this_cred.session.keytype = KEYTYPE_NULL; + +    kret = krb5_get_credentials(context, +				0, +				ccache, +				&this_cred, +				cred); +    if (kret) { +	*minor_status = kret; +	return GSS_S_FAILURE; +    } + +    ctx->lifetime = (*cred)->times.endtime; + +    ret = _gsskrb5_lifetime_left(minor_status, context, +				 ctx->lifetime, &lifetime_rec); +    if (ret) return ret; + +    if (lifetime_rec == 0) { +	*minor_status = 0; +	return GSS_S_CONTEXT_EXPIRED; +    } + +    if (time_rec) *time_rec = lifetime_rec; + +    return GSS_S_COMPLETE; +} + +static OM_uint32 +gsskrb5_initiator_ready( +	OM_uint32 * minor_status, +	gsskrb5_ctx ctx, +	krb5_context context) +{ +    OM_uint32 ret; +    int32_t seq_number; +    int is_cfx = 0; +    OM_uint32 flags = ctx->flags; +     +    krb5_free_creds(context, ctx->kcred); +    ctx->kcred = NULL; + +    if (ctx->more_flags & CLOSE_CCACHE) +	krb5_cc_close(context, ctx->ccache); +    ctx->ccache = NULL; + +    krb5_auth_getremoteseqnumber (context, ctx->auth_context, &seq_number); +     +    _gsskrb5i_is_cfx(ctx, &is_cfx); +     +    ret = _gssapi_msg_order_create(minor_status, +				   &ctx->order, +				   _gssapi_msg_order_f(flags), +				   seq_number, 0, is_cfx); +    if (ret) return ret; +     +    ctx->state	= INITIATOR_READY; +    ctx->more_flags	|= OPEN; +     +    return GSS_S_COMPLETE; +} + +/* + * handle delegated creds in init-sec-context + */ + +static void +do_delegation (krb5_context context, +	       krb5_auth_context ac, +	       krb5_ccache ccache, +	       krb5_creds *cred, +	       krb5_const_principal name, +	       krb5_data *fwd_data, +	       uint32_t flagmask, +	       uint32_t *flags) +{ +    krb5_creds creds; +    KDCOptions fwd_flags; +    krb5_error_code kret; +        +    memset (&creds, 0, sizeof(creds)); +    krb5_data_zero (fwd_data); +        +    kret = krb5_cc_get_principal(context, ccache, &creds.client); +    if (kret)  +	goto out; +        +    kret = krb5_build_principal(context, +				&creds.server, +				strlen(creds.client->realm), +				creds.client->realm, +				KRB5_TGS_NAME, +				creds.client->realm, +				NULL); +    if (kret) +	goto out;  +        +    creds.times.endtime = 0; +        +    memset(&fwd_flags, 0, sizeof(fwd_flags)); +    fwd_flags.forwarded = 1; +    fwd_flags.forwardable = 1; +        +    if ( /*target_name->name.name_type != KRB5_NT_SRV_HST ||*/ +	name->name.name_string.len < 2)  +	goto out; +        +    kret = krb5_get_forwarded_creds(context, +				    ac, +				    ccache, +				    KDCOptions2int(fwd_flags), +				    name->name.name_string.val[1], +				    &creds, +				    fwd_data); +        + out: +    if (kret) +	*flags &= ~flagmask; +    else +	*flags |= flagmask; +        +    if (creds.client) +	krb5_free_principal(context, creds.client); +    if (creds.server) +	krb5_free_principal(context, creds.server); +} + +/* + * first stage of init-sec-context + */ + +static OM_uint32 +init_auth +(OM_uint32 * minor_status, + gsskrb5_cred cred, + gsskrb5_ctx ctx, + krb5_context context, + gss_name_t name, + const gss_OID mech_type, + OM_uint32 req_flags, + OM_uint32 time_req, + const gss_buffer_t input_token, + gss_OID * actual_mech_type, + gss_buffer_t output_token, + OM_uint32 * ret_flags, + OM_uint32 * time_rec +    ) +{ +    OM_uint32 ret = GSS_S_FAILURE; +    krb5_error_code kret; +    krb5_data outbuf; +    krb5_data fwd_data; +    OM_uint32 lifetime_rec; +    int use_dns = 1; + +    krb5_data_zero(&outbuf); +    krb5_data_zero(&fwd_data); + +    *minor_status = 0; + +    if (actual_mech_type) +	*actual_mech_type = GSS_KRB5_MECHANISM; + +    if (cred == NULL) { +	kret = krb5_cc_default (context, &ctx->ccache); +	if (kret) { +	    *minor_status = kret; +	    ret = GSS_S_FAILURE; +	    goto failure; +	} +	ctx->more_flags |= CLOSE_CCACHE; +    } else +	ctx->ccache = cred->ccache; + +    kret = krb5_cc_get_principal (context, ctx->ccache, &ctx->source); +    if (kret) { +	*minor_status = kret; +	ret = GSS_S_FAILURE; +	goto failure; +    } + +    /* canon name if needed for client + target realm */ +    kret = krb5_cc_get_config(context, ctx->ccache, NULL, +			      "realm-config", &outbuf); +    if (kret == 0) { +	/* XXX 2 is no server canon */ +	if (outbuf.length < 1 || ((((unsigned char *)outbuf.data)[0]) & 2)) +	    use_dns = 0; +	krb5_data_free(&outbuf); +    } + +    ret = _gsskrb5_canon_name(minor_status, context, use_dns,  +			      name, &ctx->target); +    if (ret) +	goto failure; + +    ret = _gss_DES3_get_mic_compat(minor_status, ctx, context); +    if (ret) +	goto failure; + + +    /* +     * This is hideous glue for (NFS) clients that wants to limit the +     * available enctypes to what it can support (encryption in +     * kernel). If there is no enctypes selected for this credential, +     * reset it to the default set of enctypes. +     */ +    { +	krb5_enctype *enctypes = NULL; + +	if (cred && cred->enctypes) +	    enctypes = cred->enctypes; +	krb5_set_default_in_tkt_etypes(context, enctypes); +    } + +    ret = gsskrb5_get_creds(minor_status, +			    context, +			    ctx->ccache, +			    ctx, +			    ctx->target, +			    time_req, +			    time_rec, +			    &ctx->kcred); +    if (ret) +	goto failure; + +    ctx->lifetime = ctx->kcred->times.endtime; + +    ret = _gsskrb5_lifetime_left(minor_status, +				 context, +				 ctx->lifetime, +				 &lifetime_rec); +    if (ret) { +	goto failure; +    } + +    if (lifetime_rec == 0) { +	*minor_status = 0; +	ret = GSS_S_CONTEXT_EXPIRED; +	goto failure; +    } + +    krb5_auth_con_setkey(context,  +			 ctx->auth_context,  +			 &ctx->kcred->session); + +    kret = krb5_auth_con_generatelocalsubkey(context,  +					     ctx->auth_context, +					     &ctx->kcred->session); +    if(kret) { +	*minor_status = kret; +	ret = GSS_S_FAILURE; +	goto failure; +    } + +    return GSS_S_COMPLETE; + +failure: +    if (ctx->ccache && (ctx->more_flags & CLOSE_CCACHE)) +	krb5_cc_close(context, ctx->ccache); +    ctx->ccache = NULL; + +    return ret; + +} + +static OM_uint32 +init_auth_restart +(OM_uint32 * minor_status, + gsskrb5_cred cred, + gsskrb5_ctx ctx, + krb5_context context, + OM_uint32 req_flags, + const gss_channel_bindings_t input_chan_bindings, + const gss_buffer_t input_token, + gss_OID * actual_mech_type, + gss_buffer_t output_token, + OM_uint32 * ret_flags, + OM_uint32 * time_rec +    ) +{ +    OM_uint32 ret = GSS_S_FAILURE; +    krb5_error_code kret; +    krb5_flags ap_options; +    krb5_data outbuf; +    uint32_t flags; +    krb5_data authenticator; +    Checksum cksum; +    krb5_enctype enctype; +    krb5_data fwd_data, timedata; +    int32_t offset = 0, oldoffset; +    uint32_t flagmask; + +    krb5_data_zero(&outbuf); +    krb5_data_zero(&fwd_data); + +    *minor_status = 0; + +    /*  +     * If the credential doesn't have ok-as-delegate, check if there +     * is a realm setting and use that. +     */ +    if (!ctx->kcred->flags.b.ok_as_delegate) { +	krb5_data data; +	 +	ret = krb5_cc_get_config(context, ctx->ccache, NULL, +				 "realm-config", &data); +	if (ret == 0) { +	    /* XXX 1 is use ok-as-delegate */ +	    if (data.length < 1 || ((((unsigned char *)data.data)[0]) & 1) == 0) +		req_flags &= ~(GSS_C_DELEG_FLAG|GSS_C_DELEG_POLICY_FLAG); +	    krb5_data_free(&data); +	} +    } + +    flagmask = 0; + +    /* if we used GSS_C_DELEG_POLICY_FLAG, trust KDC */ +    if ((req_flags & GSS_C_DELEG_POLICY_FLAG) +	&& ctx->kcred->flags.b.ok_as_delegate) +	flagmask |= GSS_C_DELEG_FLAG | GSS_C_DELEG_POLICY_FLAG; +    /* if there still is a GSS_C_DELEG_FLAG, use that */ +    if (req_flags & GSS_C_DELEG_FLAG) +	flagmask |= GSS_C_DELEG_FLAG; + + +    flags = 0; +    ap_options = 0; +    if (flagmask & GSS_C_DELEG_FLAG) { +	do_delegation (context, +		       ctx->auth_context, +		       ctx->ccache, ctx->kcred, ctx->target, +		       &fwd_data, flagmask, &flags); +    } +     +    if (req_flags & GSS_C_MUTUAL_FLAG) { +	flags |= GSS_C_MUTUAL_FLAG; +	ap_options |= AP_OPTS_MUTUAL_REQUIRED; +    } +     +    if (req_flags & GSS_C_REPLAY_FLAG) +	flags |= GSS_C_REPLAY_FLAG; +    if (req_flags & GSS_C_SEQUENCE_FLAG) +	flags |= GSS_C_SEQUENCE_FLAG; +    if (req_flags & GSS_C_ANON_FLAG) +	;                               /* XXX */ +    if (req_flags & GSS_C_DCE_STYLE) { +	/* GSS_C_DCE_STYLE implies GSS_C_MUTUAL_FLAG */ +	flags |= GSS_C_DCE_STYLE | GSS_C_MUTUAL_FLAG; +	ap_options |= AP_OPTS_MUTUAL_REQUIRED; +    } +    if (req_flags & GSS_C_IDENTIFY_FLAG) +	flags |= GSS_C_IDENTIFY_FLAG; +    if (req_flags & GSS_C_EXTENDED_ERROR_FLAG) +	flags |= GSS_C_EXTENDED_ERROR_FLAG; + +    if (req_flags & GSS_C_CONF_FLAG) { +	flags |= GSS_C_CONF_FLAG; +    } +    if (req_flags & GSS_C_INTEG_FLAG) { +	flags |= GSS_C_INTEG_FLAG; +    } +    if (cred == NULL || !(cred->cred_flags & GSS_CF_NO_CI_FLAGS)) { +	flags |= GSS_C_CONF_FLAG; +	flags |= GSS_C_INTEG_FLAG; +    } +    flags |= GSS_C_TRANS_FLAG; +     +    if (ret_flags) +	*ret_flags = flags; +    ctx->flags = flags; +    ctx->more_flags |= LOCAL; +     +    ret = _gsskrb5_create_8003_checksum (minor_status, +					 input_chan_bindings, +					 flags, +					 &fwd_data, +					 &cksum); +    krb5_data_free (&fwd_data); +    if (ret) +	goto failure; + +    enctype = ctx->auth_context->keyblock->keytype; + +    ret = krb5_cc_get_config(context, ctx->ccache, ctx->target, +			     "time-offset", &timedata); +    if (ret == 0) { +	if (timedata.length == 4) { +	    const u_char *p = timedata.data; +	    offset = (p[0] <<24) | (p[1] << 16) | (p[2] << 8) | (p[3] << 0); +	} +	krb5_data_free(&timedata); +    } + +    if (offset) { +	krb5_get_kdc_sec_offset (context, &oldoffset, NULL); +	krb5_set_kdc_sec_offset (context, offset, -1); +    } + +    kret = krb5_build_authenticator (context, +				     ctx->auth_context, +				     enctype, +				     ctx->kcred, +				     &cksum, +				     NULL, +				     &authenticator, +				     KRB5_KU_AP_REQ_AUTH); + +    if (kret) { +	if (offset) +	    krb5_set_kdc_sec_offset (context, oldoffset, -1); +	*minor_status = kret; +	ret = GSS_S_FAILURE; +	goto failure; +    } + +    kret = krb5_build_ap_req (context, +			      enctype, +			      ctx->kcred, +			      ap_options, +			      authenticator, +			      &outbuf); +    if (offset) +	krb5_set_kdc_sec_offset (context, oldoffset, -1); +    if (kret) { +	*minor_status = kret; +	ret = GSS_S_FAILURE; +	goto failure; +    } + +    if (flags & GSS_C_DCE_STYLE) { +	output_token->value = outbuf.data; +	output_token->length = outbuf.length; +    } else { +        ret = _gsskrb5_encapsulate (minor_status, &outbuf, output_token, +				    (u_char *)"\x01\x00", GSS_KRB5_MECHANISM); +	krb5_data_free (&outbuf); +	if (ret) +	    goto failure; +    } + +    free_Checksum(&cksum); + +    if (flags & GSS_C_MUTUAL_FLAG) { +	ctx->state = INITIATOR_WAIT_FOR_MUTAL; +	return GSS_S_CONTINUE_NEEDED; +    } + +    return gsskrb5_initiator_ready(minor_status, ctx, context); +failure: +    if (ctx->ccache && (ctx->more_flags & CLOSE_CCACHE)) +	krb5_cc_close(context, ctx->ccache); +    ctx->ccache = NULL; + +    return ret; +} + + +static OM_uint32 +repl_mutual +(OM_uint32 * minor_status, + gsskrb5_ctx ctx, + krb5_context context, + const gss_OID mech_type, + OM_uint32 req_flags, + OM_uint32 time_req, + const gss_channel_bindings_t input_chan_bindings, + const gss_buffer_t input_token, + gss_OID * actual_mech_type, + gss_buffer_t output_token, + OM_uint32 * ret_flags, + OM_uint32 * time_rec +    ) +{ +    OM_uint32 ret; +    krb5_error_code kret; +    krb5_data indata; +    krb5_ap_rep_enc_part *repl; +    int is_cfx = 0; + +    output_token->length = 0; +    output_token->value = NULL; + +    if (actual_mech_type) +	*actual_mech_type = GSS_KRB5_MECHANISM; + +    if (ctx->flags & GSS_C_DCE_STYLE) { +	/* There is no OID wrapping. */ +	indata.length	= input_token->length; +	indata.data	= input_token->value; +    } else { +	ret = _gsskrb5_decapsulate (minor_status, +				    input_token, +				    &indata, +				    "\x02\x00", +				    GSS_KRB5_MECHANISM); +	if (ret == GSS_S_DEFECTIVE_TOKEN) { +	    /* check if there is an error token sent instead */ +	    ret = _gsskrb5_decapsulate (minor_status, +					input_token, +					&indata, +					"\x03\x00", +					GSS_KRB5_MECHANISM); +	    if (ret == GSS_S_COMPLETE) { +		KRB_ERROR error; +		 +		kret = krb5_rd_error(context, &indata, &error); +		if (kret == 0) { +		    kret = krb5_error_from_rd_error(context, &error, NULL); + +		    /* save the time skrew for this host */ +		    if (kret == KRB5KRB_AP_ERR_SKEW) { +			krb5_data timedata; +			unsigned char p[4]; +			int32_t t = error.stime - time(NULL); + +			p[0] = (t >> 24) & 0xFF; +			p[1] = (t >> 16) & 0xFF; +			p[2] = (t >> 8)  & 0xFF; +			p[3] = (t >> 0)  & 0xFF; + +			timedata.data = p; +			timedata.length = sizeof(p); + +			krb5_cc_set_config(context, ctx->ccache, ctx->target, +					   "time-offset", &timedata); + +			if ((ctx->more_flags & RETRIED) == 0) +			    ctx->state = INITIATOR_RESTART; +			ctx->more_flags |= RETRIED; +		    } +		    free_KRB_ERROR (&error); +		} +		*minor_status = kret; +		return GSS_S_FAILURE; +	    } +	    return ret; +	} +    } + +    kret = krb5_rd_rep (context, +			ctx->auth_context, +			&indata, +			&repl); +    if (kret) { +	*minor_status = kret; +	return GSS_S_FAILURE; +    } +    krb5_free_ap_rep_enc_part (context, +			       repl); +     +    _gsskrb5i_is_cfx(ctx, &is_cfx); +    if (is_cfx) { +	krb5_keyblock *key = NULL; + +	kret = krb5_auth_con_getremotesubkey(context, +					     ctx->auth_context,  +					     &key); +	if (kret == 0 && key != NULL) { +    	    ctx->more_flags |= ACCEPTOR_SUBKEY; +	    krb5_free_keyblock (context, key); +	} +    } + + +    *minor_status = 0; +    if (time_rec) { +	ret = _gsskrb5_lifetime_left(minor_status, +				     context, +				     ctx->lifetime, +				     time_rec); +    } else { +	ret = GSS_S_COMPLETE; +    } +    if (ret_flags) +	*ret_flags = ctx->flags; + +    if (req_flags & GSS_C_DCE_STYLE) { +	int32_t local_seq, remote_seq; +	krb5_data outbuf; + +	/* +	 * So DCE_STYLE is strange. The client echos the seq number +	 * that the server used in the server's mk_rep in its own +	 * mk_rep(). After when done, it resets to it's own seq number +	 * for the gss_wrap calls. +	 */ + +	krb5_auth_getremoteseqnumber(context, ctx->auth_context, &remote_seq); +	krb5_auth_con_getlocalseqnumber(context, ctx->auth_context, &local_seq); +	krb5_auth_con_setlocalseqnumber(context, ctx->auth_context, remote_seq); + +	kret = krb5_mk_rep(context, ctx->auth_context, &outbuf); +	if (kret) { +	    *minor_status = kret; +	    return GSS_S_FAILURE; +	} +	 +	/* reset local seq number */ +	krb5_auth_con_setlocalseqnumber(context, ctx->auth_context, local_seq);	 + +	output_token->length = outbuf.length; +	output_token->value  = outbuf.data; +    } + +    return gsskrb5_initiator_ready(minor_status, ctx, context); +} + +/* + * gss_init_sec_context + */ + +OM_uint32 _gsskrb5_init_sec_context +(OM_uint32 * minor_status, + const gss_cred_id_t cred_handle, + gss_ctx_id_t * context_handle, + const gss_name_t target_name, + const gss_OID mech_type, + OM_uint32 req_flags, + OM_uint32 time_req, + const gss_channel_bindings_t input_chan_bindings, + const gss_buffer_t input_token, + gss_OID * actual_mech_type, + gss_buffer_t output_token, + OM_uint32 * ret_flags, + OM_uint32 * time_rec +    ) +{ +    krb5_context context; +    gsskrb5_cred cred = (gsskrb5_cred)cred_handle; +    gsskrb5_ctx ctx; +    OM_uint32 ret; + +    GSSAPI_KRB5_INIT (&context); + +    output_token->length = 0; +    output_token->value  = NULL; + +    if (context_handle == NULL) { +	*minor_status = 0; +	return GSS_S_FAILURE | GSS_S_CALL_BAD_STRUCTURE; +    } + +    if (ret_flags) +	*ret_flags = 0; +    if (time_rec) +	*time_rec = 0; + +    if (target_name == GSS_C_NO_NAME) { +	if (actual_mech_type) +	    *actual_mech_type = GSS_C_NO_OID; +	*minor_status = 0; +	return GSS_S_BAD_NAME; +    } + +    if (mech_type != GSS_C_NO_OID &&  +	!gss_oid_equal(mech_type, GSS_KRB5_MECHANISM)) +	return GSS_S_BAD_MECH; + +    if (input_token == GSS_C_NO_BUFFER || input_token->length == 0) { +	OM_uint32 ret; + +	if (*context_handle != GSS_C_NO_CONTEXT) { +	    *minor_status = 0; +	    return GSS_S_FAILURE | GSS_S_CALL_BAD_STRUCTURE; +	} +     +	ret = _gsskrb5_create_ctx(minor_status, +				  context_handle, +				  context, +				  input_chan_bindings, +				  INITIATOR_START); +	if (ret) +	    return ret; +    } + +    if (*context_handle == GSS_C_NO_CONTEXT) { +	*minor_status = 0; +	return GSS_S_FAILURE | GSS_S_CALL_BAD_STRUCTURE; +    } + +    ctx = (gsskrb5_ctx) *context_handle; + +    HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex); + + again: +    switch (ctx->state) { +    case INITIATOR_START: +	ret = init_auth(minor_status, +			cred, +			ctx, +			context, +			target_name, +			mech_type, +			req_flags, +			time_req, +			input_token, +			actual_mech_type, +			output_token, +			ret_flags, +			time_rec); +	if (ret != GSS_S_COMPLETE) +	    break;	     +	/* FALL THOUGH */ +    case INITIATOR_RESTART: +	ret = init_auth_restart(minor_status, +				cred, +				ctx, +				context, +				req_flags, +				input_chan_bindings, +				input_token, +				actual_mech_type, +				output_token, +				ret_flags, +				time_rec); +	break; +    case INITIATOR_WAIT_FOR_MUTAL: +	ret = repl_mutual(minor_status, +			  ctx, +			  context, +			  mech_type, +			  req_flags, +			  time_req, +			  input_chan_bindings, +			  input_token, +			  actual_mech_type, +			  output_token, +			  ret_flags, +			  time_rec); +	if (ctx->state == INITIATOR_RESTART) +	    goto again; +	break; +    case INITIATOR_READY: +	/*  +	 * If we get there, the caller have called +	 * gss_init_sec_context() one time too many. +	 */ +	_gsskrb5_set_status(EINVAL, "init_sec_context " +			    "called one time too many"); +	*minor_status = EINVAL; +	ret = GSS_S_BAD_STATUS; +	break; +    default: +	_gsskrb5_set_status(EINVAL, "init_sec_context " +			    "invalid state %d for client", +			    (int)ctx->state); +	*minor_status = EINVAL; +	ret = GSS_S_BAD_STATUS; +	break; +    } +    HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); + +    /* destroy context in case of error */ +    if (GSS_ERROR(ret)) { +	OM_uint32 min2; +	_gsskrb5_delete_sec_context(&min2, context_handle, GSS_C_NO_BUFFER); +    } + +    return ret; + +} diff --git a/source4/heimdal/lib/gssapi/krb5/inquire_context.c b/source4/heimdal/lib/gssapi/krb5/inquire_context.c new file mode 100644 index 0000000000..f2e01b464a --- /dev/null +++ b/source4/heimdal/lib/gssapi/krb5/inquire_context.c @@ -0,0 +1,112 @@ +/* + * Copyright (c) 1997, 2003 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.  + */ + +#include "krb5/gsskrb5_locl.h" + +RCSID("$Id$"); + +OM_uint32 _gsskrb5_inquire_context ( +    OM_uint32 * minor_status, +	const gss_ctx_id_t context_handle, +	gss_name_t * src_name, +	gss_name_t * targ_name, +	OM_uint32 * lifetime_rec, +	gss_OID * mech_type, +	OM_uint32 * ctx_flags, +	int * locally_initiated, +	int * open_context +    ) +{ +    krb5_context context; +    OM_uint32 ret; +    gsskrb5_ctx ctx = (gsskrb5_ctx)context_handle; +    gss_name_t name; + +    if (src_name) +	*src_name = GSS_C_NO_NAME; +    if (targ_name) +	*targ_name = GSS_C_NO_NAME; + +    GSSAPI_KRB5_INIT (&context); + +    HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex); + +    if (src_name) { +	name = (gss_name_t)ctx->source; +	ret = _gsskrb5_duplicate_name (minor_status, name, src_name); +	if (ret) +	    goto failed; +    } + +    if (targ_name) { +	name = (gss_name_t)ctx->target; +	ret = _gsskrb5_duplicate_name (minor_status, name, targ_name); +	if (ret) +	    goto failed; +    } + +    if (lifetime_rec) { +	ret = _gsskrb5_lifetime_left(minor_status,  +				     context, +				     ctx->lifetime, +				     lifetime_rec); +	if (ret) +	    goto failed; +    } + +    if (mech_type) +	*mech_type = GSS_KRB5_MECHANISM; + +    if (ctx_flags) +	*ctx_flags = ctx->flags; + +    if (locally_initiated) +	*locally_initiated = ctx->more_flags & LOCAL; + +    if (open_context) +	*open_context = ctx->more_flags & OPEN; + +    *minor_status = 0; + +    HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); +    return GSS_S_COMPLETE; + +failed: +    if (src_name) +	_gsskrb5_release_name(NULL, src_name); +    if (targ_name) +	_gsskrb5_release_name(NULL, targ_name); + +    HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); +    return ret; +} diff --git a/source4/heimdal/lib/gssapi/krb5/inquire_cred.c b/source4/heimdal/lib/gssapi/krb5/inquire_cred.c new file mode 100644 index 0000000000..42488c718c --- /dev/null +++ b/source4/heimdal/lib/gssapi/krb5/inquire_cred.c @@ -0,0 +1,182 @@ +/* + * Copyright (c) 1997, 2003 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.  + */ + +#include "krb5/gsskrb5_locl.h" + +RCSID("$Id$"); + +OM_uint32 _gsskrb5_inquire_cred +(OM_uint32 * minor_status, + const gss_cred_id_t cred_handle, + gss_name_t * output_name, + OM_uint32 * lifetime, + gss_cred_usage_t * cred_usage, + gss_OID_set * mechanisms +    ) +{ +    krb5_context context; +    gss_cred_id_t aqcred_init = GSS_C_NO_CREDENTIAL; +    gss_cred_id_t aqcred_accept = GSS_C_NO_CREDENTIAL; +    gsskrb5_cred acred = NULL, icred = NULL; +    OM_uint32 ret; + +    *minor_status = 0; + +    if (output_name) +	*output_name = NULL; +    if (mechanisms) +	*mechanisms = GSS_C_NO_OID_SET; + +    GSSAPI_KRB5_INIT (&context); + +    if (cred_handle == GSS_C_NO_CREDENTIAL) { +	ret = _gsskrb5_acquire_cred(minor_status,  +				    GSS_C_NO_NAME, +				    GSS_C_INDEFINITE, +				    GSS_C_NO_OID_SET, +				    GSS_C_ACCEPT, +				    &aqcred_accept, +				    NULL, +				    NULL); +	if (ret == GSS_S_COMPLETE) +	    acred = (gsskrb5_cred)aqcred_accept; + +	ret = _gsskrb5_acquire_cred(minor_status,  +				    GSS_C_NO_NAME, +				    GSS_C_INDEFINITE, +				    GSS_C_NO_OID_SET, +				    GSS_C_INITIATE, +				    &aqcred_init, +				    NULL, +				    NULL); +	if (ret == GSS_S_COMPLETE) +	    icred = (gsskrb5_cred)aqcred_init; + +	if (icred == NULL && acred == NULL) { +	    *minor_status = 0; +	    return GSS_S_NO_CRED; +	} +    } else +	acred = (gsskrb5_cred)cred_handle; + +    if (acred) +	HEIMDAL_MUTEX_lock(&acred->cred_id_mutex); +    if (icred) +	HEIMDAL_MUTEX_lock(&icred->cred_id_mutex); + +    if (output_name != NULL) { +	if (icred && icred->principal != NULL) { +	    gss_name_t name; +	     +	    if (acred && acred->principal) +		name = (gss_name_t)acred->principal; +	    else +		name = (gss_name_t)icred->principal; +		 +            ret = _gsskrb5_duplicate_name(minor_status, name, output_name); +            if (ret) +		goto out; +	} else if (acred && acred->usage == GSS_C_ACCEPT) { +	    krb5_principal princ; +	    *minor_status = krb5_sname_to_principal(context, NULL, +						    NULL, KRB5_NT_SRV_HST,  +						    &princ); +	    if (*minor_status) { +		ret = GSS_S_FAILURE; +		goto out; +	    } +	    *output_name = (gss_name_t)princ; +	} else { +	    krb5_principal princ; +	    *minor_status = krb5_get_default_principal(context, +						       &princ); +	    if (*minor_status) { +		ret = GSS_S_FAILURE; +		goto out; +	    } +	    *output_name = (gss_name_t)princ; +	} +    } +    if (lifetime != NULL) { +	OM_uint32 alife = GSS_C_INDEFINITE, ilife = GSS_C_INDEFINITE; + +	if (acred) alife = acred->lifetime; +	if (icred) ilife = icred->lifetime; + +	ret = _gsskrb5_lifetime_left(minor_status,  +				     context, +				     min(alife,ilife), +				     lifetime); +	if (ret) +	    goto out; +    } +    if (cred_usage != NULL) { +	if (acred && icred) +	    *cred_usage = GSS_C_BOTH; +	else if (acred) +	    *cred_usage = GSS_C_ACCEPT; +	else if (icred) +	    *cred_usage = GSS_C_INITIATE; +	else +	    abort(); +    } + +    if (mechanisms != NULL) { +        ret = gss_create_empty_oid_set(minor_status, mechanisms); +        if (ret) +	    goto out; +	if (acred) +	    ret = gss_add_oid_set_member(minor_status, +					 &acred->mechanisms->elements[0], +					 mechanisms); +	if (ret == GSS_S_COMPLETE && icred) +	    ret = gss_add_oid_set_member(minor_status, +					 &icred->mechanisms->elements[0], +					 mechanisms); +        if (ret) +	    goto out; +    } +    ret = GSS_S_COMPLETE; +out: +    if (acred) +	HEIMDAL_MUTEX_unlock(&acred->cred_id_mutex); +    if (icred) +	HEIMDAL_MUTEX_unlock(&icred->cred_id_mutex); + +    if (aqcred_init != GSS_C_NO_CREDENTIAL) +	ret = _gsskrb5_release_cred(minor_status, &aqcred_init); +    if (aqcred_accept != GSS_C_NO_CREDENTIAL) +	ret = _gsskrb5_release_cred(minor_status, &aqcred_accept); + +    return ret; +} diff --git a/source4/heimdal/lib/gssapi/krb5/inquire_cred_by_mech.c b/source4/heimdal/lib/gssapi/krb5/inquire_cred_by_mech.c new file mode 100644 index 0000000000..de7ec6cd75 --- /dev/null +++ b/source4/heimdal/lib/gssapi/krb5/inquire_cred_by_mech.c @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2003, 2006, 2007 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.  + */ + +#include "krb5/gsskrb5_locl.h" + +RCSID("$Id$"); + +OM_uint32 _gsskrb5_inquire_cred_by_mech ( +    OM_uint32 * minor_status, +	const gss_cred_id_t cred_handle, +	const gss_OID mech_type, +	gss_name_t * name, +	OM_uint32 * initiator_lifetime, +	OM_uint32 * acceptor_lifetime, +	gss_cred_usage_t * cred_usage +    ) +{ +    gss_cred_usage_t usage; +    OM_uint32 maj_stat; +    OM_uint32 lifetime; + +    maj_stat =  +	_gsskrb5_inquire_cred (minor_status, cred_handle, +			       name, &lifetime, &usage, NULL); +    if (maj_stat) +	return maj_stat; + +    if (initiator_lifetime) { +	if (usage == GSS_C_INITIATE || usage == GSS_C_BOTH) +	    *initiator_lifetime = lifetime; +	else +	    *initiator_lifetime = 0; +    } +    +    if (acceptor_lifetime) { +	if (usage == GSS_C_ACCEPT || usage == GSS_C_BOTH) +	    *acceptor_lifetime = lifetime; +	else +	    *acceptor_lifetime = 0; +    } + +    if (cred_usage) +	*cred_usage = usage; + +    return GSS_S_COMPLETE; +} diff --git a/source4/heimdal/lib/gssapi/krb5/inquire_cred_by_oid.c b/source4/heimdal/lib/gssapi/krb5/inquire_cred_by_oid.c new file mode 100644 index 0000000000..2bcc17683b --- /dev/null +++ b/source4/heimdal/lib/gssapi/krb5/inquire_cred_by_oid.c @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2004, PADL Software Pty Ltd. + * 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 PADL Software 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 PADL SOFTWARE 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 PADL SOFTWARE 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. + */ + +#include "krb5/gsskrb5_locl.h" + +RCSID("$Id$"); + +OM_uint32 _gsskrb5_inquire_cred_by_oid +	   (OM_uint32 * minor_status, +	    const gss_cred_id_t cred_handle, +	    const gss_OID desired_object, +	    gss_buffer_set_t *data_set) +{ +    krb5_context context; +    gsskrb5_cred cred = (gsskrb5_cred)cred_handle; +    krb5_error_code ret; +    gss_buffer_desc buffer; +    char *str; + +    GSSAPI_KRB5_INIT (&context); + +    if (gss_oid_equal(desired_object, GSS_KRB5_COPY_CCACHE_X) == 0) { +	*minor_status = EINVAL; +	return GSS_S_FAILURE; +    } + +    HEIMDAL_MUTEX_lock(&cred->cred_id_mutex); + +    if (cred->ccache == NULL) { +	HEIMDAL_MUTEX_unlock(&cred->cred_id_mutex); +	*minor_status = EINVAL; +	return GSS_S_FAILURE; +    } + +    ret = krb5_cc_get_full_name(context, cred->ccache, &str); +    HEIMDAL_MUTEX_unlock(&cred->cred_id_mutex); +    if (ret) { +	*minor_status = ret; +	return GSS_S_FAILURE; +    } + +    buffer.value = str; +    buffer.length = strlen(str); + +    ret = gss_add_buffer_set_member(minor_status, &buffer, data_set); +    if (ret != GSS_S_COMPLETE) +	_gsskrb5_clear_status (); + +    free(str); + +    *minor_status = 0; +    return GSS_S_COMPLETE; +} + diff --git a/source4/heimdal/lib/gssapi/krb5/inquire_mechs_for_name.c b/source4/heimdal/lib/gssapi/krb5/inquire_mechs_for_name.c new file mode 100644 index 0000000000..2384c29656 --- /dev/null +++ b/source4/heimdal/lib/gssapi/krb5/inquire_mechs_for_name.c @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2003 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.  + */ + +#include "krb5/gsskrb5_locl.h" + +RCSID("$Id$"); + +OM_uint32 _gsskrb5_inquire_mechs_for_name ( +            OM_uint32 * minor_status, +            const gss_name_t input_name, +            gss_OID_set * mech_types +           ) +{ +    OM_uint32 ret; + +    ret = gss_create_empty_oid_set(minor_status, mech_types); +    if (ret) +	return ret; + +    ret = gss_add_oid_set_member(minor_status, +				 GSS_KRB5_MECHANISM, +				 mech_types); +    if (ret) +	gss_release_oid_set(NULL, mech_types); + +    return ret; +} diff --git a/source4/heimdal/lib/gssapi/krb5/inquire_names_for_mech.c b/source4/heimdal/lib/gssapi/krb5/inquire_names_for_mech.c new file mode 100644 index 0000000000..c07eb60108 --- /dev/null +++ b/source4/heimdal/lib/gssapi/krb5/inquire_names_for_mech.c @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2003 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.  + */ + +#include "krb5/gsskrb5_locl.h" + +RCSID("$Id$"); + + +static gss_OID *name_list[] = { +    &GSS_C_NT_HOSTBASED_SERVICE, +    &GSS_C_NT_USER_NAME, +    &GSS_KRB5_NT_PRINCIPAL_NAME, +    &GSS_C_NT_EXPORT_NAME, +    NULL +}; + +OM_uint32 _gsskrb5_inquire_names_for_mech ( +            OM_uint32 * minor_status, +            const gss_OID mechanism, +            gss_OID_set * name_types +           ) +{ +    OM_uint32 ret; +    int i; + +    *minor_status = 0; + +    if (gss_oid_equal(mechanism, GSS_KRB5_MECHANISM) == 0 && +	gss_oid_equal(mechanism, GSS_C_NULL_OID) == 0) { +	*name_types = GSS_C_NO_OID_SET; +	return GSS_S_BAD_MECH; +    } + +    ret = gss_create_empty_oid_set(minor_status, name_types); +    if (ret != GSS_S_COMPLETE) +	return ret; +     +    for (i = 0; name_list[i] != NULL; i++) { +	ret = gss_add_oid_set_member(minor_status,  +				     *(name_list[i]), +				     name_types); +	if (ret != GSS_S_COMPLETE) +	    break; +    } + +    if (ret != GSS_S_COMPLETE) +	gss_release_oid_set(NULL, name_types); +	 +    return GSS_S_COMPLETE; +} diff --git a/source4/heimdal/lib/gssapi/krb5/inquire_sec_context_by_oid.c b/source4/heimdal/lib/gssapi/krb5/inquire_sec_context_by_oid.c new file mode 100644 index 0000000000..24b640f4b5 --- /dev/null +++ b/source4/heimdal/lib/gssapi/krb5/inquire_sec_context_by_oid.c @@ -0,0 +1,561 @@ +/* + * Copyright (c) 2004, PADL Software Pty Ltd. + * 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 PADL Software 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 PADL SOFTWARE 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 PADL SOFTWARE 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. + */ + +#include "krb5/gsskrb5_locl.h" + +RCSID("$Id$"); + +static int +oid_prefix_equal(gss_OID oid_enc, gss_OID prefix_enc, unsigned *suffix) +{ +    int ret; +    heim_oid oid; +    heim_oid prefix; +  +    *suffix = 0; + +    ret = der_get_oid(oid_enc->elements, oid_enc->length, +		      &oid, NULL); +    if (ret) { +	return 0; +    } + +    ret = der_get_oid(prefix_enc->elements, prefix_enc->length, +		      &prefix, NULL); +    if (ret) { +	der_free_oid(&oid); +	return 0; +    } + +    ret = 0; + +    if (oid.length - 1 == prefix.length) { +	*suffix = oid.components[oid.length - 1]; +	oid.length--; +	ret = (der_heim_oid_cmp(&oid, &prefix) == 0); +	oid.length++; +    } + +    der_free_oid(&oid); +    der_free_oid(&prefix); + +    return ret; +} + +static OM_uint32 inquire_sec_context_tkt_flags +           (OM_uint32 *minor_status, +            const gsskrb5_ctx context_handle, +            gss_buffer_set_t *data_set) +{ +    OM_uint32 tkt_flags; +    unsigned char buf[4]; +    gss_buffer_desc value; + +    HEIMDAL_MUTEX_lock(&context_handle->ctx_id_mutex); + +    if (context_handle->ticket == NULL) { +	HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); +	_gsskrb5_set_status(EINVAL, "No ticket from which to obtain flags"); +	*minor_status = EINVAL; +	return GSS_S_BAD_MECH; +    } + +    tkt_flags = TicketFlags2int(context_handle->ticket->ticket.flags); +    HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); + +    _gsskrb5_encode_om_uint32(tkt_flags, buf); +    value.length = sizeof(buf); +    value.value = buf; + +    return gss_add_buffer_set_member(minor_status, +				     &value, +				     data_set); +} + +enum keytype { ACCEPTOR_KEY, INITIATOR_KEY, TOKEN_KEY }; + +static OM_uint32 inquire_sec_context_get_subkey +           (OM_uint32 *minor_status, +            const gsskrb5_ctx context_handle, +	    krb5_context context, +	    enum keytype keytype, +            gss_buffer_set_t *data_set) +{ +    krb5_keyblock *key = NULL; +    krb5_storage *sp = NULL; +    krb5_data data; +    OM_uint32 maj_stat = GSS_S_COMPLETE; +    krb5_error_code ret; + +    krb5_data_zero(&data); + +    sp = krb5_storage_emem(); +    if (sp == NULL) { +	_gsskrb5_clear_status(); +	ret = ENOMEM; +	goto out; +    } + +    HEIMDAL_MUTEX_lock(&context_handle->ctx_id_mutex); +    switch(keytype) { +    case ACCEPTOR_KEY: +	ret = _gsskrb5i_get_acceptor_subkey(context_handle, context, &key); +	break; +    case INITIATOR_KEY: +	ret = _gsskrb5i_get_initiator_subkey(context_handle, context, &key); +	break; +    case TOKEN_KEY: +	ret = _gsskrb5i_get_token_key(context_handle, context, &key); +	break; +    default: +	_gsskrb5_set_status(EINVAL, "%d is not a valid subkey type", keytype); +	ret = EINVAL; +	break; +   } +    HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); +    if (ret)  +	goto out; +    if (key == NULL) { +	_gsskrb5_set_status(EINVAL, "have no subkey of type %d", keytype); +	ret = EINVAL; +	goto out; +    } + +    ret = krb5_store_keyblock(sp, *key); +    krb5_free_keyblock (context, key); +    if (ret) +	goto out; + +    ret = krb5_storage_to_data(sp, &data); +    if (ret) +	goto out; + +    { +	gss_buffer_desc value; +	 +	value.length = data.length; +	value.value = data.data; +	 +	maj_stat = gss_add_buffer_set_member(minor_status, +					     &value, +					     data_set); +    } + +out: +    krb5_data_free(&data); +    if (sp) +	krb5_storage_free(sp); +    if (ret) { +	*minor_status = ret; +	maj_stat = GSS_S_FAILURE; +    } +    return maj_stat; +} + +static OM_uint32 inquire_sec_context_authz_data +           (OM_uint32 *minor_status, +            const gsskrb5_ctx context_handle, +	    krb5_context context, +            unsigned ad_type, +            gss_buffer_set_t *data_set) +{ +    krb5_data data; +    gss_buffer_desc ad_data; +    OM_uint32 ret; + +    *minor_status = 0; +    *data_set = GSS_C_NO_BUFFER_SET; + +    HEIMDAL_MUTEX_lock(&context_handle->ctx_id_mutex); +    if (context_handle->ticket == NULL) { +	HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); +	*minor_status = EINVAL; +	_gsskrb5_set_status(EINVAL, "No ticket to obtain authz data from"); +	return GSS_S_NO_CONTEXT; +    } + +    ret = krb5_ticket_get_authorization_data_type(context, +						  context_handle->ticket, +						  ad_type, +						  &data); +    HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); +    if (ret) { +	*minor_status = ret; +	return GSS_S_FAILURE; +    } + +    ad_data.value = data.data; +    ad_data.length = data.length; + +    ret = gss_add_buffer_set_member(minor_status, +				    &ad_data, +				    data_set); + +    krb5_data_free(&data); + +    return ret; +} + +static OM_uint32 inquire_sec_context_has_updated_spnego +           (OM_uint32 *minor_status, +            const gsskrb5_ctx context_handle, +            gss_buffer_set_t *data_set) +{ +    int is_updated = 0; + +    *minor_status = 0; +    *data_set = GSS_C_NO_BUFFER_SET; + +    /* +     * For Windows SPNEGO implementations, both the initiator and the +     * acceptor are assumed to have been updated if a "newer" [CLAR] or +     * different enctype is negotiated for use by the Kerberos GSS-API +     * mechanism. +     */ +    HEIMDAL_MUTEX_lock(&context_handle->ctx_id_mutex); +    _gsskrb5i_is_cfx(context_handle, &is_updated); +    if (is_updated == 0) { +	krb5_keyblock *acceptor_subkey; + +	if (context_handle->more_flags & LOCAL) +	    acceptor_subkey = context_handle->auth_context->remote_subkey; +	else +	    acceptor_subkey = context_handle->auth_context->local_subkey; + +	if (acceptor_subkey != NULL) +	    is_updated = (acceptor_subkey->keytype != +			  context_handle->auth_context->keyblock->keytype); +    } +    HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); + +    return is_updated ? GSS_S_COMPLETE : GSS_S_FAILURE; +} + +/* + * + */ + +static OM_uint32 +export_lucid_sec_context_v1(OM_uint32 *minor_status, +			    gsskrb5_ctx context_handle, +			    krb5_context context, +			    gss_buffer_set_t *data_set) +{ +    krb5_storage *sp = NULL; +    OM_uint32 major_status = GSS_S_COMPLETE; +    krb5_error_code ret; +    krb5_keyblock *key = NULL; +    int32_t number; +    int is_cfx; +    krb5_data data; +     +    *minor_status = 0; + +    HEIMDAL_MUTEX_lock(&context_handle->ctx_id_mutex); + +    _gsskrb5i_is_cfx(context_handle, &is_cfx); + +    sp = krb5_storage_emem(); +    if (sp == NULL) { +	_gsskrb5_clear_status(); +	ret = ENOMEM; +	goto out; +    } + +    ret = krb5_store_int32(sp, 1); +    if (ret) goto out; +    ret = krb5_store_int32(sp, (context_handle->more_flags & LOCAL) ? 1 : 0); +    if (ret) goto out; +    ret = krb5_store_int32(sp, context_handle->lifetime); +    if (ret) goto out; +    krb5_auth_con_getlocalseqnumber (context, +				     context_handle->auth_context, +				     &number); +    ret = krb5_store_uint32(sp, (uint32_t)0); /* store top half as zero */ +    if (ret) goto out; +    ret = krb5_store_uint32(sp, (uint32_t)number); +    if (ret) goto out; +    krb5_auth_getremoteseqnumber (context, +				  context_handle->auth_context, +				  &number); +    ret = krb5_store_uint32(sp, (uint32_t)0); /* store top half as zero */ +    if (ret) goto out; +    ret = krb5_store_uint32(sp, (uint32_t)number); +    if (ret) goto out; +    ret = krb5_store_int32(sp, (is_cfx) ? 1 : 0); +    if (ret) goto out; + +    ret = _gsskrb5i_get_token_key(context_handle, context, &key); +    if (ret) goto out; + +    if (is_cfx == 0) { +	int sign_alg, seal_alg; + +	switch (key->keytype) { +	case ETYPE_DES_CBC_CRC: +	case ETYPE_DES_CBC_MD4: +	case ETYPE_DES_CBC_MD5: +	    sign_alg = 0; +	    seal_alg = 0; +	    break; +	case ETYPE_DES3_CBC_MD5: +	case ETYPE_DES3_CBC_SHA1: +	    sign_alg = 4; +	    seal_alg = 2; +	    break; +	case ETYPE_ARCFOUR_HMAC_MD5: +	case ETYPE_ARCFOUR_HMAC_MD5_56: +	    sign_alg = 17; +	    seal_alg = 16; +	    break; +	default: +	    sign_alg = -1; +	    seal_alg = -1; +	    break; +	} +	ret = krb5_store_int32(sp, sign_alg); +	if (ret) goto out; +	ret = krb5_store_int32(sp, seal_alg); +	if (ret) goto out; +	/* ctx_key */ +	ret = krb5_store_keyblock(sp, *key); +	if (ret) goto out; +    } else { +	int subkey_p = (context_handle->more_flags & ACCEPTOR_SUBKEY) ? 1 : 0; + +	/* have_acceptor_subkey */ +	ret = krb5_store_int32(sp, subkey_p); +	if (ret) goto out; +	/* ctx_key */ +	ret = krb5_store_keyblock(sp, *key); +	if (ret) goto out; +	/* acceptor_subkey */ +	if (subkey_p) { +	    ret = krb5_store_keyblock(sp, *key); +	    if (ret) goto out; +	} +    } +    ret = krb5_storage_to_data(sp, &data); +    if (ret) goto out; + +    { +	gss_buffer_desc ad_data; + +	ad_data.value = data.data; +	ad_data.length = data.length; + +	ret = gss_add_buffer_set_member(minor_status, &ad_data, data_set); +	krb5_data_free(&data); +	if (ret) +	    goto out; +    } + +out: +    if (key) +	krb5_free_keyblock (context, key); +    if (sp) +	krb5_storage_free(sp); +    if (ret) { +	*minor_status = ret; +	major_status = GSS_S_FAILURE; +    } +    HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); +    return major_status; +} + +static OM_uint32 +get_authtime(OM_uint32 *minor_status, +	     gsskrb5_ctx ctx,  +	     gss_buffer_set_t *data_set) + +{ +    gss_buffer_desc value; +    unsigned char buf[4]; +    OM_uint32 authtime; + +    HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex); +    if (ctx->ticket == NULL) { +	HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); +	_gsskrb5_set_status(EINVAL, "No ticket to obtain auth time from"); +	*minor_status = EINVAL; +	return GSS_S_FAILURE; +    } +     +    authtime = ctx->ticket->ticket.authtime; +     +    HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); + +    _gsskrb5_encode_om_uint32(authtime, buf); +    value.length = sizeof(buf); +    value.value = buf; + +    return gss_add_buffer_set_member(minor_status, +				     &value, +				     data_set); +} + + +static OM_uint32  +get_service_keyblock +        (OM_uint32 *minor_status, +	 gsskrb5_ctx ctx,  +	 gss_buffer_set_t *data_set) +{ +    krb5_storage *sp = NULL; +    krb5_data data; +    OM_uint32 maj_stat = GSS_S_COMPLETE; +    krb5_error_code ret = EINVAL; +     +    sp = krb5_storage_emem(); +    if (sp == NULL) { +	_gsskrb5_clear_status(); +	*minor_status = ENOMEM; +	return GSS_S_FAILURE; +    } + +    HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex); +    if (ctx->service_keyblock == NULL) { +	HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); +	_gsskrb5_set_status(EINVAL, "No service keyblock on gssapi context"); +	*minor_status = EINVAL; +	return GSS_S_FAILURE;  +    } + +    krb5_data_zero(&data); + +    ret = krb5_store_keyblock(sp, *ctx->service_keyblock); + +    HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); + +    if (ret) +	goto out; + +    ret = krb5_storage_to_data(sp, &data); +    if (ret) +	goto out; + +    { +	gss_buffer_desc value; +	 +	value.length = data.length; +	value.value = data.data; +	 +	maj_stat = gss_add_buffer_set_member(minor_status, +					     &value, +					     data_set); +    } + +out: +    krb5_data_free(&data); +    if (sp) +	krb5_storage_free(sp); +    if (ret) { +	*minor_status = ret; +	maj_stat = GSS_S_FAILURE; +    } +    return maj_stat; +} +/* + * + */ + +OM_uint32 _gsskrb5_inquire_sec_context_by_oid +           (OM_uint32 *minor_status, +            const gss_ctx_id_t context_handle, +            const gss_OID desired_object, +            gss_buffer_set_t *data_set) +{ +    krb5_context context; +    const gsskrb5_ctx ctx = (const gsskrb5_ctx) context_handle; +    unsigned suffix; + +    if (ctx == NULL) { +	*minor_status = EINVAL; +	return GSS_S_NO_CONTEXT; +    } + +    GSSAPI_KRB5_INIT (&context); + +    if (gss_oid_equal(desired_object, GSS_KRB5_GET_TKT_FLAGS_X)) { +	return inquire_sec_context_tkt_flags(minor_status, +					     ctx, +					     data_set); +    } else if (gss_oid_equal(desired_object, GSS_C_PEER_HAS_UPDATED_SPNEGO)) { +	return inquire_sec_context_has_updated_spnego(minor_status, +						      ctx, +						      data_set); +    } else if (gss_oid_equal(desired_object, GSS_KRB5_GET_SUBKEY_X)) { +	return inquire_sec_context_get_subkey(minor_status, +					      ctx, +					      context, +					      TOKEN_KEY, +					      data_set); +    } else if (gss_oid_equal(desired_object, GSS_KRB5_GET_INITIATOR_SUBKEY_X)) { +	return inquire_sec_context_get_subkey(minor_status, +					      ctx, +					      context, +					      INITIATOR_KEY, +					      data_set); +    } else if (gss_oid_equal(desired_object, GSS_KRB5_GET_ACCEPTOR_SUBKEY_X)) { +	return inquire_sec_context_get_subkey(minor_status, +					      ctx, +					      context, +					      ACCEPTOR_KEY, +					      data_set); +    } else if (gss_oid_equal(desired_object, GSS_KRB5_GET_AUTHTIME_X)) { +	return get_authtime(minor_status, ctx, data_set); +    } else if (oid_prefix_equal(desired_object, +				GSS_KRB5_EXTRACT_AUTHZ_DATA_FROM_SEC_CONTEXT_X, +				&suffix)) { +	return inquire_sec_context_authz_data(minor_status, +					      ctx, +					      context, +					      suffix, +					      data_set); +    } else if (oid_prefix_equal(desired_object, +				GSS_KRB5_EXPORT_LUCID_CONTEXT_X, +				&suffix)) { +	if (suffix == 1) +	    return export_lucid_sec_context_v1(minor_status, +					       ctx, +					       context, +					       data_set); +	*minor_status = 0; +	return GSS_S_FAILURE; +    } else if (gss_oid_equal(desired_object, GSS_KRB5_GET_SERVICE_KEYBLOCK_X)) { +	return get_service_keyblock(minor_status, ctx, data_set); +    } else { +	*minor_status = 0; +	return GSS_S_FAILURE; +    } +} + diff --git a/source4/heimdal/lib/gssapi/krb5/prf.c b/source4/heimdal/lib/gssapi/krb5/prf.c new file mode 100644 index 0000000000..a7372d87cc --- /dev/null +++ b/source4/heimdal/lib/gssapi/krb5/prf.c @@ -0,0 +1,143 @@ +/* + * Copyright (c) 2007 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.  + */ + +#include "krb5/gsskrb5_locl.h" + +RCSID("$Id$"); + +OM_uint32 +_gsskrb5_pseudo_random(OM_uint32 *minor_status, +		       gss_ctx_id_t context_handle, +		       int prf_key, +		       const gss_buffer_t prf_in, +		       ssize_t desired_output_len, +		       gss_buffer_t prf_out) +{ +    gsskrb5_ctx ctx = (gsskrb5_ctx)context_handle; +    krb5_context context; +    krb5_error_code ret; +    krb5_crypto crypto; +    krb5_data input, output; +    uint32_t num; +    unsigned char *p; +    krb5_keyblock *key = NULL; + +    if (ctx == NULL) { +	*minor_status = 0; +	return GSS_S_NO_CONTEXT; +    } + +    if (desired_output_len <= 0) { +	*minor_status = 0; +	return GSS_S_FAILURE; +    } + +    GSSAPI_KRB5_INIT (&context); + +    switch(prf_key) { +    case GSS_C_PRF_KEY_FULL: +	_gsskrb5i_get_acceptor_subkey(ctx, context, &key); +	break; +    case GSS_C_PRF_KEY_PARTIAL: +	_gsskrb5i_get_initiator_subkey(ctx, context, &key); +	break; +    default: +	_gsskrb5_set_status(EINVAL, "unknown kerberos prf_key"); +	*minor_status = EINVAL; +	return GSS_S_FAILURE; +    } + +    if (key == NULL) { +	_gsskrb5_set_status(EINVAL, "no prf_key found"); +	*minor_status = EINVAL; +	return GSS_S_FAILURE; +    } + +    ret = krb5_crypto_init(context, key, 0, &crypto); +    krb5_free_keyblock (context, key); +    if (ret) { +	*minor_status = ret; +	return GSS_S_FAILURE; +    } + +    prf_out->value = malloc(desired_output_len); +    if (prf_out->value == NULL) { +	_gsskrb5_set_status(GSS_KRB5_S_KG_INPUT_TOO_LONG, "Out of memory"); +	*minor_status = GSS_KRB5_S_KG_INPUT_TOO_LONG; +	krb5_crypto_destroy(context, crypto); +	return GSS_S_FAILURE; +    } +    prf_out->length = desired_output_len; + +    HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex); + +    input.length = prf_in->length + 4; +    input.data = malloc(prf_in->length + 4); +    if (input.data == NULL) { +	OM_uint32 junk; +	_gsskrb5_set_status(GSS_KRB5_S_KG_INPUT_TOO_LONG, "Out of memory"); +	*minor_status = GSS_KRB5_S_KG_INPUT_TOO_LONG; +	gss_release_buffer(&junk, prf_out); +	krb5_crypto_destroy(context, crypto); +	HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); +	return GSS_S_FAILURE; +    } +    memcpy(((unsigned char *)input.data) + 4, prf_in->value, prf_in->length); + +    num = 0; +    p = prf_out->value; +    while(desired_output_len > 0) { +	_gsskrb5_encode_om_uint32(num, input.data); +	ret = krb5_crypto_prf(context, crypto, &input, &output); +	if (ret) { +	    OM_uint32 junk; +	    *minor_status = ret; +	    free(input.data); +	    gss_release_buffer(&junk, prf_out); +	    krb5_crypto_destroy(context, crypto); +	    HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); +	    return GSS_S_FAILURE; +	} +	memcpy(p, output.data, min(desired_output_len, output.length)); +	p += output.length; +	desired_output_len -= output.length; +	krb5_data_free(&output); +	num++; +    } + +    krb5_crypto_destroy(context, crypto); + +    HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); + +    return GSS_S_COMPLETE; +} diff --git a/source4/heimdal/lib/gssapi/krb5/process_context_token.c b/source4/heimdal/lib/gssapi/krb5/process_context_token.c new file mode 100644 index 0000000000..80d96f5ce4 --- /dev/null +++ b/source4/heimdal/lib/gssapi/krb5/process_context_token.c @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2003 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.  + */ + +#include "krb5/gsskrb5_locl.h" + +RCSID("$Id$"); + +OM_uint32 _gsskrb5_process_context_token ( +	OM_uint32          *minor_status, +	const gss_ctx_id_t context_handle, +	const gss_buffer_t token_buffer +    ) +{ +    krb5_context context; +    OM_uint32 ret = GSS_S_FAILURE; +    gss_buffer_desc empty_buffer; +    gss_qop_t qop_state; + +    empty_buffer.length = 0; +    empty_buffer.value = NULL; + +    GSSAPI_KRB5_INIT (&context); + +    qop_state = GSS_C_QOP_DEFAULT; + +    ret = _gsskrb5_verify_mic_internal(minor_status,  +				       (gsskrb5_ctx)context_handle, +				       context, +				       token_buffer, &empty_buffer, +				       GSS_C_QOP_DEFAULT, "\x01\x02"); + +    if (ret == GSS_S_COMPLETE) +	ret = _gsskrb5_delete_sec_context(minor_status, +					  rk_UNCONST(&context_handle), +					  GSS_C_NO_BUFFER); +    if (ret == GSS_S_COMPLETE) +	*minor_status = 0; + +    return ret; +} diff --git a/source4/heimdal/lib/gssapi/krb5/release_buffer.c b/source4/heimdal/lib/gssapi/krb5/release_buffer.c new file mode 100644 index 0000000000..e2f1f4ec14 --- /dev/null +++ b/source4/heimdal/lib/gssapi/krb5/release_buffer.c @@ -0,0 +1,48 @@ +/* + * Copyright (c) 1997 - 2000, 2003 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.  + */ + +#include "krb5/gsskrb5_locl.h" + +RCSID("$Id$"); + +OM_uint32 _gsskrb5_release_buffer +           (OM_uint32 * minor_status, +            gss_buffer_t buffer +           ) +{ +  *minor_status = 0; +  free (buffer->value); +  buffer->value  = NULL; +  buffer->length = 0; +  return GSS_S_COMPLETE; +} diff --git a/source4/heimdal/lib/gssapi/krb5/release_cred.c b/source4/heimdal/lib/gssapi/krb5/release_cred.c new file mode 100644 index 0000000000..1becd1c6b1 --- /dev/null +++ b/source4/heimdal/lib/gssapi/krb5/release_cred.c @@ -0,0 +1,80 @@ +/* + * Copyright (c) 1997-2003 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.  + */ + +#include "krb5/gsskrb5_locl.h" + +RCSID("$Id$"); + +OM_uint32 _gsskrb5_release_cred +           (OM_uint32 * minor_status, +            gss_cred_id_t * cred_handle +           ) +{ +    krb5_context context; +    gsskrb5_cred cred; +    OM_uint32 junk; + +    *minor_status = 0; + +    if (*cred_handle == NULL)  +        return GSS_S_COMPLETE; + +    cred = (gsskrb5_cred)*cred_handle; +    *cred_handle = GSS_C_NO_CREDENTIAL; + +    GSSAPI_KRB5_INIT (&context); + +    HEIMDAL_MUTEX_lock(&cred->cred_id_mutex); + +    if (cred->principal != NULL) +        krb5_free_principal(context, cred->principal); +    if (cred->keytab != NULL) +	krb5_kt_close(context, cred->keytab); +    if (cred->ccache != NULL) { +	const krb5_cc_ops *ops; +	ops = krb5_cc_get_ops(context, cred->ccache); +	if (cred->cred_flags & GSS_CF_DESTROY_CRED_ON_RELEASE) +	    krb5_cc_destroy(context, cred->ccache); +	else  +	    krb5_cc_close(context, cred->ccache); +    } +    gss_release_oid_set(&junk, &cred->mechanisms); +    if (cred->enctypes) +	free(cred->enctypes); +    HEIMDAL_MUTEX_unlock(&cred->cred_id_mutex); +    HEIMDAL_MUTEX_destroy(&cred->cred_id_mutex); +    memset(cred, 0, sizeof(*cred)); +    free(cred); +    return GSS_S_COMPLETE; +} + diff --git a/source4/heimdal/lib/gssapi/krb5/release_name.c b/source4/heimdal/lib/gssapi/krb5/release_name.c new file mode 100644 index 0000000000..e2ff9dde31 --- /dev/null +++ b/source4/heimdal/lib/gssapi/krb5/release_name.c @@ -0,0 +1,55 @@ +/* + * Copyright (c) 1997 - 2003 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.  + */ + +#include "krb5/gsskrb5_locl.h" + +RCSID("$Id$"); + +OM_uint32 _gsskrb5_release_name +           (OM_uint32 * minor_status, +            gss_name_t * input_name +           ) +{ +    krb5_context context; +    krb5_principal name = (krb5_principal)*input_name; + +    *minor_status = 0; + +    GSSAPI_KRB5_INIT (&context); + +    *input_name = GSS_C_NO_NAME; + +    krb5_free_principal(context, name); + +    return GSS_S_COMPLETE; +} diff --git a/source4/heimdal/lib/gssapi/krb5/sequence.c b/source4/heimdal/lib/gssapi/krb5/sequence.c new file mode 100644 index 0000000000..b40fe52578 --- /dev/null +++ b/source4/heimdal/lib/gssapi/krb5/sequence.c @@ -0,0 +1,294 @@ +/* + * Copyright (c) 2003 - 2006 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.  + */ + +#include "krb5/gsskrb5_locl.h" + +RCSID("$Id$"); + +#define DEFAULT_JITTER_WINDOW 20 + +struct gss_msg_order { +    OM_uint32 flags; +    OM_uint32 start; +    OM_uint32 length; +    OM_uint32 jitter_window; +    OM_uint32 first_seq; +    OM_uint32 elem[1]; +}; + + +/* + * + */ + +static OM_uint32 +msg_order_alloc(OM_uint32 *minor_status, +		struct gss_msg_order **o, +		OM_uint32 jitter_window) +{ +    size_t len; +     +    len = jitter_window * sizeof((*o)->elem[0]); +    len += sizeof(**o); +    len -= sizeof((*o)->elem[0]); +     +    *o = calloc(1, len); +    if (*o == NULL) { +	*minor_status = ENOMEM; +	return GSS_S_FAILURE; +    }	 +     +    *minor_status = 0; +    return GSS_S_COMPLETE;     +} + +/* + * + */ + +OM_uint32 +_gssapi_msg_order_create(OM_uint32 *minor_status, +			 struct gss_msg_order **o,  +			 OM_uint32 flags,  +			 OM_uint32 seq_num,  +			 OM_uint32 jitter_window, +			 int use_64) +{ +    OM_uint32 ret; + +    if (jitter_window == 0) +	jitter_window = DEFAULT_JITTER_WINDOW; + +    ret = msg_order_alloc(minor_status, o, jitter_window); +    if(ret != GSS_S_COMPLETE) +        return ret; + +    (*o)->flags = flags; +    (*o)->length = 0; +    (*o)->first_seq = seq_num; +    (*o)->jitter_window = jitter_window; +    (*o)->elem[0] = seq_num - 1; + +    *minor_status = 0; +    return GSS_S_COMPLETE; +} + +OM_uint32 +_gssapi_msg_order_destroy(struct gss_msg_order **m) +{ +    free(*m); +    *m = NULL; +    return GSS_S_COMPLETE; +} + +static void +elem_set(struct gss_msg_order *o, unsigned int slot, OM_uint32 val) +{ +    o->elem[slot % o->jitter_window] = val; +} + +static void +elem_insert(struct gss_msg_order *o,  +	    unsigned int after_slot, +	    OM_uint32 seq_num) +{ +    assert(o->jitter_window > after_slot); + +    if (o->length > after_slot) +	memmove(&o->elem[after_slot + 1], &o->elem[after_slot], +		(o->length - after_slot - 1) * sizeof(o->elem[0])); + +    elem_set(o, after_slot, seq_num); + +    if (o->length < o->jitter_window) +	o->length++; +} + +/* rule 1: expected sequence number */ +/* rule 2: > expected sequence number */ +/* rule 3: seqnum < seqnum(first) */ +/* rule 4+5: seqnum in [seqnum(first),seqnum(last)]  */ + +OM_uint32 +_gssapi_msg_order_check(struct gss_msg_order *o, OM_uint32 seq_num) +{ +    OM_uint32 r; +    int i; + +    if (o == NULL) +	return GSS_S_COMPLETE; + +    if ((o->flags & (GSS_C_REPLAY_FLAG|GSS_C_SEQUENCE_FLAG)) == 0) +	return GSS_S_COMPLETE; + +    /* check if the packet is the next in order */ +    if (o->elem[0] == seq_num - 1) { +	elem_insert(o, 0, seq_num); +	return GSS_S_COMPLETE; +    } + +    r = (o->flags & (GSS_C_REPLAY_FLAG|GSS_C_SEQUENCE_FLAG))==GSS_C_REPLAY_FLAG; + +    /* sequence number larger then largest sequence number  +     * or smaller then the first sequence number */ +    if (seq_num > o->elem[0] +	|| seq_num < o->first_seq +	|| o->length == 0)  +    { +	elem_insert(o, 0, seq_num); +	if (r) { +	    return GSS_S_COMPLETE; +	} else { +	    return GSS_S_GAP_TOKEN; +	} +    } + +    assert(o->length > 0); + +    /* sequence number smaller the first sequence number */ +    if (seq_num < o->elem[o->length - 1]) { +	if (r) +	    return(GSS_S_OLD_TOKEN); +	else +	    return(GSS_S_UNSEQ_TOKEN); +    } + +    if (seq_num == o->elem[o->length - 1]) { +	return GSS_S_DUPLICATE_TOKEN; +    } + +    for (i = 0; i < o->length - 1; i++) { +	if (o->elem[i] == seq_num) +	    return GSS_S_DUPLICATE_TOKEN; +	if (o->elem[i + 1] < seq_num && o->elem[i] < seq_num) { +	    elem_insert(o, i, seq_num); +	    if (r) +		return GSS_S_COMPLETE; +	    else +		return GSS_S_UNSEQ_TOKEN; +	} +    } + +    return GSS_S_FAILURE; +} + +OM_uint32 +_gssapi_msg_order_f(OM_uint32 flags) +{ +    return flags & (GSS_C_SEQUENCE_FLAG|GSS_C_REPLAY_FLAG); +} + +/* + * Translate `o` into inter-process format and export in to `sp'. + */ + +krb5_error_code +_gssapi_msg_order_export(krb5_storage *sp, struct gss_msg_order *o) +{ +    krb5_error_code kret; +    OM_uint32 i; +     +    kret = krb5_store_int32(sp, o->flags); +    if (kret) +        return kret; +    kret = krb5_store_int32(sp, o->start); +    if (kret) +        return kret; +    kret = krb5_store_int32(sp, o->length); +    if (kret) +        return kret; +    kret = krb5_store_int32(sp, o->jitter_window); +    if (kret) +        return kret; +    kret = krb5_store_int32(sp, o->first_seq); +    if (kret) +        return kret; +     +    for (i = 0; i < o->jitter_window; i++) { +        kret = krb5_store_int32(sp, o->elem[i]); +	if (kret) +	    return kret; +    } +     +    return 0; +} + +OM_uint32 +_gssapi_msg_order_import(OM_uint32 *minor_status, +			 krb5_storage *sp,  +			 struct gss_msg_order **o) +{ +    OM_uint32 ret; +    krb5_error_code kret; +    int32_t i, flags, start, length, jitter_window, first_seq; +     +    kret = krb5_ret_int32(sp, &flags); +    if (kret) +	goto failed; +    kret = krb5_ret_int32(sp, &start); +    if (kret) +	goto failed; +    kret = krb5_ret_int32(sp, &length); +    if (kret) +	goto failed; +    kret = krb5_ret_int32(sp, &jitter_window); +    if (kret) +	goto failed; +    kret = krb5_ret_int32(sp, &first_seq); +    if (kret) +	goto failed; +     +    ret = msg_order_alloc(minor_status, o, jitter_window); +    if (ret != GSS_S_COMPLETE) +        return ret; +     +    (*o)->flags = flags; +    (*o)->start = start; +    (*o)->length = length; +    (*o)->jitter_window = jitter_window; +    (*o)->first_seq = first_seq; +     +    for( i = 0; i < jitter_window; i++ ) { +        kret = krb5_ret_int32(sp, (int32_t*)&((*o)->elem[i])); +	if (kret) +	    goto failed; +    } + +    *minor_status = 0; +    return GSS_S_COMPLETE; + +failed: +    _gssapi_msg_order_destroy(o); +    *minor_status = kret; +    return GSS_S_FAILURE; +} diff --git a/source4/heimdal/lib/gssapi/krb5/set_cred_option.c b/source4/heimdal/lib/gssapi/krb5/set_cred_option.c new file mode 100644 index 0000000000..e47e6fdb6c --- /dev/null +++ b/source4/heimdal/lib/gssapi/krb5/set_cred_option.c @@ -0,0 +1,264 @@ +/* + * Copyright (c) 2004, PADL Software Pty Ltd. + * 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 PADL Software 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 PADL SOFTWARE 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 PADL SOFTWARE 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. + */ + +#include "krb5/gsskrb5_locl.h" + +RCSID("$Id$"); + +/* 1.2.752.43.13.17 */ +static gss_OID_desc gss_krb5_cred_no_ci_flags_x_oid_desc = +{6, rk_UNCONST("\x2a\x85\x70\x2b\x0d\x11")}; + +gss_OID GSS_KRB5_CRED_NO_CI_FLAGS_X = &gss_krb5_cred_no_ci_flags_x_oid_desc; + +/* 1.2.752.43.13.18 */ +static gss_OID_desc gss_krb5_import_cred_x_oid_desc = +{6, rk_UNCONST("\x2a\x85\x70\x2b\x0d\x12")}; + +gss_OID GSS_KRB5_IMPORT_CRED_X = &gss_krb5_import_cred_x_oid_desc; + + + +static OM_uint32 +import_cred(OM_uint32 *minor_status, +	    krb5_context context, +            gss_cred_id_t *cred_handle, +            const gss_buffer_t value) +{ +    OM_uint32 major_stat; +    krb5_error_code ret; +    krb5_principal keytab_principal = NULL; +    krb5_keytab keytab = NULL; +    krb5_storage *sp = NULL; +    krb5_ccache id = NULL; +    char *str; + +    if (cred_handle == NULL || *cred_handle != GSS_C_NO_CREDENTIAL) { +	*minor_status = 0; +	return GSS_S_FAILURE; +    } + +    sp = krb5_storage_from_mem(value->value, value->length); +    if (sp == NULL) { +	*minor_status = 0; +	return GSS_S_FAILURE; +    } + +    /* credential cache name */ +    ret = krb5_ret_string(sp, &str); +    if (ret) { +	*minor_status = ret; +	major_stat =  GSS_S_FAILURE; +	goto out; +    } +    if (str[0]) { +	ret = krb5_cc_resolve(context, str, &id); +	if (ret) { +	    *minor_status = ret; +	    major_stat =  GSS_S_FAILURE; +	    goto out; +	} +    } +    free(str); +    str = NULL; + +    /* keytab principal name */ +    ret = krb5_ret_string(sp, &str); +    if (ret == 0 && str[0]) +	ret = krb5_parse_name(context, str, &keytab_principal); +    if (ret) { +	*minor_status = ret; +	major_stat = GSS_S_FAILURE; +	goto out; +    } +    free(str); +    str = NULL; + +    /* keytab principal */ +    ret = krb5_ret_string(sp, &str); +    if (ret) { +	*minor_status = ret; +	major_stat =  GSS_S_FAILURE; +	goto out; +    } +    if (str[0]) { +	ret = krb5_kt_resolve(context, str, &keytab); +	if (ret) { +	    *minor_status = ret; +	    major_stat =  GSS_S_FAILURE; +	    goto out; +	} +    } +    free(str); +    str = NULL; + +    major_stat = _gsskrb5_import_cred(minor_status, id, keytab_principal, +				      keytab, cred_handle); +out: +    if (id) +	krb5_cc_close(context, id); +    if (keytab_principal) +	krb5_free_principal(context, keytab_principal); +    if (keytab) +	krb5_kt_close(context, keytab); +    if (str) +	free(str); +    if (sp) +	krb5_storage_free(sp); + +    return major_stat; +} + + +static OM_uint32 +allowed_enctypes(OM_uint32 *minor_status, +		 krb5_context context, +		 gss_cred_id_t *cred_handle, +		 const gss_buffer_t value) +{ +    OM_uint32 major_stat; +    krb5_error_code ret; +    size_t len, i; +    krb5_enctype *enctypes = NULL; +    krb5_storage *sp = NULL; +    gsskrb5_cred cred; + +    if (cred_handle == NULL || *cred_handle == GSS_C_NO_CREDENTIAL) { +	*minor_status = 0; +	return GSS_S_FAILURE; +    } + +    cred = (gsskrb5_cred)*cred_handle; + +    if ((value->length % 4) != 0) { +	*minor_status = 0; +	major_stat = GSS_S_FAILURE; +	goto out; +    } + +    len = value->length / 4; +    enctypes = malloc((len + 1) * 4); +    if (enctypes == NULL) { +	*minor_status = ENOMEM; +	major_stat = GSS_S_FAILURE; +	goto out; +    } + +    sp = krb5_storage_from_mem(value->value, value->length); +    if (sp == NULL) { +	*minor_status = ENOMEM; +	major_stat = GSS_S_FAILURE; +	goto out; +    } + +    for (i = 0; i < len; i++) { +	uint32_t e; + +	ret = krb5_ret_uint32(sp, &e); +	if (ret) { +	    *minor_status = ret; +	    major_stat =  GSS_S_FAILURE; +	    goto out; +	} +	enctypes[i] = e; +    } +    enctypes[i] = 0; + +    if (cred->enctypes) +	free(cred->enctypes); +    cred->enctypes = enctypes; + +    krb5_storage_free(sp); + +    return GSS_S_COMPLETE; + +out: +    if (sp) +	krb5_storage_free(sp); +    if (enctypes) +	free(enctypes); + +    return major_stat; +} + +static OM_uint32 +no_ci_flags(OM_uint32 *minor_status, +	    krb5_context context, +	    gss_cred_id_t *cred_handle, +	    const gss_buffer_t value) +{ +    gsskrb5_cred cred; + +    if (cred_handle == NULL || *cred_handle == GSS_C_NO_CREDENTIAL) { +	*minor_status = 0; +	return GSS_S_FAILURE; +    } + +    cred = (gsskrb5_cred)*cred_handle; +    cred->cred_flags |= GSS_CF_NO_CI_FLAGS; +	 +    *minor_status = 0; +    return GSS_S_COMPLETE; + +} + + +OM_uint32 +_gsskrb5_set_cred_option +           (OM_uint32 *minor_status, +            gss_cred_id_t *cred_handle, +            const gss_OID desired_object, +            const gss_buffer_t value) +{ +    krb5_context context; + +    GSSAPI_KRB5_INIT (&context); + +    if (value == GSS_C_NO_BUFFER) { +	*minor_status = EINVAL; +	return GSS_S_FAILURE; +    } + +    if (gss_oid_equal(desired_object, GSS_KRB5_IMPORT_CRED_X)) +	return import_cred(minor_status, context, cred_handle, value); + +    if (gss_oid_equal(desired_object, GSS_KRB5_SET_ALLOWABLE_ENCTYPES_X)) +	return allowed_enctypes(minor_status, context, cred_handle, value); + +    if (gss_oid_equal(desired_object, GSS_KRB5_CRED_NO_CI_FLAGS_X)) { +	return no_ci_flags(minor_status, context, cred_handle, value); +    } +	 + +    *minor_status = EINVAL; +    return GSS_S_FAILURE; +} diff --git a/source4/heimdal/lib/gssapi/krb5/set_sec_context_option.c b/source4/heimdal/lib/gssapi/krb5/set_sec_context_option.c new file mode 100644 index 0000000000..f28d2397be --- /dev/null +++ b/source4/heimdal/lib/gssapi/krb5/set_sec_context_option.c @@ -0,0 +1,251 @@ +/* + * Copyright (c) 2004, PADL Software Pty Ltd. + * 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 PADL Software 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 PADL SOFTWARE 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 PADL SOFTWARE 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. + */ + +/* + *  glue routine for _gsskrb5_inquire_sec_context_by_oid + */ + +#include "krb5/gsskrb5_locl.h" + +RCSID("$Id$"); + +static OM_uint32 +get_bool(OM_uint32 *minor_status, +	 const gss_buffer_t value, +	 int *flag) +{ +    if (value->value == NULL || value->length != 1) { +	*minor_status = EINVAL; +	return GSS_S_FAILURE; +    } +    *flag = *((const char *)value->value) != 0; +    return GSS_S_COMPLETE; +} + +static OM_uint32 +get_string(OM_uint32 *minor_status, +	   const gss_buffer_t value, +	   char **str) +{ +    if (value == NULL || value->length == 0) { +	*str = NULL; +    } else { +	*str = malloc(value->length + 1); +	if (*str == NULL) { +	    *minor_status = 0; +	    return GSS_S_UNAVAILABLE; +	} +	memcpy(*str, value->value, value->length); +	(*str)[value->length] = '\0'; +    } +    return GSS_S_COMPLETE; +} + +static OM_uint32 +get_int32(OM_uint32 *minor_status, +	  const gss_buffer_t value, +	  OM_uint32 *ret) +{ +    *minor_status = 0; +    if (value == NULL || value->length == 0) +	*ret = 0; +    else if (value->length == sizeof(*ret)) +	memcpy(ret, value->value, sizeof(*ret)); +    else +	return GSS_S_UNAVAILABLE; + +    return GSS_S_COMPLETE; +} + +static OM_uint32 +set_int32(OM_uint32 *minor_status, +	  const gss_buffer_t value, +	  OM_uint32 set) +{ +    *minor_status = 0; +    if (value->length == sizeof(set)) +	memcpy(value->value, &set, sizeof(set)); +    else +	return GSS_S_UNAVAILABLE; + +    return GSS_S_COMPLETE; +} + +OM_uint32 +_gsskrb5_set_sec_context_option +           (OM_uint32 *minor_status, +            gss_ctx_id_t *context_handle, +            const gss_OID desired_object, +            const gss_buffer_t value) +{ +    krb5_context context; +    OM_uint32 maj_stat; + +    GSSAPI_KRB5_INIT (&context); + +    if (value == GSS_C_NO_BUFFER) { +	*minor_status = EINVAL; +	return GSS_S_FAILURE; +    } + +    if (gss_oid_equal(desired_object, GSS_KRB5_COMPAT_DES3_MIC_X)) { +	gsskrb5_ctx ctx; +	int flag; + +	if (*context_handle == GSS_C_NO_CONTEXT) { +	    *minor_status = EINVAL; +	    return GSS_S_NO_CONTEXT; +	} + +	maj_stat = get_bool(minor_status, value, &flag); +	if (maj_stat != GSS_S_COMPLETE) +	    return maj_stat; + +	ctx = (gsskrb5_ctx)*context_handle; +	HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex); +	if (flag) +	    ctx->more_flags |= COMPAT_OLD_DES3; +	else +	    ctx->more_flags &= ~COMPAT_OLD_DES3; +	ctx->more_flags |= COMPAT_OLD_DES3_SELECTED; +	HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); +	return GSS_S_COMPLETE; +    } else if (gss_oid_equal(desired_object, GSS_KRB5_SET_DNS_CANONICALIZE_X)) { +	int flag; + +	maj_stat = get_bool(minor_status, value, &flag); +	if (maj_stat != GSS_S_COMPLETE) +	    return maj_stat; + +	krb5_set_dns_canonicalize_hostname(context, flag); +	return GSS_S_COMPLETE; + +    } else if (gss_oid_equal(desired_object, GSS_KRB5_REGISTER_ACCEPTOR_IDENTITY_X)) { +	char *str; + +	maj_stat = get_string(minor_status, value, &str); +	if (maj_stat != GSS_S_COMPLETE) +	    return maj_stat; + +	_gsskrb5_register_acceptor_identity(str); +	free(str); + +	*minor_status = 0; +	return GSS_S_COMPLETE; + +    } else if (gss_oid_equal(desired_object, GSS_KRB5_SET_DEFAULT_REALM_X)) { +	char *str; + +	maj_stat = get_string(minor_status, value, &str); +	if (maj_stat != GSS_S_COMPLETE) +	    return maj_stat; +	if (str == NULL) { +	    *minor_status = 0; +	    return GSS_S_CALL_INACCESSIBLE_READ; +	} + +	krb5_set_default_realm(context, str); +	free(str); + +	*minor_status = 0; +	return GSS_S_COMPLETE; + +    } else if (gss_oid_equal(desired_object, GSS_KRB5_SEND_TO_KDC_X)) { + +	if (value == NULL || value->length == 0) { +	    krb5_set_send_to_kdc_func(context, NULL, NULL); +	} else { +	    struct gsskrb5_send_to_kdc c; + +	    if (value->length != sizeof(c)) { +		*minor_status = EINVAL; +		return GSS_S_FAILURE; +	    } +	    memcpy(&c, value->value, sizeof(c)); +	    krb5_set_send_to_kdc_func(context, +				      (krb5_send_to_kdc_func)c.func,  +				      c.ptr); +	} + +	*minor_status = 0; +	return GSS_S_COMPLETE; +    } else if (gss_oid_equal(desired_object, GSS_KRB5_CCACHE_NAME_X)) { +	char *str; + +	maj_stat = get_string(minor_status, value, &str); +	if (maj_stat != GSS_S_COMPLETE) +	    return maj_stat; +	if (str == NULL) { +	    *minor_status = 0; +	    return GSS_S_CALL_INACCESSIBLE_READ; +	} + +	*minor_status = krb5_cc_set_default_name(context, str); +	free(str); +	if (*minor_status) +	    return GSS_S_FAILURE; + +	return GSS_S_COMPLETE; +    } else if (gss_oid_equal(desired_object, GSS_KRB5_SET_TIME_OFFSET_X)) { +	OM_uint32 offset; +	time_t t; + +	maj_stat = get_int32(minor_status, value, &offset); +	if (maj_stat != GSS_S_COMPLETE) +	    return maj_stat; + +	t = time(NULL) + offset; +	 +	krb5_set_real_time(context, t, 0); + +	*minor_status = 0; +	return GSS_S_COMPLETE; +    } else if (gss_oid_equal(desired_object, GSS_KRB5_GET_TIME_OFFSET_X)) { +	krb5_timestamp sec; +	int32_t usec; +	time_t t; + +	t = time(NULL); + +	krb5_us_timeofday (context, &sec, &usec); + +	maj_stat = set_int32(minor_status, value, sec - t); +	if (maj_stat != GSS_S_COMPLETE) +	    return maj_stat; + +	*minor_status = 0; +	return GSS_S_COMPLETE; +    } + +    *minor_status = EINVAL; +    return GSS_S_FAILURE; +} diff --git a/source4/heimdal/lib/gssapi/krb5/unwrap.c b/source4/heimdal/lib/gssapi/krb5/unwrap.c new file mode 100644 index 0000000000..727bbf7403 --- /dev/null +++ b/source4/heimdal/lib/gssapi/krb5/unwrap.c @@ -0,0 +1,437 @@ +/* + * Copyright (c) 1997 - 2004 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.  + */ + +#include "krb5/gsskrb5_locl.h" + +RCSID("$Id$"); + +static OM_uint32 +unwrap_des +           (OM_uint32 * minor_status, +            const gsskrb5_ctx context_handle, +            const gss_buffer_t input_message_buffer, +            gss_buffer_t output_message_buffer, +            int * conf_state, +            gss_qop_t * qop_state, +	    krb5_keyblock *key +           ) +{ +  u_char *p, *seq; +  size_t len; +  MD5_CTX md5; +  u_char hash[16]; +  DES_key_schedule schedule; +  DES_cblock deskey; +  DES_cblock zero; +  int i; +  uint32_t seq_number; +  size_t padlength; +  OM_uint32 ret; +  int cstate; +  int cmp; +  int token_len; + +  if (IS_DCE_STYLE(context_handle)) { +     token_len = 22 + 8 + 15; /* 45 */ +  } else { +     token_len = input_message_buffer->length; +  } + +  p = input_message_buffer->value; +  ret = _gsskrb5_verify_header (&p, +				   token_len, +				   "\x02\x01", +				   GSS_KRB5_MECHANISM); +  if (ret) +      return ret; + +  if (memcmp (p, "\x00\x00", 2) != 0) +    return GSS_S_BAD_SIG; +  p += 2; +  if (memcmp (p, "\x00\x00", 2) == 0) { +      cstate = 1; +  } else if (memcmp (p, "\xFF\xFF", 2) == 0) { +      cstate = 0; +  } else +      return GSS_S_BAD_MIC; +  p += 2; +  if(conf_state != NULL) +      *conf_state = cstate; +  if (memcmp (p, "\xff\xff", 2) != 0) +    return GSS_S_DEFECTIVE_TOKEN; +  p += 2; +  p += 16; + +  len = p - (u_char *)input_message_buffer->value; + +  if(cstate) { +      /* decrypt data */ +      memcpy (&deskey, key->keyvalue.data, sizeof(deskey)); + +      for (i = 0; i < sizeof(deskey); ++i) +	  deskey[i] ^= 0xf0; +      DES_set_key_unchecked (&deskey, &schedule); +      memset (&zero, 0, sizeof(zero)); +      DES_cbc_encrypt ((void *)p, +		       (void *)p, +		       input_message_buffer->length - len, +		       &schedule, +		       &zero, +		       DES_DECRYPT); +       +      memset (deskey, 0, sizeof(deskey)); +      memset (&schedule, 0, sizeof(schedule)); +  } + +  if (IS_DCE_STYLE(context_handle)) { +    padlength = 0; +  } else { +    /* check pad */ +    ret = _gssapi_verify_pad(input_message_buffer, +			     input_message_buffer->length - len, +			     &padlength); +    if (ret) +        return ret; +  } + +  MD5_Init (&md5); +  MD5_Update (&md5, p - 24, 8); +  MD5_Update (&md5, p, input_message_buffer->length - len); +  MD5_Final (hash, &md5); + +  memset (&zero, 0, sizeof(zero)); +  memcpy (&deskey, key->keyvalue.data, sizeof(deskey)); +  DES_set_key_unchecked (&deskey, &schedule); +  DES_cbc_cksum ((void *)hash, (void *)hash, sizeof(hash), +		 &schedule, &zero); +  if (memcmp (p - 8, hash, 8) != 0) +    return GSS_S_BAD_MIC; + +  /* verify sequence number */ +   +  HEIMDAL_MUTEX_lock(&context_handle->ctx_id_mutex); + +  p -= 16; +  DES_set_key_unchecked (&deskey, &schedule); +  DES_cbc_encrypt ((void *)p, (void *)p, 8, +		   &schedule, (DES_cblock *)hash, DES_DECRYPT); + +  memset (deskey, 0, sizeof(deskey)); +  memset (&schedule, 0, sizeof(schedule)); + +  seq = p; +  _gsskrb5_decode_om_uint32(seq, &seq_number); + +  if (context_handle->more_flags & LOCAL) +      cmp = memcmp(&seq[4], "\xff\xff\xff\xff", 4); +  else +      cmp = memcmp(&seq[4], "\x00\x00\x00\x00", 4); + +  if (cmp != 0) { +    HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); +    return GSS_S_BAD_MIC; +  } + +  ret = _gssapi_msg_order_check(context_handle->order, seq_number); +  if (ret) { +    HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); +    return ret; +  } + +  HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); + +  /* copy out data */ + +  output_message_buffer->length = input_message_buffer->length +    - len - padlength - 8; +  output_message_buffer->value  = malloc(output_message_buffer->length); +  if(output_message_buffer->length != 0 && output_message_buffer->value == NULL) +      return GSS_S_FAILURE; +  memcpy (output_message_buffer->value, +	  p + 24, +	  output_message_buffer->length); +  return GSS_S_COMPLETE; +} + +static OM_uint32 +unwrap_des3 +           (OM_uint32 * minor_status, +            const gsskrb5_ctx context_handle, +	    krb5_context context, +            const gss_buffer_t input_message_buffer, +            gss_buffer_t output_message_buffer, +            int * conf_state, +            gss_qop_t * qop_state, +	    krb5_keyblock *key +           ) +{ +  u_char *p; +  size_t len; +  u_char *seq; +  krb5_data seq_data; +  u_char cksum[20]; +  uint32_t seq_number; +  size_t padlength; +  OM_uint32 ret; +  int cstate; +  krb5_crypto crypto; +  Checksum csum; +  int cmp; +  int token_len; + +  if (IS_DCE_STYLE(context_handle)) { +     token_len = 34 + 8 + 15; /* 57 */ +  } else { +     token_len = input_message_buffer->length; +  } + +  p = input_message_buffer->value; +  ret = _gsskrb5_verify_header (&p, +				   token_len, +				   "\x02\x01", +				   GSS_KRB5_MECHANISM); +  if (ret) +      return ret; + +  if (memcmp (p, "\x04\x00", 2) != 0) /* HMAC SHA1 DES3_KD */ +    return GSS_S_BAD_SIG; +  p += 2; +  if (memcmp (p, "\x02\x00", 2) == 0) { +    cstate = 1; +  } else if (memcmp (p, "\xff\xff", 2) == 0) { +    cstate = 0; +  } else +    return GSS_S_BAD_MIC; +  p += 2; +  if(conf_state != NULL) +    *conf_state = cstate; +  if (memcmp (p, "\xff\xff", 2) != 0) +    return GSS_S_DEFECTIVE_TOKEN; +  p += 2; +  p += 28; + +  len = p - (u_char *)input_message_buffer->value; + +  if(cstate) { +      /* decrypt data */ +      krb5_data tmp; + +      ret = krb5_crypto_init(context, key, +			     ETYPE_DES3_CBC_NONE, &crypto); +      if (ret) { +	  *minor_status = ret; +	  return GSS_S_FAILURE; +      } +      ret = krb5_decrypt(context, crypto, KRB5_KU_USAGE_SEAL, +			 p, input_message_buffer->length - len, &tmp); +      krb5_crypto_destroy(context, crypto); +      if (ret) { +	  *minor_status = ret; +	  return GSS_S_FAILURE; +      } +      assert (tmp.length == input_message_buffer->length - len); + +      memcpy (p, tmp.data, tmp.length); +      krb5_data_free(&tmp); +  } + +  if (IS_DCE_STYLE(context_handle)) { +    padlength = 0; +  } else { +    /* check pad */ +    ret = _gssapi_verify_pad(input_message_buffer, +			     input_message_buffer->length - len, +			     &padlength); +    if (ret) +        return ret; +  } + +  /* verify sequence number */ +   +  HEIMDAL_MUTEX_lock(&context_handle->ctx_id_mutex); + +  p -= 28; + +  ret = krb5_crypto_init(context, key, +			 ETYPE_DES3_CBC_NONE, &crypto); +  if (ret) { +      *minor_status = ret; +      HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); +      return GSS_S_FAILURE; +  } +  { +      DES_cblock ivec; + +      memcpy(&ivec, p + 8, 8); +      ret = krb5_decrypt_ivec (context, +			       crypto, +			       KRB5_KU_USAGE_SEQ, +			       p, 8, &seq_data, +			       &ivec); +  } +  krb5_crypto_destroy (context, crypto); +  if (ret) { +      *minor_status = ret; +      HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); +      return GSS_S_FAILURE; +  } +  if (seq_data.length != 8) { +      krb5_data_free (&seq_data); +      *minor_status = 0; +      HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); +      return GSS_S_BAD_MIC; +  } + +  seq = seq_data.data; +  _gsskrb5_decode_om_uint32(seq, &seq_number); + +  if (context_handle->more_flags & LOCAL) +      cmp = memcmp(&seq[4], "\xff\xff\xff\xff", 4); +  else +      cmp = memcmp(&seq[4], "\x00\x00\x00\x00", 4); +   +  krb5_data_free (&seq_data); +  if (cmp != 0) { +      *minor_status = 0; +      HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); +      return GSS_S_BAD_MIC; +  } + +  ret = _gssapi_msg_order_check(context_handle->order, seq_number); +  if (ret) { +      *minor_status = 0; +      HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); +      return ret; +  } + +  HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); + +  /* verify checksum */ + +  memcpy (cksum, p + 8, 20); + +  memcpy (p + 20, p - 8, 8); + +  csum.cksumtype = CKSUMTYPE_HMAC_SHA1_DES3; +  csum.checksum.length = 20; +  csum.checksum.data   = cksum; + +  ret = krb5_crypto_init(context, key, 0, &crypto); +  if (ret) { +      *minor_status = ret; +      return GSS_S_FAILURE; +  } + +  ret = krb5_verify_checksum (context, crypto, +			      KRB5_KU_USAGE_SIGN, +			      p + 20, +			      input_message_buffer->length - len + 8, +			      &csum); +  krb5_crypto_destroy (context, crypto); +  if (ret) { +      *minor_status = ret; +      return GSS_S_FAILURE; +  } + +  /* copy out data */ + +  output_message_buffer->length = input_message_buffer->length +    - len - padlength - 8; +  output_message_buffer->value  = malloc(output_message_buffer->length); +  if(output_message_buffer->length != 0 && output_message_buffer->value == NULL) +      return GSS_S_FAILURE; +  memcpy (output_message_buffer->value, +	  p + 36, +	  output_message_buffer->length); +  return GSS_S_COMPLETE; +} + +OM_uint32 _gsskrb5_unwrap +           (OM_uint32 * minor_status, +            const gss_ctx_id_t context_handle, +            const gss_buffer_t input_message_buffer, +            gss_buffer_t output_message_buffer, +            int * conf_state, +            gss_qop_t * qop_state +           ) +{ +  krb5_keyblock *key; +  krb5_context context; +  OM_uint32 ret; +  krb5_keytype keytype; +  gsskrb5_ctx ctx = (gsskrb5_ctx) context_handle; + +  output_message_buffer->value = NULL; +  output_message_buffer->length = 0; + +  GSSAPI_KRB5_INIT (&context); + +  if (qop_state != NULL) +      *qop_state = GSS_C_QOP_DEFAULT; +  HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex); +  ret = _gsskrb5i_get_token_key(ctx, context, &key); +  HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); +  if (ret) { +      *minor_status = ret; +      return GSS_S_FAILURE; +  } +  krb5_enctype_to_keytype (context, key->keytype, &keytype); + +  *minor_status = 0; + +  switch (keytype) { +  case KEYTYPE_DES : +      ret = unwrap_des (minor_status, ctx, +			input_message_buffer, output_message_buffer, +			conf_state, qop_state, key); +      break; +  case KEYTYPE_DES3 : +      ret = unwrap_des3 (minor_status, ctx, context, +			 input_message_buffer, output_message_buffer, +			 conf_state, qop_state, key); +      break; +  case KEYTYPE_ARCFOUR: +  case KEYTYPE_ARCFOUR_56: +      ret = _gssapi_unwrap_arcfour (minor_status, ctx, context, +				    input_message_buffer, output_message_buffer, +				    conf_state, qop_state, key); +      break; +  default : +      ret = _gssapi_unwrap_cfx (minor_status, ctx, context, +				input_message_buffer, output_message_buffer, +				conf_state, qop_state, key); +      break; +  } +  krb5_free_keyblock (context, key); +  return ret; +} diff --git a/source4/heimdal/lib/gssapi/krb5/verify_mic.c b/source4/heimdal/lib/gssapi/krb5/verify_mic.c new file mode 100644 index 0000000000..df71f8f7d1 --- /dev/null +++ b/source4/heimdal/lib/gssapi/krb5/verify_mic.c @@ -0,0 +1,344 @@ +/* + * Copyright (c) 1997 - 2003 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.  + */ + +#include "krb5/gsskrb5_locl.h" + +RCSID("$Id$"); + +static OM_uint32 +verify_mic_des +           (OM_uint32 * minor_status, +            const gsskrb5_ctx context_handle, +	    krb5_context context, +            const gss_buffer_t message_buffer, +            const gss_buffer_t token_buffer, +            gss_qop_t * qop_state, +	    krb5_keyblock *key, +	    char *type +	    ) +{ +  u_char *p; +  MD5_CTX md5; +  u_char hash[16], *seq; +  DES_key_schedule schedule; +  DES_cblock zero; +  DES_cblock deskey; +  uint32_t seq_number; +  OM_uint32 ret; +  int cmp; + +  p = token_buffer->value; +  ret = _gsskrb5_verify_header (&p, +				   token_buffer->length, +				   type, +				   GSS_KRB5_MECHANISM); +  if (ret) +      return ret; + +  if (memcmp(p, "\x00\x00", 2) != 0) +      return GSS_S_BAD_SIG; +  p += 2; +  if (memcmp (p, "\xff\xff\xff\xff", 4) != 0) +    return GSS_S_BAD_MIC; +  p += 4; +  p += 16; + +  /* verify checksum */ +  MD5_Init (&md5); +  MD5_Update (&md5, p - 24, 8); +  MD5_Update (&md5, message_buffer->value, +	     message_buffer->length); +  MD5_Final (hash, &md5); + +  memset (&zero, 0, sizeof(zero)); +  memcpy (&deskey, key->keyvalue.data, sizeof(deskey)); + +  DES_set_key_unchecked (&deskey, &schedule); +  DES_cbc_cksum ((void *)hash, (void *)hash, sizeof(hash), +		 &schedule, &zero); +  if (memcmp (p - 8, hash, 8) != 0) { +    memset (deskey, 0, sizeof(deskey)); +    memset (&schedule, 0, sizeof(schedule)); +    return GSS_S_BAD_MIC; +  } + +  /* verify sequence number */ +   +  HEIMDAL_MUTEX_lock(&context_handle->ctx_id_mutex); + +  p -= 16; +  DES_set_key_unchecked (&deskey, &schedule); +  DES_cbc_encrypt ((void *)p, (void *)p, 8, +		   &schedule, (DES_cblock *)hash, DES_DECRYPT); + +  memset (deskey, 0, sizeof(deskey)); +  memset (&schedule, 0, sizeof(schedule)); + +  seq = p; +  _gsskrb5_decode_om_uint32(seq, &seq_number); + +  if (context_handle->more_flags & LOCAL) +      cmp = memcmp(&seq[4], "\xff\xff\xff\xff", 4); +  else +      cmp = memcmp(&seq[4], "\x00\x00\x00\x00", 4); + +  if (cmp != 0) { +    HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); +    return GSS_S_BAD_MIC; +  } + +  ret = _gssapi_msg_order_check(context_handle->order, seq_number); +  if (ret) { +      HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); +      return ret; +  } + +  HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); + +  return GSS_S_COMPLETE; +} + +static OM_uint32 +verify_mic_des3 +           (OM_uint32 * minor_status, +            const gsskrb5_ctx context_handle, +	    krb5_context context, +            const gss_buffer_t message_buffer, +            const gss_buffer_t token_buffer, +            gss_qop_t * qop_state, +	    krb5_keyblock *key, +	    char *type +	    ) +{ +  u_char *p; +  u_char *seq; +  uint32_t seq_number; +  OM_uint32 ret; +  krb5_crypto crypto; +  krb5_data seq_data; +  int cmp, docompat; +  Checksum csum; +  char *tmp; +  char ivec[8]; +   +  p = token_buffer->value; +  ret = _gsskrb5_verify_header (&p, +				   token_buffer->length, +				   type, +				   GSS_KRB5_MECHANISM); +  if (ret) +      return ret; + +  if (memcmp(p, "\x04\x00", 2) != 0) /* SGN_ALG = HMAC SHA1 DES3-KD */ +      return GSS_S_BAD_SIG; +  p += 2; +  if (memcmp (p, "\xff\xff\xff\xff", 4) != 0) +    return GSS_S_BAD_MIC; +  p += 4; + +  ret = krb5_crypto_init(context, key, +			 ETYPE_DES3_CBC_NONE, &crypto); +  if (ret){ +      *minor_status = ret; +      return GSS_S_FAILURE; +  } + +  /* verify sequence number */ +  docompat = 0; +retry: +  if (docompat) +      memset(ivec, 0, 8); +  else +      memcpy(ivec, p + 8, 8); + +  ret = krb5_decrypt_ivec (context, +			   crypto, +			   KRB5_KU_USAGE_SEQ, +			   p, 8, &seq_data, ivec); +  if (ret) { +      if (docompat++) { +	  krb5_crypto_destroy (context, crypto); +	  *minor_status = ret; +	  return GSS_S_FAILURE; +      } else +	  goto retry; +  } + +  if (seq_data.length != 8) { +      krb5_data_free (&seq_data); +      if (docompat++) { +	  krb5_crypto_destroy (context, crypto); +	  return GSS_S_BAD_MIC; +      } else +	  goto retry; +  } + +  HEIMDAL_MUTEX_lock(&context_handle->ctx_id_mutex); + +  seq = seq_data.data; +  _gsskrb5_decode_om_uint32(seq, &seq_number); + +  if (context_handle->more_flags & LOCAL) +      cmp = memcmp(&seq[4], "\xff\xff\xff\xff", 4); +  else +      cmp = memcmp(&seq[4], "\x00\x00\x00\x00", 4); + +  krb5_data_free (&seq_data); +  if (cmp != 0) { +      krb5_crypto_destroy (context, crypto); +      *minor_status = 0; +      HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); +      return GSS_S_BAD_MIC; +  } + +  ret = _gssapi_msg_order_check(context_handle->order, seq_number); +  if (ret) { +      krb5_crypto_destroy (context, crypto); +      *minor_status = 0; +      HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); +      return ret; +  } + +  /* verify checksum */ + +  tmp = malloc (message_buffer->length + 8); +  if (tmp == NULL) { +      krb5_crypto_destroy (context, crypto); +      HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); +      *minor_status = ENOMEM; +      return GSS_S_FAILURE; +  } + +  memcpy (tmp, p - 8, 8); +  memcpy (tmp + 8, message_buffer->value, message_buffer->length); + +  csum.cksumtype = CKSUMTYPE_HMAC_SHA1_DES3; +  csum.checksum.length = 20; +  csum.checksum.data   = p + 8; + +  ret = krb5_verify_checksum (context, crypto, +			      KRB5_KU_USAGE_SIGN, +			      tmp, message_buffer->length + 8, +			      &csum); +  free (tmp); +  if (ret) { +      krb5_crypto_destroy (context, crypto); +      *minor_status = ret; +      HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); +      return GSS_S_BAD_MIC; +  } +  HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); + +  krb5_crypto_destroy (context, crypto); +  return GSS_S_COMPLETE; +} + +OM_uint32 +_gsskrb5_verify_mic_internal +           (OM_uint32 * minor_status, +            const gsskrb5_ctx context_handle, +	    krb5_context context, +            const gss_buffer_t message_buffer, +            const gss_buffer_t token_buffer, +            gss_qop_t * qop_state, +	    char * type +	    ) +{ +    krb5_keyblock *key; +    OM_uint32 ret; +    krb5_keytype keytype; + +    HEIMDAL_MUTEX_lock(&context_handle->ctx_id_mutex); +    ret = _gsskrb5i_get_token_key(context_handle, context, &key); +    HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); +    if (ret) { +	*minor_status = ret; +	return GSS_S_FAILURE; +    } +    *minor_status = 0; +    krb5_enctype_to_keytype (context, key->keytype, &keytype); +    switch (keytype) { +    case KEYTYPE_DES : +	ret = verify_mic_des (minor_status, context_handle, context, +			      message_buffer, token_buffer, qop_state, key, +			      type); +	break; +    case KEYTYPE_DES3 : +	ret = verify_mic_des3 (minor_status, context_handle, context, +			       message_buffer, token_buffer, qop_state, key, +			       type); +	break; +    case KEYTYPE_ARCFOUR : +    case KEYTYPE_ARCFOUR_56 : +	ret = _gssapi_verify_mic_arcfour (minor_status, context_handle, +					  context, +					  message_buffer, token_buffer, +					  qop_state, key, type); +	break; +    default : +	ret = _gssapi_verify_mic_cfx (minor_status, context_handle, +				      context, +				      message_buffer, token_buffer, qop_state, +				      key); +	break; +    } +    krb5_free_keyblock (context, key); +     +    return ret; +} + +OM_uint32 +_gsskrb5_verify_mic +           (OM_uint32 * minor_status, +            const gss_ctx_id_t context_handle, +            const gss_buffer_t message_buffer, +            const gss_buffer_t token_buffer, +            gss_qop_t * qop_state +	    ) +{ +    krb5_context context; +    OM_uint32 ret; + +    GSSAPI_KRB5_INIT (&context); + +    if (qop_state != NULL) +	*qop_state = GSS_C_QOP_DEFAULT; + +    ret = _gsskrb5_verify_mic_internal(minor_status,  +				       (gsskrb5_ctx)context_handle, +				       context, +				       message_buffer, token_buffer, +				       qop_state, "\x01\x01"); + +    return ret; +} diff --git a/source4/heimdal/lib/gssapi/krb5/wrap.c b/source4/heimdal/lib/gssapi/krb5/wrap.c new file mode 100644 index 0000000000..ecd4f7cd54 --- /dev/null +++ b/source4/heimdal/lib/gssapi/krb5/wrap.c @@ -0,0 +1,569 @@ +/* + * Copyright (c) 1997 - 2003 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.  + */ + +#include "krb5/gsskrb5_locl.h" + +RCSID("$Id$"); + +/* + * Return initiator subkey, or if that doesn't exists, the subkey. + */ + +krb5_error_code +_gsskrb5i_get_initiator_subkey(const gsskrb5_ctx ctx, +			       krb5_context context, +			       krb5_keyblock **key) +{ +    krb5_error_code ret; +    *key = NULL; + +    if (ctx->more_flags & LOCAL) { +	ret = krb5_auth_con_getlocalsubkey(context, +				     ctx->auth_context,  +				     key); +    } else { +	ret = krb5_auth_con_getremotesubkey(context, +				      ctx->auth_context,  +				      key); +    } +    if (ret == 0 && *key == NULL) +	ret = krb5_auth_con_getkey(context, +				   ctx->auth_context,  +				   key); +    if (ret == 0 && *key == NULL) { +	krb5_set_error_message(context, 0, "No initiator subkey available"); +	return GSS_KRB5_S_KG_NO_SUBKEY; +    } +    return ret; +} + +krb5_error_code +_gsskrb5i_get_acceptor_subkey(const gsskrb5_ctx ctx, +			      krb5_context context, +			      krb5_keyblock **key) +{ +    krb5_error_code ret; +    *key = NULL; + +    if (ctx->more_flags & LOCAL) { +	ret = krb5_auth_con_getremotesubkey(context, +				      ctx->auth_context,  +				      key); +    } else { +	ret = krb5_auth_con_getlocalsubkey(context, +				     ctx->auth_context,  +				     key); +    } +    if (ret == 0 && *key == NULL) { +	krb5_set_error_message(context, 0, "No acceptor subkey available"); +	return GSS_KRB5_S_KG_NO_SUBKEY; +    } +    return ret; +} + +OM_uint32 +_gsskrb5i_get_token_key(const gsskrb5_ctx ctx, +			krb5_context context, +			krb5_keyblock **key) +{ +    _gsskrb5i_get_acceptor_subkey(ctx, context, key); +    if(*key == NULL) { +	/* +	 * Only use the initiator subkey or ticket session key if an +	 * acceptor subkey was not required. +	 */ +	if ((ctx->more_flags & ACCEPTOR_SUBKEY) == 0) +	    _gsskrb5i_get_initiator_subkey(ctx, context, key); +    } +    if (*key == NULL) { +	krb5_set_error_message(context, 0, "No token key available"); +	return GSS_KRB5_S_KG_NO_SUBKEY; +    } +    return 0; +} + +static OM_uint32 +sub_wrap_size ( +            OM_uint32 req_output_size, +            OM_uint32 * max_input_size, +	    int blocksize, +	    int extrasize +           ) +{ +    size_t len, total_len;  + +    len = 8 + req_output_size + blocksize + extrasize; + +    _gsskrb5_encap_length(len, &len, &total_len, GSS_KRB5_MECHANISM); + +    total_len -= req_output_size; /* token length */ +    if (total_len < req_output_size) { +        *max_input_size = (req_output_size - total_len); +        (*max_input_size) &= (~(OM_uint32)(blocksize - 1)); +    } else { +        *max_input_size = 0; +    } +    return GSS_S_COMPLETE; +} + +OM_uint32 +_gsskrb5_wrap_size_limit ( +            OM_uint32 * minor_status, +            const gss_ctx_id_t context_handle, +            int conf_req_flag, +            gss_qop_t qop_req, +            OM_uint32 req_output_size, +            OM_uint32 * max_input_size +           ) +{ +  krb5_context context; +  krb5_keyblock *key; +  OM_uint32 ret; +  krb5_keytype keytype; +  const gsskrb5_ctx ctx = (const gsskrb5_ctx) context_handle; + +  GSSAPI_KRB5_INIT (&context); + +  HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex); +  ret = _gsskrb5i_get_token_key(ctx, context, &key); +  HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); +  if (ret) { +      *minor_status = ret; +      return GSS_S_FAILURE; +  } +  krb5_enctype_to_keytype (context, key->keytype, &keytype); + +  switch (keytype) { +  case KEYTYPE_DES : +      ret = sub_wrap_size(req_output_size, max_input_size, 8, 22); +      break; +  case KEYTYPE_ARCFOUR: +  case KEYTYPE_ARCFOUR_56: +      ret = _gssapi_wrap_size_arcfour(minor_status, ctx, context, +				      conf_req_flag, qop_req,  +				      req_output_size, max_input_size, key); +      break; +  case KEYTYPE_DES3 : +      ret = sub_wrap_size(req_output_size, max_input_size, 8, 34); +      break; +  default : +      ret = _gssapi_wrap_size_cfx(minor_status, ctx, context, +				  conf_req_flag, qop_req,  +				  req_output_size, max_input_size, key); +      break; +  } +  krb5_free_keyblock (context, key); +  *minor_status = 0; +  return ret; +} + +static OM_uint32 +wrap_des +           (OM_uint32 * minor_status, +            const gsskrb5_ctx ctx, +	    krb5_context context, +            int conf_req_flag, +            gss_qop_t qop_req, +            const gss_buffer_t input_message_buffer, +            int * conf_state, +            gss_buffer_t output_message_buffer, +	    krb5_keyblock *key +           ) +{ +  u_char *p; +  MD5_CTX md5; +  u_char hash[16]; +  DES_key_schedule schedule; +  DES_cblock deskey; +  DES_cblock zero; +  int i; +  int32_t seq_number; +  size_t len, total_len, padlength, datalen; + +  if (IS_DCE_STYLE(ctx)) { +    padlength = 0; +    datalen = input_message_buffer->length; +    len = 22 + 8; +    _gsskrb5_encap_length (len, &len, &total_len, GSS_KRB5_MECHANISM); +    total_len += datalen; +    datalen += 8; +  } else { +    padlength = 8 - (input_message_buffer->length % 8); +    datalen = input_message_buffer->length + padlength + 8; +    len = datalen + 22; +    _gsskrb5_encap_length (len, &len, &total_len, GSS_KRB5_MECHANISM); +  } + +  output_message_buffer->length = total_len; +  output_message_buffer->value  = malloc (total_len); +  if (output_message_buffer->value == NULL) { +    output_message_buffer->length = 0; +    *minor_status = ENOMEM; +    return GSS_S_FAILURE; +  } + +  p = _gsskrb5_make_header(output_message_buffer->value, +			      len, +			      "\x02\x01", /* TOK_ID */ +			      GSS_KRB5_MECHANISM); + +  /* SGN_ALG */ +  memcpy (p, "\x00\x00", 2); +  p += 2; +  /* SEAL_ALG */ +  if(conf_req_flag) +      memcpy (p, "\x00\x00", 2); +  else +      memcpy (p, "\xff\xff", 2); +  p += 2; +  /* Filler */ +  memcpy (p, "\xff\xff", 2); +  p += 2; + +  /* fill in later */ +  memset (p, 0, 16); +  p += 16; + +  /* confounder + data + pad */ +  krb5_generate_random_block(p, 8); +  memcpy (p + 8, input_message_buffer->value, +	  input_message_buffer->length); +  memset (p + 8 + input_message_buffer->length, padlength, padlength); + +  /* checksum */ +  MD5_Init (&md5); +  MD5_Update (&md5, p - 24, 8); +  MD5_Update (&md5, p, datalen); +  MD5_Final (hash, &md5); + +  memset (&zero, 0, sizeof(zero)); +  memcpy (&deskey, key->keyvalue.data, sizeof(deskey)); +  DES_set_key_unchecked (&deskey, &schedule); +  DES_cbc_cksum ((void *)hash, (void *)hash, sizeof(hash), +		 &schedule, &zero); +  memcpy (p - 8, hash, 8); + +  /* sequence number */ +  HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex); +  krb5_auth_con_getlocalseqnumber (context, +				   ctx->auth_context, +				   &seq_number); + +  p -= 16; +  p[0] = (seq_number >> 0)  & 0xFF; +  p[1] = (seq_number >> 8)  & 0xFF; +  p[2] = (seq_number >> 16) & 0xFF; +  p[3] = (seq_number >> 24) & 0xFF; +  memset (p + 4, +	  (ctx->more_flags & LOCAL) ? 0 : 0xFF, +	  4); + +  DES_set_key_unchecked (&deskey, &schedule); +  DES_cbc_encrypt ((void *)p, (void *)p, 8, +		   &schedule, (DES_cblock *)(p + 8), DES_ENCRYPT); + +  krb5_auth_con_setlocalseqnumber (context, +			       ctx->auth_context, +			       ++seq_number); +  HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); + +  /* encrypt the data */ +  p += 16; + +  if(conf_req_flag) { +      memcpy (&deskey, key->keyvalue.data, sizeof(deskey)); + +      for (i = 0; i < sizeof(deskey); ++i) +	  deskey[i] ^= 0xf0; +      DES_set_key_unchecked (&deskey, &schedule); +      memset (&zero, 0, sizeof(zero)); +      DES_cbc_encrypt ((void *)p, +		       (void *)p, +		       datalen, +		       &schedule, +		       &zero, +		       DES_ENCRYPT); +  } +  memset (deskey, 0, sizeof(deskey)); +  memset (&schedule, 0, sizeof(schedule)); + +  if(conf_state != NULL) +      *conf_state = conf_req_flag; +  *minor_status = 0; +  return GSS_S_COMPLETE; +} + +static OM_uint32 +wrap_des3 +           (OM_uint32 * minor_status, +            const gsskrb5_ctx ctx, +	    krb5_context context, +            int conf_req_flag, +            gss_qop_t qop_req, +            const gss_buffer_t input_message_buffer, +            int * conf_state, +            gss_buffer_t output_message_buffer, +	    krb5_keyblock *key +           ) +{ +  u_char *p; +  u_char seq[8]; +  int32_t seq_number; +  size_t len, total_len, padlength, datalen; +  uint32_t ret; +  krb5_crypto crypto; +  Checksum cksum; +  krb5_data encdata; + +  if (IS_DCE_STYLE(ctx)) { +    padlength = 0; +    datalen = input_message_buffer->length; +    len = 34 + 8; +    _gsskrb5_encap_length (len, &len, &total_len, GSS_KRB5_MECHANISM); +    total_len += datalen; +    datalen += 8; +  } else { +    padlength = 8 - (input_message_buffer->length % 8); +    datalen = input_message_buffer->length + padlength + 8; +    len = datalen + 34; +    _gsskrb5_encap_length (len, &len, &total_len, GSS_KRB5_MECHANISM); +  } + +  output_message_buffer->length = total_len; +  output_message_buffer->value  = malloc (total_len); +  if (output_message_buffer->value == NULL) { +    output_message_buffer->length = 0; +    *minor_status = ENOMEM; +    return GSS_S_FAILURE; +  } + +  p = _gsskrb5_make_header(output_message_buffer->value, +			      len, +			      "\x02\x01", /* TOK_ID */ +			      GSS_KRB5_MECHANISM);  + +  /* SGN_ALG */ +  memcpy (p, "\x04\x00", 2);	/* HMAC SHA1 DES3-KD */ +  p += 2; +  /* SEAL_ALG */ +  if(conf_req_flag) +      memcpy (p, "\x02\x00", 2); /* DES3-KD */ +  else +      memcpy (p, "\xff\xff", 2); +  p += 2; +  /* Filler */ +  memcpy (p, "\xff\xff", 2); +  p += 2; + +  /* calculate checksum (the above + confounder + data + pad) */ + +  memcpy (p + 20, p - 8, 8); +  krb5_generate_random_block(p + 28, 8); +  memcpy (p + 28 + 8, input_message_buffer->value, +	  input_message_buffer->length); +  memset (p + 28 + 8 + input_message_buffer->length, padlength, padlength); + +  ret = krb5_crypto_init(context, key, 0, &crypto); +  if (ret) { +      free (output_message_buffer->value); +      output_message_buffer->length = 0; +      output_message_buffer->value = NULL; +      *minor_status = ret; +      return GSS_S_FAILURE; +  } + +  ret = krb5_create_checksum (context, +			      crypto, +			      KRB5_KU_USAGE_SIGN, +			      0, +			      p + 20, +			      datalen + 8, +			      &cksum); +  krb5_crypto_destroy (context, crypto); +  if (ret) { +      free (output_message_buffer->value); +      output_message_buffer->length = 0; +      output_message_buffer->value = NULL; +      *minor_status = ret; +      return GSS_S_FAILURE; +  } + +  /* zero out SND_SEQ + SGN_CKSUM in case */ +  memset (p, 0, 28); + +  memcpy (p + 8, cksum.checksum.data, cksum.checksum.length); +  free_Checksum (&cksum); + +  HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex); +  /* sequence number */ +  krb5_auth_con_getlocalseqnumber (context, +			       ctx->auth_context, +			       &seq_number); + +  seq[0] = (seq_number >> 0)  & 0xFF; +  seq[1] = (seq_number >> 8)  & 0xFF; +  seq[2] = (seq_number >> 16) & 0xFF; +  seq[3] = (seq_number >> 24) & 0xFF; +  memset (seq + 4, +	  (ctx->more_flags & LOCAL) ? 0 : 0xFF, +	  4); + + +  ret = krb5_crypto_init(context, key, ETYPE_DES3_CBC_NONE, +			 &crypto); +  if (ret) { +      free (output_message_buffer->value); +      output_message_buffer->length = 0; +      output_message_buffer->value = NULL; +      *minor_status = ret; +      return GSS_S_FAILURE; +  } + +  { +      DES_cblock ivec; + +      memcpy (&ivec, p + 8, 8); +      ret = krb5_encrypt_ivec (context, +			       crypto, +			       KRB5_KU_USAGE_SEQ, +			       seq, 8, &encdata, +			       &ivec); +  } +  krb5_crypto_destroy (context, crypto); +  if (ret) { +      free (output_message_buffer->value); +      output_message_buffer->length = 0; +      output_message_buffer->value = NULL; +      *minor_status = ret; +      return GSS_S_FAILURE; +  } +   +  assert (encdata.length == 8); + +  memcpy (p, encdata.data, encdata.length); +  krb5_data_free (&encdata); + +  krb5_auth_con_setlocalseqnumber (context, +			       ctx->auth_context, +			       ++seq_number); +  HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); + +  /* encrypt the data */ +  p += 28; + +  if(conf_req_flag) { +      krb5_data tmp; + +      ret = krb5_crypto_init(context, key, +			     ETYPE_DES3_CBC_NONE, &crypto); +      if (ret) { +	  free (output_message_buffer->value); +	  output_message_buffer->length = 0; +	  output_message_buffer->value = NULL; +	  *minor_status = ret; +	  return GSS_S_FAILURE; +      } +      ret = krb5_encrypt(context, crypto, KRB5_KU_USAGE_SEAL, +			 p, datalen, &tmp); +      krb5_crypto_destroy(context, crypto); +      if (ret) { +	  free (output_message_buffer->value); +	  output_message_buffer->length = 0; +	  output_message_buffer->value = NULL; +	  *minor_status = ret; +	  return GSS_S_FAILURE; +      } +      assert (tmp.length == datalen); + +      memcpy (p, tmp.data, datalen); +      krb5_data_free(&tmp); +  } +  if(conf_state != NULL) +      *conf_state = conf_req_flag; +  *minor_status = 0; +  return GSS_S_COMPLETE; +} + +OM_uint32 _gsskrb5_wrap +           (OM_uint32 * minor_status, +            const gss_ctx_id_t context_handle, +            int conf_req_flag, +            gss_qop_t qop_req, +            const gss_buffer_t input_message_buffer, +            int * conf_state, +            gss_buffer_t output_message_buffer +           ) +{ +  krb5_context context; +  krb5_keyblock *key; +  OM_uint32 ret; +  krb5_keytype keytype; +  const gsskrb5_ctx ctx = (const gsskrb5_ctx) context_handle; + +  GSSAPI_KRB5_INIT (&context); + +  HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex); +  ret = _gsskrb5i_get_token_key(ctx, context, &key); +  HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); +  if (ret) { +      *minor_status = ret; +      return GSS_S_FAILURE; +  } +  krb5_enctype_to_keytype (context, key->keytype, &keytype); + +  switch (keytype) { +  case KEYTYPE_DES : +      ret = wrap_des (minor_status, ctx, context, conf_req_flag, +		      qop_req, input_message_buffer, conf_state, +		      output_message_buffer, key); +      break; +  case KEYTYPE_DES3 : +      ret = wrap_des3 (minor_status, ctx, context, conf_req_flag, +		       qop_req, input_message_buffer, conf_state, +		       output_message_buffer, key); +      break; +  case KEYTYPE_ARCFOUR: +  case KEYTYPE_ARCFOUR_56: +      ret = _gssapi_wrap_arcfour (minor_status, ctx, context, conf_req_flag, +				  qop_req, input_message_buffer, conf_state, +				  output_message_buffer, key); +      break; +  default : +      ret = _gssapi_wrap_cfx (minor_status, ctx, context, conf_req_flag, +			      qop_req, input_message_buffer, conf_state, +			      output_message_buffer, key); +      break; +  } +  krb5_free_keyblock (context, key); +  return ret; +} diff --git a/source4/heimdal/lib/gssapi/mech/context.c b/source4/heimdal/lib/gssapi/mech/context.c new file mode 100644 index 0000000000..bfb303ac8e --- /dev/null +++ b/source4/heimdal/lib/gssapi/mech/context.c @@ -0,0 +1,163 @@ +#include "mech/mech_locl.h" +#include "heim_threads.h" + +RCSID("$Id$"); + +struct mg_thread_ctx { +    gss_OID mech; +    OM_uint32 maj_stat; +    OM_uint32 min_stat; +    gss_buffer_desc maj_error; +    gss_buffer_desc min_error; +}; + +static HEIMDAL_MUTEX context_mutex = HEIMDAL_MUTEX_INITIALIZER; +static int created_key; +static HEIMDAL_thread_key context_key; + + +static void +destroy_context(void *ptr) +{ +    struct mg_thread_ctx *mg = ptr; +    OM_uint32 junk; + +    if (mg == NULL) +	return; + +    gss_release_buffer(&junk, &mg->maj_error); +    gss_release_buffer(&junk, &mg->min_error); +    free(mg); +} + + +static struct mg_thread_ctx * +_gss_mechglue_thread(void) +{ +    struct mg_thread_ctx *ctx; +    int ret = 0; + +    HEIMDAL_MUTEX_lock(&context_mutex); + +    if (!created_key) { +	HEIMDAL_key_create(&context_key, destroy_context, ret); +	if (ret) { +	    HEIMDAL_MUTEX_unlock(&context_mutex); +	    return NULL; +	} +	created_key = 1; +    } +    HEIMDAL_MUTEX_unlock(&context_mutex); + +    ctx = HEIMDAL_getspecific(context_key); +    if (ctx == NULL) { + +	ctx = calloc(1, sizeof(*ctx)); +	if (ctx == NULL) +	    return NULL; +	HEIMDAL_setspecific(context_key, ctx, ret); +	if (ret) { +	    free(ctx); +	    return NULL; +	} +    } +    return ctx; +} + +OM_uint32 +_gss_mg_get_error(const gss_OID mech, OM_uint32 type, +		  OM_uint32 value, gss_buffer_t string) +{ +    struct mg_thread_ctx *mg; + +    mg = _gss_mechglue_thread(); +    if (mg == NULL) +	return GSS_S_BAD_STATUS; + +#if 0 +    /*  +     * We cant check the mech here since a pseudo-mech might have +     * called an lower layer and then the mech info is all broken +     */ +    if (mech != NULL && gss_oid_equal(mg->mech, mech) == 0) +	return GSS_S_BAD_STATUS; +#endif + +    switch (type) { +    case GSS_C_GSS_CODE: { +	if (value != mg->maj_stat || mg->maj_error.length == 0) +	    break; +	string->value = malloc(mg->maj_error.length); +	string->length = mg->maj_error.length; +	memcpy(string->value, mg->maj_error.value, mg->maj_error.length); +	return GSS_S_COMPLETE; +    } +    case GSS_C_MECH_CODE: { +	if (value != mg->min_stat || mg->min_error.length == 0) +	    break; +	string->value = malloc(mg->min_error.length); +	string->length = mg->min_error.length; +	memcpy(string->value, mg->min_error.value, mg->min_error.length); +	return GSS_S_COMPLETE; +    } +    } +    string->value = NULL; +    string->length = 0; +    return GSS_S_BAD_STATUS; +} + +void +_gss_mg_error(gssapi_mech_interface m, OM_uint32 maj, OM_uint32 min) +{ +    OM_uint32 major_status, minor_status; +    OM_uint32 message_content; +    struct mg_thread_ctx *mg; + +    /*  +     * Mechs without gss_display_status() does +     * gss_mg_collect_error() by themself. +     */ +    if (m->gm_display_status == NULL) +	return ; + +    mg = _gss_mechglue_thread(); +    if (mg == NULL) +	return; + +    gss_release_buffer(&minor_status, &mg->maj_error); +    gss_release_buffer(&minor_status, &mg->min_error); + +    mg->mech = &m->gm_mech_oid; +    mg->maj_stat = maj; +    mg->min_stat = min; + +    major_status = m->gm_display_status(&minor_status, +					maj,  +					GSS_C_GSS_CODE, +					&m->gm_mech_oid, +					&message_content, +					&mg->maj_error); +    if (GSS_ERROR(major_status)) { +	mg->maj_error.value = NULL; +	mg->maj_error.length = 0; +    } +    major_status = m->gm_display_status(&minor_status, +					min,  +					GSS_C_MECH_CODE, +					&m->gm_mech_oid, +					&message_content, +					&mg->min_error); +    if (GSS_ERROR(major_status)) { +	mg->min_error.value = NULL; +	mg->min_error.length = 0; +    } +} + +void +gss_mg_collect_error(gss_OID mech, OM_uint32 maj, OM_uint32 min) +{ +    gssapi_mech_interface m = __gss_get_mechanism(mech); +    if (m == NULL) +	return; +    _gss_mg_error(m, maj, min); +} diff --git a/source4/heimdal/lib/gssapi/mech/context.h b/source4/heimdal/lib/gssapi/mech/context.h new file mode 100644 index 0000000000..f2a7009cda --- /dev/null +++ b/source4/heimdal/lib/gssapi/mech/context.h @@ -0,0 +1,41 @@ +/*- + * Copyright (c) 2005 Doug Rabson + * 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 AUTHOR 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 AUTHOR 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. + * + *	$FreeBSD: src/lib/libgssapi/context.h,v 1.1 2005/12/29 14:40:20 dfr Exp $ + *	$Id$ + */ + +#include <gssapi_mech.h> + +struct _gss_context { +	gssapi_mech_interface	gc_mech; +	gss_ctx_id_t		gc_ctx; +}; + +void +_gss_mg_error(gssapi_mech_interface, OM_uint32, OM_uint32); + +OM_uint32 +_gss_mg_get_error(const gss_OID, OM_uint32, OM_uint32, gss_buffer_t); diff --git a/source4/heimdal/lib/gssapi/mech/cred.h b/source4/heimdal/lib/gssapi/mech/cred.h new file mode 100644 index 0000000000..01bd882dda --- /dev/null +++ b/source4/heimdal/lib/gssapi/mech/cred.h @@ -0,0 +1,41 @@ +/*- + * Copyright (c) 2005 Doug Rabson + * 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 AUTHOR 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 AUTHOR 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. + * + *	$FreeBSD: src/lib/libgssapi/cred.h,v 1.1 2005/12/29 14:40:20 dfr Exp $ + *	$Id$ + */ + +struct _gss_mechanism_cred { +	SLIST_ENTRY(_gss_mechanism_cred) gmc_link; +	gssapi_mech_interface	gmc_mech;	/* mechanism ops for MC */ +	gss_OID			gmc_mech_oid;	/* mechanism oid for MC */ +	gss_cred_id_t		gmc_cred;	/* underlying MC */ +}; +SLIST_HEAD(_gss_mechanism_cred_list, _gss_mechanism_cred); + +struct _gss_cred { +	struct _gss_mechanism_cred_list gc_mc; +}; + diff --git a/source4/heimdal/lib/gssapi/mech/gss_accept_sec_context.c b/source4/heimdal/lib/gssapi/mech/gss_accept_sec_context.c new file mode 100644 index 0000000000..5fa102193e --- /dev/null +++ b/source4/heimdal/lib/gssapi/mech/gss_accept_sec_context.c @@ -0,0 +1,291 @@ +/*- + * Copyright (c) 2005 Doug Rabson + * 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 AUTHOR 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 AUTHOR 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. + * + *	$FreeBSD: src/lib/libgssapi/gss_accept_sec_context.c,v 1.1 2005/12/29 14:40:20 dfr Exp $ + */ + +#include "mech_locl.h" +RCSID("$Id$"); + +static OM_uint32 +parse_header(const gss_buffer_t input_token, gss_OID mech_oid) +{ +	unsigned char *p = input_token->value; +	size_t len = input_token->length; +	size_t a, b; +	 +	/* +	 * Token must start with [APPLICATION 0] SEQUENCE. +	 * But if it doesn't assume it is DCE-STYLE Kerberos! +	 */ +	if (len == 0) +		return (GSS_S_DEFECTIVE_TOKEN); +	 +	p++; +	len--; +		 +	/* +	 * Decode the length and make sure it agrees with the +	 * token length. +	 */ +	if (len == 0) +		return (GSS_S_DEFECTIVE_TOKEN); +	if ((*p & 0x80) == 0) { +		a = *p; +		p++; +		len--; +	} else { +		b = *p & 0x7f; +		p++; +		len--; +		if (len < b) +		    return (GSS_S_DEFECTIVE_TOKEN); +		a = 0; +		while (b) { +		    a = (a << 8) | *p; +		    p++; +		    len--; +		    b--; +		} +	} +	if (a != len) +		return (GSS_S_DEFECTIVE_TOKEN); +		 +	/* +	 * Decode the OID for the mechanism. Simplify life by +	 * assuming that the OID length is less than 128 bytes. +	 */ +	if (len < 2 || *p != 0x06) +		return (GSS_S_DEFECTIVE_TOKEN); +	if ((p[1] & 0x80) || p[1] > (len - 2)) +		return (GSS_S_DEFECTIVE_TOKEN); +	mech_oid->length = p[1]; +	p += 2; +	len -= 2; +	mech_oid->elements = p; +	 +	return GSS_S_COMPLETE; +}		        + +static gss_OID_desc krb5_mechanism = +    {9, rk_UNCONST("\x2a\x86\x48\x86\xf7\x12\x01\x02\x02")}; +static gss_OID_desc ntlm_mechanism = +    {10, rk_UNCONST("\x2b\x06\x01\x04\x01\x82\x37\x02\x02\x0a")}; +static gss_OID_desc spnego_mechanism = +    {6, rk_UNCONST("\x2b\x06\x01\x05\x05\x02")}; + +static OM_uint32 +choose_mech(const gss_buffer_t input, gss_OID mech_oid) +{ +	OM_uint32 status; + +	/* +	 * First try to parse the gssapi token header and see if it's a +	 * correct header, use that in the first hand. +	 */ + +	status = parse_header(input, mech_oid); +	if (status == GSS_S_COMPLETE) +	    return GSS_S_COMPLETE; +     +	/* +	 * Lets guess what mech is really is, callback function to mech ?? +	 */ + +	if (input->length > 8 &&  +	    memcmp((const char *)input->value, "NTLMSSP\x00", 8) == 0) +	{ +		*mech_oid = ntlm_mechanism; +		return GSS_S_COMPLETE; +	} else if (input->length != 0 && +		   ((const char *)input->value)[0] == 0x6E) +	{ +		/* Could be a raw AP-REQ (check for APPLICATION tag) */ +		*mech_oid = krb5_mechanism; +		return GSS_S_COMPLETE; +	} else if (input->length == 0) { +		/*  +		 * There is the a wierd mode of SPNEGO (in CIFS and +		 * SASL GSS-SPENGO where the first token is zero +		 * length and the acceptor returns a mech_list, lets +		 * hope that is what is happening now. +		 */ +		*mech_oid = spnego_mechanism; +		return GSS_S_COMPLETE; +	} +	return status; +} + + +OM_uint32 gss_accept_sec_context(OM_uint32 *minor_status, +    gss_ctx_id_t *context_handle, +    const gss_cred_id_t acceptor_cred_handle, +    const gss_buffer_t input_token, +    const gss_channel_bindings_t input_chan_bindings, +    gss_name_t *src_name, +    gss_OID *mech_type, +    gss_buffer_t output_token, +    OM_uint32 *ret_flags, +    OM_uint32 *time_rec, +    gss_cred_id_t *delegated_cred_handle) +{ +	OM_uint32 major_status, mech_ret_flags, junk; +	gssapi_mech_interface m; +	struct _gss_context *ctx = (struct _gss_context *) *context_handle; +	struct _gss_cred *cred = (struct _gss_cred *) acceptor_cred_handle; +	struct _gss_mechanism_cred *mc; +	gss_cred_id_t acceptor_mc, delegated_mc; +	gss_name_t src_mn; + +	*minor_status = 0; +	if (src_name) +	    *src_name = GSS_C_NO_NAME; +	if (mech_type) +	    *mech_type = GSS_C_NO_OID; +	if (ret_flags) +	    *ret_flags = 0; +	if (time_rec) +	    *time_rec = 0; +	if (delegated_cred_handle) +	    *delegated_cred_handle = GSS_C_NO_CREDENTIAL; +	_mg_buffer_zero(output_token); + + +	/* +	 * If this is the first call (*context_handle is NULL), we must +	 * parse the input token to figure out the mechanism to use. +	 */ +	if (*context_handle == GSS_C_NO_CONTEXT) { +		gss_OID_desc mech_oid; + +		major_status = choose_mech(input_token, &mech_oid); +		if (major_status != GSS_S_COMPLETE) +			return major_status; + +		/* +		 * Now that we have a mechanism, we can find the +		 * implementation. +		 */ +		ctx = malloc(sizeof(struct _gss_context)); +		if (!ctx) { +			*minor_status = ENOMEM; +			return (GSS_S_DEFECTIVE_TOKEN); +		} +		memset(ctx, 0, sizeof(struct _gss_context)); +		m = ctx->gc_mech = __gss_get_mechanism(&mech_oid); +		if (!m) { +			free(ctx); +			return (GSS_S_BAD_MECH); +		} +		*context_handle = (gss_ctx_id_t) ctx; +	} else { +		m = ctx->gc_mech; +	} + +	if (cred) { +		SLIST_FOREACH(mc, &cred->gc_mc, gmc_link) +			if (mc->gmc_mech == m) +				break; +		if (!mc) { +		        gss_delete_sec_context(&junk, context_handle, NULL); +			return (GSS_S_BAD_MECH); +		} +		acceptor_mc = mc->gmc_cred; +	} else { +		acceptor_mc = GSS_C_NO_CREDENTIAL; +	} +	delegated_mc = GSS_C_NO_CREDENTIAL; +	 +	mech_ret_flags = 0; +	major_status = m->gm_accept_sec_context(minor_status, +	    &ctx->gc_ctx, +	    acceptor_mc, +	    input_token, +	    input_chan_bindings, +	    &src_mn, +	    mech_type, +	    output_token, +	    &mech_ret_flags, +	    time_rec, +	    &delegated_mc); +	if (major_status != GSS_S_COMPLETE && +	    major_status != GSS_S_CONTINUE_NEEDED) +	{ +		_gss_mg_error(m, major_status, *minor_status); +		gss_delete_sec_context(&junk, context_handle, NULL); +		return (major_status); +	} + +	if (src_name && src_mn) { +		/* +		 * Make a new name and mark it as an MN. +		 */ +		struct _gss_name *name = _gss_make_name(m, src_mn); + +		if (!name) { +			m->gm_release_name(minor_status, &src_mn); +		        gss_delete_sec_context(&junk, context_handle, NULL); +			return (GSS_S_FAILURE); +		} +		*src_name = (gss_name_t) name; +	} else if (src_mn) { +		m->gm_release_name(minor_status, &src_mn); +	} + +	if (mech_ret_flags & GSS_C_DELEG_FLAG) { +		if (!delegated_cred_handle) { +			m->gm_release_cred(minor_status, &delegated_mc); +			*ret_flags &= ~GSS_C_DELEG_FLAG; +		} else if (delegated_mc) { +			struct _gss_cred *dcred; +			struct _gss_mechanism_cred *dmc; + +			dcred = malloc(sizeof(struct _gss_cred)); +			if (!dcred) { +				*minor_status = ENOMEM; +				gss_delete_sec_context(&junk, context_handle, NULL); +				return (GSS_S_FAILURE); +			} +			SLIST_INIT(&dcred->gc_mc); +			dmc = malloc(sizeof(struct _gss_mechanism_cred)); +			if (!dmc) { +				free(dcred); +				*minor_status = ENOMEM; +				gss_delete_sec_context(&junk, context_handle, NULL); +				return (GSS_S_FAILURE); +			} +			dmc->gmc_mech = m; +			dmc->gmc_mech_oid = &m->gm_mech_oid; +			dmc->gmc_cred = delegated_mc; +			SLIST_INSERT_HEAD(&dcred->gc_mc, dmc, gmc_link); + +			*delegated_cred_handle = (gss_cred_id_t) dcred; +		} +	} + +	if (ret_flags) +	    *ret_flags = mech_ret_flags; +	return (major_status); +} diff --git a/source4/heimdal/lib/gssapi/mech/gss_acquire_cred.c b/source4/heimdal/lib/gssapi/mech/gss_acquire_cred.c new file mode 100644 index 0000000000..b21b3f62e8 --- /dev/null +++ b/source4/heimdal/lib/gssapi/mech/gss_acquire_cred.c @@ -0,0 +1,169 @@ +/*- + * Copyright (c) 2005 Doug Rabson + * 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 AUTHOR 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 AUTHOR 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. + * + *	$FreeBSD: src/lib/libgssapi/gss_acquire_cred.c,v 1.1 2005/12/29 14:40:20 dfr Exp $ + */ + +#include "mech_locl.h" +RCSID("$Id$"); + +OM_uint32 GSSAPI_LIB_FUNCTION +gss_acquire_cred(OM_uint32 *minor_status, +    const gss_name_t desired_name, +    OM_uint32 time_req, +    const gss_OID_set desired_mechs, +    gss_cred_usage_t cred_usage, +    gss_cred_id_t *output_cred_handle, +    gss_OID_set *actual_mechs, +    OM_uint32 *time_rec) +{ +	OM_uint32 major_status; +	gss_OID_set mechs = desired_mechs; +	gss_OID_set_desc set; +	struct _gss_name *name = (struct _gss_name *) desired_name; +	gssapi_mech_interface m; +	struct _gss_cred *cred; +	struct _gss_mechanism_cred *mc; +	OM_uint32 min_time, cred_time; +	int i; + +	*minor_status = 0; +	if (output_cred_handle) +	    *output_cred_handle = GSS_C_NO_CREDENTIAL; +	if (actual_mechs) +	    *actual_mechs = GSS_C_NO_OID_SET; +	if (time_rec) +	    *time_rec = 0; + +	_gss_load_mech(); + +	/* +	 * First make sure that at least one of the requested +	 * mechanisms is one that we support. +	 */ +	if (mechs) { +		for (i = 0; i < mechs->count; i++) { +			int t; +			gss_test_oid_set_member(minor_status, +			    &mechs->elements[i], _gss_mech_oids, &t); +			if (t) +				break; +		} +		if (i == mechs->count) { +			*minor_status = 0; +			return (GSS_S_BAD_MECH); +		} +	} + +	if (actual_mechs) { +		major_status = gss_create_empty_oid_set(minor_status, +		    actual_mechs); +		if (major_status) +			return (major_status); +	} + +	cred = malloc(sizeof(struct _gss_cred)); +	if (!cred) { +		if (actual_mechs) +			gss_release_oid_set(minor_status, actual_mechs); +		*minor_status = ENOMEM; +		return (GSS_S_FAILURE); +	} +	SLIST_INIT(&cred->gc_mc); + +	if (mechs == GSS_C_NO_OID_SET) +		mechs = _gss_mech_oids; + +	set.count = 1; +	min_time = GSS_C_INDEFINITE; +	for (i = 0; i < mechs->count; i++) { +		struct _gss_mechanism_name *mn = NULL; + +		m = __gss_get_mechanism(&mechs->elements[i]); +		if (!m) +			continue; + +		if (desired_name != GSS_C_NO_NAME) { +			major_status = _gss_find_mn(minor_status, name, +						    &mechs->elements[i], &mn); +			if (major_status != GSS_S_COMPLETE) +				continue; +		} + +		mc = malloc(sizeof(struct _gss_mechanism_cred)); +		if (!mc) { +			continue; +		} +		mc->gmc_mech = m; +		mc->gmc_mech_oid = &m->gm_mech_oid; + +		/* +		 * XXX Probably need to do something with actual_mechs. +		 */ +		set.elements = &mechs->elements[i]; +		major_status = m->gm_acquire_cred(minor_status, +		    (desired_name != GSS_C_NO_NAME +			? mn->gmn_name : GSS_C_NO_NAME), +		    time_req, &set, cred_usage, +		    &mc->gmc_cred, NULL, &cred_time); +		if (major_status) { +			free(mc); +			continue; +		} +		if (cred_time < min_time) +			min_time = cred_time; + +		if (actual_mechs) { +			major_status = gss_add_oid_set_member(minor_status, +			    mc->gmc_mech_oid, actual_mechs); +			if (major_status) { +				m->gm_release_cred(minor_status, +				    &mc->gmc_cred); +				free(mc); +				continue; +			} +		} + +		SLIST_INSERT_HEAD(&cred->gc_mc, mc, gmc_link); +	} + +	/* +	 * If we didn't manage to create a single credential, return +	 * an error. +	 */ +	if (!SLIST_FIRST(&cred->gc_mc)) { +		free(cred); +		if (actual_mechs) +			gss_release_oid_set(minor_status, actual_mechs); +		*minor_status = 0; +		return (GSS_S_NO_CRED); +	} + +	if (time_rec) +		*time_rec = min_time; +	*output_cred_handle = (gss_cred_id_t) cred; +	*minor_status = 0; +	return (GSS_S_COMPLETE); +} diff --git a/source4/heimdal/lib/gssapi/mech/gss_add_cred.c b/source4/heimdal/lib/gssapi/mech/gss_add_cred.c new file mode 100644 index 0000000000..d190852884 --- /dev/null +++ b/source4/heimdal/lib/gssapi/mech/gss_add_cred.c @@ -0,0 +1,187 @@ +/*- + * Copyright (c) 2005 Doug Rabson + * 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 AUTHOR 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 AUTHOR 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. + * + *	$FreeBSD: src/lib/libgssapi/gss_add_cred.c,v 1.1 2005/12/29 14:40:20 dfr Exp $ + */ + +#include "mech_locl.h" +RCSID("$Id$"); + +static struct _gss_mechanism_cred * +_gss_copy_cred(struct _gss_mechanism_cred *mc) +{ +	struct _gss_mechanism_cred *new_mc; +	gssapi_mech_interface m = mc->gmc_mech; +	OM_uint32 major_status, minor_status; +	gss_name_t name; +	gss_cred_id_t cred; +	OM_uint32 initiator_lifetime, acceptor_lifetime; +	gss_cred_usage_t cred_usage; + +	major_status = m->gm_inquire_cred_by_mech(&minor_status, +	    mc->gmc_cred, mc->gmc_mech_oid, +	    &name, &initiator_lifetime, &acceptor_lifetime, &cred_usage); +	if (major_status) { +		_gss_mg_error(m, major_status, minor_status); +		return (0); +	} + +	major_status = m->gm_add_cred(&minor_status, +	    GSS_C_NO_CREDENTIAL, name, mc->gmc_mech_oid, +	    cred_usage, initiator_lifetime, acceptor_lifetime, +	    &cred, 0, 0, 0); +	m->gm_release_name(&minor_status, &name); + +	if (major_status) { +		_gss_mg_error(m, major_status, minor_status); +		return (0); +	} + +	new_mc = malloc(sizeof(struct _gss_mechanism_cred)); +	if (!new_mc) { +		m->gm_release_cred(&minor_status, &cred); +		return (0); +	} +	new_mc->gmc_mech = m; +	new_mc->gmc_mech_oid = &m->gm_mech_oid; +	new_mc->gmc_cred = cred; + +	return (new_mc); +} + +OM_uint32 GSSAPI_LIB_FUNCTION +gss_add_cred(OM_uint32 *minor_status, +    const gss_cred_id_t input_cred_handle, +    const gss_name_t desired_name, +    const gss_OID desired_mech, +    gss_cred_usage_t cred_usage, +    OM_uint32 initiator_time_req, +    OM_uint32 acceptor_time_req, +    gss_cred_id_t *output_cred_handle, +    gss_OID_set *actual_mechs, +    OM_uint32 *initiator_time_rec, +    OM_uint32 *acceptor_time_rec) +{ +	OM_uint32 major_status; +	gssapi_mech_interface m; +	struct _gss_cred *cred = (struct _gss_cred *) input_cred_handle; +	struct _gss_cred *new_cred; +	gss_cred_id_t release_cred; +	struct _gss_mechanism_cred *mc, *target_mc, *copy_mc; +	struct _gss_mechanism_name *mn; +	OM_uint32 junk; + +	*minor_status = 0; +	*output_cred_handle = GSS_C_NO_CREDENTIAL; +	if (initiator_time_rec) +	    *initiator_time_rec = 0; +	if (acceptor_time_rec) +	    *acceptor_time_rec = 0; +	if (actual_mechs) +	    *actual_mechs = GSS_C_NO_OID_SET; + +	new_cred = malloc(sizeof(struct _gss_cred)); +	if (!new_cred) { +		*minor_status = ENOMEM; +		return (GSS_S_FAILURE); +	} +	SLIST_INIT(&new_cred->gc_mc); + +	/* +	 * We go through all the mc attached to the input_cred_handle +	 * and check the mechanism. If it matches, we call +	 * gss_add_cred for that mechanism, otherwise we copy the mc +	 * to new_cred. +	 */ +	target_mc = 0; +	if (cred) { +		SLIST_FOREACH(mc, &cred->gc_mc, gmc_link) { +			if (gss_oid_equal(mc->gmc_mech_oid, desired_mech)) { +				target_mc = mc; +			} +			copy_mc = _gss_copy_cred(mc); +			if (!copy_mc) { +				release_cred = (gss_cred_id_t)new_cred; +				gss_release_cred(&junk, &release_cred); +				*minor_status = ENOMEM; +				return (GSS_S_FAILURE); +			} +			SLIST_INSERT_HEAD(&new_cred->gc_mc, copy_mc, gmc_link); +		} +	} + +	/* +	 * Figure out a suitable mn, if any. +	 */ +	if (desired_name) { +		major_status = _gss_find_mn(minor_status, +					    (struct _gss_name *) desired_name, +					    desired_mech, +					    &mn); +		if (major_status != GSS_S_COMPLETE) { +			free(new_cred); +			return major_status; +		} +	} else { +		mn = 0; +	} + +	m = __gss_get_mechanism(desired_mech); + +	mc = malloc(sizeof(struct _gss_mechanism_cred)); +	if (!mc) { +		release_cred = (gss_cred_id_t)new_cred; +		gss_release_cred(&junk, &release_cred); +		*minor_status = ENOMEM; +		return (GSS_S_FAILURE); +	} +	mc->gmc_mech = m; +	mc->gmc_mech_oid = &m->gm_mech_oid; + +	major_status = m->gm_add_cred(minor_status, +	    target_mc ? target_mc->gmc_cred : GSS_C_NO_CREDENTIAL, +	    desired_name ? mn->gmn_name : GSS_C_NO_NAME, +	    desired_mech, +	    cred_usage, +	    initiator_time_req, +	    acceptor_time_req, +	    &mc->gmc_cred, +	    actual_mechs, +	    initiator_time_rec, +	    acceptor_time_rec); + +	if (major_status) { +		_gss_mg_error(m, major_status, *minor_status); +		release_cred = (gss_cred_id_t)new_cred; +		gss_release_cred(&junk, &release_cred); +		free(mc); +		return (major_status); +	} +	SLIST_INSERT_HEAD(&new_cred->gc_mc, mc, gmc_link); +	*output_cred_handle = (gss_cred_id_t) new_cred; + +	return (GSS_S_COMPLETE); +} + diff --git a/source4/heimdal/lib/gssapi/mech/gss_add_oid_set_member.c b/source4/heimdal/lib/gssapi/mech/gss_add_oid_set_member.c new file mode 100644 index 0000000000..1214e72fa9 --- /dev/null +++ b/source4/heimdal/lib/gssapi/mech/gss_add_oid_set_member.c @@ -0,0 +1,67 @@ +/* + * Copyright (c) 1997 - 2001, 2003 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.  + */ + +#include "mech_locl.h" +RCSID("$Id$"); + +OM_uint32 GSSAPI_LIB_FUNCTION +gss_add_oid_set_member (OM_uint32 * minor_status, +			const gss_OID member_oid, +			gss_OID_set * oid_set) +{ +    gss_OID tmp; +    size_t n; +    OM_uint32 res; +    int present; + +    res = gss_test_oid_set_member(minor_status, member_oid, *oid_set, &present); +    if (res != GSS_S_COMPLETE) +	return res; + +    if (present) { +	*minor_status = 0; +	return GSS_S_COMPLETE; +    } + +    n = (*oid_set)->count + 1; +    tmp = realloc ((*oid_set)->elements, n * sizeof(gss_OID_desc)); +    if (tmp == NULL) { +	*minor_status = ENOMEM; +	return GSS_S_FAILURE; +    } +    (*oid_set)->elements = tmp; +    (*oid_set)->count = n; +    (*oid_set)->elements[n-1] = *member_oid; +    *minor_status = 0; +    return GSS_S_COMPLETE; +} diff --git a/source4/heimdal/lib/gssapi/mech/gss_buffer_set.c b/source4/heimdal/lib/gssapi/mech/gss_buffer_set.c new file mode 100644 index 0000000000..9f0bb4cce3 --- /dev/null +++ b/source4/heimdal/lib/gssapi/mech/gss_buffer_set.c @@ -0,0 +1,125 @@ +/* + * Copyright (c) 2004, PADL Software Pty Ltd. + * 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 PADL Software 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 PADL SOFTWARE 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 PADL SOFTWARE 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. + */ + +#include "mech_locl.h" +RCSID("$Id$"); + +OM_uint32 GSSAPI_LIB_FUNCTION +gss_create_empty_buffer_set +	   (OM_uint32 * minor_status, +	    gss_buffer_set_t *buffer_set) +{ +    gss_buffer_set_t set; + +    set = (gss_buffer_set_desc *) malloc(sizeof(*set)); +    if (set == GSS_C_NO_BUFFER_SET) { +	*minor_status = ENOMEM; +	return GSS_S_FAILURE; +    } + +    set->count = 0; +    set->elements = NULL; + +    *buffer_set = set; + +    *minor_status = 0; +    return GSS_S_COMPLETE; +} + +OM_uint32 GSSAPI_LIB_FUNCTION +gss_add_buffer_set_member +	   (OM_uint32 * minor_status, +	    const gss_buffer_t member_buffer, +	    gss_buffer_set_t *buffer_set) +{ +    gss_buffer_set_t set; +    gss_buffer_t p; +    OM_uint32 ret; + +    if (*buffer_set == GSS_C_NO_BUFFER_SET) { +	ret = gss_create_empty_buffer_set(minor_status, +					  buffer_set); +	if (ret) { +	    return ret; +	} +    } + +    set = *buffer_set; +    set->elements = realloc(set->elements, +			    (set->count + 1) * sizeof(set->elements[0])); +    if (set->elements == NULL) { +	*minor_status = ENOMEM; +	return GSS_S_FAILURE; +    } + +    p = &set->elements[set->count]; + +    p->value = malloc(member_buffer->length); +    if (p->value == NULL) { +	*minor_status = ENOMEM; +	return GSS_S_FAILURE; +    } +    memcpy(p->value, member_buffer->value, member_buffer->length); +    p->length = member_buffer->length; + +    set->count++; + +    *minor_status = 0; +    return GSS_S_COMPLETE; +} + +OM_uint32 GSSAPI_LIB_FUNCTION +gss_release_buffer_set(OM_uint32 * minor_status, +		       gss_buffer_set_t *buffer_set) +{ +    int i; +    OM_uint32 minor; + +    *minor_status = 0; + +    if (*buffer_set == GSS_C_NO_BUFFER_SET) +	return GSS_S_COMPLETE; + +    for (i = 0; i < (*buffer_set)->count; i++) +	gss_release_buffer(&minor, &((*buffer_set)->elements[i])); + +    free((*buffer_set)->elements); + +    (*buffer_set)->elements = NULL; +    (*buffer_set)->count = 0; + +    free(*buffer_set); +    *buffer_set = GSS_C_NO_BUFFER_SET; + +    return GSS_S_COMPLETE; +} + diff --git a/source4/heimdal/lib/gssapi/mech/gss_canonicalize_name.c b/source4/heimdal/lib/gssapi/mech/gss_canonicalize_name.c new file mode 100644 index 0000000000..91a08fb2bc --- /dev/null +++ b/source4/heimdal/lib/gssapi/mech/gss_canonicalize_name.c @@ -0,0 +1,88 @@ +/*- + * Copyright (c) 2005 Doug Rabson + * 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 AUTHOR 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 AUTHOR 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. + * + *	$FreeBSD: src/lib/libgssapi/gss_canonicalize_name.c,v 1.1 2005/12/29 14:40:20 dfr Exp $ + */ + +#include "mech_locl.h" +RCSID("$Id$"); + +OM_uint32 GSSAPI_LIB_FUNCTION +gss_canonicalize_name(OM_uint32 *minor_status, +    const gss_name_t input_name, +    const gss_OID mech_type, +    gss_name_t *output_name) +{ +	OM_uint32 major_status; +	struct _gss_name *name = (struct _gss_name *) input_name; +	struct _gss_mechanism_name *mn; +	gssapi_mech_interface m; +	gss_name_t new_canonical_name; + +	*minor_status = 0; +	*output_name = 0; + +	major_status = _gss_find_mn(minor_status, name, mech_type, &mn); +	if (major_status) +		return major_status; + +	m = mn->gmn_mech; +	major_status = m->gm_canonicalize_name(minor_status, +	    mn->gmn_name, mech_type, &new_canonical_name); +	if (major_status) { +		_gss_mg_error(m, major_status, *minor_status); +		return (major_status); +	} + +	/* +	 * Now we make a new name and mark it as an MN. +	 */ +	*minor_status = 0; +	name = malloc(sizeof(struct _gss_name)); +	if (!name) { +		m->gm_release_name(minor_status, &new_canonical_name); +		*minor_status = ENOMEM; +		return (GSS_S_FAILURE); +	} +	memset(name, 0, sizeof(struct _gss_name)); + +	mn = malloc(sizeof(struct _gss_mechanism_name)); +	if (!mn) { +		m->gm_release_name(minor_status, &new_canonical_name); +		free(name); +		*minor_status = ENOMEM; +		return (GSS_S_FAILURE); +	} + +	SLIST_INIT(&name->gn_mn); +	mn->gmn_mech = m; +	mn->gmn_mech_oid = &m->gm_mech_oid; +	mn->gmn_name = new_canonical_name; +	SLIST_INSERT_HEAD(&name->gn_mn, mn, gmn_link); + +	*output_name = (gss_name_t) name; + +	return (GSS_S_COMPLETE); +} diff --git a/source4/heimdal/lib/gssapi/mech/gss_compare_name.c b/source4/heimdal/lib/gssapi/mech/gss_compare_name.c new file mode 100644 index 0000000000..3f2d0013c5 --- /dev/null +++ b/source4/heimdal/lib/gssapi/mech/gss_compare_name.c @@ -0,0 +1,77 @@ +/*- + * Copyright (c) 2005 Doug Rabson + * 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 AUTHOR 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 AUTHOR 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. + * + *	$FreeBSD: src/lib/libgssapi/gss_compare_name.c,v 1.1 2005/12/29 14:40:20 dfr Exp $ + */ + +#include "mech_locl.h" +RCSID("$Id$"); + +OM_uint32 GSSAPI_LIB_FUNCTION +gss_compare_name(OM_uint32 *minor_status, +    const gss_name_t name1_arg, +    const gss_name_t name2_arg, +    int *name_equal) +{ +	struct _gss_name *name1 = (struct _gss_name *) name1_arg; +	struct _gss_name *name2 = (struct _gss_name *) name2_arg; + +	/* +	 * First check the implementation-independant name if both +	 * names have one. Otherwise, try to find common mechanism +	 * names and compare them. +	 */ +	if (name1->gn_value.value && name2->gn_value.value) { +		*name_equal = 1; +		if (!gss_oid_equal(&name1->gn_type, &name2->gn_type)) { +			*name_equal = 0; +		} else if (name1->gn_value.length != name2->gn_value.length || +		    memcmp(name1->gn_value.value, name1->gn_value.value, +			name1->gn_value.length)) { +			*name_equal = 0; +		} +	} else { +		struct _gss_mechanism_name *mn1; +		struct _gss_mechanism_name *mn2; + +		SLIST_FOREACH(mn1, &name1->gn_mn, gmn_link) { +			OM_uint32 major_status; + +			major_status = _gss_find_mn(minor_status, name2, +						    mn1->gmn_mech_oid, &mn2); +			if (major_status == GSS_S_COMPLETE) { +				return (mn1->gmn_mech->gm_compare_name( +						minor_status, +						mn1->gmn_name, +						mn2->gmn_name, +						name_equal)); +			} +		} +		*name_equal = 0; +	} + +	*minor_status = 0; +	return (GSS_S_COMPLETE); +} diff --git a/source4/heimdal/lib/gssapi/mech/gss_context_time.c b/source4/heimdal/lib/gssapi/mech/gss_context_time.c new file mode 100644 index 0000000000..df89612060 --- /dev/null +++ b/source4/heimdal/lib/gssapi/mech/gss_context_time.c @@ -0,0 +1,41 @@ +/*- + * Copyright (c) 2005 Doug Rabson + * 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 AUTHOR 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 AUTHOR 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. + * + *	$FreeBSD: src/lib/libgssapi/gss_context_time.c,v 1.1 2005/12/29 14:40:20 dfr Exp $ + */ + +#include "mech_locl.h" +RCSID("$Id$"); + +OM_uint32 GSSAPI_LIB_FUNCTION +gss_context_time(OM_uint32 *minor_status, +    const gss_ctx_id_t context_handle, +    OM_uint32 *time_rec) +{ +	struct _gss_context *ctx = (struct _gss_context *) context_handle; +	gssapi_mech_interface m = ctx->gc_mech; + +	return (m->gm_context_time(minor_status, ctx->gc_ctx, time_rec)); +} diff --git a/source4/heimdal/lib/gssapi/mech/gss_create_empty_oid_set.c b/source4/heimdal/lib/gssapi/mech/gss_create_empty_oid_set.c new file mode 100644 index 0000000000..8858f28498 --- /dev/null +++ b/source4/heimdal/lib/gssapi/mech/gss_create_empty_oid_set.c @@ -0,0 +1,52 @@ +/*- + * Copyright (c) 2005 Doug Rabson + * 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 AUTHOR 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 AUTHOR 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. + * + *	$FreeBSD: src/lib/libgssapi/gss_create_empty_oid_set.c,v 1.1 2005/12/29 14:40:20 dfr Exp $ + */ + +#include "mech_locl.h" +RCSID("$Id$"); + +OM_uint32 GSSAPI_LIB_FUNCTION +gss_create_empty_oid_set(OM_uint32 *minor_status, +    gss_OID_set *oid_set) +{ +	gss_OID_set set; + +	*minor_status = 0; +	*oid_set = GSS_C_NO_OID_SET; + +	set = malloc(sizeof(gss_OID_set_desc)); +	if (!set) { +		*minor_status = ENOMEM; +		return (GSS_S_FAILURE); +	} + +	set->count = 0; +	set->elements = 0; +	*oid_set = set; + +	return (GSS_S_COMPLETE); +} diff --git a/source4/heimdal/lib/gssapi/mech/gss_decapsulate_token.c b/source4/heimdal/lib/gssapi/mech/gss_decapsulate_token.c new file mode 100644 index 0000000000..6dba77e410 --- /dev/null +++ b/source4/heimdal/lib/gssapi/mech/gss_decapsulate_token.c @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2006 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.  + */ + +#include "mech_locl.h" +RCSID("$Id$"); + +OM_uint32 GSSAPI_LIB_FUNCTION +gss_decapsulate_token(gss_buffer_t input_token, +		      gss_OID oid, +		      gss_buffer_t output_token) +{ +    GSSAPIContextToken ct; +    heim_oid o; +    OM_uint32 status; +    int ret; +    size_t size; + +    _mg_buffer_zero(output_token); + +    ret = der_get_oid (oid->elements, oid->length, &o, &size); +    if (ret) +	return GSS_S_FAILURE; + +    ret = decode_GSSAPIContextToken(input_token->value, input_token->length, +				    &ct, NULL); +    if (ret) { +	der_free_oid(&o); +	return GSS_S_FAILURE; +    }	 +     +    if (der_heim_oid_cmp(&ct.thisMech, &o) == 0) { +	status = GSS_S_COMPLETE; +	output_token->value = ct.innerContextToken.data; +	output_token->length = ct.innerContextToken.length; +	der_free_oid(&ct.thisMech); +    } else { +	free_GSSAPIContextToken(&ct); + 	status = GSS_S_FAILURE; +    } +    der_free_oid(&o); + +    return status; +} diff --git a/source4/heimdal/lib/gssapi/mech/gss_delete_sec_context.c b/source4/heimdal/lib/gssapi/mech/gss_delete_sec_context.c new file mode 100644 index 0000000000..96abae6b33 --- /dev/null +++ b/source4/heimdal/lib/gssapi/mech/gss_delete_sec_context.c @@ -0,0 +1,58 @@ +/*- + * Copyright (c) 2005 Doug Rabson + * 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 AUTHOR 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 AUTHOR 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. + * + *	$FreeBSD: src/lib/libgssapi/gss_delete_sec_context.c,v 1.1 2005/12/29 14:40:20 dfr Exp $ + */ + +#include "mech_locl.h" +RCSID("$Id$"); + +OM_uint32 GSSAPI_LIB_FUNCTION +gss_delete_sec_context(OM_uint32 *minor_status, +    gss_ctx_id_t *context_handle, +    gss_buffer_t output_token) +{ +	OM_uint32 major_status; +	struct _gss_context *ctx = (struct _gss_context *) *context_handle; + +	if (output_token) +	    _mg_buffer_zero(output_token); + +	*minor_status = 0; +	if (ctx) { +		/* +		 * If we have an implementation ctx, delete it, +		 * otherwise fake an empty token. +		 */ +		if (ctx->gc_ctx) { +			major_status = ctx->gc_mech->gm_delete_sec_context( +				minor_status, &ctx->gc_ctx, output_token); +		} +		free(ctx); +		*context_handle = GSS_C_NO_CONTEXT; +	} + +	return (GSS_S_COMPLETE); +} diff --git a/source4/heimdal/lib/gssapi/mech/gss_display_name.c b/source4/heimdal/lib/gssapi/mech/gss_display_name.c new file mode 100644 index 0000000000..d720ffe880 --- /dev/null +++ b/source4/heimdal/lib/gssapi/mech/gss_display_name.c @@ -0,0 +1,83 @@ +/*- + * Copyright (c) 2005 Doug Rabson + * 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 AUTHOR 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 AUTHOR 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. + * + *	$FreeBSD: src/lib/libgssapi/gss_display_name.c,v 1.1 2005/12/29 14:40:20 dfr Exp $ + */ + +#include "mech_locl.h" +RCSID("$Id$"); + +OM_uint32 GSSAPI_LIB_FUNCTION +gss_display_name(OM_uint32 *minor_status, +    const gss_name_t input_name, +    gss_buffer_t output_name_buffer, +    gss_OID *output_name_type) +{ +	OM_uint32 major_status; +	struct _gss_name *name = (struct _gss_name *) input_name; +	struct _gss_mechanism_name *mn; + +	_mg_buffer_zero(output_name_buffer); +	if (output_name_type) +	    *output_name_type = GSS_C_NO_OID; + +	if (name == NULL) { +		*minor_status = 0; +		return (GSS_S_BAD_NAME); +	} + +	/* +	 * If we know it, copy the buffer used to import the name in +	 * the first place. Otherwise, ask all the MNs in turn if +	 * they can display the thing. +	 */ +	if (name->gn_value.value) { +		output_name_buffer->value = malloc(name->gn_value.length); +		if (!output_name_buffer->value) { +			*minor_status = ENOMEM; +			return (GSS_S_FAILURE); +		} +		output_name_buffer->length = name->gn_value.length; +		memcpy(output_name_buffer->value, name->gn_value.value, +		    output_name_buffer->length); +		if (output_name_type) +			*output_name_type = &name->gn_type; + +		*minor_status = 0; +		return (GSS_S_COMPLETE); +	} else { +		SLIST_FOREACH(mn, &name->gn_mn, gmn_link) { +			major_status = mn->gmn_mech->gm_display_name( +				minor_status, mn->gmn_name, +				output_name_buffer, +				output_name_type); +			if (major_status == GSS_S_COMPLETE) +				return (GSS_S_COMPLETE); +		} +	} + +	*minor_status = 0; +	return (GSS_S_FAILURE); +} diff --git a/source4/heimdal/lib/gssapi/mech/gss_display_status.c b/source4/heimdal/lib/gssapi/mech/gss_display_status.c new file mode 100644 index 0000000000..7a91af2abc --- /dev/null +++ b/source4/heimdal/lib/gssapi/mech/gss_display_status.c @@ -0,0 +1,210 @@ +/*- + * Copyright (c) 2005 Doug Rabson + * 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 AUTHOR 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 AUTHOR 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. + * + *	$FreeBSD: src/lib/libgssapi/gss_display_status.c,v 1.1 2005/12/29 14:40:20 dfr Exp $ + */ +/* + * Copyright (c) 1998 - 2005 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.  + */ + +#include "mech_locl.h" +RCSID("$Id$"); + +static const char * +calling_error(OM_uint32 v) +{ +    static const char *msgs[] = { +	NULL,			/* 0 */ +	"A required input parameter could not be read.", /*  */ +	"A required output parameter could not be written.", /*  */ +	"A parameter was malformed" +    }; + +    v >>= GSS_C_CALLING_ERROR_OFFSET; + +    if (v == 0) +	return ""; +    else if (v >= sizeof(msgs)/sizeof(*msgs)) +	return "unknown calling error"; +    else +	return msgs[v]; +} + +static const char * +routine_error(OM_uint32 v) +{ +    static const char *msgs[] = { +	"Function completed successfully",			/* 0 */ +	"An unsupported mechanism was requested", +	"An invalid name was supplied", +	"A supplied name was of an unsupported type", +	"Incorrect channel bindings were supplied", +	"An invalid status code was supplied", +	"A token had an invalid MIC", +	"No credentials were supplied, " +	"or the credentials were unavailable or inaccessible.", +	"No context has been established", +	"A token was invalid", +	"A credential was invalid", +	"The referenced credentials have expired", +	"The context has expired", +	"Miscellaneous failure (see text)", +	"The quality-of-protection requested could not be provide", +	"The operation is forbidden by local security policy", +	"The operation or option is not available", +	"The requested credential element already exists", +	"The provided name was not a mechanism name.", +    }; + +    v >>= GSS_C_ROUTINE_ERROR_OFFSET; + +    if (v >= sizeof(msgs)/sizeof(*msgs)) +	return "unknown routine error"; +    else +	return msgs[v]; +} + +static const char * +supplementary_error(OM_uint32 v) +{ +    static const char *msgs[] = { +	"normal completion", +	"continuation call to routine required", +	"duplicate per-message token detected", +	"timed-out per-message token detected", +	"reordered (early) per-message token detected", +	"skipped predecessor token(s) detected" +    }; + +    v >>= GSS_C_SUPPLEMENTARY_OFFSET; + +    if (v >= sizeof(msgs)/sizeof(*msgs)) +	return "unknown routine error"; +    else +	return msgs[v]; +} + + +OM_uint32 GSSAPI_LIB_FUNCTION +gss_display_status(OM_uint32 *minor_status, +    OM_uint32 status_value, +    int status_type, +    const gss_OID mech_type, +    OM_uint32 *message_content, +    gss_buffer_t status_string) +{ +	OM_uint32 major_status; + +	_mg_buffer_zero(status_string); +	*message_content = 0; + +	major_status = _gss_mg_get_error(mech_type, status_type, +					 status_value, status_string); +	if (major_status == GSS_S_COMPLETE) { + +	    *message_content = 0; +	    *minor_status = 0; +	    return GSS_S_COMPLETE; +	} + +	*minor_status = 0; +	switch (status_type) { +	case GSS_C_GSS_CODE: { +		char *buf; + +		if (GSS_SUPPLEMENTARY_INFO(status_value)) +		    asprintf(&buf, "%s", supplementary_error( +		        GSS_SUPPLEMENTARY_INFO(status_value))); +		else +		    asprintf (&buf, "%s %s", +		        calling_error(GSS_CALLING_ERROR(status_value)), +			routine_error(GSS_ROUTINE_ERROR(status_value))); + +		if (buf == NULL) +		    break; + +		status_string->length = strlen(buf); +		status_string->value  = buf; + +		return GSS_S_COMPLETE; +	} +	case GSS_C_MECH_CODE: { +		OM_uint32 maj_junk, min_junk; +		gss_buffer_desc oid; +		char *buf; + +		maj_junk = gss_oid_to_str(&min_junk, mech_type, &oid); +		if (maj_junk != GSS_S_COMPLETE) { +		    oid.value = rk_UNCONST("unknown"); +		    oid.length = 7; +		} + +		asprintf (&buf, "unknown mech-code %lu for mech %.*s", +			  (unsigned long)status_value, +			  (int)oid.length, (char *)oid.value); +		if (maj_junk == GSS_S_COMPLETE) +		    gss_release_buffer(&min_junk, &oid); + +		if (buf == NULL) +		    break; + +		status_string->length = strlen(buf); +		status_string->value  = buf; + +		return GSS_S_COMPLETE; +	} +	} +	_mg_buffer_zero(status_string); +	return (GSS_S_BAD_STATUS); +} diff --git a/source4/heimdal/lib/gssapi/mech/gss_duplicate_name.c b/source4/heimdal/lib/gssapi/mech/gss_duplicate_name.c new file mode 100644 index 0000000000..6912e3329f --- /dev/null +++ b/source4/heimdal/lib/gssapi/mech/gss_duplicate_name.c @@ -0,0 +1,95 @@ +/*- + * Copyright (c) 2005 Doug Rabson + * 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 AUTHOR 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 AUTHOR 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. + * + *	$FreeBSD: src/lib/libgssapi/gss_duplicate_name.c,v 1.1 2005/12/29 14:40:20 dfr Exp $ + */ + +#include "mech_locl.h" +RCSID("$Id$"); + +OM_uint32 gss_duplicate_name(OM_uint32 *minor_status, +    const gss_name_t src_name, +    gss_name_t *dest_name) +{ +	OM_uint32		major_status; +	struct _gss_name	*name = (struct _gss_name *) src_name; +	struct _gss_name	*new_name; +	struct _gss_mechanism_name *mn; + +	*minor_status = 0; +	*dest_name = GSS_C_NO_NAME; + +	/* +	 * If this name has a value (i.e. it didn't come from +	 * gss_canonicalize_name(), we re-import the thing. Otherwise, +	 * we make copy of each mech names. +	 */ +	if (name->gn_value.value) { +		major_status = gss_import_name(minor_status, +		    &name->gn_value, &name->gn_type, dest_name); +		if (major_status != GSS_S_COMPLETE) +			return (major_status); +		new_name = (struct _gss_name *) *dest_name; +		 +		SLIST_FOREACH(mn, &name->gn_mn, gmn_link) { +		    struct _gss_mechanism_name *mn2; +		    _gss_find_mn(minor_status, new_name,  +				 mn->gmn_mech_oid, &mn2); +		} +	} else { +		new_name = malloc(sizeof(struct _gss_name)); +		if (!new_name) { +			*minor_status = ENOMEM; +			return (GSS_S_FAILURE); +		} +		memset(new_name, 0, sizeof(struct _gss_name)); +		SLIST_INIT(&new_name->gn_mn); +		*dest_name = (gss_name_t) new_name; +		 +		SLIST_FOREACH(mn, &name->gn_mn, gmn_link) { +			struct _gss_mechanism_name *new_mn; +			 +			new_mn = malloc(sizeof(*new_mn)); +			if (!new_mn) { +				*minor_status = ENOMEM; +				return GSS_S_FAILURE; +			} +			new_mn->gmn_mech = mn->gmn_mech; +			new_mn->gmn_mech_oid = mn->gmn_mech_oid; +			 +			major_status =  +			    mn->gmn_mech->gm_duplicate_name(minor_status, +				mn->gmn_name, &new_mn->gmn_name); +			if (major_status != GSS_S_COMPLETE) { +				free(new_mn); +				continue; +			} +			SLIST_INSERT_HEAD(&new_name->gn_mn, new_mn, gmn_link); +		} + +	} + +	return (GSS_S_COMPLETE); +} diff --git a/source4/heimdal/lib/gssapi/mech/gss_duplicate_oid.c b/source4/heimdal/lib/gssapi/mech/gss_duplicate_oid.c new file mode 100644 index 0000000000..59bd797766 --- /dev/null +++ b/source4/heimdal/lib/gssapi/mech/gss_duplicate_oid.c @@ -0,0 +1,68 @@ +/* + * Copyright (c) 1997 - 2003 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.  + */ + +#include "mech_locl.h" +RCSID("$Id$"); + +OM_uint32 gss_duplicate_oid ( +        OM_uint32 *minor_status, +	gss_OID src_oid, +	gss_OID *dest_oid +     ) +{ +    *minor_status = 0; + +    if (src_oid == GSS_C_NO_OID) { +	*dest_oid = GSS_C_NO_OID; +	return GSS_S_COMPLETE; +    } + +    *dest_oid = malloc(sizeof(**dest_oid)); +    if (*dest_oid == GSS_C_NO_OID) { +	*minor_status = ENOMEM; +	return GSS_S_FAILURE; +    } + +    (*dest_oid)->elements = malloc(src_oid->length); +    if ((*dest_oid)->elements == NULL) { +	free(*dest_oid); +	*dest_oid = GSS_C_NO_OID; +	*minor_status = ENOMEM; +	return GSS_S_FAILURE; +    } +    memcpy((*dest_oid)->elements, src_oid->elements, src_oid->length); +    (*dest_oid)->length = src_oid->length; + +    *minor_status = 0; +    return GSS_S_COMPLETE; +} diff --git a/source4/heimdal/lib/gssapi/mech/gss_encapsulate_token.c b/source4/heimdal/lib/gssapi/mech/gss_encapsulate_token.c new file mode 100644 index 0000000000..b9d06c28fa --- /dev/null +++ b/source4/heimdal/lib/gssapi/mech/gss_encapsulate_token.c @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2006 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.  + */ + +#include "mech_locl.h" +RCSID("$Id$"); + +OM_uint32 GSSAPI_LIB_FUNCTION +gss_encapsulate_token(gss_buffer_t input_token, +		      gss_OID oid, +		      gss_buffer_t output_token) +{ +    GSSAPIContextToken ct; +    int ret; +    size_t size; + +    ret = der_get_oid (oid->elements, oid->length, &ct.thisMech, &size); +    if (ret) { +	_mg_buffer_zero(output_token); +	return GSS_S_FAILURE; +    } + +    ct.innerContextToken.data = input_token->value; +    ct.innerContextToken.length = input_token->length; + +    ASN1_MALLOC_ENCODE(GSSAPIContextToken, +		       output_token->value, output_token->length, +		       &ct, &size, ret); +    der_free_oid(&ct.thisMech); +    if (ret) { +	_mg_buffer_zero(output_token); +	return GSS_S_FAILURE; +    }	 +    if (output_token->length != size) +	abort(); + +    return GSS_S_COMPLETE; +} diff --git a/source4/heimdal/lib/gssapi/mech/gss_export_name.c b/source4/heimdal/lib/gssapi/mech/gss_export_name.c new file mode 100644 index 0000000000..7c1e6791da --- /dev/null +++ b/source4/heimdal/lib/gssapi/mech/gss_export_name.c @@ -0,0 +1,55 @@ +/*- + * Copyright (c) 2005 Doug Rabson + * 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 AUTHOR 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 AUTHOR 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. + * + *	$FreeBSD: src/lib/libgssapi/gss_export_name.c,v 1.1 2005/12/29 14:40:20 dfr Exp $ + */ + +#include "mech_locl.h" +RCSID("$Id$"); + +OM_uint32 GSSAPI_LIB_FUNCTION +gss_export_name(OM_uint32 *minor_status, +    const gss_name_t input_name, +    gss_buffer_t exported_name) +{ +	struct _gss_name *name = (struct _gss_name *) input_name; +	struct _gss_mechanism_name *mn; + +	_mg_buffer_zero(exported_name); + +	/* +	 * If this name already has any attached MNs, export the first +	 * one, otherwise export based on the first mechanism in our +	 * list. +	 */ +	mn = SLIST_FIRST(&name->gn_mn); +	if (!mn) { +		*minor_status = 0; +		return (GSS_S_NAME_NOT_MN); +	} + +	return mn->gmn_mech->gm_export_name(minor_status, +	    mn->gmn_name, exported_name); +} diff --git a/source4/heimdal/lib/gssapi/mech/gss_export_sec_context.c b/source4/heimdal/lib/gssapi/mech/gss_export_sec_context.c new file mode 100644 index 0000000000..f3a6dc4fb5 --- /dev/null +++ b/source4/heimdal/lib/gssapi/mech/gss_export_sec_context.c @@ -0,0 +1,78 @@ +/*- + * Copyright (c) 2005 Doug Rabson + * 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 AUTHOR 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 AUTHOR 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. + * + *	$FreeBSD: src/lib/libgssapi/gss_export_sec_context.c,v 1.1 2005/12/29 14:40:20 dfr Exp $ + */ + +#include "mech_locl.h" +RCSID("$Id$"); + +OM_uint32 GSSAPI_LIB_FUNCTION +gss_export_sec_context(OM_uint32 *minor_status, +    gss_ctx_id_t *context_handle, +    gss_buffer_t interprocess_token) +{ +	OM_uint32 major_status; +	struct _gss_context *ctx = (struct _gss_context *) *context_handle; +	gssapi_mech_interface m = ctx->gc_mech; +	gss_buffer_desc buf; + +	_mg_buffer_zero(interprocess_token); + +	major_status = m->gm_export_sec_context(minor_status, +	    &ctx->gc_ctx, &buf); +	 +	if (major_status == GSS_S_COMPLETE) { +		unsigned char *p; + +		free(ctx); +		*context_handle = GSS_C_NO_CONTEXT; +		interprocess_token->length = buf.length +			+ 2 + m->gm_mech_oid.length; +		interprocess_token->value = malloc(interprocess_token->length); +		if (!interprocess_token->value) { +			/* +			 * We are in trouble here - the context is +			 * already gone. This is allowed as long as we +			 * set the caller's context_handle to +			 * GSS_C_NO_CONTEXT, which we did above. +			 * Return GSS_S_FAILURE. +			 */ +			_mg_buffer_zero(interprocess_token); +			*minor_status = ENOMEM; +			return (GSS_S_FAILURE); +		} +		p = interprocess_token->value; +		p[0] = m->gm_mech_oid.length >> 8; +		p[1] = m->gm_mech_oid.length; +		memcpy(p + 2, m->gm_mech_oid.elements, m->gm_mech_oid.length); +		memcpy(p + 2 + m->gm_mech_oid.length, buf.value, buf.length); +		gss_release_buffer(minor_status, &buf); +	} else { +		_gss_mg_error(m, major_status, *minor_status); +	} + +	return (major_status); +} diff --git a/source4/heimdal/lib/gssapi/mech/gss_get_mic.c b/source4/heimdal/lib/gssapi/mech/gss_get_mic.c new file mode 100644 index 0000000000..9cd5060fc9 --- /dev/null +++ b/source4/heimdal/lib/gssapi/mech/gss_get_mic.c @@ -0,0 +1,50 @@ +/*- + * Copyright (c) 2005 Doug Rabson + * 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 AUTHOR 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 AUTHOR 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. + * + *	$FreeBSD: src/lib/libgssapi/gss_get_mic.c,v 1.1 2005/12/29 14:40:20 dfr Exp $ + */ + +#include "mech_locl.h" +RCSID("$Id$"); + +OM_uint32 GSSAPI_LIB_FUNCTION +gss_get_mic(OM_uint32 *minor_status, +    const gss_ctx_id_t context_handle, +    gss_qop_t qop_req, +    const gss_buffer_t message_buffer, +    gss_buffer_t message_token) +{ +	struct _gss_context *ctx = (struct _gss_context *) context_handle; +	gssapi_mech_interface m = ctx->gc_mech; + +	_mg_buffer_zero(message_token); +	if (ctx == NULL) { +	    *minor_status = 0; +	    return GSS_S_NO_CONTEXT; +	} + +	return (m->gm_get_mic(minor_status, ctx->gc_ctx, qop_req, +		    message_buffer, message_token)); +} diff --git a/source4/heimdal/lib/gssapi/mech/gss_import_name.c b/source4/heimdal/lib/gssapi/mech/gss_import_name.c new file mode 100644 index 0000000000..040e228410 --- /dev/null +++ b/source4/heimdal/lib/gssapi/mech/gss_import_name.c @@ -0,0 +1,218 @@ +/*- + * Copyright (c) 2005 Doug Rabson + * 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 AUTHOR 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 AUTHOR 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. + * + *	$FreeBSD: src/lib/libgssapi/gss_import_name.c,v 1.1 2005/12/29 14:40:20 dfr Exp $ + */ + +#include "mech_locl.h" +RCSID("$Id$"); + +static OM_uint32 +_gss_import_export_name(OM_uint32 *minor_status, +    const gss_buffer_t input_name_buffer, +    gss_name_t *output_name) +{ +	OM_uint32 major_status; +	unsigned char *p = input_name_buffer->value; +	size_t len = input_name_buffer->length; +	size_t t; +	gss_OID_desc mech_oid; +	gssapi_mech_interface m; +	struct _gss_name *name; +	gss_name_t new_canonical_name; + +	*minor_status = 0; +	*output_name = 0; + +	/* +	 * Make sure that TOK_ID is {4, 1}. +	 */ +	if (len < 2) +		return (GSS_S_BAD_NAME); +	if (p[0] != 4 || p[1] != 1) +		return (GSS_S_BAD_NAME); +	p += 2; +	len -= 2; + +	/* +	 * Get the mech length and the name length and sanity +	 * check the size of of the buffer. +	 */ +	if (len < 2) +		return (GSS_S_BAD_NAME); +	t = (p[0] << 8) + p[1]; +	p += 2; +	len -= 2; + +	/* +	 * Check the DER encoded OID to make sure it agrees with the +	 * length we just decoded. +	 */ +	if (p[0] != 6)		/* 6=OID */ +		return (GSS_S_BAD_NAME); +	p++; +	len--; +	t--; +	if (p[0] & 0x80) { +		int digits = p[0]; +		p++; +		len--; +		t--; +		mech_oid.length = 0; +		while (digits--) { +			mech_oid.length = (mech_oid.length << 8) | p[0]; +			p++; +			len--; +			t--; +		} +	} else { +		mech_oid.length = p[0]; +		p++; +		len--; +		t--; +	} +	if (mech_oid.length != t) +		return (GSS_S_BAD_NAME); + +	mech_oid.elements = p; + +	if (len < t + 4) +		return (GSS_S_BAD_NAME); +	p += t; +	len -= t; + +	t = (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3]; +	p += 4; +	len -= 4; + +	if (len != t) +		return (GSS_S_BAD_NAME); + +	m = __gss_get_mechanism(&mech_oid); +	if (!m) +		return (GSS_S_BAD_MECH); + +	/* +	 * Ask the mechanism to import the name. +	 */ +	major_status = m->gm_import_name(minor_status, +	    input_name_buffer, GSS_C_NT_EXPORT_NAME, &new_canonical_name); +	if (major_status != GSS_S_COMPLETE) { +		_gss_mg_error(m, major_status, *minor_status); +		return major_status; +	} + +	/* +	 * Now we make a new name and mark it as an MN. +	 */ +	name = _gss_make_name(m, new_canonical_name); +	if (!name) { +		m->gm_release_name(minor_status, &new_canonical_name); +		return (GSS_S_FAILURE); +	} + +	*output_name = (gss_name_t) name; + +	*minor_status = 0; +	return (GSS_S_COMPLETE); +} + +OM_uint32 GSSAPI_LIB_FUNCTION +gss_import_name(OM_uint32 *minor_status, +    const gss_buffer_t input_name_buffer, +    const gss_OID input_name_type, +    gss_name_t *output_name) +{ +	gss_OID			name_type = input_name_type; +	OM_uint32		major_status; +	struct _gss_name	*name; + +	*output_name = GSS_C_NO_NAME; + +	if (input_name_buffer->length == 0) { +		*minor_status = 0; +		return (GSS_S_BAD_NAME); +	} + +	/* +	 * Use GSS_NT_USER_NAME as default name type. +	 */ +	if (name_type == GSS_C_NO_OID) +		name_type = GSS_C_NT_USER_NAME; + +	/* +	 * If this is an exported name, we need to parse it to find +	 * the mechanism and then import it as an MN. See RFC 2743 +	 * section 3.2 for a description of the format. +	 */ +	if (gss_oid_equal(name_type, GSS_C_NT_EXPORT_NAME)) { +		return _gss_import_export_name(minor_status, +		    input_name_buffer, output_name); +	} + +	/* +	 * Only allow certain name types. This is pretty bogus - we +	 * should figure out the list of supported name types using +	 * gss_inquire_names_for_mech. +	 */ +	if (!gss_oid_equal(name_type, GSS_C_NT_USER_NAME) +	    && !gss_oid_equal(name_type, GSS_C_NT_MACHINE_UID_NAME) +	    && !gss_oid_equal(name_type, GSS_C_NT_STRING_UID_NAME) +	    && !gss_oid_equal(name_type, GSS_C_NT_HOSTBASED_SERVICE_X) +	    && !gss_oid_equal(name_type, GSS_C_NT_HOSTBASED_SERVICE) +	    && !gss_oid_equal(name_type, GSS_C_NT_ANONYMOUS) +	    && !gss_oid_equal(name_type, GSS_KRB5_NT_PRINCIPAL_NAME)) { +		*minor_status = 0; +		return (GSS_S_BAD_NAMETYPE); +	} + +	*minor_status = 0; +	name = malloc(sizeof(struct _gss_name)); +	if (!name) { +		*minor_status = ENOMEM; +		return (GSS_S_FAILURE); +	} +	memset(name, 0, sizeof(struct _gss_name)); + +	major_status = _gss_copy_oid(minor_status, +	    name_type, &name->gn_type); +	if (major_status) { +		free(name); +		return (GSS_S_FAILURE); +	} + +	major_status = _gss_copy_buffer(minor_status, +	    input_name_buffer, &name->gn_value); +	if (major_status) { +		gss_name_t rname = (gss_name_t)name; +		gss_release_name(minor_status, &rname); +		return (GSS_S_FAILURE); +	} + +	SLIST_INIT(&name->gn_mn); + +	*output_name = (gss_name_t) name; +	return (GSS_S_COMPLETE); +} diff --git a/source4/heimdal/lib/gssapi/mech/gss_import_sec_context.c b/source4/heimdal/lib/gssapi/mech/gss_import_sec_context.c new file mode 100644 index 0000000000..01ca9f10df --- /dev/null +++ b/source4/heimdal/lib/gssapi/mech/gss_import_sec_context.c @@ -0,0 +1,83 @@ +/*- + * Copyright (c) 2005 Doug Rabson + * 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 AUTHOR 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 AUTHOR 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. + * + *	$FreeBSD: src/lib/libgssapi/gss_import_sec_context.c,v 1.1 2005/12/29 14:40:20 dfr Exp $ + */ + +#include "mech_locl.h" +RCSID("$Id$"); + +OM_uint32 GSSAPI_LIB_FUNCTION +gss_import_sec_context(OM_uint32 *minor_status, +    const gss_buffer_t interprocess_token, +    gss_ctx_id_t *context_handle) +{ +	OM_uint32 major_status; +	gssapi_mech_interface m; +	struct _gss_context *ctx; +	gss_OID_desc mech_oid; +	gss_buffer_desc buf; +	unsigned char *p; +	size_t len; + +	*minor_status = 0; +	*context_handle = GSS_C_NO_CONTEXT; + +	/* +	 * We added an oid to the front of the token in +	 * gss_export_sec_context. +	 */ +	p = interprocess_token->value; +	len = interprocess_token->length; +	if (len < 2) +		return (GSS_S_DEFECTIVE_TOKEN); +	mech_oid.length = (p[0] << 8) | p[1]; +	if (len < mech_oid.length + 2) +		return (GSS_S_DEFECTIVE_TOKEN); +	mech_oid.elements = p + 2; +	buf.length = len - 2 - mech_oid.length; +	buf.value = p + 2 + mech_oid.length; +	 +	m = __gss_get_mechanism(&mech_oid); +	if (!m) +		return (GSS_S_DEFECTIVE_TOKEN); + +	ctx = malloc(sizeof(struct _gss_context)); +	if (!ctx) { +		*minor_status = ENOMEM; +		return (GSS_S_FAILURE); +	} +	ctx->gc_mech = m; +	major_status = m->gm_import_sec_context(minor_status, +	    &buf, &ctx->gc_ctx); +	if (major_status != GSS_S_COMPLETE) { +		_gss_mg_error(m, major_status, *minor_status); +		free(ctx); +	} else { +		*context_handle = (gss_ctx_id_t) ctx; +	} + +	return (major_status); +} diff --git a/source4/heimdal/lib/gssapi/mech/gss_indicate_mechs.c b/source4/heimdal/lib/gssapi/mech/gss_indicate_mechs.c new file mode 100644 index 0000000000..34c0bb55d8 --- /dev/null +++ b/source4/heimdal/lib/gssapi/mech/gss_indicate_mechs.c @@ -0,0 +1,65 @@ +/*- + * Copyright (c) 2005 Doug Rabson + * 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 AUTHOR 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 AUTHOR 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. + * + *	$FreeBSD: src/lib/libgssapi/gss_indicate_mechs.c,v 1.1 2005/12/29 14:40:20 dfr Exp $ + */ + +#include "mech_locl.h" +RCSID("$Id$"); + +OM_uint32 GSSAPI_LIB_FUNCTION +gss_indicate_mechs(OM_uint32 *minor_status, +    gss_OID_set *mech_set) +{ +	struct _gss_mech_switch *m; +	OM_uint32 major_status; +	gss_OID_set set; +	int i; + +	_gss_load_mech(); + +	major_status = gss_create_empty_oid_set(minor_status, mech_set); +	if (major_status) +		return (major_status); +	 +	SLIST_FOREACH(m, &_gss_mechs, gm_link) { +		if (m->gm_mech.gm_indicate_mechs) { +			major_status = m->gm_mech.gm_indicate_mechs( +			    minor_status, &set); +			if (major_status) +				continue; +			for (i = 0; i < set->count; i++) +				major_status = gss_add_oid_set_member( +				    minor_status, &set->elements[i], mech_set); +			gss_release_oid_set(minor_status, &set); +		} else { +			major_status = gss_add_oid_set_member( +			    minor_status, &m->gm_mech_oid, mech_set); +		} +	} + +	*minor_status = 0; +	return (GSS_S_COMPLETE); +} diff --git a/source4/heimdal/lib/gssapi/mech/gss_init_sec_context.c b/source4/heimdal/lib/gssapi/mech/gss_init_sec_context.c new file mode 100644 index 0000000000..579000a7ec --- /dev/null +++ b/source4/heimdal/lib/gssapi/mech/gss_init_sec_context.c @@ -0,0 +1,149 @@ +/*- + * Copyright (c) 2005 Doug Rabson + * 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 AUTHOR 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 AUTHOR 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. + * + *	$FreeBSD: src/lib/libgssapi/gss_init_sec_context.c,v 1.1 2005/12/29 14:40:20 dfr Exp $ + */ + +#include "mech_locl.h" +RCSID("$Id$"); + +static gss_cred_id_t +_gss_mech_cred_find(gss_cred_id_t cred_handle, gss_OID mech_type) +{ +	struct _gss_cred *cred = (struct _gss_cred *)cred_handle; +	struct _gss_mechanism_cred *mc; + +	if (cred == NULL) +		return GSS_C_NO_CREDENTIAL; + +	SLIST_FOREACH(mc, &cred->gc_mc, gmc_link) { +		if (gss_oid_equal(mech_type, mc->gmc_mech_oid)) +			return mc->gmc_cred; +	} +	return GSS_C_NO_CREDENTIAL; +} + +OM_uint32 GSSAPI_LIB_FUNCTION +gss_init_sec_context(OM_uint32 * minor_status, +    const gss_cred_id_t initiator_cred_handle, +    gss_ctx_id_t * context_handle, +    const gss_name_t target_name, +    const gss_OID input_mech_type, +    OM_uint32 req_flags, +    OM_uint32 time_req, +    const gss_channel_bindings_t input_chan_bindings, +    const gss_buffer_t input_token, +    gss_OID * actual_mech_type, +    gss_buffer_t output_token, +    OM_uint32 * ret_flags, +    OM_uint32 * time_rec) +{ +	OM_uint32 major_status; +	gssapi_mech_interface m; +	struct _gss_name *name = (struct _gss_name *) target_name; +	struct _gss_mechanism_name *mn; +	struct _gss_context *ctx = (struct _gss_context *) *context_handle; +	gss_cred_id_t cred_handle; +	int allocated_ctx; +	gss_OID mech_type = input_mech_type; + +	*minor_status = 0; + +	_mg_buffer_zero(output_token); +	if (actual_mech_type) +	    *actual_mech_type = GSS_C_NO_OID; +	if (ret_flags) +	    *ret_flags = 0; +	if (time_rec) +	    *time_rec = 0; + +	/* +	 * If we haven't allocated a context yet, do so now and lookup +	 * the mechanism switch table. If we have one already, make +	 * sure we use the same mechanism switch as before. +	 */ +	if (!ctx) { +		if (mech_type == NULL) +			mech_type = GSS_KRB5_MECHANISM; + +		ctx = malloc(sizeof(struct _gss_context)); +		if (!ctx) { +			*minor_status = ENOMEM; +			return (GSS_S_FAILURE); +		} +		memset(ctx, 0, sizeof(struct _gss_context)); +		m = ctx->gc_mech = __gss_get_mechanism(mech_type); +		if (!m) { +			free(ctx); +			return (GSS_S_BAD_MECH); +		} +		allocated_ctx = 1; +	} else { +		m = ctx->gc_mech; +		mech_type = &ctx->gc_mech->gm_mech_oid; +		allocated_ctx = 0; +	} + +	/* +	 * Find the MN for this mechanism. +	 */ +	major_status = _gss_find_mn(minor_status, name, mech_type, &mn); +	if (major_status != GSS_S_COMPLETE) { +		if (allocated_ctx) +			free(ctx); +		return major_status; +	} + +	/* +	 * If we have a cred, find the cred for this mechanism. +	 */ +	cred_handle = _gss_mech_cred_find(initiator_cred_handle, mech_type); + +	major_status = m->gm_init_sec_context(minor_status, +	    cred_handle, +	    &ctx->gc_ctx, +	    mn->gmn_name, +	    mech_type, +	    req_flags, +	    time_req, +	    input_chan_bindings, +	    input_token, +	    actual_mech_type, +	    output_token, +	    ret_flags, +	    time_rec); + +	if (major_status != GSS_S_COMPLETE +	    && major_status != GSS_S_CONTINUE_NEEDED) { +		if (allocated_ctx) +			free(ctx); +		_mg_buffer_zero(output_token); +		_gss_mg_error(m, major_status, *minor_status); +	} else { +		*context_handle = (gss_ctx_id_t) ctx; +	} + +	return (major_status); +} diff --git a/source4/heimdal/lib/gssapi/mech/gss_inquire_context.c b/source4/heimdal/lib/gssapi/mech/gss_inquire_context.c new file mode 100644 index 0000000000..8872f121d0 --- /dev/null +++ b/source4/heimdal/lib/gssapi/mech/gss_inquire_context.c @@ -0,0 +1,106 @@ +/*- + * Copyright (c) 2005 Doug Rabson + * 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 AUTHOR 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 AUTHOR 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. + * + *	$FreeBSD: src/lib/libgssapi/gss_inquire_context.c,v 1.1 2005/12/29 14:40:20 dfr Exp $ + */ + +#include "mech_locl.h" +RCSID("$Id$"); + +OM_uint32 GSSAPI_LIB_FUNCTION +gss_inquire_context(OM_uint32 *minor_status, +    const gss_ctx_id_t context_handle, +    gss_name_t *src_name, +    gss_name_t *targ_name, +    OM_uint32 *lifetime_rec, +    gss_OID *mech_type, +    OM_uint32 *ctx_flags, +    int *locally_initiated, +    int *open) +{ +	OM_uint32 major_status; +	struct _gss_context *ctx = (struct _gss_context *) context_handle; +	gssapi_mech_interface m = ctx->gc_mech; +	struct _gss_name *name; +	gss_name_t src_mn, targ_mn; + +	if (locally_initiated) +	    *locally_initiated = 0; +	if (open) +	    *open = 0; +	if (lifetime_rec) +	    *lifetime_rec = 0; + +	if (src_name) +	    *src_name = GSS_C_NO_NAME; +	if (targ_name) +	    *targ_name = GSS_C_NO_NAME; +	if (mech_type) +	    *mech_type = GSS_C_NO_OID; +	src_mn = targ_mn = GSS_C_NO_NAME; + +	major_status = m->gm_inquire_context(minor_status, +	    ctx->gc_ctx, +	    src_name ? &src_mn : NULL, +	    targ_name ? &targ_mn : NULL, +	    lifetime_rec, +	    mech_type, +	    ctx_flags, +	    locally_initiated, +	    open); + +	if (major_status != GSS_S_COMPLETE) { +		_gss_mg_error(m, major_status, *minor_status); +		return (major_status); +	} + +	if (src_name) { +		name = _gss_make_name(m, src_mn); +		if (!name) { +			if (mech_type) +				*mech_type = GSS_C_NO_OID; +			m->gm_release_name(minor_status, &src_mn); +			*minor_status = 0; +			return (GSS_S_FAILURE); +		} +		*src_name = (gss_name_t) name; +	} + +	if (targ_name) { +		name = _gss_make_name(m, targ_mn); +		if (!name) { +			if (mech_type) +				*mech_type = GSS_C_NO_OID; +			if (src_name) +				gss_release_name(minor_status, src_name); +			m->gm_release_name(minor_status, &targ_mn); +			*minor_status = 0; +			return (GSS_S_FAILURE); +		} +		*targ_name = (gss_name_t) name; +	} + +	return (GSS_S_COMPLETE); +} diff --git a/source4/heimdal/lib/gssapi/mech/gss_inquire_cred.c b/source4/heimdal/lib/gssapi/mech/gss_inquire_cred.c new file mode 100644 index 0000000000..3587572672 --- /dev/null +++ b/source4/heimdal/lib/gssapi/mech/gss_inquire_cred.c @@ -0,0 +1,196 @@ +/*- + * Copyright (c) 2005 Doug Rabson + * 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 AUTHOR 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 AUTHOR 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. + * + *	$FreeBSD: src/lib/libgssapi/gss_inquire_cred.c,v 1.1 2005/12/29 14:40:20 dfr Exp $ + */ + +#include "mech_locl.h" +RCSID("$Id$"); + +#define AUSAGE 1 +#define IUSAGE 2 + +static void +updateusage(gss_cred_usage_t usage, int *usagemask) +{ +    if (usage == GSS_C_BOTH) +	*usagemask |= AUSAGE | IUSAGE; +    else if (usage == GSS_C_ACCEPT) +	*usagemask |= AUSAGE; +    else if (usage == GSS_C_INITIATE) +	*usagemask |= IUSAGE; +} + +OM_uint32 GSSAPI_LIB_FUNCTION +gss_inquire_cred(OM_uint32 *minor_status, +    const gss_cred_id_t cred_handle, +    gss_name_t *name_ret, +    OM_uint32 *lifetime, +    gss_cred_usage_t *cred_usage, +    gss_OID_set *mechanisms) +{ +	OM_uint32 major_status; +	struct _gss_mech_switch *m; +	struct _gss_cred *cred = (struct _gss_cred *) cred_handle; +	struct _gss_name *name; +	struct _gss_mechanism_name *mn; +	OM_uint32 min_lifetime; +	int found = 0; +	int usagemask = 0; +	gss_cred_usage_t usage; + +	_gss_load_mech(); + +	*minor_status = 0; +	if (name_ret) +		*name_ret = GSS_C_NO_NAME; +	if (lifetime) +		*lifetime = 0; +	if (cred_usage) +		*cred_usage = 0; +	if (mechanisms) +		*mechanisms = GSS_C_NO_OID_SET; + +	if (name_ret) { +		name = calloc(1, sizeof(*name)); +		if (name == NULL) { +			*minor_status = ENOMEM; +			return (GSS_S_FAILURE); +		} +		SLIST_INIT(&name->gn_mn); +	} else { +		name = NULL; +	} + +	if (mechanisms) { +		major_status = gss_create_empty_oid_set(minor_status, +		    mechanisms); +		if (major_status) { +			if (name) free(name); +			return (major_status); +		} +	} + +	min_lifetime = GSS_C_INDEFINITE; +	if (cred) { +		struct _gss_mechanism_cred *mc; + +		SLIST_FOREACH(mc, &cred->gc_mc, gmc_link) { +			gss_name_t mc_name; +			OM_uint32 mc_lifetime; + +			major_status = mc->gmc_mech->gm_inquire_cred(minor_status, +			    mc->gmc_cred, &mc_name, &mc_lifetime, &usage, NULL); +			if (major_status) +				continue; + +			updateusage(usage, &usagemask); +			if (name) { +				mn = malloc(sizeof(struct _gss_mechanism_name)); +				if (!mn) { +					mc->gmc_mech->gm_release_name(minor_status, +					    &mc_name); +					continue; +				} +				mn->gmn_mech = mc->gmc_mech; +				mn->gmn_mech_oid = mc->gmc_mech_oid; +				mn->gmn_name = mc_name; +				SLIST_INSERT_HEAD(&name->gn_mn, mn, gmn_link); +			} else { +				mc->gmc_mech->gm_release_name(minor_status, +				    &mc_name); +			} + +			if (mc_lifetime < min_lifetime) +				min_lifetime = mc_lifetime; + +			if (mechanisms) +				gss_add_oid_set_member(minor_status, +				    mc->gmc_mech_oid, mechanisms); +			found++; +		} +	} else { +		SLIST_FOREACH(m, &_gss_mechs, gm_link) { +			gss_name_t mc_name; +			OM_uint32 mc_lifetime; + +			major_status = m->gm_mech.gm_inquire_cred(minor_status, +			    GSS_C_NO_CREDENTIAL, &mc_name, &mc_lifetime, +			    &usage, NULL); +			if (major_status) +				continue; + +			updateusage(usage, &usagemask); +			if (name && mc_name) { +				mn = malloc( +					sizeof(struct _gss_mechanism_name)); +				if (!mn) { +					m->gm_mech.gm_release_name( +						minor_status, &mc_name); +					continue; +				} +				mn->gmn_mech = &m->gm_mech; +				mn->gmn_mech_oid = &m->gm_mech_oid; +				mn->gmn_name = mc_name; +				SLIST_INSERT_HEAD(&name->gn_mn, mn, gmn_link); +			} else if (mc_name) { +				m->gm_mech.gm_release_name(minor_status, +				    &mc_name); +			} + +			if (mc_lifetime < min_lifetime) +				min_lifetime = mc_lifetime; + +			if (mechanisms) +				gss_add_oid_set_member(minor_status, +				    &m->gm_mech_oid, mechanisms); +			found++; +		} +	} + +	if (found == 0) { +		gss_name_t n = (gss_name_t)name; +		if (n) +			gss_release_name(minor_status, &n); +		gss_release_oid_set(minor_status, mechanisms); +		*minor_status = 0; +		return (GSS_S_NO_CRED); +	} + +	*minor_status = 0; +	if (name_ret) +		*name_ret = (gss_name_t) name; +	if (lifetime) +		*lifetime = min_lifetime; +	if (cred_usage) { +		if ((usagemask & (AUSAGE|IUSAGE)) == (AUSAGE|IUSAGE)) +			*cred_usage = GSS_C_BOTH; +		else if (usagemask & IUSAGE) +			*cred_usage = GSS_C_INITIATE; +		else if (usagemask & AUSAGE) +			*cred_usage = GSS_C_ACCEPT; +	} +	return (GSS_S_COMPLETE); +} diff --git a/source4/heimdal/lib/gssapi/mech/gss_inquire_cred_by_mech.c b/source4/heimdal/lib/gssapi/mech/gss_inquire_cred_by_mech.c new file mode 100644 index 0000000000..47a2eaf279 --- /dev/null +++ b/source4/heimdal/lib/gssapi/mech/gss_inquire_cred_by_mech.c @@ -0,0 +1,93 @@ +/*- + * Copyright (c) 2005 Doug Rabson + * 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 AUTHOR 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 AUTHOR 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. + * + *	$FreeBSD: src/lib/libgssapi/gss_inquire_cred_by_mech.c,v 1.1 2005/12/29 14:40:20 dfr Exp $ + */ + +#include "mech_locl.h" +RCSID("$Id$"); + +OM_uint32 GSSAPI_LIB_FUNCTION +gss_inquire_cred_by_mech(OM_uint32 *minor_status, +    const gss_cred_id_t cred_handle, +    const gss_OID mech_type, +    gss_name_t *cred_name, +    OM_uint32 *initiator_lifetime, +    OM_uint32 *acceptor_lifetime, +    gss_cred_usage_t *cred_usage) +{ +	OM_uint32 major_status; +	gssapi_mech_interface m; +	struct _gss_mechanism_cred *mcp; +	gss_cred_id_t mc; +	gss_name_t mn; +	struct _gss_name *name; + +	*minor_status = 0; +	if (cred_name) +	    *cred_name = GSS_C_NO_NAME; +	if (initiator_lifetime) +	    *initiator_lifetime = 0; +	if (acceptor_lifetime) +	    *acceptor_lifetime = 0; +	if (cred_usage) +	    *cred_usage = 0; + +	m = __gss_get_mechanism(mech_type); +	if (!m) +		return (GSS_S_NO_CRED); + +	if (cred_handle != GSS_C_NO_CREDENTIAL) { +		struct _gss_cred *cred = (struct _gss_cred *) cred_handle; +		SLIST_FOREACH(mcp, &cred->gc_mc, gmc_link) +			if (mcp->gmc_mech == m) +				break; +		if (!mcp) +			return (GSS_S_NO_CRED); +		mc = mcp->gmc_cred; +	} else { +		mc = GSS_C_NO_CREDENTIAL; +	} + +	major_status = m->gm_inquire_cred_by_mech(minor_status, mc, mech_type, +	    &mn, initiator_lifetime, acceptor_lifetime, cred_usage); +	if (major_status != GSS_S_COMPLETE) { +		_gss_mg_error(m, major_status, *minor_status); +		return (major_status); +	} + +	if (cred_name) { +	    name = _gss_make_name(m, mn); +	    if (!name) { +		m->gm_release_name(minor_status, &mn); +		return (GSS_S_NO_CRED); +	    } +	    *cred_name = (gss_name_t) name; +	} else +	    m->gm_release_name(minor_status, &mn); + + +	return (GSS_S_COMPLETE); +} diff --git a/source4/heimdal/lib/gssapi/mech/gss_inquire_cred_by_oid.c b/source4/heimdal/lib/gssapi/mech/gss_inquire_cred_by_oid.c new file mode 100644 index 0000000000..d22231d96b --- /dev/null +++ b/source4/heimdal/lib/gssapi/mech/gss_inquire_cred_by_oid.c @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2004, PADL Software Pty Ltd. + * 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 PADL Software 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 PADL SOFTWARE 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 PADL SOFTWARE 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. + */ + +#include "mech_locl.h" +RCSID("$Id$"); + +OM_uint32 GSSAPI_LIB_FUNCTION +gss_inquire_cred_by_oid (OM_uint32 *minor_status, +			 const gss_cred_id_t cred_handle, +			 const gss_OID desired_object, +			 gss_buffer_set_t *data_set) +{ +	struct _gss_cred *cred = (struct _gss_cred *) cred_handle; +	OM_uint32		status = GSS_S_COMPLETE; +	struct _gss_mechanism_cred *mc; +	gssapi_mech_interface	m; +	gss_buffer_set_t set = GSS_C_NO_BUFFER_SET; + +	*minor_status = 0; +	*data_set = GSS_C_NO_BUFFER_SET; + +	if (cred == NULL) +		return GSS_S_NO_CRED; + +	SLIST_FOREACH(mc, &cred->gc_mc, gmc_link) { +		gss_buffer_set_t rset = GSS_C_NO_BUFFER_SET; +		int i; + +		m = mc->gmc_mech; +		if (m == NULL) { +	       		gss_release_buffer_set(minor_status, &set); +			*minor_status = 0; +			return GSS_S_BAD_MECH; +		} + +		if (m->gm_inquire_cred_by_oid == NULL) +			continue; + +		status = m->gm_inquire_cred_by_oid(minor_status, +		    mc->gmc_cred, desired_object, &rset); +		if (status != GSS_S_COMPLETE) +			continue; + +		for (i = 0; i < rset->count; i++) {  +			status = gss_add_buffer_set_member(minor_status, +			     &rset->elements[i], &set); +			if (status != GSS_S_COMPLETE) +				break; +		} +		gss_release_buffer_set(minor_status, &rset); +	} +	if (set == GSS_C_NO_BUFFER_SET) +		status = GSS_S_FAILURE; +	*data_set = set; +	*minor_status = 0; +	return status; +} + diff --git a/source4/heimdal/lib/gssapi/mech/gss_inquire_mechs_for_name.c b/source4/heimdal/lib/gssapi/mech/gss_inquire_mechs_for_name.c new file mode 100644 index 0000000000..8df7f88a0a --- /dev/null +++ b/source4/heimdal/lib/gssapi/mech/gss_inquire_mechs_for_name.c @@ -0,0 +1,77 @@ +/*- + * Copyright (c) 2005 Doug Rabson + * 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 AUTHOR 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 AUTHOR 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. + * + *	$FreeBSD: src/lib/libgssapi/gss_inquire_mechs_for_name.c,v 1.1 2005/12/29 14:40:20 dfr Exp $ + */ + +#include "mech_locl.h" +RCSID("$Id$"); + +OM_uint32 GSSAPI_LIB_FUNCTION +gss_inquire_mechs_for_name(OM_uint32 *minor_status, +    const gss_name_t input_name, +    gss_OID_set *mech_types) +{ +	OM_uint32		major_status; +	struct _gss_name	*name = (struct _gss_name *) input_name; +	struct _gss_mech_switch	*m; +	gss_OID_set		name_types; +	int			present; + +	*minor_status = 0; + +	_gss_load_mech(); + +	major_status = gss_create_empty_oid_set(minor_status, mech_types); +	if (major_status) +		return (major_status); +     +	/* +	 * We go through all the loaded mechanisms and see if this +	 * name's type is supported by the mechanism. If it is, add +	 * the mechanism to the set. +	 */ +	SLIST_FOREACH(m, &_gss_mechs, gm_link) { +		major_status = gss_inquire_names_for_mech(minor_status, +		    &m->gm_mech_oid, &name_types); +		if (major_status) { +			gss_release_oid_set(minor_status, mech_types); +			return (major_status); +		} +		gss_test_oid_set_member(minor_status, +		    &name->gn_type, name_types, &present); +		gss_release_oid_set(minor_status, &name_types); +		if (present) { +			major_status = gss_add_oid_set_member(minor_status, +			    &m->gm_mech_oid, mech_types); +			if (major_status) { +				gss_release_oid_set(minor_status, mech_types); +				return (major_status); +			} +		} +	} + +	return (GSS_S_COMPLETE); +} diff --git a/source4/heimdal/lib/gssapi/mech/gss_inquire_names_for_mech.c b/source4/heimdal/lib/gssapi/mech/gss_inquire_names_for_mech.c new file mode 100644 index 0000000000..a630d76216 --- /dev/null +++ b/source4/heimdal/lib/gssapi/mech/gss_inquire_names_for_mech.c @@ -0,0 +1,74 @@ +/*- + * Copyright (c) 2005 Doug Rabson + * 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 AUTHOR 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 AUTHOR 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. + * + *	$FreeBSD: src/lib/libgssapi/gss_inquire_names_for_mech.c,v 1.1 2005/12/29 14:40:20 dfr Exp $ + */ + +#include "mech_locl.h" +RCSID("$Id$"); + +OM_uint32 GSSAPI_LIB_FUNCTION +gss_inquire_names_for_mech(OM_uint32 *minor_status, +    const gss_OID mechanism, +    gss_OID_set *name_types) +{ +	OM_uint32 major_status; +	gssapi_mech_interface m = __gss_get_mechanism(mechanism); + +	*minor_status = 0; +	*name_types = GSS_C_NO_OID_SET; +	if (!m) +		return (GSS_S_BAD_MECH); + +	/* +	 * If the implementation can do it, ask it for a list of +	 * names, otherwise fake it. +	 */ +	if (m->gm_inquire_names_for_mech) { +		return (m->gm_inquire_names_for_mech(minor_status, +			    mechanism, name_types)); +	} else { +		major_status = gss_create_empty_oid_set(minor_status, +		    name_types); +		if (major_status) +			return (major_status); +		major_status = gss_add_oid_set_member(minor_status, +		    GSS_C_NT_HOSTBASED_SERVICE, name_types); +		if (major_status) { +			OM_uint32 junk; +			gss_release_oid_set(&junk, name_types); +			return (major_status); +		} +		major_status = gss_add_oid_set_member(minor_status, +		    GSS_C_NT_USER_NAME, name_types); +		if (major_status) { +			OM_uint32 junk; +			gss_release_oid_set(&junk, name_types); +			return (major_status); +		} +	} + +	return (GSS_S_COMPLETE); +} diff --git a/source4/heimdal/lib/gssapi/mech/gss_inquire_sec_context_by_oid.c b/source4/heimdal/lib/gssapi/mech/gss_inquire_sec_context_by_oid.c new file mode 100644 index 0000000000..9ba892dc0e --- /dev/null +++ b/source4/heimdal/lib/gssapi/mech/gss_inquire_sec_context_by_oid.c @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2004, PADL Software Pty Ltd. + * 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 PADL Software 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 PADL SOFTWARE 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 PADL SOFTWARE 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. + */ + +#include "mech_locl.h" +RCSID("$Id$"); + +OM_uint32 GSSAPI_LIB_FUNCTION +gss_inquire_sec_context_by_oid (OM_uint32 *minor_status, +	                        const gss_ctx_id_t context_handle, +	                        const gss_OID desired_object, +	                        gss_buffer_set_t *data_set) +{ +	struct _gss_context	*ctx = (struct _gss_context *) context_handle; +	OM_uint32		major_status; +	gssapi_mech_interface	m; + +	*minor_status = 0; +	*data_set = GSS_C_NO_BUFFER_SET; +	if (ctx == NULL) +		return GSS_S_NO_CONTEXT; + +	/* +	 * select the approprate underlying mechanism routine and +	 * call it. +	 */ + +	m = ctx->gc_mech; + +	if (m == NULL) +		return GSS_S_BAD_MECH; + +	if (m->gm_inquire_sec_context_by_oid != NULL) { +		major_status = m->gm_inquire_sec_context_by_oid(minor_status, +		    ctx->gc_ctx, desired_object, data_set); +		if (major_status != GSS_S_COMPLETE) +			_gss_mg_error(m, major_status, *minor_status); +	} else +		major_status = GSS_S_BAD_MECH; + +	return major_status; +} + diff --git a/source4/heimdal/lib/gssapi/mech/gss_krb5.c b/source4/heimdal/lib/gssapi/mech/gss_krb5.c new file mode 100644 index 0000000000..e224dffe05 --- /dev/null +++ b/source4/heimdal/lib/gssapi/mech/gss_krb5.c @@ -0,0 +1,922 @@ +/*- + * Copyright (c) 2005 Doug Rabson + * 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 AUTHOR 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 AUTHOR 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. + * + *	$FreeBSD: src/lib/libgssapi/gss_krb5.c,v 1.1 2005/12/29 14:40:20 dfr Exp $ + */ + +#include "mech_locl.h" +RCSID("$Id$"); + +#include <krb5.h> +#include <roken.h> + + +OM_uint32 GSSAPI_LIB_FUNCTION +gss_krb5_copy_ccache(OM_uint32 *minor_status, +		     gss_cred_id_t cred, +		     krb5_ccache out) +{ +    gss_buffer_set_t data_set = GSS_C_NO_BUFFER_SET; +    krb5_context context; +    krb5_error_code kret; +    krb5_ccache id; +    OM_uint32 ret; +    char *str; + +    ret = gss_inquire_cred_by_oid(minor_status, +				  cred, +				  GSS_KRB5_COPY_CCACHE_X, +				  &data_set); +    if (ret) +	return ret; + +    if (data_set == GSS_C_NO_BUFFER_SET || data_set->count < 1) { +	gss_release_buffer_set(minor_status, &data_set); +	*minor_status = EINVAL; +	return GSS_S_FAILURE; +    } + +    kret = krb5_init_context(&context); +    if (kret) { +	*minor_status = kret; +	gss_release_buffer_set(minor_status, &data_set); +	return GSS_S_FAILURE; +    } + +    kret = asprintf(&str, "%.*s", (int)data_set->elements[0].length, +		    (char *)data_set->elements[0].value); +    gss_release_buffer_set(minor_status, &data_set); +    if (kret == -1) { +	*minor_status = ENOMEM; +	return GSS_S_FAILURE; +    } + +    kret = krb5_cc_resolve(context, str, &id); +    free(str); +    if (kret) { +	*minor_status = kret; +	return GSS_S_FAILURE; +    } + +    kret = krb5_cc_copy_cache(context, id, out); +    krb5_cc_close(context, id); +    krb5_free_context(context); +    if (kret) { +	*minor_status = kret; +	return GSS_S_FAILURE; +    } + +    return ret; +} + +OM_uint32 GSSAPI_LIB_FUNCTION +gss_krb5_import_cred(OM_uint32 *minor_status, +		     krb5_ccache id, +		     krb5_principal keytab_principal, +		     krb5_keytab keytab, +		     gss_cred_id_t *cred) +{ +    gss_buffer_desc buffer; +    OM_uint32 major_status; +    krb5_context context; +    krb5_error_code ret; +    krb5_storage *sp; +    krb5_data data; +    char *str; + +    *cred = GSS_C_NO_CREDENTIAL; + +    ret = krb5_init_context(&context); +    if (ret) { +	*minor_status = ret; +	return GSS_S_FAILURE; +    } + +    sp = krb5_storage_emem(); +    if (sp == NULL) { +	*minor_status = ENOMEM; +	major_status = GSS_S_FAILURE; +	goto out; +    } + +    if (id) { +	ret = krb5_cc_get_full_name(context, id, &str); +	if (ret == 0) { +	    ret = krb5_store_string(sp, str); +	    free(str); +	} +    } else +	ret = krb5_store_string(sp, ""); +    if (ret) { +	*minor_status = ret; +	major_status = GSS_S_FAILURE; +	goto out; +    } + +    if (keytab_principal) { +	ret = krb5_unparse_name(context, keytab_principal, &str); +	if (ret == 0) { +	    ret = krb5_store_string(sp, str); +	    free(str); +	} +    } else +	krb5_store_string(sp, ""); +    if (ret) { +	*minor_status = ret; +	major_status = GSS_S_FAILURE; +	goto out; +    } + + +    if (keytab) { +	ret = krb5_kt_get_full_name(context, keytab, &str); +	if (ret == 0) { +	    ret = krb5_store_string(sp, str); +	    free(str); +	} +    } else +	krb5_store_string(sp, ""); +    if (ret) { +	*minor_status = ret; +	major_status = GSS_S_FAILURE; +	goto out; +    } + +    ret = krb5_storage_to_data(sp, &data); +    if (ret) { +	*minor_status = ret; +	major_status = GSS_S_FAILURE; +	goto out; +    } + +    buffer.value = data.data; +    buffer.length = data.length; +     +    major_status = gss_set_cred_option(minor_status, +				       cred, +				       GSS_KRB5_IMPORT_CRED_X, +				       &buffer); +    krb5_data_free(&data); +out: +    if (sp) +	krb5_storage_free(sp); +    krb5_free_context(context); +    return major_status; +} + +OM_uint32 GSSAPI_LIB_FUNCTION +gsskrb5_register_acceptor_identity(const char *identity) +{ +        struct _gss_mech_switch	*m; +	gss_buffer_desc buffer; +	OM_uint32 junk; + +	_gss_load_mech(); + +	buffer.value = rk_UNCONST(identity); +	buffer.length = strlen(identity); + +	SLIST_FOREACH(m, &_gss_mechs, gm_link) { +		if (m->gm_mech.gm_set_sec_context_option == NULL) +			continue; +		m->gm_mech.gm_set_sec_context_option(&junk, NULL, +		    GSS_KRB5_REGISTER_ACCEPTOR_IDENTITY_X, &buffer); +	} + +	return (GSS_S_COMPLETE); +} + +OM_uint32 GSSAPI_LIB_FUNCTION +krb5_gss_register_acceptor_identity(const char *identity) +{ +    return gsskrb5_register_acceptor_identity(identity); +} + + +OM_uint32 GSSAPI_LIB_FUNCTION +gsskrb5_set_dns_canonicalize(int flag) +{ +        struct _gss_mech_switch	*m; +	gss_buffer_desc buffer; +	OM_uint32 junk; +	char b = (flag != 0); + +	_gss_load_mech(); + +	buffer.value = &b; +	buffer.length = sizeof(b); + +	SLIST_FOREACH(m, &_gss_mechs, gm_link) { +		if (m->gm_mech.gm_set_sec_context_option == NULL) +			continue; +		m->gm_mech.gm_set_sec_context_option(&junk, NULL, +		    GSS_KRB5_SET_DNS_CANONICALIZE_X, &buffer); +	} + +	return (GSS_S_COMPLETE); +} + + + +static krb5_error_code +set_key(krb5_keyblock *keyblock, gss_krb5_lucid_key_t *key) +{ +    key->type = keyblock->keytype; +    key->length = keyblock->keyvalue.length; +    key->data = malloc(key->length); +    if (key->data == NULL && key->length != 0) +	return ENOMEM; +    memcpy(key->data, keyblock->keyvalue.data, key->length); +    return 0; +} + +static void +free_key(gss_krb5_lucid_key_t *key) +{ +    memset(key->data, 0, key->length); +    free(key->data); +    memset(key, 0, sizeof(*key)); +} + +OM_uint32 GSSAPI_LIB_FUNCTION +gss_krb5_export_lucid_sec_context(OM_uint32 *minor_status, +				  gss_ctx_id_t *context_handle, +				  OM_uint32 version, +				  void **rctx) +{ +    krb5_context context = NULL; +    krb5_error_code ret; +    gss_buffer_set_t data_set = GSS_C_NO_BUFFER_SET; +    OM_uint32 major_status; +    gss_krb5_lucid_context_v1_t *ctx = NULL; +    krb5_storage *sp = NULL; +    uint32_t num; + +    if (context_handle == NULL +	|| *context_handle == GSS_C_NO_CONTEXT +	|| version != 1) +    { +	ret = EINVAL; +	return GSS_S_FAILURE; +    } +     +    major_status = +	gss_inquire_sec_context_by_oid (minor_status, +					*context_handle, +					GSS_KRB5_EXPORT_LUCID_CONTEXT_V1_X, +					&data_set); +    if (major_status) +	return major_status; +     +    if (data_set == GSS_C_NO_BUFFER_SET || data_set->count != 1) { +	gss_release_buffer_set(minor_status, &data_set); +	*minor_status = EINVAL; +	return GSS_S_FAILURE; +    } + +    ret = krb5_init_context(&context); +    if (ret) +	goto out; + +    ctx = calloc(1, sizeof(*ctx)); +    if (ctx == NULL) { +	ret = ENOMEM; +	goto out; +    } + +    sp = krb5_storage_from_mem(data_set->elements[0].value, +			       data_set->elements[0].length); +    if (sp == NULL) { +	ret = ENOMEM; +	goto out; +    } +     +    ret = krb5_ret_uint32(sp, &num); +    if (ret) goto out; +    if (num != 1) { +	ret = EINVAL; +	goto out; +    } +    ctx->version = 1; +    /* initiator */ +    ret = krb5_ret_uint32(sp, &ctx->initiate); +    if (ret) goto out; +    /* endtime */ +    ret = krb5_ret_uint32(sp, &ctx->endtime); +    if (ret) goto out; +    /* send_seq */ +    ret = krb5_ret_uint32(sp, &num); +    if (ret) goto out; +    ctx->send_seq = ((uint64_t)num) << 32; +    ret = krb5_ret_uint32(sp, &num); +    if (ret) goto out; +    ctx->send_seq |= num; +    /* recv_seq */ +    ret = krb5_ret_uint32(sp, &num); +    if (ret) goto out; +    ctx->recv_seq = ((uint64_t)num) << 32; +    ret = krb5_ret_uint32(sp, &num); +    if (ret) goto out; +    ctx->recv_seq |= num; +    /* protocol */ +    ret = krb5_ret_uint32(sp, &ctx->protocol); +    if (ret) goto out; +    if (ctx->protocol == 0) { +	krb5_keyblock key; + +	/* sign_alg */ +	ret = krb5_ret_uint32(sp, &ctx->rfc1964_kd.sign_alg); +	if (ret) goto out; +	/* seal_alg */ +	ret = krb5_ret_uint32(sp, &ctx->rfc1964_kd.seal_alg); +	if (ret) goto out; +	/* ctx_key */ +	ret = krb5_ret_keyblock(sp, &key); +	if (ret) goto out; +	ret = set_key(&key, &ctx->rfc1964_kd.ctx_key); +	krb5_free_keyblock_contents(context, &key); +	if (ret) goto out; +    } else if (ctx->protocol == 1) { +	krb5_keyblock key; + +	/* acceptor_subkey */ +	ret = krb5_ret_uint32(sp, &ctx->cfx_kd.have_acceptor_subkey); +	if (ret) goto out; +	/* ctx_key */ +	ret = krb5_ret_keyblock(sp, &key); +	if (ret) goto out; +	ret = set_key(&key, &ctx->cfx_kd.ctx_key); +	krb5_free_keyblock_contents(context, &key); +	if (ret) goto out; +	/* acceptor_subkey */ +	if (ctx->cfx_kd.have_acceptor_subkey) { +	    ret = krb5_ret_keyblock(sp, &key); +	    if (ret) goto out; +	    ret = set_key(&key, &ctx->cfx_kd.acceptor_subkey); +	    krb5_free_keyblock_contents(context, &key); +	    if (ret) goto out; +	} +    } else { +	ret = EINVAL; +	goto out; +    } + +    *rctx = ctx; + +out: +    gss_release_buffer_set(minor_status, &data_set); +    if (sp) +	krb5_storage_free(sp); +    if (context) +	krb5_free_context(context); + +    if (ret) { +	if (ctx) +	    gss_krb5_free_lucid_sec_context(NULL, ctx); + +	*minor_status = ret; +	return GSS_S_FAILURE; +    } +    *minor_status = 0; +    return GSS_S_COMPLETE; +} + +OM_uint32 GSSAPI_LIB_FUNCTION +gss_krb5_free_lucid_sec_context(OM_uint32 *minor_status, void *c) +{ +    gss_krb5_lucid_context_v1_t *ctx = c; + +    if (ctx->version != 1) { +	if (minor_status) +	    *minor_status = 0; +	return GSS_S_FAILURE; +    } + +    if (ctx->protocol == 0) { +	free_key(&ctx->rfc1964_kd.ctx_key); +    } else if (ctx->protocol == 1) { +	free_key(&ctx->cfx_kd.ctx_key); +	if (ctx->cfx_kd.have_acceptor_subkey) +	    free_key(&ctx->cfx_kd.acceptor_subkey); +    } +    free(ctx); +    if (minor_status) +	*minor_status = 0; +    return GSS_S_COMPLETE; +} + +/* + * + */ + +OM_uint32 GSSAPI_LIB_FUNCTION +gss_krb5_set_allowable_enctypes(OM_uint32 *minor_status,  +				gss_cred_id_t cred, +				OM_uint32 num_enctypes, +				int32_t *enctypes) +{ +    krb5_error_code ret; +    OM_uint32 maj_status; +    gss_buffer_desc buffer; +    krb5_storage *sp; +    krb5_data data; +    int i; + +    sp = krb5_storage_emem(); +    if (sp == NULL) { +	*minor_status = ENOMEM; +	maj_status = GSS_S_FAILURE; +	goto out; +    } + +    for (i = 0; i < num_enctypes; i++) { +	ret = krb5_store_int32(sp, enctypes[i]); +	if (ret) { +	    *minor_status = ret; +	    maj_status = GSS_S_FAILURE; +	    goto out; +	} +    } + +    ret = krb5_storage_to_data(sp, &data); +    if (ret) { +	*minor_status = ret; +	maj_status = GSS_S_FAILURE; +	goto out; +    } + +    buffer.value = data.data; +    buffer.length = data.length; + +    maj_status = gss_set_cred_option(minor_status, +				     &cred, +				     GSS_KRB5_SET_ALLOWABLE_ENCTYPES_X, +				     &buffer); +    krb5_data_free(&data); +out: +    if (sp) +	krb5_storage_free(sp); +    return maj_status; +} + +/* + * + */ + +OM_uint32 GSSAPI_LIB_FUNCTION +gsskrb5_set_send_to_kdc(struct gsskrb5_send_to_kdc *c) +{ +    struct _gss_mech_switch *m; +    gss_buffer_desc buffer; +    OM_uint32 junk; + +    _gss_load_mech(); + +    if (c) { +	buffer.value = c; +	buffer.length = sizeof(*c); +    } else { +	buffer.value = NULL; +	buffer.length = 0; +    } + +    SLIST_FOREACH(m, &_gss_mechs, gm_link) { +	if (m->gm_mech.gm_set_sec_context_option == NULL) +	    continue; +	m->gm_mech.gm_set_sec_context_option(&junk, NULL, +	    GSS_KRB5_SEND_TO_KDC_X, &buffer); +    } + +    return (GSS_S_COMPLETE); +} + +/* + * + */ + +OM_uint32 GSSAPI_LIB_FUNCTION +gss_krb5_ccache_name(OM_uint32 *minor_status,  +		     const char *name, +		     const char **out_name) +{ +    struct _gss_mech_switch *m; +    gss_buffer_desc buffer; +    OM_uint32 junk; + +    _gss_load_mech(); + +    if (out_name) +	*out_name = NULL; + +    buffer.value = rk_UNCONST(name); +    buffer.length = strlen(name); + +    SLIST_FOREACH(m, &_gss_mechs, gm_link) { +	if (m->gm_mech.gm_set_sec_context_option == NULL) +	    continue; +	m->gm_mech.gm_set_sec_context_option(&junk, NULL, +	    GSS_KRB5_CCACHE_NAME_X, &buffer); +    } + +    return (GSS_S_COMPLETE); +} + + +/* + * + */ + +OM_uint32 GSSAPI_LIB_FUNCTION +gsskrb5_extract_authtime_from_sec_context(OM_uint32 *minor_status, +					  gss_ctx_id_t context_handle, +					  time_t *authtime) +{ +    gss_buffer_set_t data_set = GSS_C_NO_BUFFER_SET; +    OM_uint32 maj_stat; + +    if (context_handle == GSS_C_NO_CONTEXT) { +	*minor_status = EINVAL; +	return GSS_S_FAILURE; +    } +     +    maj_stat = +	gss_inquire_sec_context_by_oid (minor_status, +					context_handle, +					GSS_KRB5_GET_AUTHTIME_X, +					&data_set); +    if (maj_stat) +	return maj_stat; +     +    if (data_set == GSS_C_NO_BUFFER_SET) { +	gss_release_buffer_set(minor_status, &data_set); +	*minor_status = EINVAL; +	return GSS_S_FAILURE; +    } + +    if (data_set->count != 1) { +	gss_release_buffer_set(minor_status, &data_set); +	*minor_status = EINVAL; +	return GSS_S_FAILURE; +    } + +    if (data_set->elements[0].length != 4) { +	gss_release_buffer_set(minor_status, &data_set); +	*minor_status = EINVAL; +	return GSS_S_FAILURE; +    } + +    { +	unsigned char *buf = data_set->elements[0].value; +	*authtime = (buf[3] <<24) | (buf[2] << 16) |  +	    (buf[1] << 8) | (buf[0] << 0); +    } + +    gss_release_buffer_set(minor_status, &data_set); + +    *minor_status = 0; +    return GSS_S_COMPLETE; +} + +/* + * + */ + +OM_uint32 GSSAPI_LIB_FUNCTION +gsskrb5_extract_authz_data_from_sec_context(OM_uint32 *minor_status, +					    gss_ctx_id_t context_handle, +					    int ad_type, +					    gss_buffer_t ad_data) +{ +    gss_buffer_set_t data_set = GSS_C_NO_BUFFER_SET; +    OM_uint32 maj_stat; +    gss_OID_desc oid_flat; +    heim_oid baseoid, oid; +    size_t size; + +    if (context_handle == GSS_C_NO_CONTEXT) { +	*minor_status = EINVAL; +	return GSS_S_FAILURE; +    } + +    /* All this to append an integer to an oid... */ + +    if (der_get_oid(GSS_KRB5_EXTRACT_AUTHZ_DATA_FROM_SEC_CONTEXT_X->elements, +		    GSS_KRB5_EXTRACT_AUTHZ_DATA_FROM_SEC_CONTEXT_X->length, +		    &baseoid, NULL) != 0) { +	*minor_status = EINVAL; +	return GSS_S_FAILURE; +    } +     +    oid.length = baseoid.length + 1; +    oid.components = calloc(oid.length, sizeof(*oid.components)); +    if (oid.components == NULL) { +	der_free_oid(&baseoid); + +	*minor_status = ENOMEM; +	return GSS_S_FAILURE; +    } + +    memcpy(oid.components, baseoid.components,  +	   baseoid.length * sizeof(*baseoid.components)); +     +    der_free_oid(&baseoid); + +    oid.components[oid.length - 1] = ad_type; + +    oid_flat.length = der_length_oid(&oid); +    oid_flat.elements = malloc(oid_flat.length); +    if (oid_flat.elements == NULL) { +	free(oid.components); +	*minor_status = ENOMEM; +	return GSS_S_FAILURE; +    } + +    if (der_put_oid((unsigned char *)oid_flat.elements + oid_flat.length - 1,  +		    oid_flat.length, &oid, &size) != 0) { +	free(oid.components); +	free(oid_flat.elements); +	*minor_status = EINVAL; +	return GSS_S_FAILURE; +    } +    if (oid_flat.length != size) +	abort(); + +    free(oid.components); + +    /* FINALLY, we have the OID */ + +    maj_stat = gss_inquire_sec_context_by_oid (minor_status, +					       context_handle, +					       &oid_flat, +					       &data_set); + +    free(oid_flat.elements); + +    if (maj_stat) +	return maj_stat; +     +    if (data_set == GSS_C_NO_BUFFER_SET || data_set->count != 1) { +	gss_release_buffer_set(minor_status, &data_set); +	*minor_status = EINVAL; +	return GSS_S_FAILURE; +    } + +    ad_data->value = malloc(data_set->elements[0].length); +    if (ad_data->value == NULL) { +	gss_release_buffer_set(minor_status, &data_set); +	*minor_status = ENOMEM; +	return GSS_S_FAILURE; +    } + +    ad_data->length = data_set->elements[0].length; +    memcpy(ad_data->value, data_set->elements[0].value, ad_data->length); +    gss_release_buffer_set(minor_status, &data_set); +     +    *minor_status = 0; +    return GSS_S_COMPLETE; +} + +/* + * + */ + +static OM_uint32 +gsskrb5_extract_key(OM_uint32 *minor_status, +		    gss_ctx_id_t context_handle, +		    const gss_OID oid,  +		    krb5_keyblock **keyblock) +{ +    krb5_error_code ret; +    gss_buffer_set_t data_set = GSS_C_NO_BUFFER_SET; +    OM_uint32 major_status; +    krb5_context context = NULL; +    krb5_storage *sp = NULL; + +    if (context_handle == GSS_C_NO_CONTEXT) { +	ret = EINVAL; +	return GSS_S_FAILURE; +    } +     +    ret = krb5_init_context(&context); +    if(ret) { +	*minor_status = ret; +	return GSS_S_FAILURE; +    } + +    major_status = +	gss_inquire_sec_context_by_oid (minor_status, +					context_handle, +					oid, +					&data_set); +    if (major_status) +	return major_status; +     +    if (data_set == GSS_C_NO_BUFFER_SET || data_set->count != 1) { +	gss_release_buffer_set(minor_status, &data_set); +	*minor_status = EINVAL; +	return GSS_S_FAILURE; +    } + +    sp = krb5_storage_from_mem(data_set->elements[0].value, +			       data_set->elements[0].length); +    if (sp == NULL) { +	ret = ENOMEM; +	goto out; +    } +     +    *keyblock = calloc(1, sizeof(**keyblock)); +    if (keyblock == NULL) { +	ret = ENOMEM; +	goto out; +    } + +    ret = krb5_ret_keyblock(sp, *keyblock); + +out:  +    gss_release_buffer_set(minor_status, &data_set); +    if (sp) +	krb5_storage_free(sp); +    if (ret && keyblock) { +	krb5_free_keyblock(context, *keyblock); +	*keyblock = NULL; +    } +    if (context) +	krb5_free_context(context); + +    *minor_status = ret; +    if (ret) +	return GSS_S_FAILURE; + +    return GSS_S_COMPLETE; +} + +/* + * + */ + +OM_uint32 GSSAPI_LIB_FUNCTION +gsskrb5_extract_service_keyblock(OM_uint32 *minor_status, +				 gss_ctx_id_t context_handle, +				 krb5_keyblock **keyblock) +{ +    return gsskrb5_extract_key(minor_status, +			       context_handle, +			       GSS_KRB5_GET_SERVICE_KEYBLOCK_X, +			       keyblock); +} + +OM_uint32 GSSAPI_LIB_FUNCTION +gsskrb5_get_initiator_subkey(OM_uint32 *minor_status, +			     gss_ctx_id_t context_handle, +			     krb5_keyblock **keyblock) +{ +    return gsskrb5_extract_key(minor_status, +			       context_handle, +			       GSS_KRB5_GET_INITIATOR_SUBKEY_X, +			       keyblock); +} + +OM_uint32 GSSAPI_LIB_FUNCTION +gsskrb5_get_subkey(OM_uint32 *minor_status, +		   gss_ctx_id_t context_handle, +		   krb5_keyblock **keyblock) +{ +    return gsskrb5_extract_key(minor_status, +			       context_handle, +			       GSS_KRB5_GET_SUBKEY_X, +			       keyblock); +} + +OM_uint32 GSSAPI_LIB_FUNCTION +gsskrb5_set_default_realm(const char *realm) +{ +        struct _gss_mech_switch	*m; +	gss_buffer_desc buffer; +	OM_uint32 junk; + +	_gss_load_mech(); + +	buffer.value = rk_UNCONST(realm); +	buffer.length = strlen(realm); + +	SLIST_FOREACH(m, &_gss_mechs, gm_link) { +		if (m->gm_mech.gm_set_sec_context_option == NULL) +			continue; +		m->gm_mech.gm_set_sec_context_option(&junk, NULL, +		    GSS_KRB5_SET_DEFAULT_REALM_X, &buffer); +	} + +	return (GSS_S_COMPLETE); +} + +OM_uint32 GSSAPI_LIB_FUNCTION +gss_krb5_get_tkt_flags(OM_uint32 *minor_status, +		       gss_ctx_id_t context_handle, +		       OM_uint32 *tkt_flags) +{ + +    OM_uint32 major_status; +    gss_buffer_set_t data_set = GSS_C_NO_BUFFER_SET; + +    if (context_handle == GSS_C_NO_CONTEXT) { +	*minor_status = EINVAL; +	return GSS_S_FAILURE; +    } +     +    major_status = +	gss_inquire_sec_context_by_oid (minor_status, +					context_handle, +					GSS_KRB5_GET_TKT_FLAGS_X, +					&data_set); +    if (major_status) +	return major_status; +     +    if (data_set == GSS_C_NO_BUFFER_SET ||  +	data_set->count != 1 || +	data_set->elements[0].length < 4) { +	gss_release_buffer_set(minor_status, &data_set); +	*minor_status = EINVAL; +	return GSS_S_FAILURE; +    } + +    { +	const u_char *p = data_set->elements[0].value; +	*tkt_flags = (p[0] << 0) | (p[1] << 8) | (p[2] << 16) | (p[3] << 24); +    } + +    gss_release_buffer_set(minor_status, &data_set); +    return GSS_S_COMPLETE; +} + +OM_uint32 GSSAPI_LIB_FUNCTION +gsskrb5_set_time_offset(int offset) +{ +        struct _gss_mech_switch	*m; +	gss_buffer_desc buffer; +	OM_uint32 junk; +	int32_t o = offset; + +	_gss_load_mech(); + +	buffer.value = &o; +	buffer.length = sizeof(o); + +	SLIST_FOREACH(m, &_gss_mechs, gm_link) { +		if (m->gm_mech.gm_set_sec_context_option == NULL) +			continue; +		m->gm_mech.gm_set_sec_context_option(&junk, NULL, +		    GSS_KRB5_SET_TIME_OFFSET_X, &buffer); +	} + +	return (GSS_S_COMPLETE); +} + +OM_uint32 GSSAPI_LIB_FUNCTION +gsskrb5_get_time_offset(int *offset) +{ +        struct _gss_mech_switch	*m; +	gss_buffer_desc buffer; +	OM_uint32 maj_stat, junk; +	int32_t o; + +	_gss_load_mech(); + +	buffer.value = &o; +	buffer.length = sizeof(o); + +	SLIST_FOREACH(m, &_gss_mechs, gm_link) { +		if (m->gm_mech.gm_set_sec_context_option == NULL) +			continue; +		maj_stat = m->gm_mech.gm_set_sec_context_option(&junk, NULL, +		    GSS_KRB5_GET_TIME_OFFSET_X, &buffer); + +		if (maj_stat == GSS_S_COMPLETE) { +			*offset = o; +			return maj_stat; +		} +	} + +	return (GSS_S_UNAVAILABLE); +} diff --git a/source4/heimdal/lib/gssapi/mech/gss_mech_switch.c b/source4/heimdal/lib/gssapi/mech/gss_mech_switch.c new file mode 100644 index 0000000000..5b8d35c3dd --- /dev/null +++ b/source4/heimdal/lib/gssapi/mech/gss_mech_switch.c @@ -0,0 +1,335 @@ +/*- + * Copyright (c) 2005 Doug Rabson + * 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 AUTHOR 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 AUTHOR 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. + * + *	$FreeBSD: src/lib/libgssapi/gss_mech_switch.c,v 1.2 2006/02/04 09:40:21 dfr Exp $ + */ + +#include "mech_locl.h" +#include <heim_threads.h> +RCSID("$Id$"); + +#ifndef _PATH_GSS_MECH +#define _PATH_GSS_MECH	"/etc/gss/mech" +#endif + +struct _gss_mech_switch_list _gss_mechs = { NULL } ; +gss_OID_set _gss_mech_oids; +static HEIMDAL_MUTEX _gss_mech_mutex = HEIMDAL_MUTEX_INITIALIZER; + +/* + * Convert a string containing an OID in 'dot' form + * (e.g. 1.2.840.113554.1.2.2) to a gss_OID. + */ +static int +_gss_string_to_oid(const char* s, gss_OID oid) +{ +	int			number_count, i, j; +	size_t			byte_count; +	const char		*p, *q; +	char			*res; + +	oid->length = 0; +	oid->elements = NULL; + +	/* +	 * First figure out how many numbers in the oid, then +	 * calculate the compiled oid size. +	 */ +	number_count = 0; +	for (p = s; p; p = q) { +		q = strchr(p, '.'); +		if (q) q = q + 1; +		number_count++; +	} +	 +	/* +	 * The first two numbers are in the first byte and each +	 * subsequent number is encoded in a variable byte sequence. +	 */ +	if (number_count < 2) +		return (EINVAL); + +	/* +	 * We do this in two passes. The first pass, we just figure +	 * out the size. Second time around, we actually encode the +	 * number. +	 */ +	res = 0; +	for (i = 0; i < 2; i++) { +		byte_count = 0; +		for (p = s, j = 0; p; p = q, j++) { +			unsigned int number = 0; + +			/* +			 * Find the end of this number. +			 */ +			q = strchr(p, '.'); +			if (q) q = q + 1; + +			/* +			 * Read the number of of the string. Don't +			 * bother with anything except base ten. +			 */ +			while (*p && *p != '.') { +				number = 10 * number + (*p - '0'); +				p++; +			} + +			/* +			 * Encode the number. The first two numbers +			 * are packed into the first byte. Subsequent +			 * numbers are encoded in bytes seven bits at +			 * a time with the last byte having the high +			 * bit set. +			 */ +			if (j == 0) { +				if (res) +					*res = number * 40; +			} else if (j == 1) { +				if (res) { +					*res += number; +					res++; +				} +				byte_count++; +			} else if (j >= 2) { +				/* +				 * The number is encoded in seven bit chunks. +				 */ +				unsigned int t; +				unsigned int bytes; + +				bytes = 0; +				for (t = number; t; t >>= 7) +					bytes++; +				if (bytes == 0) bytes = 1; +				while (bytes) { +					if (res) { +						int bit = 7*(bytes-1); +						 +						*res = (number >> bit) & 0x7f; +						if (bytes != 1) +							*res |= 0x80; +						res++; +					} +					byte_count++; +					bytes--; +				} +			} +		} +		if (!res) { +			res = malloc(byte_count); +			if (!res) +				return (ENOMEM); +			oid->length = byte_count; +			oid->elements = res; +		} +	} + +	return (0); +} + +#define SYM(name)							\ +do {									\ +	m->gm_mech.gm_ ## name = dlsym(so, "gss_" #name);		\ +	if (!m->gm_mech.gm_ ## name) {					\ +		fprintf(stderr, "can't find symbol gss_" #name "\n");	\ +		goto bad;						\ +	}								\ +} while (0) + +#define OPTSYM(name)							\ +do {									\ +	m->gm_mech.gm_ ## name = dlsym(so, "gss_" #name);			\ +} while (0) + +/* + * + */ +static int +add_builtin(gssapi_mech_interface mech) +{ +    struct _gss_mech_switch *m; +    OM_uint32 minor_status; + +    /* not registering any mech is ok */ +    if (mech == NULL) +	return 0; + +    m = malloc(sizeof(*m)); +    if (m == NULL) +	return 1; +    m->gm_so = NULL; +    m->gm_mech = *mech; +    m->gm_mech_oid = mech->gm_mech_oid; /* XXX */ +    gss_add_oid_set_member(&minor_status, +			   &m->gm_mech.gm_mech_oid, &_gss_mech_oids); + +    SLIST_INSERT_HEAD(&_gss_mechs, m, gm_link); +    return 0; +} + +/* + * Load the mechanisms file (/etc/gss/mech). + */ +void +_gss_load_mech(void) +{ +	OM_uint32	major_status, minor_status; +	FILE		*fp; +	char		buf[256]; +	char		*p; +	char		*name, *oid, *lib, *kobj; +	struct _gss_mech_switch *m; +	void		*so; + + +	HEIMDAL_MUTEX_lock(&_gss_mech_mutex); + +	if (SLIST_FIRST(&_gss_mechs)) { +		HEIMDAL_MUTEX_unlock(&_gss_mech_mutex); +		return; +	} + +	major_status = gss_create_empty_oid_set(&minor_status, +	    &_gss_mech_oids); +	if (major_status) { +		HEIMDAL_MUTEX_unlock(&_gss_mech_mutex); +		return; +	} + +	add_builtin(__gss_krb5_initialize()); +	add_builtin(__gss_spnego_initialize()); +	add_builtin(__gss_ntlm_initialize()); + +#ifdef HAVE_DLOPEN +	fp = fopen(_PATH_GSS_MECH, "r"); +	if (!fp) { +		HEIMDAL_MUTEX_unlock(&_gss_mech_mutex); +		return; +	} +	rk_cloexec_file(fp); + +	while (fgets(buf, sizeof(buf), fp)) { +		if (*buf == '#') +			continue; +		p = buf; +		name = strsep(&p, "\t\n "); +		if (p) while (isspace((unsigned char)*p)) p++; +		oid = strsep(&p, "\t\n "); +		if (p) while (isspace((unsigned char)*p)) p++; +		lib = strsep(&p, "\t\n "); +		if (p) while (isspace((unsigned char)*p)) p++; +		kobj = strsep(&p, "\t\n "); +		if (!name || !oid || !lib || !kobj) +			continue; + +#ifndef RTLD_LOCAL +#define RTLD_LOCAL 0 +#endif + +		so = dlopen(lib, RTLD_LAZY | RTLD_LOCAL); +		if (!so) { +/*			fprintf(stderr, "dlopen: %s\n", dlerror()); */ +			continue; +		} + +		m = malloc(sizeof(*m)); +		if (!m) +			break; +		m->gm_so = so; +		if (_gss_string_to_oid(oid, &m->gm_mech.gm_mech_oid)) { +			free(m); +			continue; +		} +		 +		major_status = gss_add_oid_set_member(&minor_status, +		    &m->gm_mech.gm_mech_oid, &_gss_mech_oids); +		if (major_status) { +			free(m->gm_mech.gm_mech_oid.elements); +			free(m); +			continue; +		} + +		SYM(acquire_cred); +		SYM(release_cred); +		SYM(init_sec_context); +		SYM(accept_sec_context); +		SYM(process_context_token); +		SYM(delete_sec_context); +		SYM(context_time); +		SYM(get_mic); +		SYM(verify_mic); +		SYM(wrap); +		SYM(unwrap); +		SYM(display_status); +		SYM(indicate_mechs); +		SYM(compare_name); +		SYM(display_name); +		SYM(import_name); +		SYM(export_name); +		SYM(release_name); +		SYM(inquire_cred); +		SYM(inquire_context); +		SYM(wrap_size_limit); +		SYM(add_cred); +		SYM(inquire_cred_by_mech); +		SYM(export_sec_context); +		SYM(import_sec_context); +		SYM(inquire_names_for_mech); +		SYM(inquire_mechs_for_name); +		SYM(canonicalize_name); +		SYM(duplicate_name); +		OPTSYM(inquire_cred_by_oid); +		OPTSYM(inquire_sec_context_by_oid); +		OPTSYM(set_sec_context_option); +		OPTSYM(set_cred_option); +		OPTSYM(pseudo_random); + +		SLIST_INSERT_HEAD(&_gss_mechs, m, gm_link); +		continue; + +	bad: +		free(m->gm_mech.gm_mech_oid.elements); +		free(m); +		dlclose(so); +		continue; +	} +	fclose(fp); +#endif +	HEIMDAL_MUTEX_unlock(&_gss_mech_mutex); +} + +gssapi_mech_interface +__gss_get_mechanism(gss_OID mech) +{ +        struct _gss_mech_switch	*m; + +	_gss_load_mech(); +	SLIST_FOREACH(m, &_gss_mechs, gm_link) { +		if (gss_oid_equal(&m->gm_mech.gm_mech_oid, mech)) +			return &m->gm_mech; +	} +	return NULL; +} diff --git a/source4/heimdal/lib/gssapi/mech/gss_names.c b/source4/heimdal/lib/gssapi/mech/gss_names.c new file mode 100644 index 0000000000..a1b858d938 --- /dev/null +++ b/source4/heimdal/lib/gssapi/mech/gss_names.c @@ -0,0 +1,111 @@ +/*- + * Copyright (c) 2005 Doug Rabson + * 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 AUTHOR 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 AUTHOR 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. + * + *	$FreeBSD: src/lib/libgssapi/gss_names.c,v 1.1 2005/12/29 14:40:20 dfr Exp $ + */ + +#include "mech_locl.h" +RCSID("$Id$"); + +OM_uint32 +_gss_find_mn(OM_uint32 *minor_status, struct _gss_name *name, gss_OID mech,  +	     struct _gss_mechanism_name **output_mn) +{ +	OM_uint32 major_status; +	gssapi_mech_interface m; +	struct _gss_mechanism_name *mn; + +	*output_mn = NULL; + +	SLIST_FOREACH(mn, &name->gn_mn, gmn_link) { +		if (gss_oid_equal(mech, mn->gmn_mech_oid)) +			break; +	} + +	if (!mn) { +		/* +		 * If this name is canonical (i.e. there is only an +		 * MN but it is from a different mech), give up now. +		 */ +		if (!name->gn_value.value) +			return GSS_S_BAD_NAME; + +		m = __gss_get_mechanism(mech); +		if (!m) +			return (GSS_S_BAD_MECH); + +		mn = malloc(sizeof(struct _gss_mechanism_name)); +		if (!mn) +			return GSS_S_FAILURE; +		 +		major_status = m->gm_import_name(minor_status, +		    &name->gn_value, +		    (name->gn_type.elements +			? &name->gn_type : GSS_C_NO_OID), +		    &mn->gmn_name); +		if (major_status != GSS_S_COMPLETE) { +			_gss_mg_error(m, major_status, *minor_status); +			free(mn); +			return major_status; +		} + +		mn->gmn_mech = m; +		mn->gmn_mech_oid = &m->gm_mech_oid; +		SLIST_INSERT_HEAD(&name->gn_mn, mn, gmn_link); +	} +	*output_mn = mn; +	return 0; +} + + +/* + * Make a name from an MN. + */ +struct _gss_name * +_gss_make_name(gssapi_mech_interface m, gss_name_t new_mn) +{ +	struct _gss_name *name; +	struct _gss_mechanism_name *mn; + +	name = malloc(sizeof(struct _gss_name)); +	if (!name) +		return (0); +	memset(name, 0, sizeof(struct _gss_name)); + +	mn = malloc(sizeof(struct _gss_mechanism_name)); +	if (!mn) { +		free(name); +		return (0); +	} + +	SLIST_INIT(&name->gn_mn); +	mn->gmn_mech = m; +	mn->gmn_mech_oid = &m->gm_mech_oid; +	mn->gmn_name = new_mn; +	SLIST_INSERT_HEAD(&name->gn_mn, mn, gmn_link); + +	return (name); +} + diff --git a/source4/heimdal/lib/gssapi/mech/gss_oid_equal.c b/source4/heimdal/lib/gssapi/mech/gss_oid_equal.c new file mode 100644 index 0000000000..0ec6a9b5cc --- /dev/null +++ b/source4/heimdal/lib/gssapi/mech/gss_oid_equal.c @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2006 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.  + */ + +#include "mech_locl.h" +RCSID("$Id$"); + +int GSSAPI_LIB_FUNCTION +gss_oid_equal(const gss_OID a, const gss_OID b) +{ +    if (a == b) +	return 1; +    if (a == GSS_C_NO_OID || b == GSS_C_NO_OID || a->length != b->length) +	return 0; +    return memcmp(a->elements, b->elements, a->length) == 0; +} diff --git a/source4/heimdal/lib/gssapi/mech/gss_oid_to_str.c b/source4/heimdal/lib/gssapi/mech/gss_oid_to_str.c new file mode 100644 index 0000000000..69a723adb1 --- /dev/null +++ b/source4/heimdal/lib/gssapi/mech/gss_oid_to_str.c @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2006 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.  + */ + +#include "mech_locl.h" +RCSID("$Id$"); + +OM_uint32 GSSAPI_LIB_FUNCTION +gss_oid_to_str(OM_uint32 *minor_status, gss_OID oid, gss_buffer_t oid_str) +{ +    int ret; +    size_t size; +    heim_oid o; +    char *p; + +    _mg_buffer_zero(oid_str); + +    if (oid == GSS_C_NULL_OID) +	return GSS_S_FAILURE; + +    ret = der_get_oid (oid->elements, oid->length, &o, &size); +    if (ret) { +	*minor_status = ret; +	return GSS_S_FAILURE; +    } + +    ret = der_print_heim_oid(&o, ' ', &p); +    der_free_oid(&o); +    if (ret) { +	*minor_status = ret; +	return GSS_S_FAILURE; +    } +     +    oid_str->value = p; +    oid_str->length = strlen(p); + +    *minor_status = 0; +    return GSS_S_COMPLETE; +} diff --git a/source4/heimdal/lib/gssapi/mech/gss_process_context_token.c b/source4/heimdal/lib/gssapi/mech/gss_process_context_token.c new file mode 100644 index 0000000000..9dc3f5b904 --- /dev/null +++ b/source4/heimdal/lib/gssapi/mech/gss_process_context_token.c @@ -0,0 +1,42 @@ +/*- + * Copyright (c) 2005 Doug Rabson + * 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 AUTHOR 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 AUTHOR 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. + * + *	$FreeBSD: src/lib/libgssapi/gss_process_context_token.c,v 1.1 2005/12/29 14:40:20 dfr Exp $ + */ + +#include "mech_locl.h" +RCSID("$Id$"); + +OM_uint32 GSSAPI_LIB_FUNCTION +gss_process_context_token(OM_uint32 *minor_status, +    const gss_ctx_id_t context_handle, +    const gss_buffer_t token_buffer) +{ +	struct _gss_context *ctx = (struct _gss_context *) context_handle; +	gssapi_mech_interface m = ctx->gc_mech; + +	return (m->gm_process_context_token(minor_status, ctx->gc_ctx, +		    token_buffer)); +} diff --git a/source4/heimdal/lib/gssapi/mech/gss_pseudo_random.c b/source4/heimdal/lib/gssapi/mech/gss_pseudo_random.c new file mode 100644 index 0000000000..5807ee9d9b --- /dev/null +++ b/source4/heimdal/lib/gssapi/mech/gss_pseudo_random.c @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2007 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.  + */ + +/* $Id$ */ + +#include "mech_locl.h" +RCSID("$Id$"); + +OM_uint32 GSSAPI_LIB_FUNCTION +gss_pseudo_random(OM_uint32 *minor_status, +		  gss_ctx_id_t context, +		  int prf_key, +		  const gss_buffer_t prf_in, +		  ssize_t desired_output_len, +		  gss_buffer_t prf_out) +{ +    struct _gss_context *ctx = (struct _gss_context *) context; +    gssapi_mech_interface m = ctx->gc_mech; +    OM_uint32 major_status; + +    _mg_buffer_zero(prf_out); +    *minor_status = 0; + +    if (ctx == NULL) { +	*minor_status = 0; +	return GSS_S_NO_CONTEXT; +    } + +    if (m->gm_pseudo_random == NULL) +	return GSS_S_UNAVAILABLE; +     +    major_status = (*m->gm_pseudo_random)(minor_status, ctx->gc_ctx, +					  prf_key, prf_in, desired_output_len, +					  prf_out); +    if (major_status != GSS_S_COMPLETE) +	_gss_mg_error(m, major_status, *minor_status); + +    return major_status; +} diff --git a/source4/heimdal/lib/gssapi/mech/gss_release_buffer.c b/source4/heimdal/lib/gssapi/mech/gss_release_buffer.c new file mode 100644 index 0000000000..1af5289157 --- /dev/null +++ b/source4/heimdal/lib/gssapi/mech/gss_release_buffer.c @@ -0,0 +1,43 @@ +/*- + * Copyright (c) 2005 Doug Rabson + * 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 AUTHOR 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 AUTHOR 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. + * + *	$FreeBSD: src/lib/libgssapi/gss_release_buffer.c,v 1.1 2005/12/29 14:40:20 dfr Exp $ + */ + +#include "mech_locl.h" +RCSID("$Id$"); + +OM_uint32 GSSAPI_LIB_FUNCTION +gss_release_buffer(OM_uint32 *minor_status, +		   gss_buffer_t buffer) +{ + +	*minor_status = 0; +	if (buffer->value) +		free(buffer->value); +	_mg_buffer_zero(buffer); + +	return (GSS_S_COMPLETE); +} diff --git a/source4/heimdal/lib/gssapi/mech/gss_release_cred.c b/source4/heimdal/lib/gssapi/mech/gss_release_cred.c new file mode 100644 index 0000000000..40777fa2a1 --- /dev/null +++ b/source4/heimdal/lib/gssapi/mech/gss_release_cred.c @@ -0,0 +1,52 @@ +/*- + * Copyright (c) 2005 Doug Rabson + * 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 AUTHOR 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 AUTHOR 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. + * + *	$FreeBSD: src/lib/libgssapi/gss_release_cred.c,v 1.1 2005/12/29 14:40:20 dfr Exp $ + */ + +#include "mech_locl.h" +RCSID("$Id$"); + +OM_uint32 GSSAPI_LIB_FUNCTION +gss_release_cred(OM_uint32 *minor_status, gss_cred_id_t *cred_handle) +{ +	struct _gss_cred *cred = (struct _gss_cred *) *cred_handle; +	struct _gss_mechanism_cred *mc; + +	if (*cred_handle == GSS_C_NO_CREDENTIAL) +	    return (GSS_S_COMPLETE); + +	while (SLIST_FIRST(&cred->gc_mc)) { +		mc = SLIST_FIRST(&cred->gc_mc); +		SLIST_REMOVE_HEAD(&cred->gc_mc, gmc_link); +		mc->gmc_mech->gm_release_cred(minor_status, &mc->gmc_cred); +		free(mc); +	} +	free(cred); + +	*minor_status = 0; +	*cred_handle = GSS_C_NO_CREDENTIAL; +	return (GSS_S_COMPLETE); +} diff --git a/source4/heimdal/lib/gssapi/mech/gss_release_name.c b/source4/heimdal/lib/gssapi/mech/gss_release_name.c new file mode 100644 index 0000000000..ad07c60bda --- /dev/null +++ b/source4/heimdal/lib/gssapi/mech/gss_release_name.c @@ -0,0 +1,55 @@ +/*- + * Copyright (c) 2005 Doug Rabson + * 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 AUTHOR 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 AUTHOR 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. + * + *	$FreeBSD: src/lib/libgssapi/gss_release_name.c,v 1.1 2005/12/29 14:40:20 dfr Exp $ + */ + +#include "mech_locl.h" +RCSID("$Id$"); + +OM_uint32 GSSAPI_LIB_FUNCTION +gss_release_name(OM_uint32 *minor_status, +    gss_name_t *input_name) +{ +	struct _gss_name *name = (struct _gss_name *) *input_name; + +	*minor_status = 0; +	if (name) { +		if (name->gn_type.elements) +			free(name->gn_type.elements); +		while (SLIST_FIRST(&name->gn_mn)) { +			struct _gss_mechanism_name *mn; +			mn = SLIST_FIRST(&name->gn_mn); +			SLIST_REMOVE_HEAD(&name->gn_mn, gmn_link); +			mn->gmn_mech->gm_release_name(minor_status, +			    &mn->gmn_name); +			free(mn); +		} +		gss_release_buffer(minor_status, &name->gn_value); +		free(name); +		*input_name = GSS_C_NO_NAME; +	} +	return (GSS_S_COMPLETE); +} diff --git a/source4/heimdal/lib/gssapi/mech/gss_release_oid.c b/source4/heimdal/lib/gssapi/mech/gss_release_oid.c new file mode 100644 index 0000000000..dda8efb650 --- /dev/null +++ b/source4/heimdal/lib/gssapi/mech/gss_release_oid.c @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2006 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.  + */ + +#include "mech_locl.h" + +RCSID("$Id$"); + +OM_uint32 GSSAPI_LIB_FUNCTION +gss_release_oid(OM_uint32 *minor_status, gss_OID *oid) +{ +    gss_OID o = *oid; + +    *oid = GSS_C_NO_OID; + +    if (minor_status != NULL) +	*minor_status = 0; + +    if (o == GSS_C_NO_OID) +	return GSS_S_COMPLETE; + +    if (o->elements != NULL) { +	free(o->elements); +	o->elements = NULL; +    } +    o->length = 0; +    free(o); + +    return GSS_S_COMPLETE; +} diff --git a/source4/heimdal/lib/gssapi/mech/gss_release_oid_set.c b/source4/heimdal/lib/gssapi/mech/gss_release_oid_set.c new file mode 100644 index 0000000000..0ccb9e4dc6 --- /dev/null +++ b/source4/heimdal/lib/gssapi/mech/gss_release_oid_set.c @@ -0,0 +1,45 @@ +/*- + * Copyright (c) 2005 Doug Rabson + * 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 AUTHOR 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 AUTHOR 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. + * + *	$FreeBSD: src/lib/libgssapi/gss_release_oid_set.c,v 1.1 2005/12/29 14:40:20 dfr Exp $ + */ + +#include "mech_locl.h" +RCSID("$Id$"); + +OM_uint32 GSSAPI_LIB_FUNCTION +gss_release_oid_set(OM_uint32 *minor_status, +    gss_OID_set *set) +{ + +	*minor_status = 0; +	if (set && *set) { +		if ((*set)->elements) +			free((*set)->elements); +		free(*set); +		*set = GSS_C_NO_OID_SET; +	} +	return (GSS_S_COMPLETE); +} diff --git a/source4/heimdal/lib/gssapi/mech/gss_seal.c b/source4/heimdal/lib/gssapi/mech/gss_seal.c new file mode 100644 index 0000000000..f6636456ea --- /dev/null +++ b/source4/heimdal/lib/gssapi/mech/gss_seal.c @@ -0,0 +1,46 @@ +/*- + * Copyright (c) 2005 Doug Rabson + * 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 AUTHOR 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 AUTHOR 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. + * + *	$FreeBSD: src/lib/libgssapi/gss_seal.c,v 1.1 2005/12/29 14:40:20 dfr Exp $ + */ + +#include "mech_locl.h" +RCSID("$Id$"); + +OM_uint32 GSSAPI_LIB_FUNCTION +gss_seal(OM_uint32 *minor_status, +    gss_ctx_id_t context_handle, +    int conf_req_flag, +    int qop_req, +    gss_buffer_t input_message_buffer, +    int *conf_state, +    gss_buffer_t output_message_buffer) +{ + +	return (gss_wrap(minor_status, +		    context_handle, conf_req_flag, qop_req, +		    input_message_buffer, conf_state, +		    output_message_buffer)); +} diff --git a/source4/heimdal/lib/gssapi/mech/gss_set_cred_option.c b/source4/heimdal/lib/gssapi/mech/gss_set_cred_option.c new file mode 100644 index 0000000000..20eaa14d9e --- /dev/null +++ b/source4/heimdal/lib/gssapi/mech/gss_set_cred_option.c @@ -0,0 +1,119 @@ +/* + * Copyright (c) 2004, PADL Software Pty Ltd. + * 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 PADL Software 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 PADL SOFTWARE 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 PADL SOFTWARE 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. + */ + +#include "mech_locl.h" +RCSID("$Id$"); + +OM_uint32 GSSAPI_LIB_FUNCTION +gss_set_cred_option (OM_uint32 *minor_status, +		     gss_cred_id_t *cred_handle, +		     const gss_OID object, +		     const gss_buffer_t value) +{ +	struct _gss_cred *cred = (struct _gss_cred *) *cred_handle; +	OM_uint32	major_status = GSS_S_COMPLETE; +	struct _gss_mechanism_cred *mc; +	int one_ok = 0; + +	*minor_status = 0; + +	_gss_load_mech(); + +	if (cred == NULL) { +		struct _gss_mech_switch *m; + +		cred = malloc(sizeof(*cred)); +		if (cred == NULL) +		    return GSS_S_FAILURE; + +		SLIST_INIT(&cred->gc_mc); + +		SLIST_FOREACH(m, &_gss_mechs, gm_link) { + +			if (m->gm_mech.gm_set_cred_option == NULL) +				continue; + +			mc = malloc(sizeof(*mc)); +			if (mc == NULL) { +			    *cred_handle = (gss_cred_id_t)cred; +			    gss_release_cred(minor_status, cred_handle); +			    *minor_status = ENOMEM; +			    return GSS_S_FAILURE; +			} + +			mc->gmc_mech = &m->gm_mech; +			mc->gmc_mech_oid = &m->gm_mech_oid; +			mc->gmc_cred = GSS_C_NO_CREDENTIAL; + +			major_status = m->gm_mech.gm_set_cred_option( +			    minor_status, &mc->gmc_cred, object, value); + +			if (major_status) { +				free(mc); +				continue; +			} +			one_ok = 1; +			SLIST_INSERT_HEAD(&cred->gc_mc, mc, gmc_link); +		} +		*cred_handle = (gss_cred_id_t)cred; +		if (!one_ok) { +			OM_uint32 junk; +			gss_release_cred(&junk, cred_handle); +		} +	} else { +		gssapi_mech_interface	m; + +		SLIST_FOREACH(mc, &cred->gc_mc, gmc_link) { +			m = mc->gmc_mech; +	 +			if (m == NULL) +				return GSS_S_BAD_MECH; +	 +			if (m->gm_set_cred_option == NULL) +				continue; +	 +			major_status = m->gm_set_cred_option(minor_status, +			    &mc->gmc_cred, object, value); +			if (major_status == GSS_S_COMPLETE) +				one_ok = 1; +			else +				_gss_mg_error(m, major_status, *minor_status); + +		} +	} +	if (one_ok) { +		*minor_status = 0; +		return GSS_S_COMPLETE; +	} +	return major_status; +} + diff --git a/source4/heimdal/lib/gssapi/mech/gss_set_sec_context_option.c b/source4/heimdal/lib/gssapi/mech/gss_set_sec_context_option.c new file mode 100644 index 0000000000..735d59322e --- /dev/null +++ b/source4/heimdal/lib/gssapi/mech/gss_set_sec_context_option.c @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2004, PADL Software Pty Ltd. + * 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 PADL Software 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 PADL SOFTWARE 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 PADL SOFTWARE 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. + */ + +#include "mech_locl.h" +RCSID("$Id$"); + +OM_uint32 GSSAPI_LIB_FUNCTION +gss_set_sec_context_option (OM_uint32 *minor_status, +			    gss_ctx_id_t *context_handle, +			    const gss_OID object, +			    const gss_buffer_t value) +{ +	struct _gss_context	*ctx; +	OM_uint32		major_status; +	gssapi_mech_interface	m; + +	*minor_status = 0; + +	if (context_handle == NULL) +		return GSS_S_NO_CONTEXT; + +	ctx = (struct _gss_context *) *context_handle; + +	if (ctx == NULL) +		return GSS_S_NO_CONTEXT; + +	m = ctx->gc_mech; + +	if (m == NULL) +		return GSS_S_BAD_MECH; + +	if (m->gm_set_sec_context_option != NULL) { +		major_status = m->gm_set_sec_context_option(minor_status, +		    &ctx->gc_ctx, object, value); +		if (major_status != GSS_S_COMPLETE) +			_gss_mg_error(m, major_status, *minor_status); +	} else +		major_status = GSS_S_BAD_MECH; + +	return major_status; +} + diff --git a/source4/heimdal/lib/gssapi/mech/gss_sign.c b/source4/heimdal/lib/gssapi/mech/gss_sign.c new file mode 100644 index 0000000000..1d73641355 --- /dev/null +++ b/source4/heimdal/lib/gssapi/mech/gss_sign.c @@ -0,0 +1,42 @@ +/*- + * Copyright (c) 2005 Doug Rabson + * 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 AUTHOR 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 AUTHOR 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. + * + *	$FreeBSD: src/lib/libgssapi/gss_sign.c,v 1.1 2005/12/29 14:40:20 dfr Exp $ + */ + +#include "mech_locl.h" +RCSID("$Id$"); + +OM_uint32 GSSAPI_LIB_FUNCTION +gss_sign(OM_uint32 *minor_status, +    gss_ctx_id_t context_handle, +    int qop_req, +    gss_buffer_t message_buffer, +    gss_buffer_t message_token) +{ + +	return gss_get_mic(minor_status, +	    context_handle, qop_req, message_buffer, message_token); +} diff --git a/source4/heimdal/lib/gssapi/mech/gss_test_oid_set_member.c b/source4/heimdal/lib/gssapi/mech/gss_test_oid_set_member.c new file mode 100644 index 0000000000..ca1dca8fad --- /dev/null +++ b/source4/heimdal/lib/gssapi/mech/gss_test_oid_set_member.c @@ -0,0 +1,47 @@ +/*- + * Copyright (c) 2005 Doug Rabson + * 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 AUTHOR 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 AUTHOR 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. + * + *	$FreeBSD: src/lib/libgssapi/gss_test_oid_set_member.c,v 1.1 2005/12/29 14:40:20 dfr Exp $ + */ + +#include "mech_locl.h" +RCSID("$Id$"); + +OM_uint32 GSSAPI_LIB_FUNCTION +gss_test_oid_set_member(OM_uint32 *minor_status, +    const gss_OID member, +    const gss_OID_set set, +    int *present) +{ +	int i; + +	*present = 0; +	for (i = 0; i < set->count; i++) +		if (gss_oid_equal(member, &set->elements[i])) +			*present = 1; + +	*minor_status = 0; +	return (GSS_S_COMPLETE); +} diff --git a/source4/heimdal/lib/gssapi/mech/gss_unseal.c b/source4/heimdal/lib/gssapi/mech/gss_unseal.c new file mode 100644 index 0000000000..539e65a01c --- /dev/null +++ b/source4/heimdal/lib/gssapi/mech/gss_unseal.c @@ -0,0 +1,44 @@ +/*- + * Copyright (c) 2005 Doug Rabson + * 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 AUTHOR 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 AUTHOR 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. + * + *	$FreeBSD: src/lib/libgssapi/gss_unseal.c,v 1.1 2005/12/29 14:40:20 dfr Exp $ + */ + +#include "mech_locl.h" +RCSID("$Id$"); + +OM_uint32 GSSAPI_LIB_FUNCTION +gss_unseal(OM_uint32 *minor_status, +    gss_ctx_id_t context_handle, +    gss_buffer_t input_message_buffer, +    gss_buffer_t output_message_buffer, +    int *conf_state, +    int *qop_state) +{ + +	return (gss_unwrap(minor_status, +		    context_handle, input_message_buffer, +		    output_message_buffer, conf_state, (gss_qop_t *)qop_state)); +} diff --git a/source4/heimdal/lib/gssapi/mech/gss_unwrap.c b/source4/heimdal/lib/gssapi/mech/gss_unwrap.c new file mode 100644 index 0000000000..693bbe020b --- /dev/null +++ b/source4/heimdal/lib/gssapi/mech/gss_unwrap.c @@ -0,0 +1,46 @@ +/*- + * Copyright (c) 2005 Doug Rabson + * 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 AUTHOR 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 AUTHOR 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. + * + *	$FreeBSD: src/lib/libgssapi/gss_unwrap.c,v 1.1 2005/12/29 14:40:20 dfr Exp $ + */ + +#include "mech_locl.h" +RCSID("$Id$"); + +OM_uint32 GSSAPI_LIB_FUNCTION +gss_unwrap(OM_uint32 *minor_status, +    const gss_ctx_id_t context_handle, +    const gss_buffer_t input_message_buffer, +    gss_buffer_t output_message_buffer, +    int *conf_state, +    gss_qop_t *qop_state) +{ +	struct _gss_context *ctx = (struct _gss_context *) context_handle; +	gssapi_mech_interface m = ctx->gc_mech; + +	return (m->gm_unwrap(minor_status, ctx->gc_ctx, +		    input_message_buffer, output_message_buffer, +		    conf_state, qop_state)); +} diff --git a/source4/heimdal/lib/gssapi/mech/gss_utils.c b/source4/heimdal/lib/gssapi/mech/gss_utils.c new file mode 100644 index 0000000000..6e05acff03 --- /dev/null +++ b/source4/heimdal/lib/gssapi/mech/gss_utils.c @@ -0,0 +1,79 @@ +/*- + * Copyright (c) 2005 Doug Rabson + * 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 AUTHOR 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 AUTHOR 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. + * + *	$FreeBSD: src/lib/libgssapi/gss_utils.c,v 1.1 2005/12/29 14:40:20 dfr Exp $ + */ + +#include "mech_locl.h" +RCSID("$Id$"); + +OM_uint32 +_gss_copy_oid(OM_uint32 *minor_status, +    const gss_OID from_oid, gss_OID to_oid) +{ +	size_t len = from_oid->length; + +	*minor_status = 0; +	to_oid->elements = malloc(len); +	if (!to_oid->elements) { +		to_oid->length = 0; +		*minor_status = ENOMEM; +		return GSS_S_FAILURE; +	} +	to_oid->length = len; +	memcpy(to_oid->elements, from_oid->elements, len); +	return (GSS_S_COMPLETE); +} + +OM_uint32 +_gss_free_oid(OM_uint32 *minor_status, gss_OID oid) +{ +	*minor_status = 0; +	if (oid->elements) { +	    free(oid->elements); +	    oid->elements = NULL; +	    oid->length = 0; +	} +	return (GSS_S_COMPLETE); +} + +OM_uint32 +_gss_copy_buffer(OM_uint32 *minor_status, +    const gss_buffer_t from_buf, gss_buffer_t to_buf) +{ +	size_t len = from_buf->length; + +	*minor_status = 0; +	to_buf->value = malloc(len); +	if (!to_buf->value) { +		*minor_status = ENOMEM; +		to_buf->length = 0; +		return GSS_S_FAILURE; +	} +	to_buf->length = len; +	memcpy(to_buf->value, from_buf->value, len); +	return (GSS_S_COMPLETE); +} + diff --git a/source4/heimdal/lib/gssapi/mech/gss_verify.c b/source4/heimdal/lib/gssapi/mech/gss_verify.c new file mode 100644 index 0000000000..f287cb4816 --- /dev/null +++ b/source4/heimdal/lib/gssapi/mech/gss_verify.c @@ -0,0 +1,43 @@ +/*- + * Copyright (c) 2005 Doug Rabson + * 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 AUTHOR 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 AUTHOR 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. + * + *	$FreeBSD: src/lib/libgssapi/gss_verify.c,v 1.1 2005/12/29 14:40:20 dfr Exp $ + */ + +#include "mech_locl.h" +RCSID("$Id$"); + +OM_uint32 GSSAPI_LIB_FUNCTION +gss_verify(OM_uint32 *minor_status, +    gss_ctx_id_t context_handle, +    gss_buffer_t message_buffer, +    gss_buffer_t token_buffer, +    int *qop_state) +{ + +	return (gss_verify_mic(minor_status, +		    context_handle, message_buffer, token_buffer, +		    (gss_qop_t *)qop_state)); +} diff --git a/source4/heimdal/lib/gssapi/mech/gss_verify_mic.c b/source4/heimdal/lib/gssapi/mech/gss_verify_mic.c new file mode 100644 index 0000000000..1a411729c6 --- /dev/null +++ b/source4/heimdal/lib/gssapi/mech/gss_verify_mic.c @@ -0,0 +1,51 @@ +/*- + * Copyright (c) 2005 Doug Rabson + * 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 AUTHOR 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 AUTHOR 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. + * + *	$FreeBSD: src/lib/libgssapi/gss_verify_mic.c,v 1.1 2005/12/29 14:40:20 dfr Exp $ + */ + +#include "mech_locl.h" +RCSID("$Id$"); + +OM_uint32 GSSAPI_LIB_FUNCTION +gss_verify_mic(OM_uint32 *minor_status, +    const gss_ctx_id_t context_handle, +    const gss_buffer_t message_buffer, +    const gss_buffer_t token_buffer, +    gss_qop_t *qop_state) +{ +	struct _gss_context *ctx = (struct _gss_context *) context_handle; +	gssapi_mech_interface m = ctx->gc_mech; + +	if (qop_state) +	    *qop_state = 0; +	if (ctx == NULL) { +	    *minor_status = 0; +	    return GSS_S_NO_CONTEXT; +	} + +	return (m->gm_verify_mic(minor_status, ctx->gc_ctx, +		    message_buffer, token_buffer, qop_state)); +} diff --git a/source4/heimdal/lib/gssapi/mech/gss_wrap.c b/source4/heimdal/lib/gssapi/mech/gss_wrap.c new file mode 100644 index 0000000000..b3363d3f20 --- /dev/null +++ b/source4/heimdal/lib/gssapi/mech/gss_wrap.c @@ -0,0 +1,55 @@ +/*- + * Copyright (c) 2005 Doug Rabson + * 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 AUTHOR 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 AUTHOR 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. + * + *	$FreeBSD: src/lib/libgssapi/gss_wrap.c,v 1.1 2005/12/29 14:40:20 dfr Exp $ + */ + +#include "mech_locl.h" +RCSID("$Id$"); + +OM_uint32 GSSAPI_LIB_FUNCTION +gss_wrap(OM_uint32 *minor_status, +    const gss_ctx_id_t context_handle, +    int conf_req_flag, +    gss_qop_t qop_req, +    const gss_buffer_t input_message_buffer, +    int *conf_state, +    gss_buffer_t output_message_buffer) +{ +	struct _gss_context *ctx = (struct _gss_context *) context_handle; +	gssapi_mech_interface m = ctx->gc_mech; + +	if (conf_state) +	    *conf_state = 0; +	_mg_buffer_zero(output_message_buffer); +	if (ctx == NULL) { +	    *minor_status = 0; +	    return GSS_S_NO_CONTEXT; +	} + +	return (m->gm_wrap(minor_status, ctx->gc_ctx, +		    conf_req_flag, qop_req, input_message_buffer, +		    conf_state, output_message_buffer)); +} diff --git a/source4/heimdal/lib/gssapi/mech/gss_wrap_size_limit.c b/source4/heimdal/lib/gssapi/mech/gss_wrap_size_limit.c new file mode 100644 index 0000000000..15b86a9367 --- /dev/null +++ b/source4/heimdal/lib/gssapi/mech/gss_wrap_size_limit.c @@ -0,0 +1,51 @@ +/*- + * Copyright (c) 2005 Doug Rabson + * 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 AUTHOR 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 AUTHOR 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. + * + *	$FreeBSD: src/lib/libgssapi/gss_wrap_size_limit.c,v 1.1 2005/12/29 14:40:20 dfr Exp $ + */ + +#include "mech_locl.h" +RCSID("$Id$"); + +OM_uint32 GSSAPI_LIB_FUNCTION +gss_wrap_size_limit(OM_uint32 *minor_status, +    const gss_ctx_id_t context_handle, +    int conf_req_flag, +    gss_qop_t qop_req, +    OM_uint32 req_output_size, +    OM_uint32 *max_input_size) +{ +	struct _gss_context *ctx = (struct _gss_context *) context_handle; +	gssapi_mech_interface m = ctx->gc_mech; +	 +	*max_input_size = 0; +	if (ctx == NULL) { +	    *minor_status = 0; +	    return GSS_S_NO_CONTEXT; +	} + +	return (m->gm_wrap_size_limit(minor_status, ctx->gc_ctx, +		    conf_req_flag, qop_req, req_output_size, max_input_size)); +} diff --git a/source4/heimdal/lib/gssapi/mech/gssapi.asn1 b/source4/heimdal/lib/gssapi/mech/gssapi.asn1 new file mode 100644 index 0000000000..1ba7b40637 --- /dev/null +++ b/source4/heimdal/lib/gssapi/mech/gssapi.asn1 @@ -0,0 +1,12 @@ +-- $Id$ + +GSS-API DEFINITIONS ::= BEGIN + +IMPORTS heim_any_set FROM heim; + +GSSAPIContextToken ::= [APPLICATION 0] IMPLICIT SEQUENCE { +	thisMech OBJECT IDENTIFIER, +	innerContextToken heim_any_set +} + +END
\ No newline at end of file diff --git a/source4/heimdal/lib/gssapi/mech/mech_locl.h b/source4/heimdal/lib/gssapi/mech/mech_locl.h new file mode 100644 index 0000000000..8887692e08 --- /dev/null +++ b/source4/heimdal/lib/gssapi/mech/mech_locl.h @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2006 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.  + */ + +/* $Id$ */ + +#include <config.h> + +#include <krb5-types.h> + +#include <sys/types.h> + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <ctype.h> +#include <dlfcn.h> +#include <errno.h> + +#include <gssapi_asn1.h> +#include <der.h> + +#include <roken.h> + +#include <gssapi.h> +#include <gssapi_mech.h> + +#include "mechqueue.h" + +#include "context.h" +#include "cred.h" +#include "mech_switch.h" +#include "name.h" +#include "utils.h" + +#define _mg_buffer_zero(buffer) \ +	do { (buffer)->value = NULL; (buffer)->length = 0; } while(0) diff --git a/source4/heimdal/lib/gssapi/mech/mech_switch.h b/source4/heimdal/lib/gssapi/mech/mech_switch.h new file mode 100644 index 0000000000..e83a4c8a5a --- /dev/null +++ b/source4/heimdal/lib/gssapi/mech/mech_switch.h @@ -0,0 +1,42 @@ +/*- + * Copyright (c) 2005 Doug Rabson + * 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 AUTHOR 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 AUTHOR 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. + * + *	$FreeBSD: src/lib/libgssapi/mech_switch.h,v 1.1 2005/12/29 14:40:20 dfr Exp $ + *	$Id$ + */ + +#include <gssapi_mech.h> + +struct _gss_mech_switch { +	SLIST_ENTRY(_gss_mech_switch)	gm_link; +	gss_OID_desc			gm_mech_oid; +	void				*gm_so; +	gssapi_mech_interface_desc	gm_mech; +}; +SLIST_HEAD(_gss_mech_switch_list, _gss_mech_switch); +extern struct _gss_mech_switch_list _gss_mechs; +extern gss_OID_set _gss_mech_oids; + +void	_gss_load_mech(void); diff --git a/source4/heimdal/lib/gssapi/mech/mechqueue.h b/source4/heimdal/lib/gssapi/mech/mechqueue.h new file mode 100644 index 0000000000..8434b76c00 --- /dev/null +++ b/source4/heimdal/lib/gssapi/mech/mechqueue.h @@ -0,0 +1,101 @@ +/*	$NetBSD: queue.h,v 1.39 2004/04/18 14:25:34 lukem 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	_MECHQUEUE_H_ +#define	_MECHQUEUE_H_ + +#ifndef SLIST_HEAD + +/* + * Singly-linked List definitions. + */ +#define	SLIST_HEAD(name, type)						\ +struct name {								\ +	struct type *slh_first;	/* first element */			\ +} + +#define	SLIST_HEAD_INITIALIZER(head)					\ +	{ NULL } +  +#define	SLIST_ENTRY(type)						\ +struct {								\ +	struct type *sle_next;	/* next element */			\ +} +  +/* + * Singly-linked List functions. + */ +#define	SLIST_INIT(head) do {						\ +	(head)->slh_first = NULL;					\ +} while (/*CONSTCOND*/0) + +#define	SLIST_INSERT_AFTER(slistelm, elm, field) do {			\ +	(elm)->field.sle_next = (slistelm)->field.sle_next;		\ +	(slistelm)->field.sle_next = (elm);				\ +} while (/*CONSTCOND*/0) + +#define	SLIST_INSERT_HEAD(head, elm, field) do {			\ +	(elm)->field.sle_next = (head)->slh_first;			\ +	(head)->slh_first = (elm);					\ +} while (/*CONSTCOND*/0) + +#define	SLIST_REMOVE_HEAD(head, field) do {				\ +	(head)->slh_first = (head)->slh_first->field.sle_next;		\ +} while (/*CONSTCOND*/0) + +#define	SLIST_REMOVE(head, elm, type, field) do {			\ +	if ((head)->slh_first == (elm)) {				\ +		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	SLIST_FOREACH(var, head, field)					\ +	for((var) = (head)->slh_first; (var); (var) = (var)->field.sle_next) + +/* + * Singly-linked List access methods. + */ +#define	SLIST_EMPTY(head)	((head)->slh_first == NULL) +#define	SLIST_FIRST(head)	((head)->slh_first) +#define	SLIST_NEXT(elm, field)	((elm)->field.sle_next) + +#endif /* SLIST_HEAD */ + +#endif	/* !_MECHQUEUE_H_ */ diff --git a/source4/heimdal/lib/gssapi/mech/name.h b/source4/heimdal/lib/gssapi/mech/name.h new file mode 100644 index 0000000000..49b412dd73 --- /dev/null +++ b/source4/heimdal/lib/gssapi/mech/name.h @@ -0,0 +1,48 @@ +/*- + * Copyright (c) 2005 Doug Rabson + * 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 AUTHOR 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 AUTHOR 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. + * + *	$FreeBSD: src/lib/libgssapi/name.h,v 1.1 2005/12/29 14:40:20 dfr Exp $ + *	$Id$ + */ + +struct _gss_mechanism_name { +	SLIST_ENTRY(_gss_mechanism_name) gmn_link; +	gssapi_mech_interface	gmn_mech;	/* mechanism ops for MN */ +	gss_OID			gmn_mech_oid;	/* mechanism oid for MN */ +	gss_name_t		gmn_name;	/* underlying MN */ +}; +SLIST_HEAD(_gss_mechanism_name_list, _gss_mechanism_name); + +struct _gss_name { +	gss_OID_desc		gn_type;	/* type of name */ +	gss_buffer_desc		gn_value;	/* value (as imported) */ +	struct _gss_mechanism_name_list gn_mn;	/* list of MNs */ +}; + +OM_uint32 +	_gss_find_mn(OM_uint32 *, struct _gss_name *, gss_OID,  +	      struct _gss_mechanism_name **); +struct _gss_name * +	_gss_make_name(gssapi_mech_interface m, gss_name_t new_mn); diff --git a/source4/heimdal/lib/gssapi/mech/utils.h b/source4/heimdal/lib/gssapi/mech/utils.h new file mode 100644 index 0000000000..7b27d38f3c --- /dev/null +++ b/source4/heimdal/lib/gssapi/mech/utils.h @@ -0,0 +1,33 @@ +/*- + * Copyright (c) 2005 Doug Rabson + * 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 AUTHOR 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 AUTHOR 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. + * + *	$FreeBSD: src/lib/libgssapi/utils.h,v 1.1 2005/12/29 14:40:20 dfr Exp $ + *	$Id$ + */ + +OM_uint32 _gss_free_oid(OM_uint32 *, gss_OID); +OM_uint32 _gss_copy_oid(OM_uint32 *, const gss_OID, gss_OID); +OM_uint32 _gss_copy_buffer(OM_uint32 *minor_status, +    const gss_buffer_t from_buf, gss_buffer_t to_buf); diff --git a/source4/heimdal/lib/gssapi/spnego/accept_sec_context.c b/source4/heimdal/lib/gssapi/spnego/accept_sec_context.c new file mode 100644 index 0000000000..2afeaf080e --- /dev/null +++ b/source4/heimdal/lib/gssapi/spnego/accept_sec_context.c @@ -0,0 +1,1013 @@ +/* + * Copyright (c) 1997 - 2006 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden).  + * Portions Copyright (c) 2004 PADL Software Pty Ltd. + * + * 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.  + */ + +#include "spnego/spnego_locl.h" + +RCSID("$Id$"); + +static OM_uint32 +send_reject (OM_uint32 *minor_status, +	     gss_buffer_t output_token) +{ +    NegotiationToken nt; +    size_t size; + +    nt.element = choice_NegotiationToken_negTokenResp; + +    ALLOC(nt.u.negTokenResp.negResult, 1); +    if (nt.u.negTokenResp.negResult == NULL) { +	*minor_status = ENOMEM; +	return GSS_S_FAILURE; +    } +    *(nt.u.negTokenResp.negResult)  = reject; +    nt.u.negTokenResp.supportedMech = NULL; +    nt.u.negTokenResp.responseToken = NULL; +    nt.u.negTokenResp.mechListMIC   = NULL; +     +    ASN1_MALLOC_ENCODE(NegotiationToken, +		       output_token->value, output_token->length, &nt, +		       &size, *minor_status); +    free_NegotiationToken(&nt); +    if (*minor_status != 0) +	return GSS_S_FAILURE; + +    return GSS_S_BAD_MECH; +} + +static OM_uint32 +acceptor_approved(gss_name_t target_name, gss_OID mech) +{ +    gss_cred_id_t cred = GSS_C_NO_CREDENTIAL; +    gss_OID_set oidset; +    OM_uint32 junk, ret; + +    if (target_name == GSS_C_NO_NAME) +	return GSS_S_COMPLETE; + +    gss_create_empty_oid_set(&junk, &oidset); +    gss_add_oid_set_member(&junk, mech, &oidset); +     +    ret = gss_acquire_cred(&junk, target_name, GSS_C_INDEFINITE, oidset, +			   GSS_C_ACCEPT, &cred, NULL, NULL); +    gss_release_oid_set(&junk, &oidset); +    if (ret != GSS_S_COMPLETE) +	return ret; +    gss_release_cred(&junk, &cred); +     +    return GSS_S_COMPLETE; +} + +static OM_uint32 +send_supported_mechs (OM_uint32 *minor_status, +		      gss_buffer_t output_token) +{ +    NegotiationTokenWin nt; +    char hostname[MAXHOSTNAMELEN + 1], *p; +    gss_buffer_desc name_buf; +    gss_OID name_type; +    gss_name_t target_princ; +    gss_name_t canon_princ; +    OM_uint32 minor; +    size_t buf_len; +    gss_buffer_desc data; +    OM_uint32 ret; + +    memset(&nt, 0, sizeof(nt)); + +    nt.element = choice_NegotiationTokenWin_negTokenInit; +    nt.u.negTokenInit.reqFlags = NULL; +    nt.u.negTokenInit.mechToken = NULL; +    nt.u.negTokenInit.negHints = NULL; + +    ret = _gss_spnego_indicate_mechtypelist(minor_status, GSS_C_NO_NAME, +					    acceptor_approved, 1, NULL, +					    &nt.u.negTokenInit.mechTypes, NULL); +    if (ret != GSS_S_COMPLETE) { +	return ret; +    } + +    memset(&target_princ, 0, sizeof(target_princ)); +    if (gethostname(hostname, sizeof(hostname) - 2) != 0) { +	*minor_status = errno; +	free_NegotiationTokenWin(&nt); +	return GSS_S_FAILURE; +    } +    hostname[sizeof(hostname) - 1] = '\0'; + +    /* Send the constructed SAM name for this host */ +    for (p = hostname; *p != '\0' && *p != '.'; p++) { +	*p = toupper((unsigned char)*p); +    } +    *p++ = '$'; +    *p = '\0'; + +    name_buf.length = strlen(hostname); +    name_buf.value = hostname; + +    ret = gss_import_name(minor_status, &name_buf, +			  GSS_C_NO_OID, +			  &target_princ); +    if (ret != GSS_S_COMPLETE) { +	free_NegotiationTokenWin(&nt); +	return ret; +    } + +    name_buf.length = 0; +    name_buf.value = NULL; + +    /* Canonicalize the name using the preferred mechanism */ +    ret = gss_canonicalize_name(minor_status, +				target_princ, +				GSS_C_NO_OID, +				&canon_princ); +    if (ret != GSS_S_COMPLETE) { +	free_NegotiationTokenWin(&nt); +	gss_release_name(&minor, &target_princ); +	return ret; +    } + +    ret = gss_display_name(minor_status, canon_princ, +			   &name_buf, &name_type); +    if (ret != GSS_S_COMPLETE) { +	free_NegotiationTokenWin(&nt); +	gss_release_name(&minor, &canon_princ); +	gss_release_name(&minor, &target_princ); +	return ret; +    } + +    gss_release_name(&minor, &canon_princ); +    gss_release_name(&minor, &target_princ); + +    ALLOC(nt.u.negTokenInit.negHints, 1); +    if (nt.u.negTokenInit.negHints == NULL) { +	*minor_status = ENOMEM; +	gss_release_buffer(&minor, &name_buf); +	free_NegotiationTokenWin(&nt); +	return GSS_S_FAILURE; +    } + +    ALLOC(nt.u.negTokenInit.negHints->hintName, 1); +    if (nt.u.negTokenInit.negHints->hintName == NULL) { +	*minor_status = ENOMEM; +	gss_release_buffer(&minor, &name_buf); +	free_NegotiationTokenWin(&nt); +	return GSS_S_FAILURE; +    } + +    *(nt.u.negTokenInit.negHints->hintName) = name_buf.value; +    name_buf.value = NULL; +    nt.u.negTokenInit.negHints->hintAddress = NULL; + +    ASN1_MALLOC_ENCODE(NegotiationTokenWin,  +		       data.value, data.length, &nt, &buf_len, ret); +    free_NegotiationTokenWin(&nt); +    if (ret) { +	return ret; +    } +    if (data.length != buf_len) +	abort(); + +    ret = gss_encapsulate_token(&data, GSS_SPNEGO_MECHANISM, output_token); + +    free (data.value); + +    if (ret != GSS_S_COMPLETE) +	return ret; + +    *minor_status = 0; + +    return GSS_S_CONTINUE_NEEDED; +} + +static OM_uint32 +send_accept (OM_uint32 *minor_status, +	     gssspnego_ctx context_handle, +	     gss_buffer_t mech_token, +	     int initial_response, +	     gss_buffer_t mech_buf, +	     gss_buffer_t output_token) +{ +    NegotiationToken nt; +    OM_uint32 ret; +    gss_buffer_desc mech_mic_buf; +    size_t size; + +    memset(&nt, 0, sizeof(nt)); + +    nt.element = choice_NegotiationToken_negTokenResp; + +    ALLOC(nt.u.negTokenResp.negResult, 1); +    if (nt.u.negTokenResp.negResult == NULL) { +	*minor_status = ENOMEM; +	return GSS_S_FAILURE; +    } + +    if (context_handle->open) { +	if (mech_token != GSS_C_NO_BUFFER +	    && mech_token->length != 0 +	    && mech_buf != GSS_C_NO_BUFFER) +	    *(nt.u.negTokenResp.negResult)  = accept_incomplete; +	else +	    *(nt.u.negTokenResp.negResult)  = accept_completed; +    } else { +	if (initial_response && context_handle->require_mic) +	    *(nt.u.negTokenResp.negResult)  = request_mic; +	else +	    *(nt.u.negTokenResp.negResult)  = accept_incomplete; +    } + +    if (initial_response) { +	ALLOC(nt.u.negTokenResp.supportedMech, 1); +	if (nt.u.negTokenResp.supportedMech == NULL) { +	    free_NegotiationToken(&nt); +	    *minor_status = ENOMEM; +	    return GSS_S_FAILURE; +	} + +	ret = der_get_oid(context_handle->preferred_mech_type->elements, +			  context_handle->preferred_mech_type->length, +			  nt.u.negTokenResp.supportedMech, +			  NULL); +	if (ret) { +	    free_NegotiationToken(&nt); +	    *minor_status = ENOMEM; +	    return GSS_S_FAILURE; +	} +    } else { +	nt.u.negTokenResp.supportedMech = NULL; +    } + +    if (mech_token != GSS_C_NO_BUFFER && mech_token->length != 0) { +	ALLOC(nt.u.negTokenResp.responseToken, 1); +	if (nt.u.negTokenResp.responseToken == NULL) { +	    free_NegotiationToken(&nt); +	    *minor_status = ENOMEM; +	    return GSS_S_FAILURE; +	} +	nt.u.negTokenResp.responseToken->length = mech_token->length; +	nt.u.negTokenResp.responseToken->data   = mech_token->value; +	mech_token->length = 0; +	mech_token->value  = NULL; +    } else { +	nt.u.negTokenResp.responseToken = NULL; +    } + +    if (mech_buf != GSS_C_NO_BUFFER) { +	ret = gss_get_mic(minor_status, +			  context_handle->negotiated_ctx_id, +			  0, +			  mech_buf, +			  &mech_mic_buf); +	if (ret == GSS_S_COMPLETE) { +	    ALLOC(nt.u.negTokenResp.mechListMIC, 1); +	    if (nt.u.negTokenResp.mechListMIC == NULL) { +		gss_release_buffer(minor_status, &mech_mic_buf); +		free_NegotiationToken(&nt); +		*minor_status = ENOMEM; +		return GSS_S_FAILURE; +	    } +	    nt.u.negTokenResp.mechListMIC->length = mech_mic_buf.length; +	    nt.u.negTokenResp.mechListMIC->data   = mech_mic_buf.value; +	} else if (ret == GSS_S_UNAVAILABLE) { +	    nt.u.negTokenResp.mechListMIC = NULL; +	} else { +	    free_NegotiationToken(&nt); +	    return ret; +	} + +    } else +	nt.u.negTokenResp.mechListMIC = NULL; +  +    ASN1_MALLOC_ENCODE(NegotiationToken, +		       output_token->value, output_token->length, +		       &nt, &size, ret); +    if (ret) { +	free_NegotiationToken(&nt); +	*minor_status = ret; +	return GSS_S_FAILURE; +    } + +    /* +     * The response should not be encapsulated, because +     * it is a SubsequentContextToken (note though RFC 1964 +     * specifies encapsulation for all _Kerberos_ tokens). +     */ + +    if (*(nt.u.negTokenResp.negResult) == accept_completed) +	ret = GSS_S_COMPLETE; +    else +	ret = GSS_S_CONTINUE_NEEDED; +    free_NegotiationToken(&nt); +    return ret; +} + + +static OM_uint32 +verify_mechlist_mic +	   (OM_uint32 *minor_status, +	    gssspnego_ctx context_handle, +	    gss_buffer_t mech_buf, +	    heim_octet_string *mechListMIC +	   ) +{ +    OM_uint32 ret; +    gss_buffer_desc mic_buf; + +    if (context_handle->verified_mic) { +	/* This doesn't make sense, we've already verified it? */ +	*minor_status = 0; +	return GSS_S_DUPLICATE_TOKEN; +    } + +    if (mechListMIC == NULL) { +	*minor_status = 0; +	return GSS_S_DEFECTIVE_TOKEN; +    } + +    mic_buf.length = mechListMIC->length; +    mic_buf.value  = mechListMIC->data; + +    ret = gss_verify_mic(minor_status, +			 context_handle->negotiated_ctx_id, +			 mech_buf, +			 &mic_buf, +			 NULL); + +    if (ret != GSS_S_COMPLETE) +	ret = GSS_S_DEFECTIVE_TOKEN; + +    return ret; +} + +static OM_uint32 +select_mech(OM_uint32 *minor_status, MechType *mechType, int verify_p, +	    gss_OID *mech_p) +{ +    char mechbuf[64]; +    size_t mech_len; +    gss_OID_desc oid; +    gss_OID oidp; +    gss_OID_set mechs; +    int i; +    OM_uint32 ret, junk; + +    ret = der_put_oid ((unsigned char *)mechbuf + sizeof(mechbuf) - 1, +		       sizeof(mechbuf), +		       mechType, +		       &mech_len); +    if (ret) { +	return GSS_S_DEFECTIVE_TOKEN; +    } + +    oid.length   = mech_len; +    oid.elements = mechbuf + sizeof(mechbuf) - mech_len; + +    if (gss_oid_equal(&oid, GSS_SPNEGO_MECHANISM)) { +	return GSS_S_BAD_MECH; +    } + +    *minor_status = 0; + +    /* Translate broken MS Kebreros OID */ +    if (gss_oid_equal(&oid, &_gss_spnego_mskrb_mechanism_oid_desc)) +	    oidp = &_gss_spnego_krb5_mechanism_oid_desc; +    else +	    oidp = &oid; + + +    ret = gss_indicate_mechs(&junk, &mechs); +    if (ret) +	    return (ret); + +    for (i = 0; i < mechs->count; i++) +	    if (gss_oid_equal(&mechs->elements[i], oidp)) +		    break; + +    if (i == mechs->count) { +	    gss_release_oid_set(&junk, &mechs); +	    return GSS_S_BAD_MECH; +    } +    gss_release_oid_set(&junk, &mechs); + +    ret = gss_duplicate_oid(minor_status, +			    &oid, /* possibly this should be oidp */ +			    mech_p); + +    if (verify_p) { +	gss_name_t name = GSS_C_NO_NAME; +	gss_buffer_desc namebuf; +	char *str = NULL, *host, hostname[MAXHOSTNAMELEN]; + +	host = getenv("GSSAPI_SPNEGO_NAME"); +	if (host == NULL || issuid()) { +	    if (gethostname(hostname, sizeof(hostname)) != 0) { +		*minor_status = errno; +		return GSS_S_FAILURE; +	    } +	    asprintf(&str, "host@%s", hostname); +	    host = str; +	} + +	namebuf.length = strlen(host); +	namebuf.value = host; + +	ret = gss_import_name(minor_status, &namebuf, +			      GSS_C_NT_HOSTBASED_SERVICE, &name); +	if (str) +	    free(str); +	if (ret != GSS_S_COMPLETE) +	    return ret; + +	ret = acceptor_approved(name, *mech_p); +	gss_release_name(&junk, &name); +    } + +    return ret; +} + + +static OM_uint32 +acceptor_complete(OM_uint32 * minor_status, +		  gssspnego_ctx ctx, +		  int *get_mic, +		  gss_buffer_t mech_buf, +		  gss_buffer_t mech_input_token, +		  gss_buffer_t mech_output_token, +		  heim_octet_string *mic, +		  gss_buffer_t output_token) +{ +    OM_uint32 ret; +    int require_mic, verify_mic; +    gss_buffer_desc buf; + +    buf.length = 0; +    buf.value = NULL; + +    ret = _gss_spnego_require_mechlist_mic(minor_status, ctx, &require_mic); +    if (ret) +	return ret; +     +    ctx->require_mic = require_mic; + +    if (mic != NULL) +	require_mic = 1; +     +    if (ctx->open && require_mic) { +	if (mech_input_token == GSS_C_NO_BUFFER) { /* Even/One */ +	    verify_mic = 1; +	    *get_mic = 0; +	} else if (mech_output_token != GSS_C_NO_BUFFER && +		   mech_output_token->length == 0) { /* Odd */ +	    *get_mic = verify_mic = 1; +	} else { /* Even/One */ +	    verify_mic = 0; +	    *get_mic = 1; +	} +	 +	if (verify_mic || get_mic) { +	    int eret; +	    size_t buf_len; +	     +	    ASN1_MALLOC_ENCODE(MechTypeList,  +			       mech_buf->value, mech_buf->length, +			       &ctx->initiator_mech_types, &buf_len, eret); +	    if (eret) { +		*minor_status = eret; +		return GSS_S_FAILURE; +	    } +	    if (buf.length != buf_len) +		abort(); +	} +	 +	if (verify_mic) { +	    ret = verify_mechlist_mic(minor_status, ctx, mech_buf, mic); +	    if (ret) { +		if (get_mic) +		    send_reject (minor_status, output_token); +		if (buf.value) +		    free(buf.value); +		return ret; +	    } +	    ctx->verified_mic = 1; +	} +	if (buf.value) +	    free(buf.value); + +    } else +	*get_mic = 0; +     +    return GSS_S_COMPLETE; +} + + +static OM_uint32 +acceptor_start +	   (OM_uint32 * minor_status, +	    gss_ctx_id_t * context_handle, +	    const gss_cred_id_t acceptor_cred_handle, +	    const gss_buffer_t input_token_buffer, +	    const gss_channel_bindings_t input_chan_bindings, +	    gss_name_t * src_name, +	    gss_OID * mech_type, +	    gss_buffer_t output_token, +	    OM_uint32 * ret_flags, +	    OM_uint32 * time_rec, +	    gss_cred_id_t *delegated_cred_handle +	   ) +{ +    OM_uint32 ret, junk; +    NegotiationToken nt; +    size_t nt_len; +    NegTokenInit *ni; +    int i; +    gss_buffer_desc data; +    gss_buffer_t mech_input_token = GSS_C_NO_BUFFER; +    gss_buffer_desc mech_output_token; +    gss_buffer_desc mech_buf; +    gss_OID preferred_mech_type = GSS_C_NO_OID; +    gssspnego_ctx ctx; +    gssspnego_cred acceptor_cred = (gssspnego_cred)acceptor_cred_handle; +    int get_mic = 0; +    int first_ok = 0; + +    mech_output_token.value = NULL; +    mech_output_token.length = 0; +    mech_buf.value = NULL; + +    if (input_token_buffer->length == 0) +	return send_supported_mechs (minor_status, output_token); +	 +    ret = _gss_spnego_alloc_sec_context(minor_status, context_handle); +    if (ret != GSS_S_COMPLETE) +	return ret; + +    ctx = (gssspnego_ctx)*context_handle; + +    /* +     * The GSS-API encapsulation is only present on the initial +     * context token (negTokenInit). +     */ +    ret = gss_decapsulate_token (input_token_buffer, +				 GSS_SPNEGO_MECHANISM, +				 &data); +    if (ret) +	return ret; + +    ret = decode_NegotiationToken(data.value, data.length, &nt, &nt_len); +    gss_release_buffer(minor_status, &data); +    if (ret) { +	*minor_status = ret; +	return GSS_S_DEFECTIVE_TOKEN; +    } +    if (nt.element != choice_NegotiationToken_negTokenInit) { +	*minor_status = 0; +	return GSS_S_DEFECTIVE_TOKEN; +    } +    ni = &nt.u.negTokenInit; + +    if (ni->mechTypes.len < 1) { +	free_NegotiationToken(&nt); +	*minor_status = 0; +	return GSS_S_DEFECTIVE_TOKEN; +    } + +    HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex); + +    ret = copy_MechTypeList(&ni->mechTypes, &ctx->initiator_mech_types); +    if (ret) { +	HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); +	free_NegotiationToken(&nt); +	*minor_status = ret; +	return GSS_S_FAILURE; +    } + +    /* +     * First we try the opportunistic token if we have support for it, +     * don't try to verify we have credential for the token, +     * gss_accept_sec_context() will (hopefully) tell us that. +     * If that failes,  +     */ + +    ret = select_mech(minor_status, +		      &ni->mechTypes.val[0],  +		      0, +		      &preferred_mech_type); + +    if (ret == 0 && ni->mechToken != NULL) { +	gss_cred_id_t mech_delegated_cred = GSS_C_NO_CREDENTIAL; +	gss_cred_id_t mech_cred; +	gss_buffer_desc ibuf; + +	ibuf.length = ni->mechToken->length; +	ibuf.value = ni->mechToken->data; +	mech_input_token = &ibuf; + +	if (acceptor_cred != NULL) +	    mech_cred = acceptor_cred->negotiated_cred_id; +	else +	    mech_cred = GSS_C_NO_CREDENTIAL; +	 +	if (ctx->mech_src_name != GSS_C_NO_NAME) +	    gss_release_name(&junk, &ctx->mech_src_name); +	 +	ret = gss_accept_sec_context(minor_status, +				     &ctx->negotiated_ctx_id, +				     mech_cred, +				     mech_input_token, +				     input_chan_bindings, +				     &ctx->mech_src_name, +				     &ctx->negotiated_mech_type, +				     &mech_output_token, +				     &ctx->mech_flags, +				     &ctx->mech_time_rec, +				     &mech_delegated_cred); + +	if (mech_delegated_cred && delegated_cred_handle) { +	    _gss_spnego_alloc_cred(&junk, +				   mech_delegated_cred, +				   delegated_cred_handle); +	} else if (mech_delegated_cred != GSS_C_NO_CREDENTIAL) +	    gss_release_cred(&junk, &mech_delegated_cred); + +	if (ret == GSS_S_COMPLETE || ret == GSS_S_CONTINUE_NEEDED) { +	    ctx->preferred_mech_type = preferred_mech_type; +	    ctx->negotiated_mech_type = preferred_mech_type; +	    if (ret == GSS_S_COMPLETE) +		ctx->open = 1; + +	    ret = acceptor_complete(minor_status, +				    ctx, +				    &get_mic, +				    &mech_buf, +				    mech_input_token, +				    &mech_output_token, +				    ni->mechListMIC, +				    output_token); +	    if (ret != GSS_S_COMPLETE) +		goto out; + +	    first_ok = 1; +	} else { +	    gss_mg_collect_error(preferred_mech_type, ret, *minor_status); +	} +    } + +    /* +     * If opportunistic token failed, lets try the other mechs. +     */ + +    if (!first_ok && ni->mechToken != NULL) { + +	preferred_mech_type = GSS_C_NO_OID; + +	/* Call glue layer to find first mech we support */ +	for (i = 1; i < ni->mechTypes.len; ++i) { +	    ret = select_mech(minor_status, +			      &ni->mechTypes.val[i], +			      1, +			      &preferred_mech_type); +	    if (ret == 0) +		break; +	} +	if (preferred_mech_type == GSS_C_NO_OID) { +	    HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); +	    free_NegotiationToken(&nt); +	    return ret; +	} + +	ctx->preferred_mech_type = preferred_mech_type; +	ctx->negotiated_mech_type = preferred_mech_type; +    } + +    /* +     * The initial token always have a response +     */ + +    ret = send_accept (minor_status, +		       ctx, +		       &mech_output_token, +		       1, +		       get_mic ? &mech_buf : NULL, +		       output_token); +    if (ret) +	goto out; +     +out: +    if (mech_output_token.value != NULL) +	gss_release_buffer(&junk, &mech_output_token); +    if (mech_buf.value != NULL) { +	free(mech_buf.value); +	mech_buf.value = NULL; +    } +    free_NegotiationToken(&nt); + + +    if (ret == GSS_S_COMPLETE) { +	if (src_name != NULL && ctx->mech_src_name != NULL) { +	    spnego_name name; + +	    name = calloc(1, sizeof(*name)); +	    if (name) { +		name->mech = ctx->mech_src_name; +		ctx->mech_src_name = NULL; +		*src_name = (gss_name_t)name; +	    } +	} +    } +     +    if (mech_type != NULL) +	*mech_type = ctx->negotiated_mech_type; +    if (ret_flags != NULL) +	*ret_flags = ctx->mech_flags; +    if (time_rec != NULL) +	*time_rec = ctx->mech_time_rec; + +    if (ret == GSS_S_COMPLETE || ret == GSS_S_CONTINUE_NEEDED) { +	HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); + 	return ret; +    } + +    _gss_spnego_internal_delete_sec_context(&junk, context_handle, +					    GSS_C_NO_BUFFER); +     +    return ret; +} + + +static OM_uint32 +acceptor_continue +	   (OM_uint32 * minor_status, +	    gss_ctx_id_t * context_handle, +	    const gss_cred_id_t acceptor_cred_handle, +	    const gss_buffer_t input_token_buffer, +	    const gss_channel_bindings_t input_chan_bindings, +	    gss_name_t * src_name, +	    gss_OID * mech_type, +	    gss_buffer_t output_token, +	    OM_uint32 * ret_flags, +	    OM_uint32 * time_rec, +	    gss_cred_id_t *delegated_cred_handle +	   ) +{ +    OM_uint32 ret, ret2, minor, junk; +    NegotiationToken nt; +    size_t nt_len; +    NegTokenResp *na; +    unsigned int negResult = accept_incomplete; +    gss_buffer_t mech_input_token = GSS_C_NO_BUFFER; +    gss_buffer_t mech_output_token = GSS_C_NO_BUFFER; +    gss_buffer_desc mech_buf; +    gssspnego_ctx ctx; +    gssspnego_cred acceptor_cred = (gssspnego_cred)acceptor_cred_handle; + +    mech_buf.value = NULL; + +    ctx = (gssspnego_ctx)*context_handle; + +    /* +     * The GSS-API encapsulation is only present on the initial +     * context token (negTokenInit). +     */ + +    ret = decode_NegotiationToken(input_token_buffer->value,  +				  input_token_buffer->length, +				  &nt, &nt_len); +    if (ret) { +	*minor_status = ret; +	return GSS_S_DEFECTIVE_TOKEN; +    } +    if (nt.element != choice_NegotiationToken_negTokenResp) { +	*minor_status = 0; +	return GSS_S_DEFECTIVE_TOKEN; +    } +    na = &nt.u.negTokenResp; + +    if (na->negResult != NULL) { +	negResult = *(na->negResult); +    } + +    HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex); + +    { +	gss_buffer_desc ibuf, obuf; +	int require_mic, get_mic = 0; +	int require_response; +	heim_octet_string *mic; + +	if (na->responseToken != NULL) { +	    ibuf.length = na->responseToken->length; +	    ibuf.value = na->responseToken->data; +	    mech_input_token = &ibuf; +	} else { +	    ibuf.value = NULL; +	    ibuf.length = 0; +	} + +	if (mech_input_token != GSS_C_NO_BUFFER) { +	    gss_cred_id_t mech_cred; +	    gss_cred_id_t mech_delegated_cred = GSS_C_NO_CREDENTIAL; + +	    if (acceptor_cred != NULL) +		mech_cred = acceptor_cred->negotiated_cred_id; +	    else +		mech_cred = GSS_C_NO_CREDENTIAL; + +	    if (ctx->mech_src_name != GSS_C_NO_NAME) +		gss_release_name(&minor, &ctx->mech_src_name); + +	    ret = gss_accept_sec_context(&minor, +					 &ctx->negotiated_ctx_id, +					 mech_cred, +					 mech_input_token, +					 input_chan_bindings, +					 &ctx->mech_src_name, +					 &ctx->negotiated_mech_type, +					 &obuf, +					 &ctx->mech_flags, +					 &ctx->mech_time_rec, +					 &mech_delegated_cred); + +	    if (mech_delegated_cred && delegated_cred_handle) { +		_gss_spnego_alloc_cred(&junk, +				       mech_delegated_cred, +				       delegated_cred_handle); +	    } else if (mech_delegated_cred != GSS_C_NO_CREDENTIAL) +		gss_release_cred(&junk, &mech_delegated_cred); + +	    if (ret == GSS_S_COMPLETE || ret == GSS_S_CONTINUE_NEEDED) { +		mech_output_token = &obuf; +	    } +	    if (ret != GSS_S_COMPLETE && ret != GSS_S_CONTINUE_NEEDED) { +		free_NegotiationToken(&nt); +		gss_mg_collect_error(ctx->negotiated_mech_type, ret, minor); +		send_reject (minor_status, output_token); +		HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); +		return ret; +	    } +	    if (ret == GSS_S_COMPLETE) +		ctx->open = 1; +	} else +	    ret = GSS_S_COMPLETE; + +	ret2 = _gss_spnego_require_mechlist_mic(minor_status,  +						ctx, +						&require_mic); +	if (ret2) +	    goto out; + +	ctx->require_mic = require_mic; + +	mic = na->mechListMIC; +	if (mic != NULL) +	    require_mic = 1; + +	if (ret == GSS_S_COMPLETE) +	    ret = acceptor_complete(minor_status, +				    ctx, +				    &get_mic, +				    &mech_buf, +				    mech_input_token, +				    mech_output_token, +				    na->mechListMIC, +				    output_token); + +	if (ctx->mech_flags & GSS_C_DCE_STYLE) +	    require_response = (negResult != accept_completed); +	else +	    require_response = 0; + +	/* +	 * Check whether we need to send a result: there should be only +	 * one accept_completed response sent in the entire negotiation +	 */ +	if ((mech_output_token != GSS_C_NO_BUFFER && +	     mech_output_token->length != 0) +	    || (ctx->open && negResult == accept_incomplete) +	    || require_response +	    || get_mic) { +	    ret2 = send_accept (minor_status, +				ctx, +				mech_output_token, +				0, +				get_mic ? &mech_buf : NULL, +				output_token); +	    if (ret2) +		goto out; +	} + +     out: +	if (ret2 != GSS_S_COMPLETE) +	    ret = ret2; +	if (mech_output_token != NULL) +	    gss_release_buffer(&minor, mech_output_token); +	if (mech_buf.value != NULL) +	    free(mech_buf.value); +	free_NegotiationToken(&nt); +    } + +    if (ret == GSS_S_COMPLETE) { +	if (src_name != NULL && ctx->mech_src_name != NULL) { +	    spnego_name name; + +	    name = calloc(1, sizeof(*name)); +	    if (name) { +		name->mech = ctx->mech_src_name; +		ctx->mech_src_name = NULL; +		*src_name = (gss_name_t)name; +	    } +	} +    } + +    if (mech_type != NULL) +	*mech_type = ctx->negotiated_mech_type; +    if (ret_flags != NULL) +	*ret_flags = ctx->mech_flags; +    if (time_rec != NULL) +	*time_rec = ctx->mech_time_rec; + +    if (ret == GSS_S_COMPLETE || ret == GSS_S_CONTINUE_NEEDED) { +	HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); + 	return ret; +    } + +    _gss_spnego_internal_delete_sec_context(&minor, context_handle, +				   GSS_C_NO_BUFFER); + +    return ret; +} + +OM_uint32 +_gss_spnego_accept_sec_context +	   (OM_uint32 * minor_status, +	    gss_ctx_id_t * context_handle, +	    const gss_cred_id_t acceptor_cred_handle, +	    const gss_buffer_t input_token_buffer, +	    const gss_channel_bindings_t input_chan_bindings, +	    gss_name_t * src_name, +	    gss_OID * mech_type, +	    gss_buffer_t output_token, +	    OM_uint32 * ret_flags, +	    OM_uint32 * time_rec, +	    gss_cred_id_t *delegated_cred_handle +	   ) +{ +    _gss_accept_sec_context_t *func; + +    *minor_status = 0; + +    output_token->length = 0; +    output_token->value  = NULL; + +    if (src_name != NULL) +	*src_name = GSS_C_NO_NAME; +    if (mech_type != NULL) +	*mech_type = GSS_C_NO_OID; +    if (ret_flags != NULL) +	*ret_flags = 0; +    if (time_rec != NULL) +	*time_rec = 0; +    if (delegated_cred_handle != NULL) +	*delegated_cred_handle = GSS_C_NO_CREDENTIAL; + + +    if (*context_handle == GSS_C_NO_CONTEXT)  +	func = acceptor_start; +    else +	func = acceptor_continue; +     + +    return (*func)(minor_status, context_handle, acceptor_cred_handle, +		   input_token_buffer, input_chan_bindings, +		   src_name, mech_type, output_token, ret_flags, +		   time_rec, delegated_cred_handle); +} diff --git a/source4/heimdal/lib/gssapi/spnego/compat.c b/source4/heimdal/lib/gssapi/spnego/compat.c new file mode 100644 index 0000000000..67d9b202a7 --- /dev/null +++ b/source4/heimdal/lib/gssapi/spnego/compat.c @@ -0,0 +1,319 @@ +/* + * Copyright (c) 2004, PADL Software Pty Ltd. + * 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 PADL Software 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 PADL SOFTWARE 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 PADL SOFTWARE 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. + */ + +#include "spnego/spnego_locl.h" + +RCSID("$Id$"); + +/* + * Apparently Microsoft got the OID wrong, and used + * 1.2.840.48018.1.2.2 instead. We need both this and + * the correct Kerberos OID here in order to deal with + * this. Because this is manifest in SPNEGO only I'd + * prefer to deal with this here rather than inside the + * Kerberos mechanism. + */ +gss_OID_desc _gss_spnego_mskrb_mechanism_oid_desc = +	{9, (void *)"\x2a\x86\x48\x82\xf7\x12\x01\x02\x02"}; + +gss_OID_desc _gss_spnego_krb5_mechanism_oid_desc = +	{9, (void *)"\x2a\x86\x48\x86\xf7\x12\x01\x02\x02"}; + +/* + * Allocate a SPNEGO context handle + */ +OM_uint32 _gss_spnego_alloc_sec_context (OM_uint32 * minor_status, +					 gss_ctx_id_t *context_handle) +{ +    gssspnego_ctx ctx; + +    ctx = calloc(1, sizeof(*ctx)); +    if (ctx == NULL) { +	*minor_status = ENOMEM; +	return GSS_S_FAILURE; +    } + +    ctx->initiator_mech_types.len = 0; +    ctx->initiator_mech_types.val = NULL; +    ctx->preferred_mech_type = GSS_C_NO_OID; +    ctx->negotiated_mech_type = GSS_C_NO_OID; +    ctx->negotiated_ctx_id = GSS_C_NO_CONTEXT; + +    /* +     * Cache these so we can return them before returning +     * GSS_S_COMPLETE, even if the mechanism has itself +     * completed earlier +     */ +    ctx->mech_flags = 0; +    ctx->mech_time_rec = 0; +    ctx->mech_src_name = GSS_C_NO_NAME; + +    ctx->open = 0; +    ctx->local = 0; +    ctx->require_mic = 0; +    ctx->verified_mic = 0; + +    HEIMDAL_MUTEX_init(&ctx->ctx_id_mutex); + +    *context_handle = (gss_ctx_id_t)ctx; + +    return GSS_S_COMPLETE; +} + +/* + * Free a SPNEGO context handle. The caller must have acquired + * the lock before this is called. + */ +OM_uint32 _gss_spnego_internal_delete_sec_context +           (OM_uint32 *minor_status, +            gss_ctx_id_t *context_handle, +            gss_buffer_t output_token +           ) +{ +    gssspnego_ctx ctx; +    OM_uint32 ret, minor; + +    *minor_status = 0; + +    if (context_handle == NULL) { +	return GSS_S_NO_CONTEXT; +    } + +    if (output_token != GSS_C_NO_BUFFER) { +	output_token->length = 0; +	output_token->value = NULL; +    } + +    ctx = (gssspnego_ctx)*context_handle; +    *context_handle = GSS_C_NO_CONTEXT; + +    if (ctx == NULL) { +	return GSS_S_NO_CONTEXT; +    } + +    if (ctx->initiator_mech_types.val != NULL) +	free_MechTypeList(&ctx->initiator_mech_types); + +    gss_release_oid(&minor, &ctx->preferred_mech_type); +    ctx->negotiated_mech_type = GSS_C_NO_OID; + +    gss_release_name(&minor, &ctx->target_name); +    gss_release_name(&minor, &ctx->mech_src_name); + +    if (ctx->negotiated_ctx_id != GSS_C_NO_CONTEXT) { +	ret = gss_delete_sec_context(minor_status, +				     &ctx->negotiated_ctx_id, +				     output_token); +	ctx->negotiated_ctx_id = GSS_C_NO_CONTEXT; +    } else { +	ret = GSS_S_COMPLETE; +    } + +    HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); +    HEIMDAL_MUTEX_destroy(&ctx->ctx_id_mutex); + +    free(ctx); +    *context_handle = NULL; + +    return ret; +} + +/* + * For compatability with the Windows SPNEGO implementation, the + * default is to ignore the mechListMIC unless CFX is used and + * a non-preferred mechanism was negotiated + */ + +OM_uint32 +_gss_spnego_require_mechlist_mic(OM_uint32 *minor_status, +				 gssspnego_ctx ctx, +				 int *require_mic) +{ +    gss_buffer_set_t buffer_set = GSS_C_NO_BUFFER_SET; +    OM_uint32 minor; + +    *minor_status = 0; +    *require_mic = 0; + +    if (ctx == NULL) { +	return GSS_S_COMPLETE; +    } + +    if (ctx->require_mic) { +	/* Acceptor requested it: mandatory to honour */ +	*require_mic = 1; +	return GSS_S_COMPLETE; +    } + +    /* +     * Check whether peer indicated implicit support for updated SPNEGO +     * (eg. in the Kerberos case by using CFX) +     */ +    if (gss_inquire_sec_context_by_oid(&minor, ctx->negotiated_ctx_id, +				       GSS_C_PEER_HAS_UPDATED_SPNEGO, +				       &buffer_set) == GSS_S_COMPLETE) { +	*require_mic = 1; +	gss_release_buffer_set(&minor, &buffer_set); +    } + +    /* Safe-to-omit MIC rules follow */ +    if (*require_mic) { +	if (gss_oid_equal(ctx->negotiated_mech_type, ctx->preferred_mech_type)) { +	    *require_mic = 0; +	} else if (gss_oid_equal(ctx->negotiated_mech_type, &_gss_spnego_krb5_mechanism_oid_desc) && +		   gss_oid_equal(ctx->preferred_mech_type, &_gss_spnego_mskrb_mechanism_oid_desc)) { +	    *require_mic = 0; +	} +    } + +    return GSS_S_COMPLETE; +} + +static int +add_mech_type(gss_OID mech_type, +	      int includeMSCompatOID, +	      MechTypeList *mechtypelist) +{ +    MechType mech; +    int ret; + +    if (gss_oid_equal(mech_type, GSS_SPNEGO_MECHANISM)) +	return 0; + +    if (includeMSCompatOID && +	gss_oid_equal(mech_type, &_gss_spnego_krb5_mechanism_oid_desc)) { +	ret = der_get_oid(_gss_spnego_mskrb_mechanism_oid_desc.elements, +			  _gss_spnego_mskrb_mechanism_oid_desc.length, +			  &mech, +			  NULL); +	if (ret) +	    return ret; +	ret = add_MechTypeList(mechtypelist, &mech); +	free_MechType(&mech); +	if (ret) +	    return ret; +    } +    ret = der_get_oid(mech_type->elements, mech_type->length, &mech, NULL); +    if (ret) +	return ret; +    ret = add_MechTypeList(mechtypelist, &mech); +    free_MechType(&mech); +    return ret; +} + + +OM_uint32 +_gss_spnego_indicate_mechtypelist (OM_uint32 *minor_status, +				   gss_name_t target_name, +				   OM_uint32 (*func)(gss_name_t, gss_OID), +				   int includeMSCompatOID, +				   const gssspnego_cred cred_handle, +				   MechTypeList *mechtypelist, +				   gss_OID *preferred_mech) +{ +    gss_OID_set supported_mechs = GSS_C_NO_OID_SET; +    gss_OID first_mech = GSS_C_NO_OID; +    OM_uint32 ret; +    int i; + +    mechtypelist->len = 0; +    mechtypelist->val = NULL; + +    if (cred_handle != NULL) { +	ret = gss_inquire_cred(minor_status, +			       cred_handle->negotiated_cred_id, +			       NULL, +			       NULL, +			       NULL, +			       &supported_mechs); +    } else { +	ret = gss_indicate_mechs(minor_status, &supported_mechs); +    } + +    if (ret != GSS_S_COMPLETE) { +	return ret; +    } + +    if (supported_mechs->count == 0) { +	*minor_status = ENOENT; +	gss_release_oid_set(minor_status, &supported_mechs); +	return GSS_S_FAILURE; +    } + +    ret = (*func)(target_name, GSS_KRB5_MECHANISM); +    if (ret == GSS_S_COMPLETE) { +	ret = add_mech_type(GSS_KRB5_MECHANISM, +			    includeMSCompatOID, +			    mechtypelist); +	if (!GSS_ERROR(ret)) +	    first_mech = GSS_KRB5_MECHANISM; +    } +    ret = GSS_S_COMPLETE; + +    for (i = 0; i < supported_mechs->count; i++) { +	OM_uint32 subret; +	if (gss_oid_equal(&supported_mechs->elements[i], GSS_SPNEGO_MECHANISM)) +	    continue; +	if (gss_oid_equal(&supported_mechs->elements[i], GSS_KRB5_MECHANISM)) +	    continue; + +	subret = (*func)(target_name, &supported_mechs->elements[i]); +	if (subret != GSS_S_COMPLETE) +	    continue; + +	ret = add_mech_type(&supported_mechs->elements[i], +			    includeMSCompatOID, +			    mechtypelist); +	if (ret != 0) { +	    *minor_status = ret; +	    ret = GSS_S_FAILURE; +	    break; +	} +	if (first_mech == GSS_C_NO_OID) +	    first_mech = &supported_mechs->elements[i]; +    } + +    if (mechtypelist->len == 0) { +	gss_release_oid_set(minor_status, &supported_mechs); +	*minor_status = 0; +	return GSS_S_BAD_MECH; +    } + +    if (preferred_mech != NULL) { +	ret = gss_duplicate_oid(minor_status, first_mech, preferred_mech); +	if (ret != GSS_S_COMPLETE) +	    free_MechTypeList(mechtypelist); +    } +    gss_release_oid_set(minor_status, &supported_mechs); + +    return ret; +} diff --git a/source4/heimdal/lib/gssapi/spnego/context_stubs.c b/source4/heimdal/lib/gssapi/spnego/context_stubs.c new file mode 100644 index 0000000000..60c53058b8 --- /dev/null +++ b/source4/heimdal/lib/gssapi/spnego/context_stubs.c @@ -0,0 +1,949 @@ +/* + * Copyright (c) 2004, PADL Software Pty Ltd. + * 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 PADL Software 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 PADL SOFTWARE 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 PADL SOFTWARE 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. + */ + +#include "spnego/spnego_locl.h" + +RCSID("$Id$"); + +static OM_uint32 +spnego_supported_mechs(OM_uint32 *minor_status, gss_OID_set *mechs) +{ +    OM_uint32 ret, junk; +    gss_OID_set m; +    int i; + +    ret = gss_indicate_mechs(minor_status, &m); +    if (ret != GSS_S_COMPLETE) +	return ret; + +    ret = gss_create_empty_oid_set(minor_status, mechs); +    if (ret != GSS_S_COMPLETE) { +	gss_release_oid_set(&junk, &m); +	return ret; +    } + +    for (i = 0; i < m->count; i++) { +	if (gss_oid_equal(&m->elements[i], GSS_SPNEGO_MECHANISM)) +	    continue; + +	ret = gss_add_oid_set_member(minor_status, &m->elements[i], mechs); +	if (ret) { +	    gss_release_oid_set(&junk, &m); +	    gss_release_oid_set(&junk, mechs); +	    return ret; +	} +    } +    return ret; +} + + + +OM_uint32 _gss_spnego_process_context_token +           (OM_uint32 *minor_status, +            const gss_ctx_id_t context_handle, +            const gss_buffer_t token_buffer +           ) +{ +    gss_ctx_id_t context ; +    gssspnego_ctx ctx; +    OM_uint32 ret; + +    if (context_handle == GSS_C_NO_CONTEXT) +	return GSS_S_NO_CONTEXT; + +    context = context_handle; +    ctx = (gssspnego_ctx)context_handle; + +    HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex); + +    ret = gss_process_context_token(minor_status, +				    ctx->negotiated_ctx_id, +				    token_buffer); +    if (ret != GSS_S_COMPLETE) { +	HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); +	return ret; +    } + +    ctx->negotiated_ctx_id = GSS_C_NO_CONTEXT; + +    return _gss_spnego_internal_delete_sec_context(minor_status, +					   &context, +					   GSS_C_NO_BUFFER); +} + +OM_uint32 _gss_spnego_delete_sec_context +           (OM_uint32 *minor_status, +            gss_ctx_id_t *context_handle, +            gss_buffer_t output_token +           ) +{ +    gssspnego_ctx ctx; + +    if (context_handle == NULL || *context_handle == GSS_C_NO_CONTEXT) +	return GSS_S_NO_CONTEXT; + +    ctx = (gssspnego_ctx)*context_handle; + +    HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex); + +    return _gss_spnego_internal_delete_sec_context(minor_status, +						   context_handle, +						   output_token); +} + +OM_uint32 _gss_spnego_context_time +           (OM_uint32 *minor_status, +            const gss_ctx_id_t context_handle, +            OM_uint32 *time_rec +           ) +{ +    gssspnego_ctx ctx; +    *minor_status = 0; + +    if (context_handle == GSS_C_NO_CONTEXT) { +	return GSS_S_NO_CONTEXT; +    } + +    ctx = (gssspnego_ctx)context_handle; + +    if (ctx->negotiated_ctx_id == GSS_C_NO_CONTEXT) { +	return GSS_S_NO_CONTEXT; +    } + +    return gss_context_time(minor_status, +			    ctx->negotiated_ctx_id, +			    time_rec); +} + +OM_uint32 _gss_spnego_get_mic +           (OM_uint32 *minor_status, +            const gss_ctx_id_t context_handle, +            gss_qop_t qop_req, +            const gss_buffer_t message_buffer, +            gss_buffer_t message_token +           ) +{ +    gssspnego_ctx ctx; + +    *minor_status = 0; + +    if (context_handle == GSS_C_NO_CONTEXT) { +	return GSS_S_NO_CONTEXT; +    } + +    ctx = (gssspnego_ctx)context_handle; + +    if (ctx->negotiated_ctx_id == GSS_C_NO_CONTEXT) { +	return GSS_S_NO_CONTEXT; +    } + +    return gss_get_mic(minor_status, ctx->negotiated_ctx_id, +		       qop_req, message_buffer, message_token); +} + +OM_uint32 _gss_spnego_verify_mic +           (OM_uint32 * minor_status, +            const gss_ctx_id_t context_handle, +            const gss_buffer_t message_buffer, +            const gss_buffer_t token_buffer, +            gss_qop_t * qop_state +           ) +{ +    gssspnego_ctx ctx; + +    *minor_status = 0; + +    if (context_handle == GSS_C_NO_CONTEXT) { +	return GSS_S_NO_CONTEXT; +    } + +    ctx = (gssspnego_ctx)context_handle; + +    if (ctx->negotiated_ctx_id == GSS_C_NO_CONTEXT) { +	return GSS_S_NO_CONTEXT; +    } + +    return gss_verify_mic(minor_status, +			  ctx->negotiated_ctx_id, +			  message_buffer, +			  token_buffer, +			  qop_state); +} + +OM_uint32 _gss_spnego_wrap +           (OM_uint32 * minor_status, +            const gss_ctx_id_t context_handle, +            int conf_req_flag, +            gss_qop_t qop_req, +            const gss_buffer_t input_message_buffer, +            int * conf_state, +            gss_buffer_t output_message_buffer +           ) +{ +    gssspnego_ctx ctx; + +    *minor_status = 0; + +    if (context_handle == GSS_C_NO_CONTEXT) { +	return GSS_S_NO_CONTEXT; +    } + +    ctx = (gssspnego_ctx)context_handle; + +    if (ctx->negotiated_ctx_id == GSS_C_NO_CONTEXT) { +	return GSS_S_NO_CONTEXT; +    } + +    return gss_wrap(minor_status, +		    ctx->negotiated_ctx_id, +		    conf_req_flag, +		    qop_req, +		    input_message_buffer, +		    conf_state, +		    output_message_buffer); +} + +OM_uint32 _gss_spnego_unwrap +           (OM_uint32 * minor_status, +            const gss_ctx_id_t context_handle, +            const gss_buffer_t input_message_buffer, +            gss_buffer_t output_message_buffer, +            int * conf_state, +            gss_qop_t * qop_state +           ) +{ +    gssspnego_ctx ctx; + +    *minor_status = 0; + +    if (context_handle == GSS_C_NO_CONTEXT) { +	return GSS_S_NO_CONTEXT; +    } + +    ctx = (gssspnego_ctx)context_handle; + +    if (ctx->negotiated_ctx_id == GSS_C_NO_CONTEXT) { +	return GSS_S_NO_CONTEXT; +    } + +    return gss_unwrap(minor_status, +		      ctx->negotiated_ctx_id, +		      input_message_buffer, +		      output_message_buffer, +		      conf_state, +		      qop_state); +} + +OM_uint32 _gss_spnego_compare_name +           (OM_uint32 *minor_status, +            const gss_name_t name1, +            const gss_name_t name2, +            int * name_equal +           ) +{ +    spnego_name n1 = (spnego_name)name1; +    spnego_name n2 = (spnego_name)name2; + +    *name_equal = 0; + +    if (!gss_oid_equal(&n1->type, &n2->type)) +	return GSS_S_COMPLETE; +    if (n1->value.length != n2->value.length) +	return GSS_S_COMPLETE; +    if (memcmp(n1->value.value, n2->value.value, n2->value.length) != 0) +	return GSS_S_COMPLETE; + +    *name_equal = 1; + +    return GSS_S_COMPLETE; +} + +OM_uint32 _gss_spnego_display_name +           (OM_uint32 * minor_status, +            const gss_name_t input_name, +            gss_buffer_t output_name_buffer, +            gss_OID * output_name_type +           ) +{ +    spnego_name name = (spnego_name)input_name; + +    *minor_status = 0; + +    if (name == NULL || name->mech == GSS_C_NO_NAME) +	return GSS_S_FAILURE; + +    return gss_display_name(minor_status, name->mech, +			    output_name_buffer, output_name_type); +} + +OM_uint32 _gss_spnego_import_name +           (OM_uint32 * minor_status, +            const gss_buffer_t name_buffer, +            const gss_OID name_type, +            gss_name_t * output_name +           ) +{ +    spnego_name name; +    OM_uint32 maj_stat; + +    *minor_status = 0; + +    name = calloc(1, sizeof(*name)); +    if (name == NULL) { +	*minor_status = ENOMEM; +	return GSS_S_FAILURE; +    } +     +    maj_stat = _gss_copy_oid(minor_status, name_type, &name->type); +    if (maj_stat) { +	free(name); +	return GSS_S_FAILURE; +    } +     +    maj_stat = _gss_copy_buffer(minor_status, name_buffer, &name->value); +    if (maj_stat) { +	gss_name_t rname = (gss_name_t)name; +	_gss_spnego_release_name(minor_status, &rname); +	return GSS_S_FAILURE; +    } +    name->mech = GSS_C_NO_NAME; +    *output_name = (gss_name_t)name; + +    return GSS_S_COMPLETE; +} + +OM_uint32 _gss_spnego_export_name +           (OM_uint32  * minor_status, +            const gss_name_t input_name, +            gss_buffer_t exported_name +           ) +{ +    spnego_name name; +    *minor_status = 0; + +    if (input_name == GSS_C_NO_NAME) +	return GSS_S_BAD_NAME; + +    name = (spnego_name)input_name; +    if (name->mech == GSS_C_NO_NAME) +	return GSS_S_BAD_NAME; + +    return gss_export_name(minor_status, name->mech, exported_name); +} + +OM_uint32 _gss_spnego_release_name +           (OM_uint32 * minor_status, +            gss_name_t * input_name +           ) +{ +    *minor_status = 0; + +    if (*input_name != GSS_C_NO_NAME) { +	OM_uint32 junk; +	spnego_name name = (spnego_name)*input_name; +	_gss_free_oid(&junk, &name->type); +	gss_release_buffer(&junk, &name->value); +	if (name->mech != GSS_C_NO_NAME) +	    gss_release_name(&junk, &name->mech); +	free(name); + +	*input_name = GSS_C_NO_NAME; +    } +    return GSS_S_COMPLETE; +} + +OM_uint32 _gss_spnego_inquire_context ( +            OM_uint32 * minor_status, +            const gss_ctx_id_t context_handle, +            gss_name_t * src_name, +            gss_name_t * targ_name, +            OM_uint32 * lifetime_rec, +            gss_OID * mech_type, +            OM_uint32 * ctx_flags, +            int * locally_initiated, +            int * open_context +           ) +{ +    gssspnego_ctx ctx; +    OM_uint32 maj_stat, junk; +    gss_name_t src_mn, targ_mn; + +    *minor_status = 0; + +    if (context_handle == GSS_C_NO_CONTEXT) +	return GSS_S_NO_CONTEXT; + +    ctx = (gssspnego_ctx)context_handle; + +    if (ctx->negotiated_ctx_id == GSS_C_NO_CONTEXT) +	return GSS_S_NO_CONTEXT; + +    maj_stat = gss_inquire_context(minor_status, +				   ctx->negotiated_ctx_id, +				   &src_mn, +				   &targ_mn, +				   lifetime_rec, +				   mech_type, +				   ctx_flags, +				   locally_initiated, +				   open_context); +    if (maj_stat != GSS_S_COMPLETE) +	return maj_stat; + +    if (src_name) { +	spnego_name name = calloc(1, sizeof(*name)); +	if (name == NULL) +	    goto enomem; +	name->mech = src_mn; +	*src_name = (gss_name_t)name; +    } else +	gss_release_name(&junk, &src_mn); +     +    if (targ_name) { +	spnego_name name = calloc(1, sizeof(*name)); +	if (name == NULL) { +	    gss_release_name(minor_status, src_name); +	    goto enomem; +	} +	name->mech = targ_mn; +	*targ_name = (gss_name_t)name; +    } else +	gss_release_name(&junk, &targ_mn); + +    return GSS_S_COMPLETE; + +enomem: +    gss_release_name(&junk, &targ_mn); +    gss_release_name(&junk, &src_mn); +    *minor_status = ENOMEM; +    return GSS_S_FAILURE; +} + +OM_uint32 _gss_spnego_wrap_size_limit ( +            OM_uint32 * minor_status, +            const gss_ctx_id_t context_handle, +            int conf_req_flag, +            gss_qop_t qop_req, +            OM_uint32 req_output_size, +            OM_uint32 * max_input_size +           ) +{ +    gssspnego_ctx ctx; + +    *minor_status = 0; + +    if (context_handle == GSS_C_NO_CONTEXT) { +	return GSS_S_NO_CONTEXT; +    } + +    ctx = (gssspnego_ctx)context_handle; + +    if (ctx->negotiated_ctx_id == GSS_C_NO_CONTEXT) { +	return GSS_S_NO_CONTEXT; +    } + +    return gss_wrap_size_limit(minor_status, +			       ctx->negotiated_ctx_id, +			       conf_req_flag, +			       qop_req, +			       req_output_size, +			       max_input_size); +} + +OM_uint32 _gss_spnego_export_sec_context ( +            OM_uint32 * minor_status, +            gss_ctx_id_t * context_handle, +            gss_buffer_t interprocess_token +           ) +{ +    gssspnego_ctx ctx; +    OM_uint32 ret; + +    *minor_status = 0; + +    if (context_handle == NULL) { +	return GSS_S_NO_CONTEXT; +    } + +    ctx = (gssspnego_ctx)*context_handle; + +    if (ctx == NULL) +	return GSS_S_NO_CONTEXT; + +    HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex); + +    if (ctx->negotiated_ctx_id == GSS_C_NO_CONTEXT) { +	HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); +	return GSS_S_NO_CONTEXT; +    } + +    ret = gss_export_sec_context(minor_status, +				 &ctx->negotiated_ctx_id, +				 interprocess_token); +    if (ret == GSS_S_COMPLETE) { +	ret = _gss_spnego_internal_delete_sec_context(minor_status, +					     context_handle, +					     GSS_C_NO_BUFFER); +	if (ret == GSS_S_COMPLETE) +	    return GSS_S_COMPLETE; +    } + +    HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); + +    return ret; +} + +OM_uint32 _gss_spnego_import_sec_context ( +            OM_uint32 * minor_status, +            const gss_buffer_t interprocess_token, +            gss_ctx_id_t *context_handle +           ) +{ +    OM_uint32 ret, minor; +    gss_ctx_id_t context; +    gssspnego_ctx ctx; + +    ret = _gss_spnego_alloc_sec_context(minor_status, &context); +    if (ret != GSS_S_COMPLETE) { +	return ret; +    } +    ctx = (gssspnego_ctx)context; + +    HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex); + +    ret = gss_import_sec_context(minor_status, +				 interprocess_token, +				 &ctx->negotiated_ctx_id); +    if (ret != GSS_S_COMPLETE) { +	_gss_spnego_internal_delete_sec_context(&minor, context_handle, GSS_C_NO_BUFFER); +	return ret; +    } + +    ctx->open = 1; +    /* don't bother filling in the rest of the fields */ + +    HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); + +    *context_handle = (gss_ctx_id_t)ctx; + +    return GSS_S_COMPLETE; +} + +OM_uint32 _gss_spnego_inquire_names_for_mech ( +            OM_uint32 * minor_status, +            const gss_OID mechanism, +            gss_OID_set * name_types +           ) +{ +    gss_OID_set mechs, names, n; +    OM_uint32 ret, junk; +    int i, j; + +    *name_types = NULL; + +    ret = spnego_supported_mechs(minor_status, &mechs); +    if (ret != GSS_S_COMPLETE) +	return ret; + +    ret = gss_create_empty_oid_set(minor_status, &names); +    if (ret != GSS_S_COMPLETE) +	goto out; + +    for (i = 0; i < mechs->count; i++) { +	ret = gss_inquire_names_for_mech(minor_status, +					 &mechs->elements[i], +					 &n); +	if (ret) +	    continue; + +	for (j = 0; j < n->count; j++) +	    gss_add_oid_set_member(minor_status, +				   &n->elements[j], +				   &names); +	gss_release_oid_set(&junk, &n); +    } + +    ret = GSS_S_COMPLETE; +    *name_types = names; +out: + +    gss_release_oid_set(&junk, &mechs); + +    return GSS_S_COMPLETE; +} + +OM_uint32 _gss_spnego_inquire_mechs_for_name ( +            OM_uint32 * minor_status, +            const gss_name_t input_name, +            gss_OID_set * mech_types +           ) +{ +    OM_uint32 ret, junk; + +    ret = gss_create_empty_oid_set(minor_status, mech_types); +    if (ret) +	return ret; + +    ret = gss_add_oid_set_member(minor_status, +				 GSS_SPNEGO_MECHANISM, +				 mech_types); +    if (ret) +	gss_release_oid_set(&junk, mech_types); + +    return ret; +} + +OM_uint32 _gss_spnego_canonicalize_name ( +            OM_uint32 * minor_status, +            const gss_name_t input_name, +            const gss_OID mech_type, +            gss_name_t * output_name +           ) +{ +    /* XXX */ +    return gss_duplicate_name(minor_status, input_name, output_name); +} + +OM_uint32 _gss_spnego_duplicate_name ( +            OM_uint32 * minor_status, +            const gss_name_t src_name, +            gss_name_t * dest_name +           ) +{ +    return gss_duplicate_name(minor_status, src_name, dest_name); +} + +OM_uint32 _gss_spnego_sign +           (OM_uint32 * minor_status, +            gss_ctx_id_t context_handle, +            int qop_req, +            gss_buffer_t message_buffer, +            gss_buffer_t message_token +           ) +{ +    gssspnego_ctx ctx; + +    *minor_status = 0; + +    if (context_handle == GSS_C_NO_CONTEXT) { +	return GSS_S_NO_CONTEXT; +    } + +    ctx = (gssspnego_ctx)context_handle; + +    if (ctx->negotiated_ctx_id == GSS_C_NO_CONTEXT) { +	return GSS_S_NO_CONTEXT; +    } + +    return gss_sign(minor_status, +		    ctx->negotiated_ctx_id, +		    qop_req, +		    message_buffer, +		    message_token); +} + +OM_uint32 _gss_spnego_verify +           (OM_uint32 * minor_status, +            gss_ctx_id_t context_handle, +            gss_buffer_t message_buffer, +            gss_buffer_t token_buffer, +            int * qop_state +           ) +{ +    gssspnego_ctx ctx; + +    *minor_status = 0; + +    if (context_handle == GSS_C_NO_CONTEXT) { +	return GSS_S_NO_CONTEXT; +    } + +    ctx = (gssspnego_ctx)context_handle; + +    if (ctx->negotiated_ctx_id == GSS_C_NO_CONTEXT) { +	return GSS_S_NO_CONTEXT; +    } + +    return gss_verify(minor_status, +		      ctx->negotiated_ctx_id, +		      message_buffer, +		      token_buffer, +		      qop_state); +} + +OM_uint32 _gss_spnego_seal +           (OM_uint32 * minor_status, +            gss_ctx_id_t context_handle, +            int conf_req_flag, +            int qop_req, +            gss_buffer_t input_message_buffer, +            int * conf_state, +            gss_buffer_t output_message_buffer +           ) +{ +    gssspnego_ctx ctx; + +    *minor_status = 0; + +    if (context_handle == GSS_C_NO_CONTEXT) { +	return GSS_S_NO_CONTEXT; +    } + +    ctx = (gssspnego_ctx)context_handle; + +    if (ctx->negotiated_ctx_id == GSS_C_NO_CONTEXT) { +	return GSS_S_NO_CONTEXT; +    } + +    return gss_seal(minor_status, +		    ctx->negotiated_ctx_id, +		    conf_req_flag, +		    qop_req, +		    input_message_buffer, +		    conf_state, +		    output_message_buffer); +} + +OM_uint32 _gss_spnego_unseal +           (OM_uint32 * minor_status, +            gss_ctx_id_t context_handle, +            gss_buffer_t input_message_buffer, +            gss_buffer_t output_message_buffer, +            int * conf_state, +            int * qop_state +           ) +{ +    gssspnego_ctx ctx; + +    *minor_status = 0; + +    if (context_handle == GSS_C_NO_CONTEXT) { +	return GSS_S_NO_CONTEXT; +    } + +    ctx = (gssspnego_ctx)context_handle; + +    if (ctx->negotiated_ctx_id == GSS_C_NO_CONTEXT) { +	return GSS_S_NO_CONTEXT; +    } + +    return gss_unseal(minor_status, +		      ctx->negotiated_ctx_id, +		      input_message_buffer, +		      output_message_buffer, +		      conf_state, +		      qop_state); +} + +#if 0 +OM_uint32 _gss_spnego_unwrap_ex +           (OM_uint32 * minor_status, +            const gss_ctx_id_t context_handle, +	    const gss_buffer_t token_header_buffer, +	    const gss_buffer_t associated_data_buffer, +	    const gss_buffer_t input_message_buffer, +	    gss_buffer_t output_message_buffer, +	    int * conf_state, +	    gss_qop_t * qop_state) +{ +    gssspnego_ctx ctx; + +    *minor_status = 0; + +    if (context_handle == GSS_C_NO_CONTEXT) { +	return GSS_S_NO_CONTEXT; +    } + +    ctx = (gssspnego_ctx)context_handle; + +    if (ctx->negotiated_ctx_id == GSS_C_NO_CONTEXT) { +	return GSS_S_NO_CONTEXT; +    } + +    return gss_unwrap_ex(minor_status, +			 ctx->negotiated_ctx_id, +			 token_header_buffer, +			 associated_data_buffer, +			 input_message_buffer, +			 output_message_buffer, +			 conf_state, +			 qop_state); +} + +OM_uint32 _gss_spnego_wrap_ex +           (OM_uint32 * minor_status, +            const gss_ctx_id_t context_handle, +            int conf_req_flag, +            gss_qop_t qop_req, +            const gss_buffer_t associated_data_buffer, +            const gss_buffer_t input_message_buffer, +            int * conf_state, +            gss_buffer_t output_token_buffer, +            gss_buffer_t output_message_buffer +	   ) +{ +    gssspnego_ctx ctx; + +    *minor_status = 0; + +    if (context_handle == GSS_C_NO_CONTEXT) { +	return GSS_S_NO_CONTEXT; +    } + +    ctx = (gssspnego_ctx)context_handle; + +    if (ctx->negotiated_ctx_id == GSS_C_NO_CONTEXT) { +	return GSS_S_NO_CONTEXT; +    } + +    if ((ctx->mech_flags & GSS_C_DCE_STYLE) == 0 && +	associated_data_buffer->length != input_message_buffer->length) { +	*minor_status = EINVAL; +	return GSS_S_BAD_QOP; +    } + +    return gss_wrap_ex(minor_status, +		       ctx->negotiated_ctx_id, +		       conf_req_flag, +		       qop_req, +		       associated_data_buffer, +		       input_message_buffer, +		       conf_state, +		       output_token_buffer, +		       output_message_buffer); +} + +OM_uint32 _gss_spnego_complete_auth_token +           (OM_uint32 * minor_status, +            const gss_ctx_id_t context_handle, +	    gss_buffer_t input_message_buffer) +{ +    gssspnego_ctx ctx; + +    *minor_status = 0; + +    if (context_handle == GSS_C_NO_CONTEXT) { +	return GSS_S_NO_CONTEXT; +    } + +    ctx = (gssspnego_ctx)context_handle; + +    if (ctx->negotiated_ctx_id == GSS_C_NO_CONTEXT) { +	return GSS_S_NO_CONTEXT; +    } + +    return gss_complete_auth_token(minor_status, +				   ctx->negotiated_ctx_id, +				   input_message_buffer); +} +#endif + +OM_uint32 _gss_spnego_inquire_sec_context_by_oid +           (OM_uint32 * minor_status, +            const gss_ctx_id_t context_handle, +            const gss_OID desired_object, +            gss_buffer_set_t *data_set) +{ +    gssspnego_ctx ctx; + +    *minor_status = 0; + +    if (context_handle == GSS_C_NO_CONTEXT) { +	return GSS_S_NO_CONTEXT; +    } + +    ctx = (gssspnego_ctx)context_handle; + +    if (ctx->negotiated_ctx_id == GSS_C_NO_CONTEXT) { +	return GSS_S_NO_CONTEXT; +    } + +    return gss_inquire_sec_context_by_oid(minor_status, +					  ctx->negotiated_ctx_id, +					  desired_object, +					  data_set); +} + +OM_uint32 _gss_spnego_set_sec_context_option +           (OM_uint32 * minor_status, +            gss_ctx_id_t * context_handle, +            const gss_OID desired_object, +            const gss_buffer_t value) +{ +    gssspnego_ctx ctx; + +    *minor_status = 0; + +    if (context_handle == NULL || *context_handle == GSS_C_NO_CONTEXT) { +	return GSS_S_NO_CONTEXT; +    } + +    ctx = (gssspnego_ctx)*context_handle; + +    if (ctx->negotiated_ctx_id == GSS_C_NO_CONTEXT) { +	return GSS_S_NO_CONTEXT; +    } + +    return gss_set_sec_context_option(minor_status, +				      &ctx->negotiated_ctx_id, +				      desired_object, +				      value); +} + + +OM_uint32 +_gss_spnego_pseudo_random(OM_uint32 *minor_status, +			  gss_ctx_id_t context_handle, +			  int prf_key, +			  const gss_buffer_t prf_in, +			  ssize_t desired_output_len, +			  gss_buffer_t prf_out) +{ +    gssspnego_ctx ctx; + +    *minor_status = 0; + +    if (context_handle == GSS_C_NO_CONTEXT) +	return GSS_S_NO_CONTEXT; + +    ctx = (gssspnego_ctx)context_handle; + +    if (ctx->negotiated_ctx_id == GSS_C_NO_CONTEXT) +	return GSS_S_NO_CONTEXT; + +    return gss_pseudo_random(minor_status, +			     ctx->negotiated_ctx_id, +			     prf_key, +			     prf_in, +			     desired_output_len, +			     prf_out); +} diff --git a/source4/heimdal/lib/gssapi/spnego/cred_stubs.c b/source4/heimdal/lib/gssapi/spnego/cred_stubs.c new file mode 100644 index 0000000000..836b63f437 --- /dev/null +++ b/source4/heimdal/lib/gssapi/spnego/cred_stubs.c @@ -0,0 +1,356 @@ +/* + * Copyright (c) 2004, PADL Software Pty Ltd. + * 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 PADL Software 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 PADL SOFTWARE 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 PADL SOFTWARE 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. + */ + +#include "spnego/spnego_locl.h" + +RCSID("$Id$"); + +OM_uint32 +_gss_spnego_release_cred(OM_uint32 *minor_status, gss_cred_id_t *cred_handle) +{ +    gssspnego_cred cred; +    OM_uint32 ret; +     +    *minor_status = 0; + +    if (*cred_handle == GSS_C_NO_CREDENTIAL) { +	return GSS_S_COMPLETE; +    } +    cred = (gssspnego_cred)*cred_handle; + +    ret = gss_release_cred(minor_status, &cred->negotiated_cred_id); + +    free(cred); +    *cred_handle = GSS_C_NO_CREDENTIAL; + +    return ret; +} + +OM_uint32 +_gss_spnego_alloc_cred(OM_uint32 *minor_status, +		       gss_cred_id_t mech_cred_handle, +		       gss_cred_id_t *cred_handle) +{ +    gssspnego_cred cred; + +    if (*cred_handle != GSS_C_NO_CREDENTIAL) { +	*minor_status = EINVAL; +	return GSS_S_FAILURE; +    } + +    cred = calloc(1, sizeof(*cred)); +    if (cred == NULL) { +	*cred_handle = GSS_C_NO_CREDENTIAL; +	*minor_status = ENOMEM; +	return GSS_S_FAILURE; +    } + +    cred->negotiated_cred_id = mech_cred_handle; + +    *cred_handle = (gss_cred_id_t)cred; + +    return GSS_S_COMPLETE;  +} + +/* + * For now, just a simple wrapper that avoids recursion. When + * we support gss_{get,set}_neg_mechs() we will need to expose + * more functionality. + */ +OM_uint32 _gss_spnego_acquire_cred +(OM_uint32 *minor_status, + const gss_name_t desired_name, + OM_uint32 time_req, + const gss_OID_set desired_mechs, + gss_cred_usage_t cred_usage, + gss_cred_id_t * output_cred_handle, + gss_OID_set * actual_mechs, + OM_uint32 * time_rec +    ) +{ +    const spnego_name dname = (const spnego_name)desired_name; +    gss_name_t name = GSS_C_NO_NAME; +    OM_uint32 ret, tmp; +    gss_OID_set_desc actual_desired_mechs; +    gss_OID_set mechs; +    int i, j; +    gss_cred_id_t cred_handle = GSS_C_NO_CREDENTIAL; +    gssspnego_cred cred; + +    *output_cred_handle = GSS_C_NO_CREDENTIAL; + +    if (dname) { +	ret = gss_import_name(minor_status, &dname->value, &dname->type, &name); +	if (ret) { +	    return ret; +	} +    } +     +    ret = gss_indicate_mechs(minor_status, &mechs); +    if (ret != GSS_S_COMPLETE) { +	gss_release_name(minor_status, &name); +	return ret; +    } + +    /* Remove ourselves from this list */ +    actual_desired_mechs.count = mechs->count; +    actual_desired_mechs.elements = malloc(actual_desired_mechs.count * +					   sizeof(gss_OID_desc)); +    if (actual_desired_mechs.elements == NULL) { +	*minor_status = ENOMEM; +	ret = GSS_S_FAILURE; +	goto out; +    } + +    for (i = 0, j = 0; i < mechs->count; i++) { +	if (gss_oid_equal(&mechs->elements[i], GSS_SPNEGO_MECHANISM)) +	    continue; + +	actual_desired_mechs.elements[j] = mechs->elements[i]; +	j++; +    } +    actual_desired_mechs.count = j; + +    ret = _gss_spnego_alloc_cred(minor_status, GSS_C_NO_CREDENTIAL, +				 &cred_handle); +    if (ret != GSS_S_COMPLETE) +	goto out; + +    cred = (gssspnego_cred)cred_handle; +    ret = gss_acquire_cred(minor_status, name, +			   time_req, &actual_desired_mechs, +			   cred_usage, +			   &cred->negotiated_cred_id, +			   actual_mechs, time_rec); +    if (ret != GSS_S_COMPLETE) +	goto out; + +    *output_cred_handle = cred_handle; + +out: +    gss_release_name(minor_status, &name); +    gss_release_oid_set(&tmp, &mechs); +    if (actual_desired_mechs.elements != NULL) { +	free(actual_desired_mechs.elements); +    } +    if (ret != GSS_S_COMPLETE) { +	_gss_spnego_release_cred(&tmp, &cred_handle); +    } + +    return ret; +} + +OM_uint32 _gss_spnego_inquire_cred +           (OM_uint32 * minor_status, +            const gss_cred_id_t cred_handle, +            gss_name_t * name, +            OM_uint32 * lifetime, +            gss_cred_usage_t * cred_usage, +            gss_OID_set * mechanisms +           ) +{ +    gssspnego_cred cred; +    spnego_name sname = NULL; +    OM_uint32 ret; + +    if (cred_handle == GSS_C_NO_CREDENTIAL) { +	*minor_status = 0; +	return GSS_S_NO_CRED; +    } + +    if (name) { +	sname = calloc(1, sizeof(*sname)); +	if (sname == NULL) { +	    *minor_status = ENOMEM; +	    return GSS_S_FAILURE; +	} +    } + +    cred = (gssspnego_cred)cred_handle; + +    ret = gss_inquire_cred(minor_status, +			   cred->negotiated_cred_id, +			   sname ? &sname->mech : NULL, +			   lifetime, +			   cred_usage, +			   mechanisms); +    if (ret) { +	if (sname) +	    free(sname); +	return ret; +    } +    if (name) +	*name = (gss_name_t)sname; + +    return ret; +} + +OM_uint32 _gss_spnego_add_cred ( +            OM_uint32 * minor_status, +            const gss_cred_id_t input_cred_handle, +            const gss_name_t desired_name, +            const gss_OID desired_mech, +            gss_cred_usage_t cred_usage, +            OM_uint32 initiator_time_req, +            OM_uint32 acceptor_time_req, +            gss_cred_id_t * output_cred_handle, +            gss_OID_set * actual_mechs, +            OM_uint32 * initiator_time_rec, +            OM_uint32 * acceptor_time_rec +           ) +{ +    gss_cred_id_t spnego_output_cred_handle = GSS_C_NO_CREDENTIAL; +    OM_uint32 ret, tmp; +    gssspnego_cred input_cred, output_cred; + +    *output_cred_handle = GSS_C_NO_CREDENTIAL; + +    ret = _gss_spnego_alloc_cred(minor_status, GSS_C_NO_CREDENTIAL, +				 &spnego_output_cred_handle); +    if (ret) +	return ret; + +    input_cred = (gssspnego_cred)input_cred_handle; +    output_cred = (gssspnego_cred)spnego_output_cred_handle; + +    ret = gss_add_cred(minor_status, +		       input_cred->negotiated_cred_id, +		       desired_name, +		       desired_mech, +		       cred_usage, +		       initiator_time_req, +		       acceptor_time_req, +		       &output_cred->negotiated_cred_id, +		       actual_mechs, +		       initiator_time_rec, +		       acceptor_time_rec); +    if (ret) { +	_gss_spnego_release_cred(&tmp, &spnego_output_cred_handle); +	return ret; +    } + +    *output_cred_handle = spnego_output_cred_handle; + +    return GSS_S_COMPLETE; +} + +OM_uint32 _gss_spnego_inquire_cred_by_mech ( +            OM_uint32 * minor_status, +            const gss_cred_id_t cred_handle, +            const gss_OID mech_type, +            gss_name_t * name, +            OM_uint32 * initiator_lifetime, +            OM_uint32 * acceptor_lifetime, +            gss_cred_usage_t * cred_usage +           ) +{ +    gssspnego_cred cred; +    spnego_name sname = NULL; +    OM_uint32 ret; + +    if (cred_handle == GSS_C_NO_CREDENTIAL) { +	*minor_status = 0; +	return GSS_S_NO_CRED; +    } + +    if (name) { +	sname = calloc(1, sizeof(*sname)); +	if (sname == NULL) { +	    *minor_status = ENOMEM; +	    return GSS_S_FAILURE; +	} +    } + +    cred = (gssspnego_cred)cred_handle; + +    ret = gss_inquire_cred_by_mech(minor_status, +				   cred->negotiated_cred_id, +				   mech_type, +				   sname ? &sname->mech : NULL, +				   initiator_lifetime, +				   acceptor_lifetime, +				   cred_usage); + +    if (ret) { +	if (sname) +	    free(sname); +	return ret; +    } +    if (name) +	*name = (gss_name_t)sname; + +    return GSS_S_COMPLETE; +} + +OM_uint32 _gss_spnego_inquire_cred_by_oid +           (OM_uint32 * minor_status, +            const gss_cred_id_t cred_handle, +            const gss_OID desired_object, +            gss_buffer_set_t *data_set) +{ +    gssspnego_cred cred; +    OM_uint32 ret; + +    if (cred_handle == GSS_C_NO_CREDENTIAL) { +	*minor_status = 0; +	return GSS_S_NO_CRED; +    } +    cred = (gssspnego_cred)cred_handle; + +    ret = gss_inquire_cred_by_oid(minor_status, +				  cred->negotiated_cred_id, +				  desired_object, +				  data_set); + +    return ret; +} + +OM_uint32 +_gss_spnego_set_cred_option (OM_uint32 *minor_status, +			     gss_cred_id_t *cred_handle, +			     const gss_OID object, +			     const gss_buffer_t value) +{ +    gssspnego_cred cred; + +    if (cred_handle == NULL || *cred_handle == GSS_C_NO_CREDENTIAL) { +	*minor_status = 0; +	return GSS_S_NO_CRED; +    } + +    cred = (gssspnego_cred)*cred_handle; +    return gss_set_cred_option(minor_status, +			      &cred->negotiated_cred_id, +			      object, +			      value); +} + diff --git a/source4/heimdal/lib/gssapi/spnego/external.c b/source4/heimdal/lib/gssapi/spnego/external.c new file mode 100644 index 0000000000..d5718c3fd3 --- /dev/null +++ b/source4/heimdal/lib/gssapi/spnego/external.c @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2004, PADL Software Pty Ltd. + * 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 PADL Software 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 PADL SOFTWARE 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 PADL SOFTWARE 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. + */ + +#include "spnego/spnego_locl.h" +#include <gssapi_mech.h> + +RCSID("$Id$"); + +/* + * RFC2478, SPNEGO: + *  The security mechanism of the initial + *  negotiation token is identified by the Object Identifier + *  iso.org.dod.internet.security.mechanism.snego (1.3.6.1.5.5.2). + */ + +static gssapi_mech_interface_desc spnego_mech = { +    GMI_VERSION, +    "spnego", +    {6, (void *)"\x2b\x06\x01\x05\x05\x02"}, +    _gss_spnego_acquire_cred, +    _gss_spnego_release_cred, +    _gss_spnego_init_sec_context, +    _gss_spnego_accept_sec_context, +    _gss_spnego_process_context_token, +    _gss_spnego_internal_delete_sec_context, +    _gss_spnego_context_time, +    _gss_spnego_get_mic, +    _gss_spnego_verify_mic, +    _gss_spnego_wrap, +    _gss_spnego_unwrap, +    NULL, /* gm_display_status */ +    NULL, /* gm_indicate_mechs */ +    _gss_spnego_compare_name, +    _gss_spnego_display_name, +    _gss_spnego_import_name, +    _gss_spnego_export_name, +    _gss_spnego_release_name, +    _gss_spnego_inquire_cred, +    _gss_spnego_inquire_context, +    _gss_spnego_wrap_size_limit, +    _gss_spnego_add_cred, +    _gss_spnego_inquire_cred_by_mech, +    _gss_spnego_export_sec_context, +    _gss_spnego_import_sec_context, +    _gss_spnego_inquire_names_for_mech, +    _gss_spnego_inquire_mechs_for_name, +    _gss_spnego_canonicalize_name, +    _gss_spnego_duplicate_name, +    _gss_spnego_inquire_sec_context_by_oid, +    _gss_spnego_inquire_cred_by_oid, +    _gss_spnego_set_sec_context_option, +    _gss_spnego_set_cred_option, +    _gss_spnego_pseudo_random +}; + +gssapi_mech_interface +__gss_spnego_initialize(void) +{ +	return &spnego_mech; +} + +static gss_OID_desc _gss_spnego_mechanism_desc =  +    {6, (void *)"\x2b\x06\x01\x05\x05\x02"}; + +gss_OID GSS_SPNEGO_MECHANISM = &_gss_spnego_mechanism_desc; diff --git a/source4/heimdal/lib/gssapi/spnego/init_sec_context.c b/source4/heimdal/lib/gssapi/spnego/init_sec_context.c new file mode 100644 index 0000000000..f032757fdd --- /dev/null +++ b/source4/heimdal/lib/gssapi/spnego/init_sec_context.c @@ -0,0 +1,668 @@ +/* + * Copyright (c) 1997 - 2004 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden).  + * Portions Copyright (c) 2004 PADL Software Pty Ltd. + * + * 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.  + */ + +#include "spnego/spnego_locl.h" + +RCSID("$Id$"); + +/* + * Is target_name an sane target for `mech´. + */ + +static OM_uint32 +initiator_approved(gss_name_t target_name, gss_OID mech) +{ +    OM_uint32 min_stat, maj_stat; +    gss_ctx_id_t ctx = GSS_C_NO_CONTEXT; +    gss_buffer_desc out; +     +    maj_stat = gss_init_sec_context(&min_stat, +				    GSS_C_NO_CREDENTIAL, +				    &ctx, +				    target_name, +				    mech, +				    0, +				    GSS_C_INDEFINITE, +				    GSS_C_NO_CHANNEL_BINDINGS, +				    GSS_C_NO_BUFFER, +				    NULL, +				    &out, +				    NULL, +				    NULL); +    if (GSS_ERROR(maj_stat)) { +	gss_mg_collect_error(mech, maj_stat, min_stat); +	return GSS_S_BAD_MECH; +    } +    gss_release_buffer(&min_stat, &out); +    gss_delete_sec_context(&min_stat, &ctx, NULL); + +    return GSS_S_COMPLETE; +} + +/* + * Send a reply. Note that we only need to send a reply if we + * need to send a MIC or a mechanism token. Otherwise, we can + * return an empty buffer. + * + * The return value of this will be returned to the API, so it + * must return GSS_S_CONTINUE_NEEDED if a token was generated. + */ +static OM_uint32 +spnego_reply_internal(OM_uint32 *minor_status, +		      gssspnego_ctx context_handle, +		      const gss_buffer_t mech_buf, +		      gss_buffer_t mech_token, +		      gss_buffer_t output_token) +{ +    NegotiationToken nt; +    gss_buffer_desc mic_buf; +    OM_uint32 ret; +    size_t size; + +    if (mech_buf == GSS_C_NO_BUFFER && mech_token->length == 0) { +	output_token->length = 0; +	output_token->value = NULL; + +	return context_handle->open ? GSS_S_COMPLETE : GSS_S_FAILURE; +    } + +    memset(&nt, 0, sizeof(nt)); + +    nt.element = choice_NegotiationToken_negTokenResp; + +    ALLOC(nt.u.negTokenResp.negResult, 1); +    if (nt.u.negTokenResp.negResult == NULL) { +	*minor_status = ENOMEM; +	return GSS_S_FAILURE; +    } + +    nt.u.negTokenResp.supportedMech = NULL; + +    output_token->length = 0; +    output_token->value = NULL; + +    if (mech_token->length == 0) { +	nt.u.negTokenResp.responseToken = NULL; +	*(nt.u.negTokenResp.negResult)  = accept_completed; +    } else { +	ALLOC(nt.u.negTokenResp.responseToken, 1); +	if (nt.u.negTokenResp.responseToken == NULL) { +	    free_NegotiationToken(&nt); +	    *minor_status = ENOMEM; +	    return GSS_S_FAILURE; +	} +	nt.u.negTokenResp.responseToken->length = mech_token->length; +	nt.u.negTokenResp.responseToken->data   = mech_token->value; +	mech_token->length = 0; +	mech_token->value  = NULL; + +	*(nt.u.negTokenResp.negResult)  = accept_incomplete; +    } + +    if (mech_buf != GSS_C_NO_BUFFER) { + +	ret = gss_get_mic(minor_status, +			  context_handle->negotiated_ctx_id, +			  0, +			  mech_buf, +			  &mic_buf); +	if (ret == GSS_S_COMPLETE) { +	    ALLOC(nt.u.negTokenResp.mechListMIC, 1); +	    if (nt.u.negTokenResp.mechListMIC == NULL) { +		gss_release_buffer(minor_status, &mic_buf); +		free_NegotiationToken(&nt); +		*minor_status = ENOMEM; +		return GSS_S_FAILURE; +	    } + +	    nt.u.negTokenResp.mechListMIC->length = mic_buf.length; +	    nt.u.negTokenResp.mechListMIC->data   = mic_buf.value; +	} else if (ret == GSS_S_UNAVAILABLE) { +	    nt.u.negTokenResp.mechListMIC = NULL; +	} if (ret) { +	    free_NegotiationToken(&nt); +	    *minor_status = ENOMEM; +	    return GSS_S_FAILURE; +	} +    } else { +	nt.u.negTokenResp.mechListMIC = NULL; +    } + +    ASN1_MALLOC_ENCODE(NegotiationToken, +		       output_token->value, output_token->length, +		       &nt, &size, ret); +    if (ret) { +	free_NegotiationToken(&nt); +	*minor_status = ret; +	return GSS_S_FAILURE; +    } + +    if (*(nt.u.negTokenResp.negResult) == accept_completed) +	ret = GSS_S_COMPLETE; +    else +	ret = GSS_S_CONTINUE_NEEDED; + +    free_NegotiationToken(&nt); +    return ret; +} + +static OM_uint32 +spnego_initial +           (OM_uint32 * minor_status, +	    gssspnego_cred cred, +            gss_ctx_id_t * context_handle, +            const gss_name_t target_name, +            const gss_OID mech_type, +            OM_uint32 req_flags, +            OM_uint32 time_req, +            const gss_channel_bindings_t input_chan_bindings, +            const gss_buffer_t input_token, +            gss_OID * actual_mech_type, +            gss_buffer_t output_token, +            OM_uint32 * ret_flags, +            OM_uint32 * time_rec +    ) +{ +    NegTokenInit ni; +    int ret; +    OM_uint32 sub, minor; +    gss_buffer_desc mech_token; +    u_char *buf; +    size_t buf_size, buf_len; +    gss_buffer_desc data; +    size_t ni_len; +    gss_ctx_id_t context; +    gssspnego_ctx ctx; +    spnego_name name = (spnego_name)target_name; + +    *minor_status = 0; + +    memset (&ni, 0, sizeof(ni)); + +    *context_handle = GSS_C_NO_CONTEXT; + +    if (target_name == GSS_C_NO_NAME) +	return GSS_S_BAD_NAME; + +    sub = _gss_spnego_alloc_sec_context(&minor, &context); +    if (GSS_ERROR(sub)) { +	*minor_status = minor; +	return sub; +    } +    ctx = (gssspnego_ctx)context; + +    HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex); + +    ctx->local = 1; + +    sub = gss_import_name(&minor, &name->value, &name->type, &ctx->target_name); +    if (GSS_ERROR(sub)) { +	*minor_status = minor; +	_gss_spnego_internal_delete_sec_context(&minor, &context, GSS_C_NO_BUFFER); +	return sub; +    } + +    sub = _gss_spnego_indicate_mechtypelist(&minor,  +					    ctx->target_name, +					    initiator_approved, +					    0, +					    cred, +					    &ni.mechTypes, +					    &ctx->preferred_mech_type); +    if (GSS_ERROR(sub)) { +	*minor_status = minor; +	_gss_spnego_internal_delete_sec_context(&minor, &context, GSS_C_NO_BUFFER); +	return sub; +    } + +    ni.reqFlags = NULL; + +    /* +     * If we have a credential handle, use it to select the mechanism +     * that we will use +     */ + +    /* generate optimistic token */ +    sub = gss_init_sec_context(&minor, +			       (cred != NULL) ? cred->negotiated_cred_id : +			          GSS_C_NO_CREDENTIAL, +			       &ctx->negotiated_ctx_id, +			       ctx->target_name, +			       ctx->preferred_mech_type, +			       req_flags, +			       time_req, +			       input_chan_bindings, +			       input_token, +			       &ctx->negotiated_mech_type, +			       &mech_token, +			       &ctx->mech_flags, +			       &ctx->mech_time_rec); +    if (GSS_ERROR(sub)) { +	free_NegTokenInit(&ni); +	*minor_status = minor; +	gss_mg_collect_error(ctx->preferred_mech_type, sub, minor); +	_gss_spnego_internal_delete_sec_context(&minor, &context, GSS_C_NO_BUFFER); +	return sub; +    } +    if (sub == GSS_S_COMPLETE) +	ctx->maybe_open = 1; + +    if (mech_token.length != 0) { +	ALLOC(ni.mechToken, 1); +	if (ni.mechToken == NULL) { +	    free_NegTokenInit(&ni); +	    gss_release_buffer(&minor, &mech_token); +	    _gss_spnego_internal_delete_sec_context(&minor, &context, GSS_C_NO_BUFFER); +	    *minor_status = ENOMEM; +	    return GSS_S_FAILURE; +	} +	ni.mechToken->length = mech_token.length; +	ni.mechToken->data = malloc(mech_token.length); +	if (ni.mechToken->data == NULL && mech_token.length != 0) { +	    free_NegTokenInit(&ni); +	    gss_release_buffer(&minor, &mech_token); +	    *minor_status = ENOMEM; +	    _gss_spnego_internal_delete_sec_context(&minor, &context, GSS_C_NO_BUFFER); +	    return GSS_S_FAILURE; +	} +	memcpy(ni.mechToken->data, mech_token.value, mech_token.length); +	gss_release_buffer(&minor, &mech_token); +    } else +	ni.mechToken = NULL; + +    ni.mechListMIC = NULL; + +    ni_len = length_NegTokenInit(&ni); +    buf_size = 1 + der_length_len(ni_len) + ni_len; + +    buf = malloc(buf_size); +    if (buf == NULL) { +	free_NegTokenInit(&ni); +	*minor_status = ENOMEM; +	_gss_spnego_internal_delete_sec_context(&minor, &context, GSS_C_NO_BUFFER); +	return GSS_S_FAILURE; +    } + +    ret = encode_NegTokenInit(buf + buf_size - 1, +			      ni_len, +			      &ni, &buf_len); +    if (ret == 0 && ni_len != buf_len) +	abort(); + +    if (ret == 0) { +	size_t tmp; + +	ret = der_put_length_and_tag(buf + buf_size - buf_len - 1, +				     buf_size - buf_len, +				     buf_len, +				     ASN1_C_CONTEXT, +				     CONS, +				     0, +				     &tmp); +	if (ret == 0 && tmp + buf_len != buf_size) +	    abort(); +    } +    if (ret) { +	*minor_status = ret; +	free(buf); +	free_NegTokenInit(&ni); +	_gss_spnego_internal_delete_sec_context(&minor, &context, GSS_C_NO_BUFFER); +	return GSS_S_FAILURE; +    } + +    data.value  = buf; +    data.length = buf_size; + +    ctx->initiator_mech_types.len = ni.mechTypes.len; +    ctx->initiator_mech_types.val = ni.mechTypes.val; +    ni.mechTypes.len = 0; +    ni.mechTypes.val = NULL; +  +    free_NegTokenInit(&ni); + +    sub = gss_encapsulate_token(&data, +				GSS_SPNEGO_MECHANISM, +				output_token); +    free (buf); + +    if (sub) { +	_gss_spnego_internal_delete_sec_context(&minor, &context, GSS_C_NO_BUFFER); +	return sub; +    } + +    if (actual_mech_type) +	*actual_mech_type = ctx->negotiated_mech_type; +    if (ret_flags) +	*ret_flags = ctx->mech_flags; +    if (time_rec) +	*time_rec = ctx->mech_time_rec; + +    HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); + +    *context_handle = context; + +    return GSS_S_CONTINUE_NEEDED; +} + +static OM_uint32 +spnego_reply +           (OM_uint32 * minor_status, +	    const gssspnego_cred cred, +            gss_ctx_id_t * context_handle, +            const gss_name_t target_name, +            const gss_OID mech_type, +            OM_uint32 req_flags, +            OM_uint32 time_req, +            const gss_channel_bindings_t input_chan_bindings, +            const gss_buffer_t input_token, +            gss_OID * actual_mech_type, +            gss_buffer_t output_token, +            OM_uint32 * ret_flags, +            OM_uint32 * time_rec +    ) +{ +    OM_uint32 ret, minor; +    NegTokenResp resp; +    size_t len, taglen; +    gss_OID_desc mech; +    int require_mic; +    size_t buf_len; +    gss_buffer_desc mic_buf, mech_buf; +    gss_buffer_desc mech_output_token; +    gssspnego_ctx ctx; + +    *minor_status = 0; + +    ctx = (gssspnego_ctx)*context_handle; + +    output_token->length = 0; +    output_token->value  = NULL; + +    mech_output_token.length = 0; +    mech_output_token.value = NULL; + +    mech_buf.value = NULL; +    mech_buf.length = 0; + +    ret = der_match_tag_and_length(input_token->value, input_token->length, +				   ASN1_C_CONTEXT, CONS, 1, &len, &taglen); +    if (ret) +	return ret; + +    if (len > input_token->length - taglen) +	return ASN1_OVERRUN; + +    ret = decode_NegTokenResp((const unsigned char *)input_token->value+taglen, +			      len, &resp, NULL); +    if (ret) { +	*minor_status = ENOMEM; +	return GSS_S_FAILURE; +    } + +    if (resp.negResult == NULL +	|| *(resp.negResult) == reject +	/* || resp.supportedMech == NULL */ +	) +    { +	free_NegTokenResp(&resp); +	return GSS_S_BAD_MECH; +    } + +    /* +     * Pick up the mechanism that the acceptor selected, only allow it +     * to be sent in packet. +     */ + +    HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex); + +    if (resp.supportedMech) { + +	if (ctx->oidlen) { +	    free_NegTokenResp(&resp); +	    HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); +	    return GSS_S_BAD_MECH; +	} +	ret = der_put_oid(ctx->oidbuf + sizeof(ctx->oidbuf) - 1, +			  sizeof(ctx->oidbuf), +			  resp.supportedMech, +			  &ctx->oidlen); +	/* Avoid recursively embedded SPNEGO */ +	if (ret || (ctx->oidlen == GSS_SPNEGO_MECHANISM->length && +		    memcmp(ctx->oidbuf + sizeof(ctx->oidbuf) - ctx->oidlen, +			   GSS_SPNEGO_MECHANISM->elements, +			   ctx->oidlen) == 0)) +	{ +	    free_NegTokenResp(&resp); +	    HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); +	    return GSS_S_BAD_MECH; +	} + +	/* check if the acceptor took our optimistic token */ +	if (ctx->oidlen != ctx->preferred_mech_type->length || +	    memcmp(ctx->oidbuf + sizeof(ctx->oidbuf) - ctx->oidlen, +		   ctx->preferred_mech_type->elements, +		   ctx->oidlen) != 0) +	{ +	    gss_delete_sec_context(&minor, &ctx->negotiated_ctx_id,  +				   GSS_C_NO_BUFFER); +	    ctx->negotiated_ctx_id = GSS_C_NO_CONTEXT; +	} +    } else if (ctx->oidlen == 0) { +	free_NegTokenResp(&resp); +	HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); +	return GSS_S_BAD_MECH; +    } + +    /* if a token (of non zero length), or no context, pass to underlaying mech */ +    if ((resp.responseToken != NULL && resp.responseToken->length) ||  +	ctx->negotiated_ctx_id == GSS_C_NO_CONTEXT) { +	gss_buffer_desc mech_input_token; + +	if (resp.responseToken) { +	    mech_input_token.length = resp.responseToken->length; +	    mech_input_token.value  = resp.responseToken->data; +	} else { +	    mech_input_token.length = 0; +	    mech_input_token.value = NULL; +	} + + +	mech.length = ctx->oidlen; +	mech.elements = ctx->oidbuf + sizeof(ctx->oidbuf) - ctx->oidlen; + +	/* Fall through as if the negotiated mechanism +	   was requested explicitly */ +	ret = gss_init_sec_context(&minor, +				   (cred != NULL) ? cred->negotiated_cred_id : +				       GSS_C_NO_CREDENTIAL, +				   &ctx->negotiated_ctx_id, +				   ctx->target_name, +				   &mech, +				   req_flags, +				   time_req, +				   input_chan_bindings, +				   &mech_input_token, +				   &ctx->negotiated_mech_type, +				   &mech_output_token, +				   &ctx->mech_flags, +				   &ctx->mech_time_rec); +	if (GSS_ERROR(ret)) { +	    HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); +	    free_NegTokenResp(&resp); +	    gss_mg_collect_error(&mech, ret, minor); +	    *minor_status = minor; +	    return ret; +	} +	if (ret == GSS_S_COMPLETE) { +	    ctx->open = 1; +	} +    } else if (*(resp.negResult) == accept_completed) { +	if (ctx->maybe_open) +	    ctx->open = 1; +    } + +    if (*(resp.negResult) == request_mic) { +	ctx->require_mic = 1; +    } + +    if (ctx->open) { +	/* +	 * Verify the mechListMIC if one was provided or CFX was +	 * used and a non-preferred mechanism was selected +	 */ +	if (resp.mechListMIC != NULL) { +	    require_mic = 1; +	} else { +	    ret = _gss_spnego_require_mechlist_mic(minor_status, ctx, +						   &require_mic); +	    if (ret) { +		HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); +		free_NegTokenResp(&resp); +		gss_release_buffer(&minor, &mech_output_token); +		return ret; +	    } +	} +    } else { +	require_mic = 0; +    } + +    if (require_mic) { +	ASN1_MALLOC_ENCODE(MechTypeList, mech_buf.value, mech_buf.length, +			   &ctx->initiator_mech_types, &buf_len, ret); +	if (ret) { +	    HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); +	    free_NegTokenResp(&resp); +	    gss_release_buffer(&minor, &mech_output_token); +	    *minor_status = ret; +	    return GSS_S_FAILURE; +	} +	if (mech_buf.length != buf_len) +	    abort(); + +	if (resp.mechListMIC == NULL) { +	    HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); +	    free(mech_buf.value); +	    free_NegTokenResp(&resp); +	    *minor_status = 0; +	    return GSS_S_DEFECTIVE_TOKEN; +	} +	mic_buf.length = resp.mechListMIC->length; +	mic_buf.value  = resp.mechListMIC->data; + +	if (mech_output_token.length == 0) { +	    ret = gss_verify_mic(minor_status, +				 ctx->negotiated_ctx_id, +				 &mech_buf, +				 &mic_buf, +				 NULL); +	   if (ret) { +		HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); +		free(mech_buf.value); +		gss_release_buffer(&minor, &mech_output_token); +		free_NegTokenResp(&resp); +		return GSS_S_DEFECTIVE_TOKEN; +	    } +	    ctx->verified_mic = 1; +	} +    } + +    ret = spnego_reply_internal(minor_status, ctx, +				require_mic ? &mech_buf : NULL, +				&mech_output_token, +				output_token); + +    if (mech_buf.value != NULL) +	free(mech_buf.value); + +    free_NegTokenResp(&resp); +    gss_release_buffer(&minor, &mech_output_token); + +    if (actual_mech_type) +	*actual_mech_type = ctx->negotiated_mech_type; +    if (ret_flags) +	*ret_flags = ctx->mech_flags; +    if (time_rec) +	*time_rec = ctx->mech_time_rec; + +    HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); +    return ret; +} + +OM_uint32 _gss_spnego_init_sec_context +           (OM_uint32 * minor_status, +            const gss_cred_id_t initiator_cred_handle, +            gss_ctx_id_t * context_handle, +            const gss_name_t target_name, +            const gss_OID mech_type, +            OM_uint32 req_flags, +            OM_uint32 time_req, +            const gss_channel_bindings_t input_chan_bindings, +            const gss_buffer_t input_token, +            gss_OID * actual_mech_type, +            gss_buffer_t output_token, +            OM_uint32 * ret_flags, +            OM_uint32 * time_rec +           ) +{ +    gssspnego_cred cred = (gssspnego_cred)initiator_cred_handle; + +    if (*context_handle == GSS_C_NO_CONTEXT) +	return spnego_initial (minor_status, +			       cred, +			       context_handle, +			       target_name, +			       mech_type, +			       req_flags, +			       time_req, +			       input_chan_bindings, +			       input_token, +			       actual_mech_type, +			       output_token, +			       ret_flags, +			       time_rec); +    else +	return spnego_reply (minor_status, +			     cred, +			     context_handle, +			     target_name, +			     mech_type, +			     req_flags, +			     time_req, +			     input_chan_bindings, +			     input_token, +			     actual_mech_type, +			     output_token, +			     ret_flags, +			     time_rec); +} + diff --git a/source4/heimdal/lib/gssapi/spnego/spnego.asn1 b/source4/heimdal/lib/gssapi/spnego/spnego.asn1 new file mode 100644 index 0000000000..048e86bb43 --- /dev/null +++ b/source4/heimdal/lib/gssapi/spnego/spnego.asn1 @@ -0,0 +1,63 @@ +-- $Id$ + +SPNEGO DEFINITIONS ::= +BEGIN + +MechType::= OBJECT IDENTIFIER + +MechTypeList ::= SEQUENCE OF MechType + +ContextFlags ::= BIT STRING { +    delegFlag       (0), +    mutualFlag      (1), +    replayFlag      (2), +    sequenceFlag    (3), +    anonFlag        (4), +    confFlag        (5), +    integFlag       (6) +} + +NegHints ::= SEQUENCE { +    hintName       [0]  GeneralString	OPTIONAL, +    hintAddress    [1]  OCTET STRING	OPTIONAL +}  + +NegTokenInitWin ::= SEQUENCE { +    mechTypes       [0] MechTypeList, +    reqFlags        [1] ContextFlags   OPTIONAL, +    mechToken       [2] OCTET STRING   OPTIONAL, +    negHints        [3] NegHints       OPTIONAL +} + +NegTokenInit ::= SEQUENCE { +    mechTypes       [0] MechTypeList, +    reqFlags        [1] ContextFlags   OPTIONAL, +    mechToken       [2] OCTET STRING   OPTIONAL, +    mechListMIC	    [3] OCTET STRING   OPTIONAL, +    ... +} + +-- NB: negResult is not OPTIONAL in the new SPNEGO spec but +-- Windows clients do not always send it +NegTokenResp ::= SEQUENCE { +    negResult      [0] ENUMERATED { +                            accept_completed    (0), +                            accept_incomplete   (1), +                            reject              (2), +                            request-mic         (3) }          OPTIONAL, +    supportedMech  [1] MechType                                OPTIONAL, +    responseToken  [2] OCTET STRING                            OPTIONAL, +    mechListMIC    [3] OCTET STRING                            OPTIONAL, +    ... +} + +NegotiationToken ::= CHOICE { +	negTokenInit[0]		NegTokenInit, +	negTokenResp[1]		NegTokenResp +} + +NegotiationTokenWin ::= CHOICE { +	negTokenInit[0]		NegTokenInitWin +} + +END diff --git a/source4/heimdal/lib/gssapi/spnego/spnego_locl.h b/source4/heimdal/lib/gssapi/spnego/spnego_locl.h new file mode 100644 index 0000000000..8344e750ae --- /dev/null +++ b/source4/heimdal/lib/gssapi/spnego/spnego_locl.h @@ -0,0 +1,114 @@ +/* + * Copyright (c) 2004, PADL Software Pty Ltd. + * 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 PADL Software 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 PADL SOFTWARE 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 PADL SOFTWARE 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$ */ + +#ifndef SPNEGO_LOCL_H +#define SPNEGO_LOCL_H + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#ifdef HAVE_SYS_TYPES_H +#include <sys/types.h> +#endif +#ifdef HAVE_SYS_PARAM_H +#include <sys/param.h> +#endif + +#ifdef HAVE_PTHREAD_H +#include <pthread.h> +#endif + +#include <gssapi/gssapi_spnego.h> +#include <gssapi.h> +#include <assert.h> +#include <stdlib.h> +#include <string.h> +#include <errno.h> +#include <ctype.h> +#ifdef HAVE_NETDB_H +#include <netdb.h> +#endif + +#include <heim_threads.h> +#include <asn1_err.h> + +#include <gssapi_mech.h> + +#include "spnego_asn1.h" +#include "mech/utils.h" +#include <der.h> + +#include <roken.h> + +#define ALLOC(X, N) (X) = calloc((N), sizeof(*(X))) + +typedef struct { +	gss_cred_id_t		negotiated_cred_id; +} *gssspnego_cred; + +typedef struct { +	MechTypeList		initiator_mech_types; +	gss_OID			preferred_mech_type; +	gss_OID			negotiated_mech_type; +	gss_ctx_id_t		negotiated_ctx_id; +	OM_uint32		mech_flags; +	OM_uint32		mech_time_rec; +	gss_name_t		mech_src_name; +	unsigned int		open : 1; +	unsigned int		local : 1; +	unsigned int		require_mic : 1; +	unsigned int		verified_mic : 1; +	unsigned int		maybe_open : 1; +	HEIMDAL_MUTEX		ctx_id_mutex; + +	gss_name_t		target_name; + +	u_char			oidbuf[17]; + 	size_t			oidlen; + +} *gssspnego_ctx; + +typedef struct { +	gss_OID_desc		type; +	gss_buffer_desc		value; +	gss_name_t		mech; +} *spnego_name; + +extern gss_OID_desc _gss_spnego_mskrb_mechanism_oid_desc; +extern gss_OID_desc _gss_spnego_krb5_mechanism_oid_desc; + +#include <spnego/spnego-private.h> + +#endif /* SPNEGO_LOCL_H */ | 
