diff options
Diffstat (limited to 'src/lib/gssapi')
28 files changed, 1945 insertions, 2136 deletions
diff --git a/src/lib/gssapi/ChangeLog b/src/lib/gssapi/ChangeLog index 1e0213f..060c2e7 100644 --- a/src/lib/gssapi/ChangeLog +++ b/src/lib/gssapi/ChangeLog @@ -1,3 +1,7 @@ +2000-06-03 Tom Yu <tlyu@mit.edu> + + * Makefile.in(LIBMINOR): Bump library version. + Tue Feb 22 10:23:19 2000 Ezra Peisach <epeisach@mit.edu> * Makefile.in (clean-unix): Add clean-libobjs. diff --git a/src/lib/gssapi/Makefile.in b/src/lib/gssapi/Makefile.in index bee2b85..20936da 100644 --- a/src/lib/gssapi/Makefile.in +++ b/src/lib/gssapi/Makefile.in @@ -24,7 +24,7 @@ SRCS=\ LIB=gssapi_krb5 LIBMAJOR=2 -LIBMINOR=1 +LIBMINOR=2 STOBJLISTS=OBJS.ST generic/OBJS.ST krb5/OBJS.ST SHLIB_EXPDEPS=\ $(TOPLIBD)/libkrb5$(SHLIBEXT) \ diff --git a/src/lib/gssapi/generic/ChangeLog b/src/lib/gssapi/generic/ChangeLog index 234c953..db4ab13 100644 --- a/src/lib/gssapi/generic/ChangeLog +++ b/src/lib/gssapi/generic/ChangeLog @@ -1,3 +1,32 @@ +2000-11-19 Alexandra Ellwood <lxs@mit.edu> + * gssapi_generic.h: Fixed check for Mac OS X includes. + +2001-10-29 Miro Jurisic <meeroh@mit.edu> + * pullup from krb5-1-2 branch after krb5-1-2-2-bp + * gssapi.hin, gssapi_generic.h, gssapi_generic.c: + added oids from rfc 2744. Kept old oids for compatibility. + * gssapi.hin: Changed KerberosConditionalMacros.h to + KerberosSupport.h. + * gssapi.hin: Fixed Mac OS preprocessor test + * gssapi_generic.h: corrected Mac OS include to <GSS/gssapi.h> + * gssapiP_generic.h: use "" include for krb5.h + * disp_com_err_status.c, gssapi.hin: Updated Mac OS #defines + and #includes for new header layout and Mac OS X frameworks + * gssapi_generic.h: Added check for Mac OS X includes. This will + not break autoconf-style builds because they do not include + ConditionalMacros.h. + +2001-10-20 Ken Raeburn <raeburn@mit.edu> + + * gssapiP_generic.h (g_*): For every g_ function declared here, + first define the name as a macro using a gssint_ prefix to avoid + conflicting with glib function names. + +2000-09-11 Alexandra Ellwood <lxs@mit.edu> + * gssapi_generic.h: Added check for Mac OS X includes. This will + not break autoconf-style builds because they do not include + ConditionalMacros.h. + 1999-10-26 Tom Yu <tlyu@mit.edu> * Makefile.in: Clean up usage of CFLAGS, CPPFLAGS, DEFS, DEFINES, diff --git a/src/lib/gssapi/generic/disp_com_err_status.c b/src/lib/gssapi/generic/disp_com_err_status.c index c4db913..d09c914 100644 --- a/src/lib/gssapi/generic/disp_com_err_status.c +++ b/src/lib/gssapi/generic/disp_com_err_status.c @@ -25,7 +25,12 @@ */ #include "gssapiP_generic.h" + +#if TARGET_OS_MAC +#include <KerberosComErr/KerberosComErr.h> +#else #include "com_err.h" +#endif /* XXXX internationalization!! */ diff --git a/src/lib/gssapi/generic/gssapi.hin b/src/lib/gssapi/generic/gssapi.hin index f6a0f57..9e2d597 100644 --- a/src/lib/gssapi/generic/gssapi.hin +++ b/src/lib/gssapi/generic/gssapi.hin @@ -27,13 +27,22 @@ * Determine platform-dependent configuration. */ -#if defined(_MSDOS) || defined(_WIN32) || defined(macintosh) -#include <win-mac.h> - -/* Macintoh CFM-68K magic incantation */ -#if defined(macintosh) && defined(__CFM68K__) && !defined(__USING_STATIC_LIBS__) -#pragma import on +#if defined(macintosh) || (defined(__MACH__) && defined(__APPLE__)) + #include <KerberosSupport/KerberosSupport.h> + + #if TARGET_API_MAC_OS8 || (TARGET_API_MAC_CARBON && !TARGET_API_MAC_OSX) + #include <Kerberos5/win-mac.h> + #endif + + /* This is an API divergence in 1.2.3. This will be reconciled in 1.3, when + all platforms will have RFC-compliant OID declarations. */ + #define GSS_RFC_COMPLIANT_OIDS 1 +#else + #define GSS_RFC_COMPLIANT_OIDS 0 #endif + +#if defined(_MSDOS) || defined(_WIN32) +#include <win-mac.h> #endif #ifndef KRB5_CALLCONV @@ -329,8 +338,122 @@ typedef int gss_cred_usage_t; #ifdef __cplusplus extern "C" { +#endif /* __cplusplus */ + +/* Macintoh CFM-68K magic incantation */ +#if PRAGMA_IMPORT +#pragma import on +#endif + +#if PRAGMA_STRUCT_ALIGN + #pragma options align=mac68k +#elif PRAGMA_STRUCT_PACKPUSH + #pragma pack(push, 2) +#elif PRAGMA_STRUCT_PACK + #pragma pack(2) #endif +/* RFC-compliant GSS_oids will be present on all platforms in 1.3 */ +#if GSS_RFC_COMPLIANT_OIDS + +/* Reserved static storage for GSS_oids. Comments are quotes from RFC 2744. + * + * 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. + */ +GSS_DLLIMP extern 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. + */ +GSS_DLLIMP extern 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. + */ +GSS_DLLIMP extern 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 + */ +GSS_DLLIMP extern 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. + */ +GSS_DLLIMP extern 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. + */ +GSS_DLLIMP extern 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. + */ +GSS_DLLIMP extern gss_OID GSS_C_NT_EXPORT_NAME; + +#endif /* GSS_RFC_COMPLIANT_OIDS */ + +/* Function Prototypes */ + GSS_DLLIMP OM_uint32 KRB5_CALLCONV gss_acquire_cred PROTOTYPE( (OM_uint32 FAR *, /* minor_status */ gss_name_t, /* desired_name */ @@ -684,9 +807,24 @@ PROTOTYPE( (OM_uint32 *, /* minor_status */ gss_name_t * /* output_name */ )); +/* Macintosh CFM-68K magic incantation */ +#if PRAGMA_STRUCT_ALIGN + #pragma options align=reset +#elif PRAGMA_STRUCT_PACKPUSH + #pragma pack(pop) +#elif PRAGMA_STRUCT_PACK + #pragma pack() +#endif + +#ifdef PRAGMA_IMPORT_OFF +#pragma import off +#elif PRAGMA_IMPORT +#pragma import reset +#endif + #ifdef __cplusplus } -#endif +#endif /* __cplusplus */ /* XXXX these are not part of the GSSAPI C bindings! (but should be) */ @@ -700,9 +838,4 @@ PROTOTYPE( (OM_uint32 *, /* minor_status */ /* XXXX This is a necessary evil until the spec is fixed */ #define GSS_S_CRED_UNAVAIL GSS_S_FAILURE -/* Macintoh CFM-68K magic incantation */ -#if defined(macintosh) && defined(__CFM68K__) && !defined(__USING_STATIC_LIBS__) -#pragma import reset -#endif - #endif /* _GSSAPI_H_ */ diff --git a/src/lib/gssapi/generic/gssapiP_generic.h b/src/lib/gssapi/generic/gssapiP_generic.h index a0fa7c4..3f7fd75 100644 --- a/src/lib/gssapi/generic/gssapiP_generic.h +++ b/src/lib/gssapi/generic/gssapiP_generic.h @@ -28,7 +28,7 @@ */ #if (defined(_MSDOS) || defined(_WIN32) || defined(macintosh)) -#include <k5-int.h> +#include "k5-int.h" #else #ifdef HAVE_STDLIB_H #include <stdlib.h> @@ -97,6 +97,38 @@ /** helper functions **/ +/* hide names from applications, especially glib applications */ +#define g_set_init gssint_g_set_init +#define g_set_destroy gssint_g_set_destroy +#define g_set_entry_add gssint_g_set_entry_add +#define g_set_entry_delete gssint_g_set_entry_delete +#define g_set_entry_get gssint_g_set_entry_get +#define g_save_name gssint_g_save_name +#define g_save_cred_id gssint_g_save_cred_id +#define g_save_ctx_id gssint_g_save_ctx_id +#define g_validate_name gssint_g_validate_name +#define g_validate_cred_id gssint_g_validate_cred_id +#define g_validate_ctx_id gssint_g_validate_ctx_id +#define g_delete_name gssint_g_delete_name +#define g_delete_cred_id gssint_g_delete_cred_id +#define g_delete_ctx_id gssint_g_delete_ctx_id +#define g_make_string_buffer gssint_g_make_string_buffer +#define g_copy_OID_set gssint_g_copy_OID_set +#define g_token_size gssint_g_token_size +#define g_make_token_header gssint_g_make_token_header +#define g_verify_token_header gssint_g_verify_token_header +#define g_display_major_status gssint_g_display_major_status +#define g_display_com_err_status gssint_g_display_com_err_status +#define g_order_init gssint_g_order_init +#define g_order_check gssint_g_order_check +#define g_order_free gssint_g_order_free +#define g_queue_size gssint_g_queue_size +#define g_queue_externalize gssint_g_queue_externalize +#define g_queue_internalize gssint_g_queue_internalize +#define g_canonicalize_host gssint_g_canonicalize_host +#define g_local_host_name gssint_g_local_host_name +#define g_strdup gssint_g_strdup + typedef struct _g_set *g_set; int g_set_init PROTOTYPE((g_set *s)); diff --git a/src/lib/gssapi/generic/gssapi_generic.c b/src/lib/gssapi/generic/gssapi_generic.c index 10cc4d7..ea7cb82 100644 --- a/src/lib/gssapi/generic/gssapi_generic.c +++ b/src/lib/gssapi/generic/gssapi_generic.c @@ -53,17 +53,111 @@ */ static gss_OID_desc oids[] = { - {10, "\052\206\110\206\367\022\001\002\001\001"}, - {10, "\052\206\110\206\367\022\001\002\001\002"}, - {10, "\052\206\110\206\367\022\001\002\001\003"}, - {10, "\052\206\110\206\367\022\001\002\001\004"}, - { 6, "\053\006\001\005\006\004"}, - { 6, "\053\006\001\005\006\002"}, + /* + * 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. + */ + + /* + * 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. + */ + + /* + * 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. + */ + + /* + * 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 + */ + + /* + * 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. + */ + + /* + * 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. + */ + + /* + * 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. + */ }; -GSS_DLLIMP gss_OID gss_nt_user_name = oids+0; -GSS_DLLIMP gss_OID gss_nt_machine_uid_name = oids+1; -GSS_DLLIMP gss_OID gss_nt_string_uid_name = oids+2; -GSS_DLLIMP gss_OID gss_nt_service_name = oids+3; -GSS_DLLIMP gss_OID gss_nt_exported_name = oids+4; -GSS_DLLIMP gss_OID gss_nt_service_name_v2 = oids+5; +/* Here are the constants which point to the static structure above. + * + * Constants of the form GSS_C_NT_* are specified by rfc 2744. + * + * Constants of the form gss_nt_* are the original MIT krb5 names + * found in gssapi_generic.h. They are provided for compatibility. */ + +#if GSS_RFC_COMPLIANT_OIDS +GSS_DLLIMP gss_OID GSS_C_NT_USER_NAME = oids+0; +GSS_DLLIMP gss_OID GSS_C_NT_MACHINE_UID_NAME = oids+1; +GSS_DLLIMP gss_OID GSS_C_NT_STRING_UID_NAME = oids+2; +GSS_DLLIMP gss_OID GSS_C_NT_HOSTBASED_SERVICE_X = oids+3; +GSS_DLLIMP gss_OID GSS_C_NT_HOSTBASED_SERVICE = oids+4; +GSS_DLLIMP gss_OID GSS_C_NT_ANONYMOUS = oids+5; +GSS_DLLIMP gss_OID GSS_C_NT_EXPORT_NAME = oids+6; +#endif /* GSS_RFC_COMPLIANT_OIDS */ + +GSS_DLLIMP gss_OID gss_nt_user_name = oids+0; +GSS_DLLIMP gss_OID gss_nt_machine_uid_name = oids+1; +GSS_DLLIMP gss_OID gss_nt_string_uid_name = oids+2; +GSS_DLLIMP gss_OID gss_nt_service_name_v2 = oids+3; +GSS_DLLIMP gss_OID gss_nt_service_name = oids+4; +GSS_DLLIMP gss_OID gss_nt_exported_name = oids+6; diff --git a/src/lib/gssapi/generic/gssapi_generic.h b/src/lib/gssapi/generic/gssapi_generic.h index 8317cad..af85b7c 100644 --- a/src/lib/gssapi/generic/gssapi_generic.h +++ b/src/lib/gssapi/generic/gssapi_generic.h @@ -27,17 +27,21 @@ * $Id$ */ -#if defined(__MWERKS__) || defined(applec) || defined(THINK_C) -#include <gssapi.h> +#if defined(macintosh) || (defined(__MACH__) && defined(__APPLE__)) +#include <GSS/gssapi.h> #else #include <gssapi/gssapi.h> #endif +/* Deprecated MIT krb5 oid names provided for compatibility. + * The correct oids (GSS_C_NT_USER_NAME, etc) from rfc 2744 + * are defined in gssapi.h. */ + GSS_DLLIMP extern gss_OID gss_nt_user_name; GSS_DLLIMP extern gss_OID gss_nt_machine_uid_name; GSS_DLLIMP extern gss_OID gss_nt_string_uid_name; +GSS_DLLIMP extern gss_OID gss_nt_service_name_v2; GSS_DLLIMP extern gss_OID gss_nt_service_name; GSS_DLLIMP extern gss_OID gss_nt_exported_name; -GSS_DLLIMP extern gss_OID gss_nt_service_name_v2; #endif /* _GSSAPI_GENERIC_H_ */ diff --git a/src/lib/gssapi/krb5/3des.txt b/src/lib/gssapi/krb5/3des.txt new file mode 100644 index 0000000..f39c6fc --- /dev/null +++ b/src/lib/gssapi/krb5/3des.txt @@ -0,0 +1,274 @@ +CAT Working Group K. Raeburn +Internet-draft MIT +Category: June xx, 2000 +Updates: RFC 1964 +Document: draft-raeburn-gssapi-krb5-3des-XX.txt + + Triple-DES Support for the Kerberos 5 GSSAPI Mechanism + +Status of this Memo + + This document is an Internet-Draft and is in full conformance with + all provisions of Section 10 of RFC2026 [1]. Internet-Drafts are + working documents of the Internet Engineering Task Force (IETF), + its areas, and its working groups. Note that other groups may also + distribute working documents as Internet-Drafts. Internet-Drafts + are draft documents valid for a maximum of six months and may be + updated, replaced, or obsoleted by other documents at any time. It + is inappropriate to use Internet-Drafts as reference material or to + cite them other than as "work in progress." + + The list of current Internet-Drafts can be accessed at + http://www.ietf.org/ietf/1id-abstracts.txt + + The list of Internet-Draft Shadow Directories can be accessed at + http://www.ietf.org/shadow.html. + +1. Abstract + + The MIT Kerberos 5 release version 1.2 includes support for + triple-DES with key derivation [KrbRev]. Recent work by the EFF + [EFF] has demonstrated the vulnerability of single-DES mechanisms + to brute-force attacks by sufficiently motivated and well-funded + parties. + + The GSSAPI Kerberos 5 mechanism definition [GSSAPI-KRB5] + specifically enumerates encryption and checksum types, + independently of how such schemes may be used in Kerberos. In the + long run, a new Kerberos-based mechanism, which does not require + separately enumerating for the GSSAPI mechanism each of the various + encryption types defined by Kerberos, is a better approach. + Efforts to produce such a specification are under way. + + In the interest of providing increased security in the near term, + however, MIT is adding support for triple-DES to the existing + mechanism implementation we ship, as described here. + +2. New Algorithm Identifiers + + One new sealing algorithm is defined, for use in WRAP tokens: + + 02 00 - DES3-KD + + This algorithm uses triple-DES with key derivation, with a usage + value KG_USAGE_SEAL. Padding is still to 8-byte multiples, and the + IV for encrypting application data is zero. + + One new signing algorithm is defined, for use in MIC, Wrap, and + Delete tokens: + + 04 00 - HMAC SHA1 DES3-KD + + This algorithm generates an HMAC using SHA-1 and a derived DES3 key + with usage KG_USAGE_SIGN, as (should be described) in [KrbRev]. + [XXX: The current [KrbRev] description refers to out-of-date I-Ds + from Marc Horowitz. The text in [KrbRev] may be inadequate to + produce an interoperable implementation.] + + The checksum size for this algorithm is 20 octets. See section 4.3 + below for the use of checksum lengths of other than eight bytes. + +3. Key Derivation + + For purposes of key derivation, we add three new usage values to the + list defined in [KrbRev]; one for signing messages, one for + sealing messages, and one for encrypting sequence numbers: + + #define KG_USAGE_SEAL 22 + #define KG_USAGE_SIGN 23 + #define KG_USAGE_SEQ 24 + +4. Adjustments to Previous Definitions + +4.1. Quality of Protection + + The GSSAPI specification [GSSAPI] says that a zero QOP value + indicates the "default". The original specification for the + Kerberos 5 mechanism says that a zero QOP value (or a QOP value + with the appropriate bits clear) means DES encryption. + + Rather than continue to force the use of plain DES when the + application doesn't use mechanism-specific QOP values, the better + choice appears to be to redefine the DES QOP value as some non-zero + value, and define a triple-DES value as well. Then a zero value + continues to imply the default, which would be triple-DES + protection when given a triple-DES session key. + + Our values are: + + GSS_KRB5_INTEG_C_QOP_HMAC_SHA1 0x0004 + /* SHA-1 checksum encrypted with key derivation */ + + GSS_KRB5_CONF_C_QOP_DES 0x0100 + /* plain DES encryption */ + GSS_KRB5_CONF_C_QOP_DES3_KD 0x0200 + /* triple-DES with key derivation */ + + Rather than open the question of whether to specify means for + deriving a key of one type given a key of another type, and the + security implications of whether to generate a long key from a + shorter one, our implementation will simply return an error if the + QOP value specified does not correspond to the session key type. + + [XXX: Not implemented yet. Currently an error is reported for all + non-zero values. This should be changed before the release, so an + application can insist on getting no less than triple-DES + protection.] + +4.2. MIC Sequence Number Encryption + + The sequence numbers are encrypted in the context key (as defined + in [GSSAPI-KRB5] -- this will be either the Kerberos session key or + asubkey provided by the context initiator), using whatever + encryption system is designated by the type of that context key. + The IV is formed from the first N bytes of the SGN_CKSUM field, + where N is the number of bytes needed for the IV. (With all + algorithms described here and in [GSSAPI-KRB5], the checksum is at + least as large as the IV.) + +4.3. Message Layout + + Both MIC and Wrap tokens, as defined in [GSSAPI-KRB5], contain an + checksum field SGN_CKSUM. In [GSSAPI-KRB5], this field was + specified as being 8 bytes long. We now change this size to be + "defined by the checksum algorithm", and retroactively amend the + descriptions of all the checksum algorithms described in + [GSSAPI-KRB5] to explicitly specify 8-byte output. Application + data continues to immediately follow the checksum field in the Wrap + token. + + The revised message descriptions are thus: + + MIC: + + Byte no Name Description + 0..1 TOK_ID Identification field. + 2..3 SGN_ALG Integrity algorithm indicator. + 4..7 Filler Contains ff ff ff ff + 8..15 SND_SEQ Sequence number field. + 16..s+15 SGN_CKSUM Checksum of "to-be-signed data", + calculated according to algorithm + specified in SGN_ALG field. + + Wrap: + + Byte no Name Description + 0..1 TOK_ID Identification field. + Tokens emitted by GSS_Wrap() contain + the hex value 02 01 in this field. + 2..3 SGN_ALG Checksum algorithm indicator. + 4..5 SEAL_ALG Sealing algorithm indicator. + 6..7 Filler Contains ff ff + 8..15 SND_SEQ Encrypted sequence number field. + 16..s+15 SGN_CKSUM Checksum of plaintext padded data, + calculated according to algorithm + specified in SGN_ALG field. + s+16..last Data encrypted or plaintext padded data + + Where "s" indicates the size of the checksum. + + As indicated above in section 2, we define the HMAC SHA1 DES3-KD + checksum algorithm to produce a 20-byte output, so encrypted data + begins at byte 36. + +5. Backwards Compatibility Considerations + + The context initiator should request of the KDC credentials using + session-key cryptosystem types supported by that implementation; if + the only types returned by the KDC are not supported by the + mechanism implementation, it should indicate a failure. This may + seem obvious, but early implementations of both Kerberos and the + GSSAPI Kerberos mechanism supported only DES keys, so the + cryptosystem compatibility question was easy to overlook. + + Under the current mechanism, no negotiation of algorithm types + occurs, so server-side (acceptor) implementations cannot request + that clients not use algorithm types not understood by the server. + However, administration of the server's Kerberos data has to be + done in communication with the KDC, and it is from the KDC that the + client will request credentials. The KDC could therefore be tasked + with limiting session keys for a given service to types actually + supported by the Kerberos and GSSAPI software on the server. + + This does have a drawback for cases where a service principal name + is used both for GSSAPI-based and non-GSSAPI-based communication, + if the GSSAPI implementation does not understand triple-DES but the + Kerberos implementation does. It means that triple-DES session + keys cannot be issued for that service principal, which keeps the + protection of non-GSSAPI services weaker than necessary. However, + in the most recent MIT releases thus far, while triple-DES support + has been present, it has required additional work to enable, so it + should not be in use for many services. + + It would also be possible to have clients attempt to get single-DES + session keys before trying to get triple-DES session keys, and have + the KDC refuse to issue the single-DES keys only for the most + critical of services, for which single-DES protection is considered + inadequate. However, that would eliminate the possibility of + connecting with the more secure cryptosystem to any service that + can be accessed with the weaker cryptosystem. + + We have chosen to go with the former approach, putting the burden + on the KDC administration and gaining the best protection possible + for GSSAPI services, possibly at the cost of protection of + non-GSSAPI Kerberos services running earlier versions of the + software. + [XXX: Actually, we haven't entirely decided and cast it in stone + yet, it's just what I've implemented; it's easy to change.] + +6. Security Considerations + + Various tradeoffs arise regarding the mixing of new and old + software, or GSSAPI-based and non-GSSAPI Kerberos authentication. + They are discussed in section 4. + +7. References + + [EFF] Electronic Frontier Foundation, "Cracking DES: Secrets of + Encryption Research, Wiretap Politics, and Chip Design", O'Reilly & + Associates, Inc., May, 1998. + + [GSSAPI] Linn, J., "Generic Security Service Application Program + Interface Version 2, Update 1", RFC 2743, January, 2000. + + [GSSAPI-KRB5] Linn, J., "The Kerberos Version 5 GSS-API Mechanism", + RFC 1964, June, 1996. + + [KrbRev] Neuman, C., Kohl, J., Ts'o, T., "The Kerberos Network + Authentication Service (V5)", + draft-ietf-cat-kerberos-revisions-05.txt, March 10, 2000. + +8. Author's Address + + Kenneth Raeburn + Massachusetts Institute of Technology + 77 Massachusetts Avenue + Cambridge, MA 02139 + +9. Full Copyright Statement + + Copyright (C) The Internet Society (2000). All Rights Reserved. + + This document and translations of it may be copied and furnished to + others, and derivative works that comment on or otherwise explain it + or assist in its implementation may be prepared, copied, published + and distributed, in whole or in part, without restriction of any + kind, provided that the above copyright notice and this paragraph + are included on all such copies and derivative works. However, this + document itself may not be modified in any way, such as by removing + the copyright notice or references to the Internet Society or other + Internet organizations, except as needed for the purpose of + developing Internet standards in which case the procedures for + copyrights defined in the Internet Standards process must be + followed, or as required to translate it into languages other than + English. + + The limited permissions granted above are perpetual and will not be + revoked by the Internet Society or its successors or assigns. + + This document and the information contained herein is provided on an + "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING + TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING + BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION + HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF + MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE." diff --git a/src/lib/gssapi/krb5/ChangeLog b/src/lib/gssapi/krb5/ChangeLog index 06639d4..3bffb7c 100644 --- a/src/lib/gssapi/krb5/ChangeLog +++ b/src/lib/gssapi/krb5/ChangeLog @@ -1,4 +1,152 @@ -2000-01-27 Ken Raeburn <raeburn@raeburn.org> +2001-10-29 Miro Jurisic <meeroh@mit.edu> + * pullup from krb5-1-2 branch after krb5-1-2-2-bp + * add_cred.c (krb5_gss_add_cred): Added constness to some char*s to make + them compiler with strict compilers. + * gssapi_krb5.h, gssapi_krb5.c: Added oids from rfc 1964 using the + suggested names. + * gssapi_krb5.h: Added #include of KerberosSupport.h in case this header + is included by itself. + * disp-status.c, gssapiP_krb5.h, gssapi_krb5.h: Updated Mac OS #defines + and #includes for new header layout and Mac OS X frameworks + +2001-10-04 Tom Yu <tlyu@mit.edu> + + * accept_sec_context.c (krb5_gss_accept_sec_context): Ignore + unrecognized options properly. [krb5-libs/738] + +2001-10-01 Tom Yu <tlyu@mit.edu> + + * accept_sec_context.c (rd_and_store_for_creds): Handle error + returns from krb5_rd_cred more sanely. + +2001-01-30 Ezra Peisach <epeisach@mit.edu> + + * accept_sec_context.c (krb5_gss_accept_sec_context): If an error + occurs after the auth_context is established, but before the + krb5_gss_ctx_id_rec is established, release our pointer to the + replay cache and invoke krb5_auth_con_free(). [krb5-libs/855] + +2000-09-19 Miro Jurisic <meeroh@mit.edu> + + * accept_sec_context.c (krb5_gss_accept_sec_context) + * acquire_cred.c (krb5_gss_acquire_cred) + * import_sec_context.c (krb5_gss_convert_static_mech_oid) + * init_sec_context.c (krb5_gss_init_sec_context) + * inq_cred.c (krb5_gss_inquire_cred) + Cast away constness from gss_OID where necessary to compile + with strict compilers + +2000-06-27 Tom Yu <tlyu@mit.edu> + + * init_sec_context.c (get_credentials): Add initial iteration of + krb5_get_credentials in order to differentiate between an actual + missing credential and merely a bad match based on enctype. This + was causing problems with kadmin. + +2000-06-09 Tom Yu <tlyu@mit.edu> + + * init_sec_context.c (get_credentials): The KDC as well as the + ccache may indicate that an enctype is not supported; reflect that + in the loop breakout condition. + +2000-06-07 Tom Yu <tlyu@mit.edu> + + * init_sec_context.c (get_credentials): Rework the enctype loop + again. + + * accept_sec_context.c (krb5_gss_accept_sec_context): Remove + explicit check of mech OID against credential. + +2000-06-04 Tom Yu <tlyu@mit.edu> + + * init_sec_context.c (get_credentials): Reverse sense of test; + break out of enctype loop if one succeeds. + +2000-06-03 Tom Yu <tlyu@mit.edu> + + * util_crypt.c (kg_encrypt): Copy ivec, since c_encrypt() now + updates ivecs. + (kg_decrypt): Copy ivec, since c_decrypt() now updates ivecs. + +2000-06-02 Ken Raeburn <raeburn@mit.edu> + + * init_sec_context.c (get_credentials): Don't check each enctype + against a list from the krb5 library; instead, just try to use it, + and go on to the next if the error code indicates we can't use it. + +2000-05-31 Ken Raeburn <raeburn@mit.edu> + + * gssapiP_krb5.h (KG_USAGE_SEQ): New value. + (enum qop): New type, derived from spec but currently not used. + * util_crypt.c (kg_encrypt, kg_decrypt): Added key derivation + usage value as an argument. Prototypes and callers updated; all + callers use KG_USAGE_SEAL, except KG_USAGE_SEQ when encrypting + sequence numbers. + * 3des.txt: New file. + +2000-5-19 Alexandra Ellwood <lxs@mit.edu> + + * acquire_cred.c: Changed to use krb5int_cc_default. This function + supports the Kerberos Login Library and pops up a dialog if the cache does + not contain valid tickets. This is used to automatically get a tgt before + obtaining service tickets. Note that this should be an internal function + because callers don't expect krb5_cc_default to pop up a dialog! + (We found this out the hard way :-) + +2000-05-03 Nalin Dahyabhai <nalin@redhat.com> + + * add_cred.c (krb5_gss_add_cred): Don't overflow buffers "ktboth" + or "ccboth". + +2000-04-21 Ken Raeburn <raeburn@mit.edu> + + * gssapiP_krb5.h (struct _krb5_gss_ctx_id_rec): Delete field + gsskrb5_version. + (struct _krb5_gss_cred_id_rec): Delete field rfcv2_mech. + * accept_sec_context.c, acquire_cred.c, add_cred.c, inq_cred.c, + k5seal.c, k5unseal.c, ser_ctx.c: + Delete krb5-mech2 support. + + * init_sec_context.c (get_credentials): Enctype argument is now a + pointer to a list of enctypes. Explicitly try each in order until + success or an error other than cryptosystem not being supported. + (krb5_gss_init_sec_context): Pass list of cryptosystems, starting + with 3DES. + + * gssapiP_krb5.h (enum sgn_alg, enum seal_alg): New types, + giving symbolic names for values from RFC 1964, a Microsoft win2k + I-D, and our proposed 3des-sha1 values. + (KG_USAGE_SEAL, KG_USAGE_SIGN): New macros. + + * accept_sec_context.c (rd_req_keyproc): Already-disabled routine + deleted. + (krb5_gss_accept_sec_context): Use sgn_alg and seal_alg symbolic + names. Add a case for des3-hmac-sha1. + * k5seal.c (make_seal_token_v1): Likewise. Do key derivation for + checksums. + * k5unseal.c (kg_unseal_v1): Likewise. + * util_crypt.c (kg_encrypt, kg_decrypt): Do key derivation for + encryption. + + * util_crypt.c (zeros): Unused variable deleted. + +2000-04-18 Ken Raeburn <raeburn@mit.edu> + + * wrap_size_limit.c: Remove mech2 support. Add MIT copyright. + +2000-04-08 Tom Yu <tlyu@mit.edu> + + * wrap_size_limit.c (krb5_gss_wrap_size_limit): Fix up + wrap_size_limit() to deal with integrity wrap tokens properly. + The rfc1964 mech always pads and confounds regardless of whether + confidentiality is requested. + +2000-03-20 Ken Raeburn <raeburn@mit.edu> + + * accept_sec_context.c, init_sec_context.c: Disable krb5-mech2 + stuff for now. (Tom Yu's krb5-1.1 patch.) + +2000-01-27 Ken Raeburn <raeburn@mit.edu> * init_sec_context.c (krb5_gss_init_sec_context): Default to des-cbc-crc. diff --git a/src/lib/gssapi/krb5/accept_sec_context.c b/src/lib/gssapi/krb5/accept_sec_context.c index fc920ec..ba2d96a 100644 --- a/src/lib/gssapi/krb5/accept_sec_context.c +++ b/src/lib/gssapi/krb5/accept_sec_context.c @@ -1,4 +1,28 @@ /* + * Copyright 2000 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + * + */ +/* * Copyright 1993 by OpenVision Technologies, Inc. * * Permission to use, copy, modify, distribute, and sell this software @@ -49,39 +73,12 @@ #include "k5-int.h" #include "gssapiP_krb5.h" #include <memory.h> +#include <assert.h> /* * $Id$ */ -#if 0 - -/* XXXX This widen/narrow stuff is bletcherous, but it seems to be - necessary. Perhaps there is a "better" way, but I don't know what it - is */ - -#include <krb5/widen.h> -static krb5_error_code -rd_req_keyproc(krb5_pointer keyprocarg, krb5_principal server, - krb5_kvno kvno, krb5_keyblock **keyblock) -#include <krb5/narrow.h> -{ - krb5_error_code code; - krb5_keytab_entry ktentry; - - if (code = krb5_kt_get_entry((krb5_keytab) keyprocarg, server, kvno, - &ktentry)) - return(code); - - code = krb5_copy_keyblock(&ktentry.key, keyblock); - - (void) krb5_kt_free_entry(&ktentry); - - return(code); -} - -#endif - /* Decode, decrypt and store the forwarded creds in the local ccache. */ static krb5_error_code rd_and_store_for_creds(context, inbuf, out_cred) @@ -89,9 +86,9 @@ rd_and_store_for_creds(context, inbuf, out_cred) krb5_data *inbuf; krb5_gss_cred_id_t *out_cred; { - krb5_creds ** creds; + krb5_creds ** creds = NULL; krb5_error_code retval; - krb5_ccache ccache; + krb5_ccache ccache = NULL; krb5_gss_cred_id_t cred = NULL; extern krb5_cc_ops krb5_mcc_ops; krb5_auth_context auth_context = NULL; @@ -145,7 +142,6 @@ rd_and_store_for_creds(context, inbuf, out_cred) /* cred->princ already set */ cred->prerfc_mech = 1; /* this cred will work with all three mechs */ cred->rfc_mech = 1; - cred->rfcv2_mech = 1; cred->keytab = NULL; /* no keytab associated with this... */ cred->ccache = ccache; /* but there is a credential cache */ cred->tgt_expire = creds[0]->times.endtime; /* store the end time */ @@ -157,7 +153,8 @@ rd_and_store_for_creds(context, inbuf, out_cred) goto cleanup; */ cleanup: - krb5_free_tgt_creds(context, creds); + if (creds) + krb5_free_tgt_creds(context, creds); if (!cred && ccache) (void)krb5_cc_close(context, ccache); @@ -206,11 +203,10 @@ krb5_gss_accept_sec_context(minor_status, context_handle, krb5_ui_4 gss_flags = 0; int decode_req_message = 0; krb5_gss_ctx_id_rec *ctx = 0; -#if 0 krb5_enctype enctype; -#endif krb5_timestamp now; gss_buffer_desc token; + int err; krb5_auth_context auth_context = NULL; krb5_ticket * ticket = NULL; int option_id; @@ -222,7 +218,6 @@ krb5_gss_accept_sec_context(minor_status, context_handle, gss_cred_id_t cred_handle = NULL; krb5_gss_cred_id_t deleg_cred = NULL; int token_length; - int gsskrb5_vers; int nctypes; krb5_cksumtype *ctypes = 0; struct kg2_option fwcred; @@ -296,13 +291,7 @@ krb5_gss_accept_sec_context(minor_status, context_handle, &(ap_req.length), &ptr, KG_TOK_CTX_AP_REQ, input_token->length))) { - if (! cred->rfc_mech) { - code = G_WRONG_MECH; - major_status = GSS_S_DEFECTIVE_TOKEN; - goto fail; - } mech_used = gss_mech_krb5; - gsskrb5_vers = 1000; } else if ((code == G_WRONG_MECH) && !(code = g_verify_token_header((gss_OID) gss_mech_krb5_old, &(ap_req.length), @@ -315,56 +304,15 @@ krb5_gss_accept_sec_context(minor_status, context_handle, * compatibility, and use it to decide when to use the * old behavior. */ - if (! cred->prerfc_mech) { - code = G_WRONG_MECH; - major_status = GSS_S_DEFECTIVE_TOKEN; - goto fail; - } mech_used = gss_mech_krb5_old; - gsskrb5_vers = 1000; - } else if ((code == G_WRONG_MECH) && - !(code = g_verify_token_header((gss_OID) gss_mech_krb5_v2, - &token_length, - &ptr, KG2_TOK_INITIAL, - input_token->length))) { - if (! cred->rfcv2_mech) { - code = G_WRONG_MECH; - major_status = GSS_S_DEFECTIVE_TOKEN; - goto fail; - } - mech_used = gss_mech_krb5_v2; - gsskrb5_vers = 2000; } else { major_status = GSS_S_DEFECTIVE_TOKEN; goto fail; } - if (gsskrb5_vers == 2000) { - /* gss krb5 v2 */ - - fwcred.option_id = KRB5_GSS_FOR_CREDS_OPTION; - fwcred.data = NULL; - - if (GSS_ERROR(major_status = - kg2_parse_token(&code, ptr, token_length, - &gss_flags, &nctypes, &ctypes, - delegated_cred_handle?1:0, - &fwcred, &ap_req, NULL))) { - goto fail; - } - - gss_flags = (ptr[0]<<24) | (ptr[1]<<16) | (ptr[2]<<8) | ptr[3]; - - gss_flags &= ~GSS_C_DELEG_FLAG; /* mask out the delegation flag; - if there's a delegation, we'll - set it below */ - } else { - /* gss krb5 v1 */ - - sptr = (char *) ptr; - TREAD_STR(sptr, ap_req.data, ap_req.length); - decode_req_message = 1; - } + sptr = (char *) ptr; + TREAD_STR(sptr, ap_req.data, ap_req.length); + decode_req_message = 1; /* construct the sender_addr */ @@ -416,9 +364,7 @@ krb5_gss_accept_sec_context(minor_status, context_handle, } #endif - if (gsskrb5_vers == 2000) { - bigend = 1; - } else { + { /* gss krb5 v1 */ /* stash this now, for later. */ @@ -502,21 +448,31 @@ krb5_gss_accept_sec_context(minor_status, context_handle, i = authdat->checksum->length - 24; - while(i>0) { + while (i >= 4) { TREAD_INT16(ptr, option_id, bigend); - switch(option_id) { + TREAD_INT16(ptr, option.length, bigend); - case KRB5_GSS_FOR_CREDS_OPTION: + i -= 4; + + /* have to use ptr2, since option.data is wrong type and + macro uses ptr as both lvalue and rvalue */ - TREAD_INT16(ptr, option.length, bigend); + if (i < option.length || option.length < 0) { + code = KG_BAD_LENGTH; + major_status = GSS_S_FAILURE; + goto fail; + } + + TREAD_STR(ptr, ptr2, bigend); + option.data = (char FAR *) ptr2; - /* have to use ptr2, since option.data is wrong type and - macro uses ptr as both lvalue and rvalue */ + i -= option.length; - TREAD_STR(ptr, ptr2, bigend); - option.data = (char FAR *) ptr2; + switch(option_id) { + + case KRB5_GSS_FOR_CREDS_OPTION: /* store the delegated credential */ @@ -527,8 +483,6 @@ krb5_gss_accept_sec_context(minor_status, context_handle, goto fail; } - i -= option.length + 4; - gss_flags |= GSS_C_DELEG_FLAG; /* got a delegation */ break; @@ -551,13 +505,12 @@ krb5_gss_accept_sec_context(minor_status, context_handle, } memset(ctx, 0, sizeof(krb5_gss_ctx_id_rec)); - ctx->mech_used = mech_used; + ctx->mech_used = (gss_OID) mech_used; ctx->auth_context = auth_context; ctx->initiate = 0; ctx->gss_flags = KG_IMPLFLAGS(gss_flags); ctx->seed_init = 0; ctx->big_endian = bigend; - ctx->gsskrb5_version = gsskrb5_vers; /* Intern the ctx pointer so that delete_sec_context works */ if (! kg_save_ctx_id((gss_ctx_id_t) ctx)) { @@ -603,114 +556,37 @@ krb5_gss_accept_sec_context(minor_status, context_handle, goto fail; } - if (gsskrb5_vers == 2000) { - int cblen; - krb5_boolean valid; - - /* intersect the token ctypes with the local ctypes */ - - if (code = krb5_c_keyed_checksum_types(context, ctx->subkey->enctype, - &ctx->nctypes, &ctx->ctypes)) - goto fail; - - if (nctypes == 0) { - code = KRB5_CRYPTO_INTERNAL; - goto fail; - } - - kg2_intersect_ctypes(&ctx->nctypes, ctx->ctypes, nctypes, ctypes); - - if (nctypes == 0) { - code = KG_NO_CTYPES; - goto fail; - } - - /* process the delegated cred, if any */ - - if (fwcred.data) { - krb5_data option; - - option.length = fwcred.length; - option.data = fwcred.data; - - if (code = rd_and_store_for_creds(context, &option, &deleg_cred)) { - major_status = GSS_S_FAILURE; - goto fail; - } - - gss_flags |= GSS_C_DELEG_FLAG; /* got a delegation */ - } + switch(ctx->subkey->enctype) { + case ENCTYPE_DES_CBC_MD5: + case ENCTYPE_DES_CBC_CRC: + ctx->subkey->enctype = ENCTYPE_DES_CBC_RAW; + ctx->signalg = SGN_ALG_DES_MAC_MD5; + ctx->cksum_size = 8; + ctx->sealalg = SEAL_ALG_DES; - /* construct the checksum buffer */ - - cblen = 4*5; - if (input_chan_bindings) - cblen += (input_chan_bindings->initiator_address.length+ - input_chan_bindings->acceptor_address.length+ - input_chan_bindings->application_data.length); - - cksumdata.length = cblen + ((char *)(ap_req.data-2) - (char *)(ptr-2)); + /* fill in the encryption descriptors */ - if ((cksumdata.data = (char *) malloc(cksumdata.length)) == NULL) { - code = ENOMEM; + if ((code = krb5_copy_keyblock(context, ctx->subkey, &ctx->enc))) { major_status = GSS_S_FAILURE; goto fail; } - ptr2 = cksumdata.data; - - if (input_chan_bindings) { - TWRITE_INT(ptr2, input_chan_bindings->initiator_addrtype, 1); - TWRITE_BUF(ptr2, input_chan_bindings->initiator_address, 1); - TWRITE_INT(ptr2, input_chan_bindings->acceptor_addrtype, 1); - TWRITE_BUF(ptr2, input_chan_bindings->acceptor_address, 1); - TWRITE_BUF(ptr2, input_chan_bindings->application_data, 1); - } else { - memset(ptr2, 0, cblen); - ptr2 += cblen; - } - - memcpy(ptr2, ptr-2, ((char *)(ap_req.data-2) - (char *)(ptr-2))); + for (i=0; i<ctx->enc->length; i++) + /*SUPPRESS 113*/ + ctx->enc->contents[i] ^= 0xf0; - if (code = krb5_c_verify_checksum(context, ctx->subkey, - KRB5_KEYUSAGE_AP_REQ_AUTH_CKSUM, - &cksumdata, authdat->checksum, - &valid)) { + if ((code = krb5_copy_keyblock(context, ctx->subkey, &ctx->seq))) { major_status = GSS_S_FAILURE; goto fail; } - free(cksumdata.data); - cksumdata.data = 0; - - if (!valid) { - code = 0; - major_status = GSS_S_BAD_SIG; - goto fail; - } - } else { - /* gss krb5 v1 */ + break; - switch(ctx->subkey->enctype) { - case ENCTYPE_DES_CBC_MD5: - case ENCTYPE_DES_CBC_CRC: - ctx->subkey->enctype = ENCTYPE_DES_CBC_RAW; - ctx->signalg = 0; - ctx->cksum_size = 8; - ctx->sealalg = 0; - break; -#if 0 - case ENCTYPE_DES3_CBC_MD5: - enctype = ENCTYPE_DES3_CBC_RAW; - ctx->signalg = 3; - ctx->cksum_size = 16; - ctx->sealalg = 1; - break; -#endif - default: - code = KRB5_BAD_ENCTYPE; - goto fail; - } + case ENCTYPE_DES3_CBC_SHA1: + ctx->subkey->enctype = ENCTYPE_DES3_CBC_RAW; + ctx->signalg = SGN_ALG_HMAC_SHA1_DES3_KD; + ctx->cksum_size = 20; + ctx->sealalg = SEAL_ALG_DES3KD; /* fill in the encryption descriptors */ @@ -719,14 +595,16 @@ krb5_gss_accept_sec_context(minor_status, context_handle, goto fail; } - for (i=0; i<ctx->enc->length; i++) - /*SUPPRESS 113*/ - ctx->enc->contents[i] ^= 0xf0; - if ((code = krb5_copy_keyblock(context, ctx->subkey, &ctx->seq))) { major_status = GSS_S_FAILURE; goto fail; } + + break; + + default: + code = KRB5_BAD_ENCTYPE; + goto fail; } ctx->endtime = ticket->enc_part2->times.endtime; @@ -769,122 +647,22 @@ krb5_gss_accept_sec_context(minor_status, context_handle, /* the reply token hasn't been sent yet, but that's ok. */ ctx->established = 1; - if (ctx->gsskrb5_version == 2000) { - krb5_ui_4 tok_flags; - - tok_flags = - (ctx->gss_flags & GSS_C_DELEG_FLAG)?KG2_RESP_FLAG_DELEG_OK:0; - - cksumdata.length = 8 + 4*ctx->nctypes + 4; - - if ((cksumdata.data = (char *) malloc(cksumdata.length)) == NULL) { - code = ENOMEM; - major_status = GSS_S_FAILURE; - goto fail; - } - - /* construct the token fields */ - - ptr = cksumdata.data; - - ptr[0] = (KG2_TOK_RESPONSE >> 8) & 0xff; - ptr[1] = KG2_TOK_RESPONSE & 0xff; - - ptr[2] = (tok_flags >> 24) & 0xff; - ptr[3] = (tok_flags >> 16) & 0xff; - ptr[4] = (tok_flags >> 8) & 0xff; - ptr[5] = tok_flags & 0xff; - - ptr[6] = (ctx->nctypes >> 8) & 0xff; - ptr[7] = ctx->nctypes & 0xff; - - ptr += 8; - - for (i=0; i<ctx->nctypes; i++) { - ptr[i] = (ctx->ctypes[i] >> 24) & 0xff; - ptr[i+1] = (ctx->ctypes[i] >> 16) & 0xff; - ptr[i+2] = (ctx->ctypes[i] >> 8) & 0xff; - ptr[i+3] = ctx->ctypes[i] & 0xff; - - ptr += 4; - } - - memset(ptr, 0, 4); - - /* make the MIC token */ + token.length = g_token_size((gss_OID) mech_used, ap_rep.length); - { - gss_buffer_desc text, token; - - text.length = cksumdata.length; - text.value = cksumdata.data; - - /* ctx->seq_send must be set before this call */ - - if (GSS_ERROR(major_status = - krb5_gss_get_mic(&code, ctx, - GSS_C_QOP_DEFAULT, - &text, &token))) - goto fail; - - mic.length = token.length; - mic.data = token.value; - } - - token.length = g_token_size((gss_OID) mech_used, - (cksumdata.length-2)+4+ap_rep.length+ - mic.length); - - if ((token.value = (unsigned char *) xmalloc(token.length)) - == NULL) { - code = ENOMEM; - major_status = GSS_S_FAILURE; - goto fail; - } - ptr = token.value; - g_make_token_header((gss_OID) mech_used, - (cksumdata.length-2)+4+ap_rep.length+mic.length, - &ptr, KG2_TOK_RESPONSE); - - memcpy(ptr, cksumdata.data+2, cksumdata.length-2); - ptr += cksumdata.length-2; - - ptr[0] = (ap_rep.length >> 8) & 0xff; - ptr[1] = ap_rep.length & 0xff; - memcpy(ptr+2, ap_rep.data, ap_rep.length); - - ptr += (2+ap_rep.length); - - ptr[0] = (mic.length >> 8) & 0xff; - ptr[1] = mic.length & 0xff; - memcpy(ptr+2, mic.data, mic.length); - - ptr += (2+mic.length); - - free(cksumdata.data); - cksumdata.data = 0; - - /* gss krb5 v2 */ - } else { - /* gss krb5 v1 */ - - token.length = g_token_size((gss_OID) mech_used, ap_rep.length); - - if ((token.value = (unsigned char *) xmalloc(token.length)) - == NULL) { - major_status = GSS_S_FAILURE; - code = ENOMEM; - goto fail; - } - ptr = token.value; - g_make_token_header((gss_OID) mech_used, ap_rep.length, - &ptr, KG_TOK_CTX_AP_REP); + if ((token.value = (unsigned char *) xmalloc(token.length)) + == NULL) { + major_status = GSS_S_FAILURE; + code = ENOMEM; + goto fail; + } + ptr = token.value; + g_make_token_header((gss_OID) mech_used, ap_rep.length, + &ptr, KG_TOK_CTX_AP_REP); - TWRITE_STR(ptr, ap_rep.data, ap_rep.length); + TWRITE_STR(ptr, ap_rep.data, ap_rep.length); - ctx->established = 1; + ctx->established = 1; - } } else { token.length = 0; token.value = NULL; @@ -943,6 +721,11 @@ krb5_gss_accept_sec_context(minor_status, context_handle, free(ctypes); if (authdat) krb5_free_authenticator(context, authdat); + /* The ctx structure has the handle of the auth_context */ + if (auth_context && !ctx) { + (void)krb5_auth_con_setrcache(context, auth_context, NULL); + krb5_auth_con_free(context, auth_context); + } if (reqcksum.contents) xfree(reqcksum.contents); if (ap_rep.data) @@ -1014,13 +797,8 @@ krb5_gss_accept_sec_context(minor_status, context_handle, if (code) return (major_status); - if (gsskrb5_vers == 2000) { - tmsglen = 12+scratch.length; - toktype = KG2_TOK_RESPONSE; - } else { - tmsglen = scratch.length; - toktype = KG_TOK_CTX_ERROR; - } + tmsglen = scratch.length; + toktype = KG_TOK_CTX_ERROR; token.length = g_token_size((gss_OID) mech_used, tmsglen); token.value = (unsigned char *) xmalloc(token.length); @@ -1030,24 +808,6 @@ krb5_gss_accept_sec_context(minor_status, context_handle, ptr = token.value; g_make_token_header((gss_OID) mech_used, tmsglen, &ptr, toktype); - if (gsskrb5_vers == 2000) { - krb5_ui_4 flags; - - flags = KG2_RESP_FLAG_ERROR; - - ptr[0] = (flags << 24) & 0xff; - ptr[1] = (flags << 16) & 0xff; - ptr[2] = (flags << 8) & 0xff; - ptr[3] = flags & 0xff; - - memset(ptr+4, 0, 6); - - ptr[10] = (scratch.length << 8) & 0xff; - ptr[11] = scratch.length & 0xff; - - ptr += 12; - } - TWRITE_STR(ptr, scratch.data, scratch.length); xfree(scratch.data); diff --git a/src/lib/gssapi/krb5/acquire_cred.c b/src/lib/gssapi/krb5/acquire_cred.c index b67eb4f..c2921f2 100644 --- a/src/lib/gssapi/krb5/acquire_cred.c +++ b/src/lib/gssapi/krb5/acquire_cred.c @@ -1,4 +1,28 @@ /* + * Copyright 2000 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + * + */ +/* * Copyright 1993 by OpenVision Technologies, Inc. * * Permission to use, copy, modify, distribute, and sell this software @@ -154,7 +178,7 @@ acquire_init_cred(context, minor_status, desired_name, output_princ, cred) /* open the default credential cache */ - if ((code = krb5_cc_default(context, &ccache))) { + if ((code = krb5int_cc_default(context, &ccache))) { *minor_status = code; return(GSS_S_CRED_UNAVAIL); } @@ -283,7 +307,7 @@ krb5_gss_acquire_cred(minor_status, desired_name, time_req, size_t i; krb5_gss_cred_id_t cred; gss_OID_set ret_mechs; - int req_old, req_new, req_v2; + int req_old, req_new; OM_uint32 ret; krb5_error_code code; @@ -313,22 +337,18 @@ krb5_gss_acquire_cred(minor_status, desired_name, time_req, if (desired_mechs == GSS_C_NULL_OID_SET) { req_old = 1; req_new = 1; - req_v2 = 1; } else { req_old = 0; req_new = 0; - req_v2 = 0; for (i=0; i<desired_mechs->count; i++) { if (g_OID_equal(gss_mech_krb5_old, &(desired_mechs->elements[i]))) req_old++; if (g_OID_equal(gss_mech_krb5, &(desired_mechs->elements[i]))) req_new++; - if (g_OID_equal(gss_mech_krb5_v2, &(desired_mechs->elements[i]))) - req_v2++; } - if (!req_old && !req_new && !req_v2) { + if (!req_old && !req_new) { *minor_status = 0; return(GSS_S_BAD_MECH); } @@ -347,7 +367,6 @@ krb5_gss_acquire_cred(minor_status, desired_name, time_req, cred->princ = NULL; cred->prerfc_mech = req_old; cred->rfc_mech = req_new; - cred->rfcv2_mech = req_v2; cred->keytab = NULL; cred->ccache = NULL; @@ -442,15 +461,11 @@ krb5_gss_acquire_cred(minor_status, desired_name, time_req, &ret_mechs)) || (cred->prerfc_mech && GSS_ERROR(ret = generic_gss_add_oid_set_member(minor_status, - gss_mech_krb5_old, + (gss_OID) gss_mech_krb5_old, &ret_mechs))) || (cred->rfc_mech && GSS_ERROR(ret = generic_gss_add_oid_set_member(minor_status, - gss_mech_krb5, - &ret_mechs))) || - (cred->rfcv2_mech && - GSS_ERROR(ret = generic_gss_add_oid_set_member(minor_status, - gss_mech_krb5_v2, + (gss_OID) gss_mech_krb5, &ret_mechs)))) { if (cred->ccache) (void)krb5_cc_close(context, cred->ccache); diff --git a/src/lib/gssapi/krb5/add_cred.c b/src/lib/gssapi/krb5/add_cred.c index 2a6fdb4..a13ba52 100644 --- a/src/lib/gssapi/krb5/add_cred.c +++ b/src/lib/gssapi/krb5/add_cred.c @@ -1,4 +1,28 @@ /* + * Copyright 2000 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + * + */ +/* * Copyright (C) 1998 by the FundsXpress, INC. * * All rights reserved. @@ -110,8 +134,7 @@ krb5_gss_add_cred(minor_status, input_cred_handle, /* check that desired_mech isn't already in the credential */ if ((g_OID_equal(desired_mech, gss_mech_krb5_old) && cred->prerfc_mech) || - (g_OID_equal(desired_mech, gss_mech_krb5) && cred->rfc_mech) || - (g_OID_equal(desired_mech, gss_mech_krb5_v2) && cred->rfcv2_mech)) { + (g_OID_equal(desired_mech, gss_mech_krb5) && cred->rfc_mech)) { *minor_status = 0; return(GSS_S_DUPLICATE_ELEMENT); } @@ -143,7 +166,9 @@ krb5_gss_add_cred(minor_status, input_cred_handle, /* make a copy */ krb5_gss_cred_id_t new_cred; char *kttype, ktboth[1024]; - char *cctype, *ccname, ccboth[1024]; + char ccboth[1024]; + const char *ccname; + const char *cctype; if ((new_cred = (krb5_gss_cred_id_t) xmalloc(sizeof(krb5_gss_cred_id_rec))) @@ -156,7 +181,6 @@ krb5_gss_add_cred(minor_status, input_cred_handle, new_cred->usage = cred_usage; new_cred->prerfc_mech = cred->prerfc_mech; new_cred->rfc_mech = cred->rfc_mech; - new_cred->rfcv2_mech = cred->rfcv2_mech; new_cred->tgt_expire = cred->tgt_expire; if (code = krb5_copy_principal(context, cred->princ, @@ -177,8 +201,9 @@ krb5_gss_add_cred(minor_status, input_cred_handle, return(GSS_S_FAILURE); } - strcpy(ktboth, kttype); - strcat(ktboth, ":"); + strncpy(ktboth, kttype, sizeof(ktboth) - 1); + ktboth[sizeof(ktboth) - 1] = '\0'; + strncat(ktboth, ":", sizeof(ktboth) - 1 - strlen(ktboth)); if (code = krb5_kt_get_name(context, cred->keytab, ktboth+strlen(ktboth), @@ -234,9 +259,10 @@ krb5_gss_add_cred(minor_status, input_cred_handle, return(GSS_S_FAILURE); } - strcpy(ccboth, cctype); - strcat(ccboth, ":"); - strcat(ccboth, ccname); + strncpy(ccboth, cctype, sizeof(ccboth) - 1); + ccboth[sizeof(ccboth) - 1] = '\0'; + strncat(ccboth, ":", sizeof(ccboth) - 1 - strlen(ccboth)); + strncat(ccboth, ccname, sizeof(ccboth) - 1 - strlen(ccboth)); if (code = krb5_cc_resolve(context, ccboth, &new_cred->ccache)) { if (new_cred->rcache) @@ -280,8 +306,6 @@ krb5_gss_add_cred(minor_status, input_cred_handle, cred->prerfc_mech = 1; else if (g_OID_equal(desired_mech, gss_mech_krb5)) cred->rfc_mech = 1; - else if (g_OID_equal(desired_mech, gss_mech_krb5_v2)) - cred->rfcv2_mech = 1; /* set the outputs */ diff --git a/src/lib/gssapi/krb5/disp_status.c b/src/lib/gssapi/krb5/disp_status.c index 3a6ba7b..0229296 100644 --- a/src/lib/gssapi/krb5/disp_status.c +++ b/src/lib/gssapi/krb5/disp_status.c @@ -21,7 +21,12 @@ */ #include "gssapiP_krb5.h" + +#if TARGET_OS_MAC +#include <KerberosComErr/KerberosComErr.h> +#else #include "com_err.h" +#endif /* XXXX internationalization!! */ diff --git a/src/lib/gssapi/krb5/gssapiP_krb5.h b/src/lib/gssapi/krb5/gssapiP_krb5.h index e344b4f..080176b 100644 --- a/src/lib/gssapi/krb5/gssapiP_krb5.h +++ b/src/lib/gssapi/krb5/gssapiP_krb5.h @@ -1,4 +1,28 @@ /* + * Copyright 2000 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + * + */ +/* * Copyright 1993 by OpenVision Technologies, Inc. * * Permission to use, copy, modify, distribute, and sell this software @@ -27,7 +51,12 @@ * $Id$ */ +#if TARGET_OS_MAC +#include <Kerberos5/Kerberos5.h> +#else #include <krb5.h> +#endif + #include <memory.h> /* work around sunos braindamage */ @@ -79,6 +108,39 @@ #define KG2_RESP_FLAG_ERROR 0x0001 #define KG2_RESP_FLAG_DELEG_OK 0x0002 +/* These are to be stored in little-endian order, i.e., des-mac is + stored as 02 00. */ +enum sgn_alg { + SGN_ALG_DES_MAC_MD5 = 0x0000, + SGN_ALG_MD2_5 = 0x0001, + SGN_ALG_DES_MAC = 0x0002, + SGN_ALG_3 = 0x0003, /* not published */ + SGN_ALG_HMAC_MD5 = 0x0011, /* microsoft w2k; no support */ + SGN_ALG_HMAC_SHA1_DES3_KD = 0x0004 +}; +enum seal_alg { + SEAL_ALG_NONE = 0xffff, + SEAL_ALG_DES = 0x0000, + SEAL_ALG_1 = 0x0001, /* not published */ + SEAL_ALG_MICROSOFT_RC4 = 0x0010, /* microsoft w2k; no support */ + SEAL_ALG_DES3KD = 0x0002 +}; + +#define KG_USAGE_SEAL 22 +#define KG_USAGE_SIGN 23 +#define KG_USAGE_SEQ 24 + +enum qop { + GSS_KRB5_INTEG_C_QOP_MD5 = 0x0001, /* *partial* MD5 = "MD2.5" */ + GSS_KRB5_INTEG_C_QOP_DES_MD5 = 0x0002, + GSS_KRB5_INTEG_C_QOP_DES_MAC = 0x0003, + GSS_KRB5_INTEG_C_QOP_HMAC_SHA1 = 0x0004, + GSS_KRB5_INTEG_C_QOP_MASK = 0x00ff, + GSS_KRB5_CONF_C_QOP_DES = 0x0100, + GSS_KRB5_CONF_C_QOP_DES3_KD = 0x0200, + GSS_KRB5_CONF_C_QOP_MASK = 0xff00 +}; + /** internal types **/ typedef krb5_principal krb5_gss_name_t; @@ -89,7 +151,6 @@ typedef struct _krb5_gss_cred_id_rec { krb5_principal princ; /* this is not interned as a gss_name_t */ int prerfc_mech; int rfc_mech; - int rfcv2_mech; /* keytab (accept) data */ krb5_keytab keytab; @@ -125,7 +186,6 @@ typedef struct _krb5_gss_ctx_id_rec { int big_endian; krb5_auth_context auth_context; gss_OID_desc *mech_used; - int gsskrb5_version; int nctypes; krb5_cksumtype *ctypes; } krb5_gss_ctx_id_rec, *krb5_gss_ctx_id_t; @@ -190,12 +250,18 @@ int kg_encrypt_size PROTOTYPE((krb5_context context, krb5_keyblock *key, int n)); krb5_error_code kg_encrypt PROTOTYPE((krb5_context context, - krb5_keyblock *key, - krb5_pointer iv, krb5_pointer in, krb5_pointer out, int length)); + krb5_keyblock *key, int usage, + krb5_pointer iv, + krb5_pointer in, + krb5_pointer out, + int length)); krb5_error_code kg_decrypt PROTOTYPE((krb5_context context, - krb5_keyblock *key, - krb5_pointer iv, krb5_pointer in, krb5_pointer out, int length)); + krb5_keyblock *key, int usage, + krb5_pointer iv, + krb5_pointer in, + krb5_pointer out, + int length)); OM_uint32 kg_seal PROTOTYPE((krb5_context context, OM_uint32 *minor_status, diff --git a/src/lib/gssapi/krb5/gssapi_krb5.c b/src/lib/gssapi/krb5/gssapi_krb5.c index e700bb8..5f84b59 100644 --- a/src/lib/gssapi/krb5/gssapi_krb5.c +++ b/src/lib/gssapi/krb5/gssapi_krb5.c @@ -90,16 +90,28 @@ const gss_OID_desc krb5_gss_oid_array[] = { /* this is the v2 assigned OID */ {9, "\052\206\110\206\367\022\001\002\003"}, /* these two are name type OID's */ + + /* 2.1.1. Kerberos Principal Name Form: (rfc 1964) + * 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". */ {10, "\052\206\110\206\367\022\001\002\002\001"}, + + /* gss_nt_krb5_principal. Object identifier for a krb5_principal. Do not use. */ {10, "\052\206\110\206\367\022\001\002\002\002"}, { 0, 0 } }; -const gss_OID_desc * const gss_mech_krb5 = krb5_gss_oid_array+0; -const gss_OID_desc * const gss_mech_krb5_old = krb5_gss_oid_array+1; -const gss_OID_desc * const gss_mech_krb5_v2 = krb5_gss_oid_array+2; -const gss_OID_desc * const gss_nt_krb5_name = krb5_gss_oid_array+3; -const gss_OID_desc * const gss_nt_krb5_principal = krb5_gss_oid_array+4; +const gss_OID_desc * const gss_mech_krb5 = krb5_gss_oid_array+0; +const gss_OID_desc * const gss_mech_krb5_old = krb5_gss_oid_array+1; +const gss_OID_desc * const gss_mech_krb5_v2 = krb5_gss_oid_array+2; +const gss_OID_desc * const gss_nt_krb5_name = krb5_gss_oid_array+3; +const gss_OID_desc * const gss_nt_krb5_principal = krb5_gss_oid_array+4; +#if GSS_RFC_COMPLIANT_OIDS +const gss_OID_desc * const GSS_KRB5_NT_PRINCIPAL_NAME = krb5_gss_oid_array+3; +#endif /* GSS_RFC_COMPLIANT_OIDS */ + static const gss_OID_set_desc oidsets[] = { {1, (gss_OID) krb5_gss_oid_array+0}, diff --git a/src/lib/gssapi/krb5/gssapi_krb5.h b/src/lib/gssapi/krb5/gssapi_krb5.h index e4bac76..8995924 100644 --- a/src/lib/gssapi/krb5/gssapi_krb5.h +++ b/src/lib/gssapi/krb5/gssapi_krb5.h @@ -23,13 +23,63 @@ #ifndef _GSSAPI_KRB5_H_ #define _GSSAPI_KRB5_H_ +#if defined(macintosh) || (defined(__MACH__) && defined(__APPLE__)) + #include <KerberosSupport/KerberosSupport.h> +#endif + +#if TARGET_OS_MAC +#include <Kerberos5/Kerberos5.h> +#else #include <krb5.h> +#endif /* C++ friendlyness */ #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ +#if GSS_RFC_COMPLIANT_OIDS +/* Reserved static storage for GSS_oids. See rfc 1964 for more details. */ + +/* 2.1.1. Kerberos Principal Name Form: */ +GSS_DLLIMP extern const gss_OID_desc * const GSS_KRB5_NT_PRINCIPAL_NAME; +/* 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". */ + +/* 2.1.2. Host-Based Service Name Form */ +#define GSS_KRB5_NT_HOSTBASED_SERVICE_NAME GSS_C_NT_HOSTBASED_SERVICE +/* 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) service_name(4)}. The previously recommended symbolic + * name for this type is "GSS_KRB5_NT_HOSTBASED_SERVICE_NAME". The + * currently preferred symbolic name for this type is + * "GSS_C_NT_HOSTBASED_SERVICE". */ + +/* 2.2.1. User Name Form */ +#define GSS_KRB5_NT_USER_NAME GSS_C_NT_USER_NAME +/* 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". */ + +/* 2.2.2. Machine UID Form */ +#define GSS_KRB5_NT_MACHINE_UID_NAME GSS_C_NT_MACHINE_UID_NAME +/* 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". */ + +/* 2.2.3. String UID Form */ +#define GSS_KRB5_NT_STRING_UID_NAME GSS_C_NT_STRING_UID_NAME +/* 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". */ + +#endif /* GSS_RFC_COMPLIANT_OIDS */ + extern const gss_OID_desc * const gss_mech_krb5; extern const gss_OID_desc * const gss_mech_krb5_old; extern const gss_OID_desc * const gss_mech_krb5_v2; diff --git a/src/lib/gssapi/krb5/import_sec_context.c b/src/lib/gssapi/krb5/import_sec_context.c index fd5415a..659cdc2 100644 --- a/src/lib/gssapi/krb5/import_sec_context.c +++ b/src/lib/gssapi/krb5/import_sec_context.c @@ -44,7 +44,7 @@ gss_OID krb5_gss_convert_static_mech_oid(oid) if ((oid->length == p->length) && (memcmp(oid->elements, p->elements, p->length) == 0)) { gss_release_oid(&minor_status, &oid); - return p; + return (gss_OID) p; } } return oid; diff --git a/src/lib/gssapi/krb5/init_sec_context.c b/src/lib/gssapi/krb5/init_sec_context.c index d0c8bc9..8cc1294 100644 --- a/src/lib/gssapi/krb5/init_sec_context.c +++ b/src/lib/gssapi/krb5/init_sec_context.c @@ -1,4 +1,28 @@ /* + * Copyright 2000 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + * + */ +/* * Copyright 1993 by OpenVision Technologies, Inc. * * Permission to use, copy, modify, distribute, and sell this software @@ -49,6 +73,7 @@ #include "gssapiP_krb5.h" #include <memory.h> #include <stdlib.h> +#include <assert.h> /* * $Id$ @@ -63,17 +88,18 @@ int krb5_gss_dbg_client_expcreds = 0; * ccache. */ static krb5_error_code get_credentials(context, cred, server, now, - endtime, enctype, out_creds) + endtime, enctypes, out_creds) krb5_context context; krb5_gss_cred_id_t cred; krb5_principal server; krb5_timestamp now; krb5_timestamp endtime; - krb5_enctype enctype; + const krb5_enctype *enctypes; krb5_creds **out_creds; { krb5_error_code code; krb5_creds in_creds; + int i; memset((char *) &in_creds, 0, sizeof(krb5_creds)); @@ -82,10 +108,15 @@ static krb5_error_code get_credentials(context, cred, server, now, if ((code = krb5_copy_principal(context, server, &in_creds.server))) goto cleanup; in_creds.times.endtime = endtime; - in_creds.keyblock.enctype = enctype; - if ((code = krb5_get_credentials(context, 0, cred->ccache, - &in_creds, out_creds))) + in_creds.keyblock.enctype = 0; + + code = krb5_set_default_tgs_enctypes (context, enctypes); + if (code) + goto cleanup; + code = krb5_get_credentials(context, 0, cred->ccache, + &in_creds, out_creds); + if (code) goto cleanup; /* @@ -93,7 +124,8 @@ static krb5_error_code get_credentials(context, cred, server, now, * boundaries) because accept_sec_context code is also similarly * non-forgiving. */ - if (!krb5_gss_dbg_client_expcreds && (*out_creds)->times.endtime < now) { + if (!krb5_gss_dbg_client_expcreds && *out_creds != NULL && + (*out_creds)->times.endtime < now) { code = KRB5KRB_AP_ERR_TKT_EXPIRED; goto cleanup; } @@ -117,196 +149,8 @@ make_ap_req_v2(context, ctx, cred, k_cred, chan_bindings, mech_type, token) gss_OID mech_type; gss_buffer_t token; { - krb5_flags mk_req_flags = 0; - krb5_int32 con_flags; - krb5_error_code code; - krb5_data credmsg, cksumdata, ap_req; - int i, tlen, cblen, nctypes; - krb5_cksumtype *ctypes; - unsigned char *t, *ptr; - - credmsg.data = 0; - cksumdata.data = 0; - ap_req.data = 0; - ctypes = 0; - - /* create the option data if necessary */ - if (ctx->gss_flags & GSS_C_DELEG_FLAG) { - /* first get KRB_CRED message, so we know its length */ - - /* clear the time check flag that was set in krb5_auth_con_init() */ - krb5_auth_con_getflags(context, ctx->auth_context, &con_flags); - krb5_auth_con_setflags(context, ctx->auth_context, - con_flags & ~KRB5_AUTH_CONTEXT_DO_TIME); - - code = krb5_fwd_tgt_creds(context, ctx->auth_context, 0, - cred->princ, ctx->there, cred->ccache, 1, - &credmsg); - - /* turn KRB5_AUTH_CONTEXT_DO_TIME back on */ - krb5_auth_con_setflags(context, ctx->auth_context, con_flags); - - if (code) { - /* don't fail here; just don't accept/do the delegation - request */ - ctx->gss_flags &= ~GSS_C_DELEG_FLAG; - } else { - if (credmsg.length > KRB5_INT16_MAX) { - krb5_free_data_contents(context, &credmsg); - return(KRB5KRB_ERR_FIELD_TOOLONG); - } - } - } else { - credmsg.length = 0; - } - - /* construct the list of compatible cksum types */ - - if ((code = krb5_c_keyed_checksum_types(context, - k_cred->keyblock.enctype, - &nctypes, &ctypes))) - goto cleanup; - - if (nctypes == 0) { - code = KRB5_CRYPTO_INTERNAL; - goto cleanup; - } - - /* construct the checksum fields */ - - cblen = 4*5; - if (chan_bindings) - cblen += (chan_bindings->initiator_address.length+ - chan_bindings->acceptor_address.length+ - chan_bindings->application_data.length); - - cksumdata.length = cblen + 8 + 4*nctypes + 4; - if (credmsg.length) - cksumdata.length += 4 + credmsg.length; - - if ((cksumdata.data = (char *) malloc(cksumdata.length)) == NULL) - goto cleanup; - - /* helper macros. This code currently depends on a long being 32 - bits, and htonl dtrt. */ - - ptr = cksumdata.data; - - if (chan_bindings) { - TWRITE_INT(ptr, chan_bindings->initiator_addrtype, 1); - TWRITE_BUF(ptr, chan_bindings->initiator_address, 1); - TWRITE_INT(ptr, chan_bindings->acceptor_addrtype, 1); - TWRITE_BUF(ptr, chan_bindings->acceptor_address, 1); - TWRITE_BUF(ptr, chan_bindings->application_data, 1); - } else { - memset(ptr, 0, cblen); - ptr += cblen; - } - - /* construct the token fields */ - - ptr[0] = (KG2_TOK_INITIAL >> 8) & 0xff; - ptr[1] = KG2_TOK_INITIAL & 0xff; - - ptr[2] = (ctx->gss_flags >> 24) & 0xff; - ptr[3] = (ctx->gss_flags >> 16) & 0xff; - ptr[4] = (ctx->gss_flags >> 8) & 0xff; - ptr[5] = ctx->gss_flags & 0xff; - - ptr[6] = (nctypes >> 8) & 0xff; - ptr[7] = nctypes & 0xff; - - ptr += 8; - - for (i=0; i<nctypes; i++) { - ptr[0] = (ctypes[i] >> 24) & 0xff; - ptr[1] = (ctypes[i] >> 16) & 0xff; - ptr[2] = (ctypes[i] >> 8) & 0xff; - ptr[3] = ctypes[i] & 0xff; - - ptr += 4; - } - - if (credmsg.length) { - ptr[0] = (KRB5_GSS_FOR_CREDS_OPTION >> 8) & 0xff; - ptr[1] = KRB5_GSS_FOR_CREDS_OPTION & 0xff; - - ptr[2] = (credmsg.length >> 8) & 0xff; - ptr[3] = credmsg.length & 0xff; - - ptr += 4; - - memcpy(ptr, credmsg.data, credmsg.length); - - ptr += credmsg.length; - } - - memset(ptr, 0, 4); - - /* call mk_req. subkey and ap_req need to be used or destroyed */ - - mk_req_flags = AP_OPTS_USE_SUBKEY; - - if (ctx->gss_flags & GSS_C_MUTUAL_FLAG) - mk_req_flags |= AP_OPTS_MUTUAL_REQUIRED; - - if ((code = krb5_mk_req_extended(context, &ctx->auth_context, mk_req_flags, - &cksumdata, k_cred, &ap_req))) - goto cleanup; - - /* store the interesting stuff from creds and authent */ - ctx->endtime = k_cred->times.endtime; - ctx->krb_flags = k_cred->ticket_flags; - - /* build up the token */ - - /* allocate space for the token */ - tlen = g_token_size((gss_OID) mech_type, - (cksumdata.length-(2+cblen))+2+ap_req.length); - - if ((t = (unsigned char *) xmalloc(tlen)) == NULL) { - code = ENOMEM; - goto cleanup; - } - - ptr = t; - - g_make_token_header((gss_OID) mech_type, - (cksumdata.length-(2+cblen))+2+ap_req.length, - &ptr, KG2_TOK_INITIAL); - - /* skip over the channel bindings and the token id */ - memcpy(ptr, cksumdata.data+cblen+2, cksumdata.length-(cblen+2)); - ptr += cksumdata.length-(cblen+2); - ptr[0] = (ap_req.length >> 8) & 0xff; - ptr[1] = ap_req.length & 0xff; - ptr += 2; - memcpy(ptr, ap_req.data, ap_req.length); - - /* pass allocated data back */ - - ctx->nctypes = nctypes; - ctx->ctypes = ctypes; - - token->length = tlen; - token->value = (void *) t; - - code = 0; - -cleanup: - if (code) { - if (ctypes) - krb5_free_cksumtypes(context, ctypes); - } - - if (credmsg.data) - free(credmsg.data); - if (ap_req.data) - free(ap_req.data); - if (cksumdata.data) - free(cksumdata.data); - - return(code); + int krb5_mech2_supported = 0; + assert(krb5_mech2_supported); } static krb5_error_code @@ -480,13 +324,19 @@ krb5_gss_init_sec_context(minor_status, claimant_cred_handle, krb5_context context; krb5_gss_cred_id_t cred; krb5_creds *k_cred = 0; - krb5_enctype enctype = ENCTYPE_DES_CBC_CRC; + static const krb5_enctype wanted_enctypes[] = { +#if 1 + ENCTYPE_DES3_CBC_SHA1, +#endif + ENCTYPE_DES_CBC_CRC, + ENCTYPE_DES_CBC_MD5, ENCTYPE_DES_CBC_MD4, + 0 + }; krb5_error_code code; krb5_gss_ctx_id_rec *ctx, *ctx_free; krb5_timestamp now; gss_buffer_desc token; - int gsskrb5_vers = 0; - int i, err; + int i, j, err; int default_mech = 0; krb5_ui_4 resp_flags; OM_uint32 major_status; @@ -528,32 +378,19 @@ krb5_gss_init_sec_context(minor_status, claimant_cred_handle, err = 0; if (mech_type == GSS_C_NULL_OID) { default_mech = 1; - if (cred->rfcv2_mech) { - mech_type = gss_mech_krb5_v2; - gsskrb5_vers = 2000; - } else if (cred->rfc_mech) { - mech_type = gss_mech_krb5; - gsskrb5_vers = 1000; - enctype = ENCTYPE_DES_CBC_CRC; + if (cred->rfc_mech) { + mech_type = (gss_OID) gss_mech_krb5; } else if (cred->prerfc_mech) { - mech_type = gss_mech_krb5_old; - gsskrb5_vers = 1000; - enctype = ENCTYPE_DES_CBC_CRC; + mech_type = (gss_OID) gss_mech_krb5_old; } else { err = 1; } - } else if (g_OID_equal(mech_type, gss_mech_krb5_v2)) { - if (!cred->rfcv2_mech) - err = 1; - gsskrb5_vers = 2000; } else if (g_OID_equal(mech_type, gss_mech_krb5)) { if (!cred->rfc_mech) err = 1; - gsskrb5_vers = 1000; } else if (g_OID_equal(mech_type, gss_mech_krb5_old)) { if (!cred->prerfc_mech) err = 1; - gsskrb5_vers = 1000; } else { err = 1; } @@ -607,7 +444,6 @@ krb5_gss_init_sec_context(minor_status, claimant_cred_handle, ctx->seed_init = 0; ctx->big_endian = 0; /* all initiators do little-endian, as per spec */ ctx->seqstate = 0; - ctx->gsskrb5_version = gsskrb5_vers; ctx->nctypes = 0; ctx->ctypes = 0; @@ -628,27 +464,12 @@ krb5_gss_init_sec_context(minor_status, claimant_cred_handle, goto fail; if ((code = get_credentials(context, cred, ctx->there, now, - ctx->endtime, enctype, &k_cred))) + ctx->endtime, wanted_enctypes, &k_cred))) goto fail; - /* - * If the default mechanism was requested, and the keytype is - * DES_CBC, force the old mechanism - */ - if (default_mech && - ((k_cred->keyblock.enctype == ENCTYPE_DES_CBC_CRC) || - (k_cred->keyblock.enctype == ENCTYPE_DES_CBC_MD4) || - (k_cred->keyblock.enctype == ENCTYPE_DES_CBC_MD5))) { - ctx->gsskrb5_version = gsskrb5_vers = 1000; - mech_type = gss_mech_krb5; - if (k_cred->keyblock.enctype != ENCTYPE_DES_CBC_CRC) { - krb5_free_creds(context, k_cred); - enctype = ENCTYPE_DES_CBC_CRC; - if ((code = get_credentials(context, cred, ctx->there, now, - ctx->endtime, enctype, &k_cred))) - goto fail; - } - } + if (default_mech) { + mech_type = (gss_OID) gss_mech_krb5; + } if (generic_gss_copy_oid(minor_status, mech_type, &ctx->mech_used) != GSS_S_COMPLETE) { @@ -660,24 +481,7 @@ krb5_gss_init_sec_context(minor_status, claimant_cred_handle, */ ctx->mech_used = krb5_gss_convert_static_mech_oid(ctx->mech_used); - if (ctx->gsskrb5_version == 2000) { - /* gsskrb5 v2 */ - if ((code = make_ap_req_v2(context, ctx, - cred, k_cred, input_chan_bindings, - mech_type, &token))) { - if ((code == KRB5_FCC_NOFILE) || (code == KRB5_CC_NOTFOUND) || - (code == KG_EMPTY_CCACHE)) - major_status = GSS_S_NO_CRED; - if (code == KRB5KRB_AP_ERR_TKT_EXPIRED) - major_status = GSS_S_CREDENTIALS_EXPIRED; - goto fail; - } - - krb5_auth_con_getlocalseqnumber(context, ctx->auth_context, - &ctx->seq_send); - krb5_auth_con_getlocalsubkey(context, ctx->auth_context, - &ctx->subkey); - } else { + { /* gsskrb5 v1 */ if ((code = make_ap_req_v1(context, ctx, cred, k_cred, input_chan_bindings, @@ -699,11 +503,41 @@ krb5_gss_init_sec_context(minor_status, claimant_cred_handle, switch(ctx->subkey->enctype) { case ENCTYPE_DES_CBC_MD5: + case ENCTYPE_DES_CBC_MD4: case ENCTYPE_DES_CBC_CRC: ctx->subkey->enctype = ENCTYPE_DES_CBC_RAW; - ctx->signalg = 0; + ctx->signalg = SGN_ALG_DES_MAC_MD5; ctx->cksum_size = 8; - ctx->sealalg = 0; + ctx->sealalg = SEAL_ALG_DES; + + /* The encryption key is the session key XOR + 0xf0f0f0f0f0f0f0f0. */ + if ((code = krb5_copy_keyblock(context, ctx->subkey, &ctx->enc))) + goto fail; + + for (i=0; i<ctx->enc->length; i++) + /*SUPPRESS 113*/ + ctx->enc->contents[i] ^= 0xf0; + + if ((code = krb5_copy_keyblock(context, ctx->subkey, &ctx->seq))) + goto fail; + + break; + + case ENCTYPE_DES3_CBC_SHA1: + ctx->subkey->enctype = ENCTYPE_DES3_CBC_RAW; + ctx->signalg = SGN_ALG_HMAC_SHA1_DES3_KD; + ctx->cksum_size = 20; + ctx->sealalg = SEAL_ALG_DES3KD; + + code = krb5_copy_keyblock (context, ctx->subkey, &ctx->enc); + if (code) + goto fail; + code = krb5_copy_keyblock (context, ctx->subkey, &ctx->seq); + if (code) { + krb5_free_keyblock (context, ctx->enc); + goto fail; + } break; #if 0 case ENCTYPE_DES3_CBC_MD5: @@ -714,20 +548,10 @@ krb5_gss_init_sec_context(minor_status, claimant_cred_handle, break; #endif default: + *minor_status = KRB5_BAD_ENCTYPE; return GSS_S_FAILURE; } - /* the encryption key is the session key XOR 0xf0f0f0f0f0f0f0f0 */ - - if ((code = krb5_copy_keyblock(context, ctx->subkey, &ctx->enc))) - goto fail; - - for (i=0; i<ctx->enc->length; i++) - /*SUPPRESS 113*/ - ctx->enc->contents[i] ^= 0xf0; - - if ((code = krb5_copy_keyblock(context, ctx->subkey, &ctx->seq))) - goto fail; } if (k_cred) { @@ -824,94 +648,38 @@ krb5_gss_init_sec_context(minor_status, claimant_cred_handle, ptr = (unsigned char *) input_token->value; - if (ctx->gsskrb5_version == 2000) { - int token_length; - int nctypes; - krb5_cksumtype *ctypes = 0; - - /* gsskrb5 v2 */ - - if ((code = g_verify_token_header((gss_OID) ctx->mech_used, - &token_length, - &ptr, KG2_TOK_RESPONSE, - input_token->length))) { - major_status = GSS_S_DEFECTIVE_TOKEN; - goto fail; - } - - if (GSS_ERROR(major_status = - kg2_parse_token(minor_status, ptr, token_length, - &resp_flags, &nctypes, &ctypes, - 0, NULL, &ap_rep, &mic))) { - if (ctypes) - free(ctypes); - code = *minor_status; - goto fail; - } - major_status = GSS_S_FAILURE; - - kg2_intersect_ctypes(&ctx->nctypes, ctx->ctypes, nctypes, ctypes); + if ((err = g_verify_token_header((gss_OID) ctx->mech_used, + &(ap_rep.length), + &ptr, KG_TOK_CTX_AP_REP, + input_token->length))) { + if (g_verify_token_header((gss_OID) ctx->mech_used, + &(ap_rep.length), + &ptr, KG_TOK_CTX_ERROR, + input_token->length) == 0) { - free(ctypes); - - if (ctx->nctypes == 0) { - code = KG_NO_CTYPES; - goto fail; - } + /* Handle a KRB_ERROR message from the server */ - if (resp_flags & KG2_RESP_FLAG_ERROR) { - if ((code = krb5_rd_error(context, &ap_rep, &krb_error))) + sptr = (char *) ptr; /* PC compiler bug */ + TREAD_STR(sptr, ap_rep.data, ap_rep.length); + + code = krb5_rd_error(context, &ap_rep, &krb_error); + if (code) goto fail; - if (krb_error->error) code = krb_error->error + ERROR_TABLE_BASE_krb5; else code = 0; - krb5_free_error(context, krb_error); goto fail; + } else { + *minor_status = 0; + return(GSS_S_DEFECTIVE_TOKEN); } - - if (resp_flags & KG2_RESP_FLAG_DELEG_OK) - ctx->gss_flags |= GSS_C_DELEG_FLAG; - - /* drop through to ap_rep handling */ - } else { - /* gsskrb5 v1 */ - - if ((err = g_verify_token_header((gss_OID) ctx->mech_used, - &(ap_rep.length), - &ptr, KG_TOK_CTX_AP_REP, - input_token->length))) { - if (g_verify_token_header((gss_OID) ctx->mech_used, - &(ap_rep.length), - &ptr, KG_TOK_CTX_ERROR, - input_token->length) == 0) { - - /* Handle a KRB_ERROR message from the server */ - - sptr = (char *) ptr; /* PC compiler bug */ - TREAD_STR(sptr, ap_rep.data, ap_rep.length); - - code = krb5_rd_error(context, &ap_rep, &krb_error); - if (code) - goto fail; - if (krb_error->error) - code = krb_error->error + ERROR_TABLE_BASE_krb5; - else - code = 0; - krb5_free_error(context, krb_error); - goto fail; - } else { - *minor_status = 0; - return(GSS_S_DEFECTIVE_TOKEN); - } - } - - sptr = (char *) ptr; /* PC compiler bug */ - TREAD_STR(sptr, ap_rep.data, ap_rep.length); } + sptr = (char *) ptr; /* PC compiler bug */ + TREAD_STR(sptr, ap_rep.data, ap_rep.length); + /* decode the ap_rep */ if ((code = krb5_rd_rep(context, ctx->auth_context, &ap_rep, &ap_rep_data))) { @@ -938,26 +706,6 @@ krb5_gss_init_sec_context(minor_status, claimant_cred_handle, /* set established */ ctx->established = 1; - if (ctx->gsskrb5_version == 2000) { - gss_buffer_desc mic_data, mic_token; - - /* start with the token id */ - mic_data.value = ptr-2; - /* end before the ap-rep length */ - mic_data.length = ((char*)(ap_rep.data-2)-(char*)(ptr-2)); - - mic_token.length = mic.length; - mic_token.value = mic.data; - - if (GSS_ERROR(major_status = - krb5_gss_verify_mic(minor_status, *context_handle, - &mic_data, &mic_token, NULL))) { - code = *minor_status; - goto fail; - } - major_status = GSS_S_FAILURE; - } - /* set returns */ if (time_rec) { diff --git a/src/lib/gssapi/krb5/inq_cred.c b/src/lib/gssapi/krb5/inq_cred.c index c800012..6fbbadc 100644 --- a/src/lib/gssapi/krb5/inq_cred.c +++ b/src/lib/gssapi/krb5/inq_cred.c @@ -1,4 +1,28 @@ /* + * Copyright 2000 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + * + */ +/* * Copyright 1993 by OpenVision Technologies, Inc. * * Permission to use, copy, modify, distribute, and sell this software @@ -116,15 +140,11 @@ krb5_gss_inquire_cred(minor_status, cred_handle, name, lifetime_ret, &mechs)) || (cred->prerfc_mech && GSS_ERROR(ret = generic_gss_add_oid_set_member(minor_status, - gss_mech_krb5_old, + (gss_OID) gss_mech_krb5_old, &mechs))) || (cred->rfc_mech && GSS_ERROR(ret = generic_gss_add_oid_set_member(minor_status, - gss_mech_krb5, - &mechs))) || - (cred->rfcv2_mech && - GSS_ERROR(ret = generic_gss_add_oid_set_member(minor_status, - gss_mech_krb5_v2, + (gss_OID) gss_mech_krb5, &mechs)))) { krb5_free_principal(context, ret_name); /* *minor_status set above */ diff --git a/src/lib/gssapi/krb5/k5seal.c b/src/lib/gssapi/krb5/k5seal.c index ae8cc75..1ca108e 100644 --- a/src/lib/gssapi/krb5/k5seal.c +++ b/src/lib/gssapi/krb5/k5seal.c @@ -1,6 +1,6 @@ /* * Copyright 1993 by OpenVision Technologies, Inc. - * + * * Permission to use, copy, modify, distribute, and sell this software * and its documentation for any purpose is hereby granted without fee, * provided that the above copyright notice appears in all copies and @@ -10,7 +10,7 @@ * without specific, written prior permission. OpenVision makes no * representations about the suitability of this software for any * purpose. It is provided "as is" without express or implied warranty. - * + * * OPENVISION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO * EVENT SHALL OPENVISION BE LIABLE FOR ANY SPECIAL, INDIRECT OR @@ -22,14 +22,14 @@ /* * Copyright (C) 1998 by the FundsXpress, INC. - * + * * All rights reserved. - * + * * Export of this software from the United States of America may require * a specific license from the United States Government. It is the * responsibility of any person or organization contemplating export to * obtain such a license before exporting. - * + * * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and * distribute this software and its documentation for any purpose and * without fee is hereby granted, provided that the above copyright @@ -40,7 +40,7 @@ * permission. FundsXpress makes no representations about the suitability of * this software for any purpose. It is provided "as is" without express * or implied warranty. - * + * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. @@ -49,196 +49,280 @@ #include "gssapiP_krb5.h" static krb5_error_code -make_priv_token_v2 PROTOTYPE((krb5_context context, - krb5_keyblock *subkey, +make_seal_token_v1 PROTOTYPE((krb5_context context, + krb5_keyblock *enc, + krb5_keyblock *seq, krb5_int32 *seqnum, int direction, gss_buffer_t text, gss_buffer_t token, + int signalg, + int cksum_size, + int sealalg, + int encrypt, + int toktype, + int bigend, gss_OID oid)); static krb5_error_code -make_priv_token_v2(context, subkey, seqnum, direction, text, token, oid) - krb5_context context; - krb5_keyblock *subkey; - krb5_int32 *seqnum; - int direction; - gss_buffer_t text; - gss_buffer_t token; - gss_OID oid; -{ - krb5_data plain; - krb5_enc_data cipher; - krb5_error_code code; - size_t enclen; - int tlen; - unsigned char *t, *ptr; - - plain.data = 0; - cipher.ciphertext.data = 0; - t = 0; - - plain.length = 7+text->length; - if ((plain.data = (void *) malloc(plain.length)) == NULL) { - code = ENOMEM; - goto cleanup; - } - - plain.data[0] = (*seqnum >> 24) & 0xff; - plain.data[1] = (*seqnum >> 16) & 0xff; - plain.data[2] = (*seqnum >> 8) & 0xff; - plain.data[3] = *seqnum & 0xff; - - plain.data[4] = direction?0:0xff; - - plain.data[5] = (text->length >> 8) & 0xff; - plain.data[6] = text->length & 0xff; - - memcpy(plain.data+7, text->value, text->length); - - if (code = krb5_c_encrypt_length(context, subkey->enctype, - plain.length, &enclen)) - goto cleanup; - - tlen = g_token_size((gss_OID) oid, 2+enclen); - - if ((t = (unsigned char *) xmalloc(tlen)) == NULL) - return(ENOMEM); - - ptr = t; - - g_make_token_header((gss_OID) oid, 2+enclen, &ptr, - KG2_TOK_WRAP_PRIV); - - ptr[0] = (enclen >> 8) & 0xff; - ptr[1] = enclen & 0xff; - - cipher.ciphertext.length = enclen; - cipher.ciphertext.data = ptr+2; - - if (code = krb5_c_encrypt(context, subkey, - KRB5_KEYUSAGE_GSS_TOK_WRAP_PRIV, - 0, &plain, &cipher)) - goto cleanup; - - /* that's it. return the token */ - - (*seqnum)++; - - token->length = tlen; - token->value = (void *) t; - - code = 0; - -cleanup: - if (plain.data) - free(plain.data); - if (code) { - if (t) - free(t); - } - - return(code); -} - -static krb5_error_code -make_integ_token_v2 PROTOTYPE((krb5_context context, - krb5_keyblock *subkey, - krb5_cksumtype ctype, - krb5_int32 *seqnum, - int direction, - gss_buffer_t text, - gss_buffer_t token, - int toktype, - gss_OID oid)); - -static krb5_error_code -make_integ_token_v2(context, subkey, ctype, seqnum, direction, text, token, - toktype, oid) - krb5_context context; - krb5_keyblock *subkey; - krb5_cksumtype ctype; - krb5_int32 *seqnum; - int direction; - gss_buffer_t text; - gss_buffer_t token; - int toktype; - gss_OID oid; +make_seal_token_v1(context, enc, seq, seqnum, direction, text, token, + signalg, cksum_size, sealalg, encrypt, toktype, + bigend, oid) + krb5_context context; + krb5_keyblock *enc; + krb5_keyblock *seq; + krb5_int32 *seqnum; + int direction; + gss_buffer_t text; + gss_buffer_t token; + int signalg; + int cksum_size; + int sealalg; + int encrypt; + int toktype; + int bigend; + gss_OID oid; { krb5_error_code code; - int tmp, tlen; - unsigned char *t, *ptr; - krb5_data plain; + size_t sumlen; + char *data_ptr; + krb5_data plaind; + krb5_checksum md5cksum; krb5_checksum cksum; + int conflen=0, tmsglen, tlen; + unsigned char *t, *ptr; - plain.data = 0; - t = 0; - cksum.contents = 0; + int encblksize, sumblksize; + + switch (signalg) { + case SGN_ALG_DES_MAC_MD5: + case SGN_ALG_MD2_5: + case SGN_ALG_HMAC_MD5: + sumblksize = 1; + break; + case SGN_ALG_DES_MAC: + sumblksize = 8; + break; + case SGN_ALG_HMAC_SHA1_DES3_KD: + sumblksize = 1; + break; + default: + abort (); + return 123; /* find error code */ + } - /* assemble the checksum buffer and compute the checksum */ + switch (sealalg) { + case SEAL_ALG_NONE: + case SEAL_ALG_DES: + case SEAL_ALG_DES3KD: + encblksize = 8; + break; + default: + abort (); + return 12345654321; + } - plain.length = 7+text->length; + /* create the token buffer */ - if ((plain.data = (char *) malloc(plain.length)) == NULL) { - code = errno; - goto cleanup; + if (toktype == KG_TOK_SEAL_MSG) { + if (bigend && !encrypt) { + tmsglen = text->length; + } else { + conflen = kg_confounder_size(context, enc); + /* XXX knows that des block size is 8 */ + tmsglen = (conflen+text->length+8)&(~7); + } + } else { + tmsglen = 0; } - plain.data[0] = (*seqnum >> 24) & 0xff; - plain.data[1] = (*seqnum >> 16) & 0xff; - plain.data[2] = (*seqnum >> 8) & 0xff; - plain.data[3] = *seqnum & 0xff; + tlen = g_token_size((gss_OID) oid, 14+cksum_size+tmsglen); - plain.data[4] = direction?0:0xff; + if ((t = (unsigned char *) xmalloc(tlen)) == NULL) + return(ENOMEM); - plain.data[5] = (text->length >> 8) & 0xff; - plain.data[6] = text->length & 0xff; + /*** fill in the token */ - memcpy(plain.data+7, text->value, text->length); + ptr = t; - if (code = krb5_c_make_checksum(context, ctype, subkey, - (toktype == KG2_TOK_WRAP_INTEG)? - KRB5_KEYUSAGE_GSS_TOK_WRAP_INTEG: - KRB5_KEYUSAGE_GSS_TOK_MIC, - &plain, &cksum)) - goto cleanup; + g_make_token_header((gss_OID) oid, 14+cksum_size+tmsglen, &ptr, toktype); - /* assemble the token itself */ + /* 0..1 SIGN_ALG */ - if (toktype == KG2_TOK_WRAP_INTEG) - tmp = 4+(7+text->length)+2+cksum.length; - else - tmp = 4+(5)+2+cksum.length; + ptr[0] = signalg & 0xff; + ptr[1] = (signalg >> 8) & 0xff; - tlen = g_token_size((gss_OID) oid, tmp); + /* 2..3 SEAL_ALG or Filler */ - if ((t = (unsigned char *) xmalloc(tlen)) == NULL) - return(ENOMEM); + if ((toktype == KG_TOK_SEAL_MSG) && encrypt) { + ptr[2] = sealalg & 0xff; + ptr[3] = (sealalg >> 8) & 0xff; + } else { + /* No seal */ + ptr[2] = 0xff; + ptr[3] = 0xff; + } - ptr = t; + /* 4..5 Filler */ + + ptr[4] = 0xff; + ptr[5] = 0xff; + + /* pad the plaintext, encrypt if needed, and stick it in the token */ + + /* initialize the the cksum */ + switch (signalg) { + case SGN_ALG_DES_MAC_MD5: + case SGN_ALG_MD2_5: + case SGN_ALG_HMAC_MD5: + md5cksum.checksum_type = CKSUMTYPE_RSA_MD5; + break; + case SGN_ALG_HMAC_SHA1_DES3_KD: + md5cksum.checksum_type = CKSUMTYPE_HMAC_SHA1_DES3; + break; + default: + case SGN_ALG_DES_MAC: + abort (); + } - g_make_token_header((gss_OID) oid, tmp, &ptr, toktype); + if (code = krb5_c_checksum_length(context, md5cksum.checksum_type, &sumlen)) + return(code); + md5cksum.length = sumlen; + + if (toktype == KG_TOK_SEAL_MSG) { + unsigned char *plain; + unsigned char pad; + + if (!bigend || encrypt) { + if ((plain = (unsigned char *) xmalloc(tmsglen)) == NULL) { + xfree(t); + return(ENOMEM); + } + + if ((code = kg_make_confounder(context, enc, plain))) { + xfree(plain); + xfree(t); + return(code); + } + + memcpy(plain+conflen, text->value, text->length); + + /* XXX 8 is DES cblock size */ + pad = 8-(text->length%8); + + memset(plain+conflen+text->length, pad, pad); + } else { + /* plain is never used in the bigend && !encrypt case */ + plain = NULL; + } + + if (encrypt) { + if ((code = kg_encrypt(context, enc, KG_USAGE_SEAL, NULL, + (krb5_pointer) plain, + (krb5_pointer) (ptr+cksum_size+14), + tmsglen))) { + if (plain) + xfree(plain); + xfree(t); + return(code); + } + } else { + if (bigend) + memcpy(ptr+14+cksum_size, text->value, text->length); + else + memcpy(ptr+14+cksum_size, plain, tmsglen); + } + + /* compute the checksum */ + + /* 8 = head of token body as specified by mech spec */ + if (! (data_ptr = + (char *) xmalloc(8 + (bigend ? text->length : tmsglen)))) { + if (plain) + xfree(plain); + xfree(t); + return(ENOMEM); + } + (void) memcpy(data_ptr, ptr-2, 8); + if (bigend) + (void) memcpy(data_ptr+8, text->value, text->length); + else + (void) memcpy(data_ptr+8, plain, tmsglen); + plaind.length = 8 + (bigend ? text->length : tmsglen); + plaind.data = data_ptr; + code = krb5_c_make_checksum(context, md5cksum.checksum_type, seq, + KG_USAGE_SIGN, &plaind, &md5cksum); + xfree(data_ptr); + + if (code) { + if (plain) + xfree(plain); + xfree(t); + return(code); + } - ptr[0] = (ctype >> 24) & 0xff; - ptr[1] = (ctype >> 16) & 0xff; - ptr[2] = (ctype >> 8) & 0xff; - ptr[3] = ctype & 0xff; + if (plain) + xfree(plain); + } else { + /* Sign only. */ + /* compute the checksum */ - ptr += 4; + if (! (data_ptr = (char *) xmalloc(8 + text->length))) { + xfree(t); + return(ENOMEM); + } + (void) memcpy(data_ptr, ptr-2, 8); + (void) memcpy(data_ptr+8, text->value, text->length); + plaind.length = 8 + text->length; + plaind.data = data_ptr; + code = krb5_c_make_checksum(context, md5cksum.checksum_type, seq, + KG_USAGE_SIGN, &plaind, &md5cksum); + xfree(data_ptr); + if (code) { + xfree(t); + return(code); + } + } - if (toktype == KG2_TOK_WRAP_INTEG) { - memcpy(ptr, plain.data, 7+text->length); - ptr += 7+text->length; - } else { - memcpy(ptr, plain.data, 5); - ptr += 5; + switch(signalg) { + case SGN_ALG_DES_MAC_MD5: + case 3: + + if ((code = kg_encrypt(context, seq, KG_USAGE_SEAL, + (g_OID_equal(oid, gss_mech_krb5_old) ? + seq->contents : NULL), + md5cksum.contents, md5cksum.contents, 16))) { + xfree(md5cksum.contents); + xfree(t); + return code; + } + + cksum.length = cksum_size; + cksum.contents = md5cksum.contents + 16 - cksum.length; + + memcpy(ptr+14, cksum.contents, cksum.length); + break; + + case SGN_ALG_HMAC_SHA1_DES3_KD: + /* + * Using key derivation, the call to krb5_c_make_checksum + * already dealt with encrypting. + */ + if (md5cksum.length != cksum_size) + abort (); + memcpy (ptr+14, md5cksum.contents, md5cksum.length); + break; } - ptr[0] = (cksum.length >> 8) & 0xff; - ptr[1] = cksum.length & 0xff; - ptr += 2; + xfree(md5cksum.contents); + + /* create the seq_num */ - memcpy(ptr, cksum.contents, cksum.length); + if ((code = kg_make_seq_num(context, seq, direction?0:0xff, *seqnum, + ptr+14, ptr+6))) { + xfree(t); + return(code); + } /* that's it. return the token */ @@ -247,372 +331,110 @@ make_integ_token_v2(context, subkey, ctype, seqnum, direction, text, token, token->length = tlen; token->value = (void *) t; - code = 0; - -cleanup: - if (plain.data) - free(plain.data); - if (cksum.contents) - krb5_free_checksum_contents(context, &cksum); - if (code) { - if (t) - free(t); - } - - return(code); + return(0); } -static krb5_error_code -make_seal_token_v1 PROTOTYPE((krb5_context context, - krb5_keyblock *enc, - krb5_keyblock *seq, - krb5_int32 *seqnum, - int direction, - gss_buffer_t text, - gss_buffer_t token, - int signalg, - int cksum_size, - int sealalg, - int encrypt, - int toktype, - int bigend, - gss_OID oid)); +/* if signonly is true, ignore conf_req, conf_state, + and do not encode the ENC_TYPE, MSG_LENGTH, or MSG_TEXT fields */ -static krb5_error_code -make_seal_token_v1(context, enc, seq, seqnum, direction, text, token, - signalg, cksum_size, sealalg, encrypt, toktype, - bigend, oid) - krb5_context context; - krb5_keyblock *enc; - krb5_keyblock *seq; - krb5_int32 *seqnum; - int direction; - gss_buffer_t text; - gss_buffer_t token; - int signalg; - int cksum_size; - int sealalg; - int encrypt; - int toktype; - int bigend; - gss_OID oid; +OM_uint32 +kg_seal(context, minor_status, context_handle, conf_req_flag, qop_req, + input_message_buffer, conf_state, output_message_buffer, toktype) + krb5_context context; + 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; + int toktype; { - krb5_error_code code; - size_t sumlen; - char *data_ptr; - krb5_data plaind; - krb5_checksum md5cksum; - krb5_checksum cksum; - int conflen=0, tmsglen, tlen; - unsigned char *t, *ptr; - - /* create the token buffer */ - - if (toktype == KG_TOK_SEAL_MSG) { - if (bigend && !encrypt) { - tmsglen = text->length; - } else { - conflen = kg_confounder_size(context, enc); - /* XXX knows that des block size is 8 */ - tmsglen = (conflen+text->length+8)&(~7); - } - } else { - tmsglen = 0; - } - - tlen = g_token_size((gss_OID) oid, 14+cksum_size+tmsglen); - - if ((t = (unsigned char *) xmalloc(tlen)) == NULL) - return(ENOMEM); - - /*** fill in the token */ - - ptr = t; - - g_make_token_header((gss_OID) oid, 14+cksum_size+tmsglen, &ptr, toktype); - - /* 0..1 SIGN_ALG */ - - ptr[0] = signalg; - ptr[1] = 0; - - /* 2..3 SEAL_ALG or Filler */ - - if ((toktype == KG_TOK_SEAL_MSG) && encrypt) { - ptr[2] = sealalg; - ptr[3] = 0; - } else { - /* No seal */ - ptr[2] = 0xff; - ptr[3] = 0xff; - } - - /* 4..5 Filler */ - - ptr[4] = 0xff; - ptr[5] = 0xff; - - /* pad the plaintext, encrypt if needed, and stick it in the token */ - - /* initialize the the cksum */ - if (code = krb5_c_checksum_length(context, CKSUMTYPE_RSA_MD5, &sumlen)) - return(code); - - md5cksum.checksum_type = CKSUMTYPE_RSA_MD5; - md5cksum.length = sumlen; - if (toktype == KG_TOK_SEAL_MSG) { - unsigned char *plain; - unsigned char pad; - - if (!bigend || encrypt) { - if ((plain = (unsigned char *) xmalloc(tmsglen)) == NULL) { - xfree(t); - return(ENOMEM); - } - - if ((code = kg_make_confounder(context, enc, plain))) { - xfree(plain); - xfree(t); - return(code); - } - - memcpy(plain+conflen, text->value, text->length); - - /* XXX 8 is DES cblock size */ - pad = 8-(text->length%8); - - memset(plain+conflen+text->length, pad, pad); - } else { - /* plain is never used in the bigend && !encrypt case */ - plain = NULL; - } + krb5_gss_ctx_id_rec *ctx; + krb5_error_code code; + krb5_timestamp now; - if (encrypt) { - if ((code = kg_encrypt(context, enc, NULL, (krb5_pointer) plain, - (krb5_pointer) (ptr+cksum_size+14), - tmsglen))) { - if (plain) - xfree(plain); - xfree(t); - return(code); - } - } else { - if (bigend) - memcpy(ptr+14+cksum_size, text->value, text->length); - else - memcpy(ptr+14+cksum_size, plain, tmsglen); - } - - /* compute the checksum */ - - /* 8 = head of token body as specified by mech spec */ - if (! (data_ptr = - (char *) xmalloc(8 + (bigend ? text->length : tmsglen)))) { - if (plain) - xfree(plain); - xfree(t); - return(ENOMEM); - } - (void) memcpy(data_ptr, ptr-2, 8); - if (bigend) - (void) memcpy(data_ptr+8, text->value, text->length); - else - (void) memcpy(data_ptr+8, plain, tmsglen); - plaind.length = 8 + (bigend ? text->length : tmsglen); - plaind.data = data_ptr; - code = krb5_c_make_checksum(context, md5cksum.checksum_type, - 0, 0, &plaind, &md5cksum); - xfree(data_ptr); - - if (code) { - if (plain) - xfree(plain); - xfree(t); - return(code); - memcpy(ptr+14+cksum_size, plain, tmsglen); - } - - if (plain) - xfree(plain); - } else { - /* compute the checksum */ - - if (! (data_ptr = (char *) xmalloc(8 + text->length))) { - xfree(t); - return(ENOMEM); - } - (void) memcpy(data_ptr, ptr-2, 8); - (void) memcpy(data_ptr+8, text->value, text->length); - plaind.length = 8 + text->length; - plaind.data = data_ptr; - code = krb5_c_make_checksum(context, md5cksum.checksum_type, 0, 0, - &plaind, &md5cksum); - xfree(data_ptr); - if (code) { - xfree(t); - return(code); - } - } - - switch(signalg) { - case 0: - case 3: + output_message_buffer->length = 0; + output_message_buffer->value = NULL; + /* only default qop or matching established cryptosystem is allowed */ + #if 0 - /* XXX this depends on the key being a single-des key */ - - /* DES CBC doesn't use a zero IV like it should in some - krb5 implementations (beta5+). So we just do the - DES encryption the long way, and keep the last block - as the MAC */ - - /* XXX not converted to new api since it's inside an #if 0 */ - - /* initialize the the cksum and allocate the contents buffer */ - cksum.checksum_type = CKSUMTYPE_DESCBC; - cksum.length = krb5_checksum_size(context, CKSUMTYPE_DESCBC); - if ((cksum.contents = (krb5_octet *) xmalloc(cksum.length)) == NULL) - return(ENOMEM); - - /* XXX not converted to new api since it's inside an #if 0 */ - if (code = krb5_calculate_checksum(context, cksum.checksum_type, - md5cksum.contents, 16, - seq->contents, - seq->length, - &cksum)) { - xfree(cksum.contents); - xfree(md5cksum.contents); - xfree(t); - return(code); - } - - memcpy(ptr+14, cksum.contents, 8); - - xfree(cksum.contents); + switch (qop_req & GSS_KRB5_CONF_C_QOP_MASK) { + case GSS_C_QOP_DEFAULT: + break; + default: + unknown_qop: + *minor_status = (OM_uint32) G_UNKNOWN_QOP; + return GSS_S_FAILURE; + case GSS_KRB5_CONF_C_QOP_DES: + if (ctx->sealalg != SEAL_ALG_DES) { + bad_qop: + *minor_status = (OM_uint32) G_BAD_QOP; + return GSS_S_FAILURE; + } + break; + case GSS_KRB5_CONF_C_QOP_DES3: + if (ctx->sealalg != SEAL_ALG_DES3) + goto bad_qop; + break; + } + switch (qop_req & GSS_KRB5_INTEG_C_QOP_MASK) { + case GSS_C_QOP_DEFAULT: + break; + default: + goto unknown_qop; + case GSS_KRB5_INTEG_C_QOP_MD5: + case GSS_KRB5_INTEG_C_QOP_DES_MD5: + case GSS_KRB5_INTEG_C_QOP_DES_MAC: + if (ctx->sealalg != SEAL_ALG_DES) + goto bad_qop; + break; + case GSS_KRB5_INTEG_C_QOP_HMAC_SHA1: + if (ctx->sealalg != SEAL_ALG_DES3KD) + goto bad_qop; + break; + } #else - if ((code = kg_encrypt(context, seq, - (g_OID_equal(oid, gss_mech_krb5_old) ? - seq->contents : NULL), - md5cksum.contents, md5cksum.contents, 16))) { - xfree(md5cksum.contents); - xfree(t); - return code; - } - - cksum.length = cksum_size; - cksum.contents = md5cksum.contents + 16 - cksum.length; - - memcpy(ptr+14, cksum.contents, cksum.length); + if (qop_req != 0) { + *minor_status = (OM_uint32) G_UNKNOWN_QOP; + return GSS_S_FAILURE; + } #endif - break; - } - - xfree(md5cksum.contents); - - /* create the seq_num */ + /* validate the context handle */ + if (! kg_validate_ctx_id(context_handle)) { + *minor_status = (OM_uint32) G_VALIDATE_FAILED; + return(GSS_S_NO_CONTEXT); + } - if ((code = kg_make_seq_num(context, seq, direction?0:0xff, *seqnum, - ptr+14, ptr+6))) { - xfree(t); - return(code); - } + ctx = (krb5_gss_ctx_id_rec *) context_handle; - /* that's it. return the token */ + if (! ctx->established) { + *minor_status = KG_CTX_INCOMPLETE; + return(GSS_S_NO_CONTEXT); + } - (*seqnum)++; + if ((code = krb5_timeofday(context, &now))) { + *minor_status = code; + return(GSS_S_FAILURE); + } - token->length = tlen; - token->value = (void *) t; + code = make_seal_token_v1(context, ctx->enc, ctx->seq, + &ctx->seq_send, ctx->initiate, + input_message_buffer, output_message_buffer, + ctx->signalg, ctx->cksum_size, ctx->sealalg, + conf_req_flag, toktype, ctx->big_endian, + ctx->mech_used); - return(0); -} + if (code) { + *minor_status = code; + return(GSS_S_FAILURE); + } -/* if signonly is true, ignore conf_req, conf_state, - and do not encode the ENC_TYPE, MSG_LENGTH, or MSG_TEXT fields */ + if (conf_state) + *conf_state = conf_req_flag; -OM_uint32 -kg_seal(context, minor_status, context_handle, conf_req_flag, qop_req, - input_message_buffer, conf_state, output_message_buffer, toktype) - krb5_context context; - 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; - int toktype; -{ - krb5_gss_ctx_id_rec *ctx; - krb5_error_code code; - krb5_timestamp now; - - output_message_buffer->length = 0; - output_message_buffer->value = NULL; - - /* only default qop is allowed */ - if (qop_req != GSS_C_QOP_DEFAULT) { - *minor_status = (OM_uint32) G_UNKNOWN_QOP; - return(GSS_S_FAILURE); - } - - /* validate the context handle */ - if (! kg_validate_ctx_id(context_handle)) { - *minor_status = (OM_uint32) G_VALIDATE_FAILED; - return(GSS_S_NO_CONTEXT); - } - - ctx = (krb5_gss_ctx_id_rec *) context_handle; - - if (! ctx->established) { - *minor_status = KG_CTX_INCOMPLETE; - return(GSS_S_NO_CONTEXT); - } - - if ((code = krb5_timeofday(context, &now))) { - *minor_status = code; - return(GSS_S_FAILURE); - } - - if (ctx->gsskrb5_version == 2000) { - if (toktype == KG_TOK_WRAP_MSG) { - if (conf_req_flag) - toktype = KG2_TOK_WRAP_PRIV; - else - toktype = KG2_TOK_WRAP_INTEG; - } else { - toktype = KG2_TOK_MIC; - } - - if (conf_req_flag) { - code = make_priv_token_v2(context, ctx->subkey, &ctx->seq_send, - ctx->initiate, input_message_buffer, - output_message_buffer, ctx->mech_used); - } else { - code = make_integ_token_v2(context, ctx->subkey, ctx->ctypes[0], - &ctx->seq_send, ctx->initiate, - input_message_buffer, - output_message_buffer, toktype, - ctx->mech_used); - } - } else { - code = make_seal_token_v1(context, ctx->enc, ctx->seq, - &ctx->seq_send, ctx->initiate, - input_message_buffer, output_message_buffer, - ctx->signalg, ctx->cksum_size, ctx->sealalg, - conf_req_flag, toktype, ctx->big_endian, - ctx->mech_used); - } - - if (code) { - *minor_status = code; - return(GSS_S_FAILURE); - } - - if (conf_state) - *conf_state = conf_req_flag; - - *minor_status = 0; - return((ctx->endtime < now)?GSS_S_CONTEXT_EXPIRED:GSS_S_COMPLETE); + *minor_status = 0; + return((ctx->endtime < now)?GSS_S_CONTEXT_EXPIRED:GSS_S_COMPLETE); } diff --git a/src/lib/gssapi/krb5/k5unseal.c b/src/lib/gssapi/krb5/k5unseal.c index 64a9539..9e4d353 100644 --- a/src/lib/gssapi/krb5/k5unseal.c +++ b/src/lib/gssapi/krb5/k5unseal.c @@ -1,6 +1,6 @@ /* * Copyright 1993 by OpenVision Technologies, Inc. - * + * * Permission to use, copy, modify, distribute, and sell this software * and its documentation for any purpose is hereby granted without fee, * provided that the above copyright notice appears in all copies and @@ -10,7 +10,7 @@ * without specific, written prior permission. OpenVision makes no * representations about the suitability of this software for any * purpose. It is provided "as is" without express or implied warranty. - * + * * OPENVISION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO * EVENT SHALL OPENVISION BE LIABLE FOR ANY SPECIAL, INDIRECT OR @@ -22,14 +22,14 @@ /* * Copyright (C) 1998 by the FundsXpress, INC. - * + * * All rights reserved. - * + * * Export of this software from the United States of America may require * a specific license from the United States Government. It is the * responsibility of any person or organization contemplating export to * obtain such a license before exporting. - * + * * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and * distribute this software and its documentation for any purpose and * without fee is hereby granted, provided that the above copyright @@ -40,7 +40,7 @@ * permission. FundsXpress makes no representations about the suitability of * this software for any purpose. It is provided "as is" without express * or implied warranty. - * + * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. @@ -53,834 +53,438 @@ * $Id$ */ -static OM_uint32 -kg2_verify_mic(context, minor_status, ctx, ptr, bodysize, - text, qop_state) - krb5_context context; - OM_uint32 *minor_status; - krb5_gss_ctx_id_rec *ctx; - unsigned char *ptr; - int bodysize; - gss_buffer_t text; - gss_qop_t *qop_state; +/* message_buffer is an input if SIGN, output if SEAL, and ignored if DEL_CTX + conf_state is only valid if SEAL. */ + +OM_uint32 +kg_unseal_v1(context, minor_status, ctx, ptr, bodysize, message_buffer, + conf_state, qop_state, toktype) + krb5_context context; + OM_uint32 *minor_status; + krb5_gss_ctx_id_rec *ctx; + unsigned char *ptr; + int bodysize; + gss_buffer_t message_buffer; + int *conf_state; + int *qop_state; + int toktype; { - size_t cksumlen; krb5_error_code code; - krb5_data plain; - krb5_cksumtype tctype; - krb5_ui_4 tseqnum; - int tdirection; + int tmsglen; + int conflen = 0; + int signalg; + int sealalg; + gss_buffer_desc token; krb5_checksum cksum; - krb5_boolean ckvalid; + krb5_checksum md5cksum; + krb5_data plaind; + char *data_ptr; krb5_timestamp now; + unsigned char *plain; + int cksum_len = 0; + int plainlen; + int direction; + krb5_int32 seqnum; OM_uint32 retval; + size_t sumlen; - plain.data = 0; - cksum.contents = 0; - - /* verify the header */ - - if (bodysize < 11) { - free(plain.data); - *minor_status = G_TOK_TRUNC; - return(GSS_S_DEFECTIVE_TOKEN); + if (toktype == KG_TOK_SEAL_MSG) { + message_buffer->length = 0; + message_buffer->value = NULL; } - /* allocate the checksum buffer */ - - plain.length = 7+text->length; - - if ((plain.data = (char *) malloc(plain.length)) == NULL) { - *minor_status = ENOMEM; - return(GSS_S_FAILURE); - } + /* get the sign and seal algorithms */ - /* suck out the body parts from the token */ + signalg = ptr[0] + (ptr[1]<<8); + sealalg = ptr[2] + (ptr[3]<<8); - tctype = (krb5_cksumtype) ((ptr[0]<<24) | (ptr[1]<<16) | - (ptr[2]<<8) | ptr[3]); - ptr += 4; + /* Sanity checks */ - memcpy(plain.data, ptr, 5); - tseqnum = ((ptr[0]<<24) | (ptr[1]<<16) | (ptr[2]<<8) | ptr[3]); - ptr += 4; - tdirection = ptr[0]; - ptr += 1; - - cksum.length = (ptr[0]<<8) | ptr[1]; - ptr += 2; - bodysize -= 11; - - if (cksum.length != bodysize) { - free(plain.data); - *minor_status = G_TOK_TRUNC; - return(GSS_S_DEFECTIVE_TOKEN); + if ((ptr[4] != 0xff) || (ptr[5] != 0xff)) { + *minor_status = 0; + return GSS_S_DEFECTIVE_TOKEN; } - cksum.contents = ptr; - cksum.checksum_type = tctype; + if ((toktype != KG_TOK_SEAL_MSG) && + (sealalg != 0xffff)) { + *minor_status = 0; + return GSS_S_DEFECTIVE_TOKEN; + } - /* finish assembling the checksum buffer and compute the checksum */ + /* in the current spec, there is only one valid seal algorithm per + key type, so a simple comparison is ok */ - plain.data[5] = (text->length >> 8) & 0xff; - plain.data[6] = text->length & 0xff; + if ((toktype == KG_TOK_SEAL_MSG) && + !((sealalg == 0xffff) || + (sealalg == ctx->sealalg))) { + *minor_status = 0; + return GSS_S_DEFECTIVE_TOKEN; + } - memcpy(plain.data+7, text->value, text->length); + /* there are several mappings of seal algorithms to sign algorithms, + but few enough that we can try them all. */ - if (code = krb5_c_verify_checksum(context, ctx->subkey, - KRB5_KEYUSAGE_GSS_TOK_MIC, - &plain, &cksum, &ckvalid)) { - free(plain.data); - *minor_status = code; - return(GSS_S_FAILURE); + if ((ctx->sealalg == SEAL_ALG_NONE && signalg > 1) || + (ctx->sealalg == SEAL_ALG_1 && signalg != SGN_ALG_3) || + (ctx->sealalg == SEAL_ALG_DES3KD && + signalg != SGN_ALG_HMAC_SHA1_DES3_KD)) { + *minor_status = 0; + return GSS_S_DEFECTIVE_TOKEN; } - if (!ckvalid) { - free(plain.data); + switch (signalg) { + case SGN_ALG_DES_MAC_MD5: + case SGN_ALG_MD2_5: + cksum_len = 8; + break; + case SGN_ALG_3: + cksum_len = 16; + break; + case SGN_ALG_HMAC_SHA1_DES3_KD: + cksum_len = 20; + break; + default: *minor_status = 0; - return(GSS_S_BAD_SIG); + return GSS_S_DEFECTIVE_TOKEN; } - /* check context expiry */ + if (toktype == KG_TOK_SEAL_MSG) + tmsglen = bodysize-(14+cksum_len); - if ((code = krb5_timeofday(context, &now))) { - free(plain.data); - *minor_status = code; - return(GSS_S_FAILURE); - } + /* get the token parameters */ - if (now > ctx->endtime) { - free(plain.data); - *minor_status = 0; - return(GSS_S_CONTEXT_EXPIRED); - } + /* decode the message, if SEAL */ - /* do sequencing checks */ + if (toktype == KG_TOK_SEAL_MSG) { + if (sealalg != 0xffff) { + if ((plain = (unsigned char *) xmalloc(tmsglen)) == NULL) { + *minor_status = ENOMEM; + return(GSS_S_FAILURE); + } - if ((ctx->initiate && tdirection != 0xff) || - (!ctx->initiate && tdirection != 0)) { - free(plain.data); - *minor_status = G_BAD_DIRECTION; - return(GSS_S_BAD_SIG); - } + if ((code = kg_decrypt(context, ctx->enc, KG_USAGE_SEAL, NULL, + ptr+14+cksum_len, plain, tmsglen))) { + xfree(plain); + *minor_status = code; + return(GSS_S_FAILURE); + } + } else { + plain = ptr+14+cksum_len; + } - retval = g_order_check(&(ctx->seqstate), tseqnum); + plainlen = tmsglen; - free(plain.data); + if ((sealalg == 0xffff) && ctx->big_endian) { + token.length = tmsglen; + } else { + conflen = kg_confounder_size(context, ctx->enc); + token.length = tmsglen - conflen - plain[tmsglen-1]; + } - if (retval) { - *minor_status = 0; - return(retval); - } + if (token.length) { + if ((token.value = (void *) xmalloc(token.length)) == NULL) { + if (sealalg != 0xffff) + xfree(plain); + *minor_status = ENOMEM; + return(GSS_S_FAILURE); + } + memcpy(token.value, plain+conflen, token.length); + } + } else if (toktype == KG_TOK_SIGN_MSG) { + token = *message_buffer; + plain = token.value; + plainlen = token.length; + } else { + token.length = 0; + token.value = NULL; + plain = token.value; + plainlen = token.length; + } - if (qop_state) - *qop_state = GSS_C_QOP_DEFAULT; + /* compute the checksum of the message */ + + /* initialize the the cksum */ + switch (signalg) { + case SGN_ALG_DES_MAC_MD5: + case SGN_ALG_MD2_5: + case SGN_ALG_HMAC_MD5: + case SGN_ALG_DES_MAC: + case SGN_ALG_3: + md5cksum.checksum_type = CKSUMTYPE_RSA_MD5; + break; + case SGN_ALG_HMAC_SHA1_DES3_KD: + md5cksum.checksum_type = CKSUMTYPE_HMAC_SHA1_DES3; + break; + default: + abort (); + } - *minor_status = 0; - return(GSS_S_COMPLETE); -} + if (code = krb5_c_checksum_length(context, md5cksum.checksum_type, &sumlen)) + return(code); + md5cksum.length = sumlen; -static OM_uint32 -kg2_unwrap_integ(context, minor_status, ctx, ptr, bodysize, output, qop_state) - krb5_context context; - OM_uint32 *minor_status; - krb5_gss_ctx_id_rec *ctx; - unsigned char *ptr; - int bodysize; - gss_buffer_t output; - gss_qop_t *qop_state; -{ - krb5_error_code code; - OM_uint32 retval; - krb5_ui_4 tseqnum; - int tdirection; - int tmsglen; - unsigned char *tmsg; - krb5_data plain; - krb5_checksum tcksum; - krb5_boolean ckvalid; - krb5_timestamp now; + switch (signalg) { + case SGN_ALG_DES_MAC_MD5: + case SGN_ALG_3: + /* compute the checksum of the message */ - output->length = 0; - output->value = NULL; + /* 8 = bytes of token body to be checksummed according to spec */ - /* read the body parts out of the message */ + if (! (data_ptr = (void *) + xmalloc(8 + (ctx->big_endian ? token.length : plainlen)))) { + if (sealalg != 0xffff) + xfree(plain); + if (toktype == KG_TOK_SEAL_MSG) + xfree(token.value); + *minor_status = ENOMEM; + return(GSS_S_FAILURE); + } - if (bodysize < 11) { - *minor_status = G_TOK_TRUNC; - return(GSS_S_DEFECTIVE_TOKEN); - } + (void) memcpy(data_ptr, ptr-2, 8); - tcksum.checksum_type = (krb5_cksumtype) ((ptr[0]<<24) | (ptr[1]<<16) | - (ptr[2]<<8) | ptr[3]); - ptr += 4; + if (ctx->big_endian) + (void) memcpy(data_ptr+8, token.value, token.length); + else + (void) memcpy(data_ptr+8, plain, plainlen); - plain.data = ptr; + plaind.length = 8 + (ctx->big_endian ? token.length : plainlen); + plaind.data = data_ptr; + code = krb5_c_make_checksum(context, md5cksum.checksum_type, + ctx->seq, KG_USAGE_SIGN, + &plaind, &md5cksum); + xfree(data_ptr); + + if (code) { + if (toktype == KG_TOK_SEAL_MSG) + xfree(token.value); + *minor_status = code; + return(GSS_S_FAILURE); + } - tseqnum = ((ptr[0]<<24) | (ptr[1]<<16) | (ptr[2]<<8) | ptr[3]); - ptr += 4; - tdirection = ptr[0]; - ptr += 1; + if ((code = kg_encrypt(context, ctx->seq, KG_USAGE_SEAL, + (g_OID_equal(ctx->mech_used, gss_mech_krb5_old) ? + ctx->seq->contents : NULL), + md5cksum.contents, md5cksum.contents, 16))) { + xfree(md5cksum.contents); + if (toktype == KG_TOK_SEAL_MSG) + xfree(token.value); + *minor_status = code; + return GSS_S_FAILURE; + } - tmsglen = (ptr[0]<<8) | ptr[1]; - ptr += 2; - bodysize -= 11; + if (signalg == 0) + cksum.length = 8; + else + cksum.length = 16; + cksum.contents = md5cksum.contents + 16 - cksum.length; - if (bodysize < tmsglen) { - *minor_status = G_TOK_TRUNC; - return(GSS_S_DEFECTIVE_TOKEN); - } + code = memcmp(cksum.contents, ptr+14, cksum.length); + break; - tmsg = ptr; - ptr += tmsglen; - bodysize -= tmsglen; + case SGN_ALG_MD2_5: + if (!ctx->seed_init && + (code = kg_make_seed(context, ctx->subkey, ctx->seed))) { + xfree(md5cksum.contents); + if (sealalg != 0xffff) + xfree(plain); + if (toktype == KG_TOK_SEAL_MSG) + xfree(token.value); + *minor_status = code; + return GSS_S_FAILURE; + } - plain.length = ((char*)ptr) - ((char *)plain.data); + if (! (data_ptr = (void *) + xmalloc(sizeof(ctx->seed) + 8 + + (ctx->big_endian ? token.length : plainlen)))) { + xfree(md5cksum.contents); + if (sealalg == 0) + xfree(plain); + if (toktype == KG_TOK_SEAL_MSG) + xfree(token.value); + *minor_status = ENOMEM; + return(GSS_S_FAILURE); + } + (void) memcpy(data_ptr, ptr-2, 8); + (void) memcpy(data_ptr+8, ctx->seed, sizeof(ctx->seed)); + if (ctx->big_endian) + (void) memcpy(data_ptr+8+sizeof(ctx->seed), + token.value, token.length); + else + (void) memcpy(data_ptr+8+sizeof(ctx->seed), + plain, plainlen); + plaind.length = 8 + sizeof(ctx->seed) + + (ctx->big_endian ? token.length : plainlen); + plaind.data = data_ptr; + xfree(md5cksum.contents); + code = krb5_c_make_checksum(context, md5cksum.checksum_type, + ctx->seq, KG_USAGE_SIGN, + &plaind, &md5cksum); + xfree(data_ptr); + + if (code) { + if (sealalg == 0) + xfree(plain); + if (toktype == KG_TOK_SEAL_MSG) + xfree(token.value); + *minor_status = code; + return(GSS_S_FAILURE); + } - tcksum.length = (ptr[0]<<8) | ptr[1]; - ptr += 2; - bodysize -= 2; + code = memcmp(md5cksum.contents, ptr+14, 8); + /* Falls through to defective-token?? */ - if (bodysize != tcksum.length) { - *minor_status = G_TOK_TRUNC; + default: + *minor_status = 0; return(GSS_S_DEFECTIVE_TOKEN); - } - - tcksum.contents = ptr; - /* verify the MIC */ + case SGN_ALG_HMAC_SHA1_DES3_KD: + /* compute the checksum of the message */ - if (code = krb5_c_verify_checksum(context, ctx->subkey, - KRB5_KEYUSAGE_GSS_TOK_WRAP_INTEG, - &plain, &tcksum, &ckvalid)) { - *minor_status = code; - return(GSS_S_FAILURE); - } + /* 8 = bytes of token body to be checksummed according to spec */ - if (!ckvalid) { - *minor_status = 0; - return(GSS_S_BAD_SIG); - } + if (! (data_ptr = (void *) + xmalloc(8 + (ctx->big_endian ? token.length : plainlen)))) { + if (sealalg != 0xffff) + xfree(plain); + if (toktype == KG_TOK_SEAL_MSG) + xfree(token.value); + *minor_status = ENOMEM; + return(GSS_S_FAILURE); + } - /* check context expiry */ - - if ((code = krb5_timeofday(context, &now))) { - *minor_status = code; - return(GSS_S_FAILURE); - } - - if (now > ctx->endtime) { - *minor_status = 0; - return(GSS_S_CONTEXT_EXPIRED); - } - - /* do sequencing checks */ - - if ((ctx->initiate && tdirection != 0xff) || - (!ctx->initiate && tdirection != 0)) { - *minor_status = G_BAD_DIRECTION; - return(GSS_S_BAD_SIG); - } - - if (retval = g_order_check(&(ctx->seqstate), tseqnum)) { - *minor_status = 0; - return(retval); - } - - if (tmsglen) { - if ((output->value = (void *) malloc(tmsglen)) == NULL) { - *minor_status = ENOMEM; - return(GSS_S_FAILURE); - } - memcpy(output->value, tmsg, tmsglen); - output->length = tmsglen; - } - - if (qop_state) - *qop_state = GSS_C_QOP_DEFAULT; - - *minor_status = 0; - return(GSS_S_COMPLETE); -} + (void) memcpy(data_ptr, ptr-2, 8); -static OM_uint32 -kg2_unwrap_priv(context, minor_status, ctx, ptr, bodysize, output, qop_state) - krb5_context context; - OM_uint32 *minor_status; - krb5_gss_ctx_id_rec *ctx; - unsigned char *ptr; - int bodysize; - gss_buffer_t output; - gss_qop_t *qop_state; -{ - krb5_error_code code; - OM_uint32 retval; - krb5_enc_data cipher; - krb5_data plain; - krb5_ui_4 tseqnum; - int tdirection; - int tmsglen; - unsigned char *tmsg; - krb5_timestamp now; + if (ctx->big_endian) + (void) memcpy(data_ptr+8, token.value, token.length); + else + (void) memcpy(data_ptr+8, plain, plainlen); - output->length = 0; - output->value = NULL; + plaind.length = 8 + (ctx->big_endian ? token.length : plainlen); + plaind.data = data_ptr; + code = krb5_c_make_checksum(context, md5cksum.checksum_type, + ctx->seq, KG_USAGE_SIGN, + &plaind, &md5cksum); + xfree(data_ptr); - /* read the body parts out of the message */ + if (code) { + if (toktype == KG_TOK_SEAL_MSG) + xfree(token.value); + *minor_status = code; + return(GSS_S_FAILURE); + } - if (bodysize < 2) { - *minor_status = G_TOK_TRUNC; - return(GSS_S_DEFECTIVE_TOKEN); + code = memcmp(md5cksum.contents, ptr+14, md5cksum.length); + break; } - cipher.ciphertext.length = (ptr[0]<<8) | ptr[1]; - ptr += 2; - bodysize -= 2; + xfree(md5cksum.contents); + if (sealalg != 0xffff) + xfree(plain); - if (bodysize != cipher.ciphertext.length) { - *minor_status = G_TOK_TRUNC; - return(GSS_S_DEFECTIVE_TOKEN); - } + /* compare the computed checksum against the transmitted checksum */ - cipher.ciphertext.data = ptr; - cipher.enctype = ENCTYPE_UNKNOWN; - - plain.length = cipher.ciphertext.length; - if ((plain.data = (char *) malloc(plain.length)) == NULL) { + if (code) { + if (toktype == KG_TOK_SEAL_MSG) + xfree(token.value); *minor_status = 0; - return(GSS_S_FAILURE); - } - - /* decrypt (and implicitly verify) the encrypted data */ - - if (code = krb5_c_decrypt(context, ctx->subkey, - KRB5_KEYUSAGE_GSS_TOK_WRAP_PRIV, - 0, &cipher, &plain)) { - free(plain.data); - *minor_status = code; - return(GSS_S_FAILURE); + return(GSS_S_BAD_SIG); } - /* parse out the encrypted fields */ - ptr = plain.data; - bodysize = plain.length; + /* it got through unscathed. Make sure the context is unexpired */ - if (bodysize < 7) { - free(plain.data); - *minor_status = G_TOK_TRUNC; - return(GSS_S_DEFECTIVE_TOKEN); - } + if (toktype == KG_TOK_SEAL_MSG) + *message_buffer = token; - tseqnum = ((ptr[0]<<24) | (ptr[1]<<16) | (ptr[2]<<8) | ptr[3]); - ptr += 4; - tdirection = ptr[0]; - ptr += 1; + if (conf_state) + *conf_state = (sealalg != 0xffff); - tmsglen = (ptr[0]<<8) | ptr[1]; - ptr += 2; - bodysize -= 7; - - /* check context expiry */ + if (qop_state) + *qop_state = GSS_C_QOP_DEFAULT; if ((code = krb5_timeofday(context, &now))) { - free(plain.data); *minor_status = code; return(GSS_S_FAILURE); } if (now > ctx->endtime) { - free(plain.data); *minor_status = 0; return(GSS_S_CONTEXT_EXPIRED); } /* do sequencing checks */ - if ((ctx->initiate && tdirection != 0xff) || - (!ctx->initiate && tdirection != 0)) { - free(plain.data); - *minor_status = G_BAD_DIRECTION; + if ((code = kg_get_seq_num(context, ctx->seq, ptr+14, ptr+6, &direction, + &seqnum))) { + if (toktype == KG_TOK_SEAL_MSG) + xfree(token.value); + *minor_status = code; return(GSS_S_BAD_SIG); } - if (retval = g_order_check(&(ctx->seqstate), tseqnum)) { - free(plain.data); - *minor_status = 0; - return(retval); - } - - /* now copy out the data. can't do a strict equality check here, - since the output could be padded. */ - - if (bodysize < tmsglen) { - free(plain.data); - *minor_status = G_TOK_TRUNC; - return(GSS_S_DEFECTIVE_TOKEN); - } - - tmsg = ptr; - - if (tmsglen) { - if ((output->value = (void *) malloc(tmsglen)) == NULL) { - free(plain.data); - *minor_status = ENOMEM; - return(GSS_S_FAILURE); - } - memcpy(output->value, tmsg, tmsglen); - output->length = tmsglen; + if ((ctx->initiate && direction != 0xff) || + (!ctx->initiate && direction != 0)) { + if (toktype == KG_TOK_SEAL_MSG) + xfree(token.value); + *minor_status = G_BAD_DIRECTION; + return(GSS_S_BAD_SIG); } - if (qop_state) - *qop_state = GSS_C_QOP_DEFAULT; + retval = g_order_check(&(ctx->seqstate), seqnum); - free(plain.data); + /* success or ordering violation */ *minor_status = 0; - return(GSS_S_COMPLETE); + return(retval); } /* message_buffer is an input if SIGN, output if SEAL, and ignored if DEL_CTX conf_state is only valid if SEAL. */ OM_uint32 -kg_unseal_v1(context, minor_status, ctx, ptr, bodysize, message_buffer, - conf_state, qop_state, toktype) - krb5_context context; - OM_uint32 *minor_status; - krb5_gss_ctx_id_rec *ctx; - unsigned char *ptr; - int bodysize; - gss_buffer_t message_buffer; - int *conf_state; - int *qop_state; - int toktype; +kg_unseal(context, minor_status, context_handle, input_token_buffer, + message_buffer, conf_state, qop_state, toktype) + krb5_context context; + OM_uint32 *minor_status; + gss_ctx_id_t context_handle; + gss_buffer_t input_token_buffer; + gss_buffer_t message_buffer; + int *conf_state; + int *qop_state; + int toktype; { - krb5_error_code code; - int tmsglen; - int conflen = 0; - int signalg; - int sealalg; - gss_buffer_desc token; - krb5_checksum cksum; - krb5_checksum desmac; - krb5_checksum md5cksum; - krb5_data plaind; - char *data_ptr; - krb5_timestamp now; - unsigned char *plain; - int cksum_len = 0; - int plainlen; - int err; - int direction; - krb5_int32 seqnum; - OM_uint32 retval; - size_t sumlen; - - if (toktype == KG_TOK_SEAL_MSG) { - message_buffer->length = 0; - message_buffer->value = NULL; - } - - /* get the sign and seal algorithms */ - - signalg = ptr[0] + (ptr[1]<<8); - sealalg = ptr[2] + (ptr[3]<<8); - - /* Sanity checks */ - - if ((ptr[4] != 0xff) || (ptr[5] != 0xff)) { - *minor_status = 0; - return GSS_S_DEFECTIVE_TOKEN; - } - - if ((toktype != KG_TOK_SEAL_MSG) && - (sealalg != 0xffff)) { - *minor_status = 0; - return GSS_S_DEFECTIVE_TOKEN; - } - - /* in the current spec, there is only one valid seal algorithm per - key type, so a simple comparison is ok */ - - if ((toktype == KG_TOK_SEAL_MSG) && - !((sealalg == 0xffff) || - (sealalg == ctx->sealalg))) { - *minor_status = 0; - return GSS_S_DEFECTIVE_TOKEN; - } - - /* there are several mappings of seal algorithms to sign algorithms, - but few enough that we can try them all. */ - - if (((ctx->sealalg == 0) && - (signalg > 1)) || - ((ctx->sealalg == 1) && - (signalg != 3))) { - *minor_status = 0; - return GSS_S_DEFECTIVE_TOKEN; - } - - switch (signalg) { - case 0: - case 1: - cksum_len = 8; - break; - case 3: - cksum_len = 16; - break; - } - - if (toktype == KG_TOK_SEAL_MSG) - tmsglen = bodysize-(14+cksum_len); - - /* get the token parameters */ - - /* decode the message, if SEAL */ - - if (toktype == KG_TOK_SEAL_MSG) { - if (sealalg != 0xffff) { - if ((plain = (unsigned char *) xmalloc(tmsglen)) == NULL) { - *minor_status = ENOMEM; - return(GSS_S_FAILURE); - } + krb5_gss_ctx_id_rec *ctx; + unsigned char *ptr; + int bodysize; + int err; + + /* validate the context handle */ + if (! kg_validate_ctx_id(context_handle)) { + *minor_status = (OM_uint32) G_VALIDATE_FAILED; + return(GSS_S_NO_CONTEXT); + } - if ((code = kg_decrypt(context, ctx->enc, NULL, - ptr+14+cksum_len, plain, tmsglen))) { - xfree(plain); - *minor_status = code; - return(GSS_S_FAILURE); - } - } else { - plain = ptr+14+cksum_len; - } - - plainlen = tmsglen; - - if ((sealalg == 0xffff) && ctx->big_endian) { - token.length = tmsglen; - } else { - conflen = kg_confounder_size(context, ctx->enc); - token.length = tmsglen - conflen - plain[tmsglen-1]; - } - - if (token.length) { - if ((token.value = (void *) xmalloc(token.length)) == NULL) { - if (sealalg != 0xffff) - xfree(plain); - *minor_status = ENOMEM; - return(GSS_S_FAILURE); - } - memcpy(token.value, plain+conflen, token.length); - } - } else if (toktype == KG_TOK_SIGN_MSG) { - token = *message_buffer; - plain = token.value; - plainlen = token.length; - } else { - token.length = 0; - token.value = NULL; - plain = token.value; - plainlen = token.length; - } - - /* compute the checksum of the message */ - - /* initialize the the cksum */ - if (code = krb5_c_checksum_length(context, CKSUMTYPE_RSA_MD5, &sumlen)) - return(code); - - md5cksum.checksum_type = CKSUMTYPE_RSA_MD5; - md5cksum.length = sumlen; - - switch (signalg) { - case 0: - case 3: - /* compute the checksum of the message */ - - /* 8 = bytes of token body to be checksummed according to spec */ - - if (! (data_ptr = (void *) - xmalloc(8 + (ctx->big_endian ? token.length : plainlen)))) { - if (sealalg != 0xffff) - xfree(plain); - if (toktype == KG_TOK_SEAL_MSG) - xfree(token.value); - *minor_status = ENOMEM; - return(GSS_S_FAILURE); - } - - (void) memcpy(data_ptr, ptr-2, 8); - - if (ctx->big_endian) - (void) memcpy(data_ptr+8, token.value, token.length); - else - (void) memcpy(data_ptr+8, plain, plainlen); - - plaind.length = 8 + (ctx->big_endian ? token.length : plainlen); - plaind.data = data_ptr; - code = krb5_c_make_checksum(context, md5cksum.checksum_type, 0, 0, - &plaind, &md5cksum); - xfree(data_ptr); - - if (code) { - if (toktype == KG_TOK_SEAL_MSG) - xfree(token.value); - *minor_status = code; - return(GSS_S_FAILURE); - } - -#if 0 - /* XXX this depends on the key being a single-des key, but that's - all that kerberos supports right now */ - - /* initialize the the cksum and allocate the contents buffer */ - cksum.checksum_type = CKSUMTYPE_DESCBC; - cksum.length = krb5_checksum_size(context, CKSUMTYPE_DESCBC); - if ((cksum.contents = (krb5_octet *) xmalloc(cksum.length)) == NULL) { - xfree(md5cksum.contents); - if (toktype == KG_TOK_SEAL_MSG) - xfree(token.value); - *minor_status = ENOMEM; - return(GSS_S_FAILURE); - } - - /* XXX not converted to new api since it's inside an #if 0 */ - if (code = krb5_calculate_checksum(context, cksum.checksum_type, - md5cksum.contents, 16, - ctx->seq.key->contents, - ctx->seq.key->length, - &cksum)) { - xfree(cksum.contents); - xfree(md5cksum.contents); - if (toktype == KG_TOK_SEAL_MSG) - xfree(token.value); - *minor_status = code; - return(GSS_S_FAILURE); - } - - code = memcmp(cksum.contents, ptr+14, cksum.length); - - xfree(cksum.contents); -#else - if ((code = kg_encrypt(context, ctx->seq, - (g_OID_equal(ctx->mech_used, gss_mech_krb5_old) ? - ctx->seq->contents : NULL), - md5cksum.contents, md5cksum.contents, 16))) { - xfree(md5cksum.contents); - if (toktype == KG_TOK_SEAL_MSG) - xfree(token.value); - *minor_status = code; - return GSS_S_FAILURE; - } - - if (signalg == 0) - cksum.length = 8; - else - cksum.length = 16; - cksum.contents = md5cksum.contents + 16 - cksum.length; - - code = memcmp(cksum.contents, ptr+14, cksum.length); -#endif - break; - - case 1: - if (!ctx->seed_init && - (code = kg_make_seed(context, ctx->subkey, ctx->seed))) { - xfree(md5cksum.contents); - if (sealalg != 0xffff) - xfree(plain); - if (toktype == KG_TOK_SEAL_MSG) - xfree(token.value); - *minor_status = code; - return GSS_S_FAILURE; - } - - if (! (data_ptr = (void *) - xmalloc(sizeof(ctx->seed) + 8 + - (ctx->big_endian ? token.length : plainlen)))) { - xfree(md5cksum.contents); - if (sealalg == 0) - xfree(plain); - if (toktype == KG_TOK_SEAL_MSG) - xfree(token.value); - *minor_status = ENOMEM; - return(GSS_S_FAILURE); - } - (void) memcpy(data_ptr, ptr-2, 8); - (void) memcpy(data_ptr+8, ctx->seed, sizeof(ctx->seed)); - if (ctx->big_endian) - (void) memcpy(data_ptr+8+sizeof(ctx->seed), - token.value, token.length); - else - (void) memcpy(data_ptr+8+sizeof(ctx->seed), - plain, plainlen); - plaind.length = 8 + sizeof(ctx->seed) + - (ctx->big_endian ? token.length : plainlen); - plaind.data = data_ptr; - xfree(md5cksum.contents); - code = krb5_c_make_checksum(context, md5cksum.checksum_type, 0, 0, - &plaind, &md5cksum); - xfree(data_ptr); - - if (code) { - if (sealalg == 0) - xfree(plain); - if (toktype == KG_TOK_SEAL_MSG) - xfree(token.value); - *minor_status = code; - return(GSS_S_FAILURE); - } - - code = memcmp(md5cksum.contents, ptr+14, 8); - - default: - *minor_status = 0; - return(GSS_S_DEFECTIVE_TOKEN); - } - - xfree(md5cksum.contents); - if (sealalg != 0xffff) - xfree(plain); - - /* compare the computed checksum against the transmitted checksum */ - - if (code) { - if (toktype == KG_TOK_SEAL_MSG) - xfree(token.value); - *minor_status = 0; - return(GSS_S_BAD_SIG); - } - - - /* it got through unscathed. Make sure the context is unexpired */ - - if (toktype == KG_TOK_SEAL_MSG) - *message_buffer = token; - - if (conf_state) - *conf_state = (sealalg != 0xffff); - - if (qop_state) - *qop_state = GSS_C_QOP_DEFAULT; - - if ((code = krb5_timeofday(context, &now))) { - *minor_status = code; - return(GSS_S_FAILURE); - } - - if (now > ctx->endtime) { - *minor_status = 0; - return(GSS_S_CONTEXT_EXPIRED); - } - - /* do sequencing checks */ - - if ((code = kg_get_seq_num(context, ctx->seq, ptr+14, ptr+6, &direction, - &seqnum))) { - if (toktype == KG_TOK_SEAL_MSG) - xfree(token.value); - *minor_status = code; - return(GSS_S_BAD_SIG); - } - - if ((ctx->initiate && direction != 0xff) || - (!ctx->initiate && direction != 0)) { - if (toktype == KG_TOK_SEAL_MSG) - xfree(token.value); - *minor_status = G_BAD_DIRECTION; - return(GSS_S_BAD_SIG); - } - - retval = g_order_check(&(ctx->seqstate), seqnum); - - /* success or ordering violation */ - - *minor_status = 0; - return(retval); -} + ctx = (krb5_gss_ctx_id_rec *) context_handle; -/* message_buffer is an input if SIGN, output if SEAL, and ignored if DEL_CTX - conf_state is only valid if SEAL. */ + if (! ctx->established) { + *minor_status = KG_CTX_INCOMPLETE; + return(GSS_S_NO_CONTEXT); + } -OM_uint32 -kg_unseal(context, minor_status, context_handle, input_token_buffer, - message_buffer, conf_state, qop_state, toktype) - krb5_context context; - OM_uint32 *minor_status; - gss_ctx_id_t context_handle; - gss_buffer_t input_token_buffer; - gss_buffer_t message_buffer; - int *conf_state; - int *qop_state; - int toktype; -{ - krb5_gss_ctx_id_rec *ctx; - unsigned char *ptr; - int bodysize; - int err; - OM_uint32 retval; - - /* validate the context handle */ - if (! kg_validate_ctx_id(context_handle)) { - *minor_status = (OM_uint32) G_VALIDATE_FAILED; - return(GSS_S_NO_CONTEXT); - } - - ctx = (krb5_gss_ctx_id_rec *) context_handle; - - if (! ctx->established) { - *minor_status = KG_CTX_INCOMPLETE; - return(GSS_S_NO_CONTEXT); - } - - /* parse the token, leave the data in message_buffer, setting conf_state */ - - /* verify the header */ - - ptr = (unsigned char *) input_token_buffer->value; - - if (ctx->gsskrb5_version == 2000) { - if (!(err = g_verify_token_header((gss_OID) ctx->mech_used, - &bodysize, &ptr, KG2_TOK_MIC, - input_token_buffer->length))) { - return(kg2_verify_mic(context, minor_status, ctx, ptr, bodysize, - message_buffer, qop_state)); - } else if (!(err = g_verify_token_header((gss_OID) ctx->mech_used, - &bodysize, &ptr, - KG2_TOK_WRAP_INTEG, - input_token_buffer->length))) { - if (GSS_ERROR(retval = kg2_unwrap_integ(context, minor_status, - ctx, ptr, bodysize, - message_buffer, qop_state))) - return(retval); - - if (conf_state) - *conf_state = 0; - return(GSS_S_COMPLETE); - } else if (!(err = g_verify_token_header((gss_OID) ctx->mech_used, - &bodysize, &ptr, - KG2_TOK_WRAP_PRIV, - input_token_buffer->length))) { - if (GSS_ERROR(retval = kg2_unwrap_priv(context, minor_status, - ctx, ptr, bodysize, - message_buffer, qop_state))) - return(retval); - - if (conf_state) - *conf_state = 1; - return(GSS_S_COMPLETE); - } - } else { - if (!(err = g_verify_token_header((gss_OID) ctx->mech_used, - &bodysize, &ptr, toktype, - input_token_buffer->length))) { - return(kg_unseal_v1(context, minor_status, ctx, ptr, bodysize, - message_buffer, conf_state, qop_state, - toktype)); - } - } - - *minor_status = err; - return(GSS_S_DEFECTIVE_TOKEN); + /* parse the token, leave the data in message_buffer, setting conf_state */ + + /* verify the header */ + + ptr = (unsigned char *) input_token_buffer->value; + + if (!(err = g_verify_token_header((gss_OID) ctx->mech_used, + &bodysize, &ptr, toktype, + input_token_buffer->length))) { + return(kg_unseal_v1(context, minor_status, ctx, ptr, bodysize, + message_buffer, conf_state, qop_state, + toktype)); + } + + *minor_status = err; + return(GSS_S_DEFECTIVE_TOKEN); } diff --git a/src/lib/gssapi/krb5/ser_sctx.c b/src/lib/gssapi/krb5/ser_sctx.c index 2a6231e..1989a7d 100644 --- a/src/lib/gssapi/krb5/ser_sctx.c +++ b/src/lib/gssapi/krb5/ser_sctx.c @@ -233,7 +233,6 @@ kg_ctx_size(kcontext, arg, sizep) * krb5_int32 for seq_recv. * krb5_int32 for established. * krb5_int32 for big_endian. - * krb5_int32 for gsskrb5_version. * krb5_int32 for nctypes. * krb5_int32 for trailer. */ @@ -349,8 +348,6 @@ kg_ctx_externalize(kcontext, arg, buffer, lenremain) &bp, &remain); (void) krb5_ser_pack_int32((krb5_int32) ctx->big_endian, &bp, &remain); - (void) krb5_ser_pack_int32((krb5_int32) ctx->gsskrb5_version, - &bp, &remain); (void) krb5_ser_pack_int32((krb5_int32) ctx->nctypes, &bp, &remain); @@ -477,8 +474,6 @@ kg_ctx_internalize(kcontext, argp, buffer, lenremain) (void) krb5_ser_unpack_int32(&ibuf, &bp, &remain); ctx->big_endian = (int) ibuf; (void) krb5_ser_unpack_int32(&ibuf, &bp, &remain); - ctx->gsskrb5_version = (int) ibuf; - (void) krb5_ser_unpack_int32(&ibuf, &bp, &remain); ctx->nctypes = (int) ibuf; if ((kret = kg_oid_internalize(kcontext, &ctx->mech_used, &bp, diff --git a/src/lib/gssapi/krb5/util_cksum.c b/src/lib/gssapi/krb5/util_cksum.c index 10e6b65..47ffc5b 100644 --- a/src/lib/gssapi/krb5/util_cksum.c +++ b/src/lib/gssapi/krb5/util_cksum.c @@ -27,6 +27,7 @@ #include "gssapiP_krb5.h" #include <memory.h> +/* Checksumming the channel bindings always uses plain MD5. */ krb5_error_code kg_checksum_channel_bindings(context, cb, cksum, bigend) krb5_context context; diff --git a/src/lib/gssapi/krb5/util_crypt.c b/src/lib/gssapi/krb5/util_crypt.c index 93d4694..049e4d6 100644 --- a/src/lib/gssapi/krb5/util_crypt.c +++ b/src/lib/gssapi/krb5/util_crypt.c @@ -54,8 +54,6 @@ * $Id$ */ -static unsigned char zeros[8] = {0,0,0,0,0,0,0,0}; - int kg_confounder_size(context, key) krb5_context context; @@ -105,9 +103,10 @@ kg_encrypt_size(context, key, n) } krb5_error_code -kg_encrypt(context, key, iv, in, out, length) +kg_encrypt(context, key, usage, iv, in, out, length) krb5_context context; krb5_keyblock *key; + int usage; krb5_pointer iv; krb5_pointer in; krb5_pointer out; @@ -123,7 +122,10 @@ kg_encrypt(context, key, iv, in, out, length) return(code); ivd.length = blocksize; - ivd.data = iv; + ivd.data = malloc(ivd.length); + if (ivd.data == NULL) + return ENOMEM; + memcpy(ivd.data, iv, ivd.length); pivd = &ivd; } else { pivd = NULL; @@ -135,18 +137,19 @@ kg_encrypt(context, key, iv, in, out, length) outputd.ciphertext.length = length; outputd.ciphertext.data = out; - return(krb5_c_encrypt(context, key, - /* XXX this routine is only used for the old - bare-des stuff which doesn't use the - key usage */ 0, pivd, &inputd, &outputd)); + code = krb5_c_encrypt(context, key, usage, pivd, &inputd, &outputd); + if (pivd != NULL) + krb5_free_data_contents(context, pivd); + return code; } /* length is the length of the cleartext. */ krb5_error_code -kg_decrypt(context, key, iv, in, out, length) +kg_decrypt(context, key, usage, iv, in, out, length) krb5_context context; krb5_keyblock *key; + int usage; krb5_pointer iv; krb5_pointer in; krb5_pointer out; @@ -162,7 +165,10 @@ kg_decrypt(context, key, iv, in, out, length) return(code); ivd.length = blocksize; - ivd.data = iv; + ivd.data = malloc(ivd.length); + if (ivd.data == NULL) + return ENOMEM; + memcpy(ivd.data, iv, ivd.length); pivd = &ivd; } else { pivd = NULL; @@ -175,8 +181,8 @@ kg_decrypt(context, key, iv, in, out, length) outputd.length = length; outputd.data = out; - return(krb5_c_decrypt(context, key, - /* XXX this routine is only used for the old - bare-des stuff which doesn't use the - key usage */ 0, pivd, &inputd, &outputd)); + code = krb5_c_decrypt(context, key, usage, pivd, &inputd, &outputd); + if (pivd != NULL) + krb5_free_data_contents(context, pivd); + return code; } diff --git a/src/lib/gssapi/krb5/util_seed.c b/src/lib/gssapi/krb5/util_seed.c index 206ee68..b4a9044 100644 --- a/src/lib/gssapi/krb5/util_seed.c +++ b/src/lib/gssapi/krb5/util_seed.c @@ -47,7 +47,7 @@ kg_make_seed(context, key, seed) for (i=0; i<tmpkey->length; i++) tmpkey->contents[i] = key->contents[key->length - 1 - i]; - code = kg_encrypt(context, tmpkey, NULL, zeros, seed, 16); + code = kg_encrypt(context, tmpkey, KG_USAGE_SEAL, NULL, zeros, seed, 16); krb5_free_keyblock(context, tmpkey); diff --git a/src/lib/gssapi/krb5/util_seqnum.c b/src/lib/gssapi/krb5/util_seqnum.c index e14b2f3..b8f2b38 100644 --- a/src/lib/gssapi/krb5/util_seqnum.c +++ b/src/lib/gssapi/krb5/util_seqnum.c @@ -47,7 +47,7 @@ kg_make_seq_num(context, key, direction, seqnum, cksum, buf) plain[6] = direction; plain[7] = direction; - return(kg_encrypt(context, key, cksum, plain, buf, 8)); + return(kg_encrypt(context, key, KG_USAGE_SEQ, cksum, plain, buf, 8)); } krb5_error_code kg_get_seq_num(context, key, cksum, buf, direction, seqnum) @@ -61,7 +61,7 @@ krb5_error_code kg_get_seq_num(context, key, cksum, buf, direction, seqnum) krb5_error_code code; unsigned char plain[8]; - if (code = kg_decrypt(context, key, cksum, buf, plain, 8)) + if (code = kg_decrypt(context, key, KG_USAGE_SEQ, cksum, buf, plain, 8)) return(code); if ((plain[4] != plain[5]) || diff --git a/src/lib/gssapi/krb5/wrap_size_limit.c b/src/lib/gssapi/krb5/wrap_size_limit.c index f7fee73..55d4bce 100644 --- a/src/lib/gssapi/krb5/wrap_size_limit.c +++ b/src/lib/gssapi/krb5/wrap_size_limit.c @@ -1,4 +1,28 @@ /* + * Copyright 2000 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + * + */ +/* * Copyright 1993 by OpenVision Technologies, Inc. * * Permission to use, copy, modify, distribute, and sell this software @@ -66,6 +90,9 @@ krb5_gss_wrap_size_limit(minor_status, context_handle, conf_req_flag, krb5_context context; krb5_gss_ctx_id_rec *ctx; krb5_error_code code; + OM_uint32 data_size, conflen; + OM_uint32 ohlen; + int overhead; if (GSS_ERROR(kg_get_context(minor_status, &context))) return(GSS_S_FAILURE); @@ -88,92 +115,23 @@ krb5_gss_wrap_size_limit(minor_status, context_handle, conf_req_flag, return(GSS_S_NO_CONTEXT); } - if (ctx->gsskrb5_version == 2000) { - if (conf_req_flag) { - /* this is pretty gross. take the max output, and call - krb5_c_encrypt_length to see how much overhead is added - on. subtract that much, and see if it fits in the - requested space. If not, start subtracting 1 until it - does. This doesn't necessarily give us the optimal - packing, but I think that's ok (I could start adding 1 - until I went over, but that seems like it's not worth - the effort). This is probably O(blocksize), but that's - never going to be large. */ - - OM_uint32 headerlen, plainlen; - size_t enclen; - - headerlen = g_token_size((gss_OID) ctx->mech_used, 2); - plainlen = req_output_size - headerlen; - - if (code = krb5_c_encrypt_length(context, ctx->enc->enctype, - plainlen, &enclen)) { - *minor_status = code; - return(GSS_S_FAILURE); - } - - plainlen -= plainlen - (enclen - plainlen); - - if (code = krb5_c_encrypt_length(context, ctx->enc->enctype, - plainlen, &enclen)) { - *minor_status = code; - return(GSS_S_FAILURE); - } - - while (headerlen + enclen > req_output_size) { - plainlen--; - - if (code = krb5_c_encrypt_length(context, ctx->enc->enctype, - plainlen, &enclen)) { - *minor_status = code; - return(GSS_S_FAILURE); - } - } - - /* subtract off the fixed size inside the encrypted part */ - - plainlen -= 7; - - *max_input_size = plainlen; - } else { - size_t cksumlen; - OM_uint32 headerlen; - - if (code = krb5_c_checksum_length(context, ctx->ctypes[0], - &cksumlen)) { - *minor_status = code; - return(GSS_S_FAILURE); - } - - headerlen = g_token_size((gss_OID) ctx->mech_used, 13 + cksumlen); - - *max_input_size = req_output_size - headerlen; - } - } else { - OM_uint32 data_size, conflen; - OM_uint32 ohlen; - int overhead; - - /* Calculate the token size and subtract that from the output size */ - overhead = 7 + ctx->mech_used->length; - data_size = req_output_size; - if (conf_req_flag) { - conflen = kg_confounder_size(context, ctx->enc); - data_size = (conflen + data_size + 8) & (~7); - } - ohlen = g_token_size((gss_OID) ctx->mech_used, - (unsigned int) (data_size + ctx->cksum_size + 14)) - - req_output_size; - - if (ohlen+overhead < req_output_size) - /* - * Cannot have trailer length that will cause us to pad over - * our length - */ - *max_input_size = (req_output_size - ohlen - overhead) & (~7); - else - *max_input_size = 0; - } + /* Calculate the token size and subtract that from the output size */ + overhead = 7 + ctx->mech_used->length; + data_size = req_output_size; + conflen = kg_confounder_size(context, ctx->enc); + data_size = (conflen + data_size + 8) & (~(OM_uint32)7); + ohlen = g_token_size((gss_OID) ctx->mech_used, + (unsigned int) (data_size + ctx->cksum_size + 14)) + - req_output_size; + + if (ohlen+overhead < req_output_size) + /* + * Cannot have trailer length that will cause us to pad over our + * length. + */ + *max_input_size = (req_output_size - ohlen - overhead) & (~(OM_uint32)7); + else + *max_input_size = 0; *minor_status = 0; return(GSS_S_COMPLETE); |